Contact Us | Stratusphere FinOps | StratusGrid Home | Blog
GitHub: StratusGrid/terraform-state-s3-bucket-centralized-with-roles
This is intended to be used by an organization for all of their own accounts. This does not protect access to DynamoDB locking of other accounts, it only restricts access S3 paths for each account.
This restriction is put in place by creating a unique role for each account, then attaching an assumerole policy that trusts the corresponding account to assume it. You will still need to give permission to assume roles to your users/roles that are used to apply terraform in other accounts, and configure your state appropriately to use this.
As of v3.0, all public access is blocked by default. There are individual parameters which can be set to "false" if public bucket/state access is desired:
- block_public_acls
- block_public_policy
- ignore_public_acls
- restrict_public_buckets
module "terraform_state_backend" {
source = "StratusGrid/terraform-state-s3-bucket-centralized-with-roles/aws"
version = "~> 4.1"
name_prefix = "mycompany"
log_bucket_id = module.s3_bucket_logging.bucket_id
account_arns = [
"arn:aws:iam::123456789012:root",
"arn:aws:iam::098765432109:root"
]
global_account_arns = ["arn:aws:iam::123456789012:root"]
input_tags = local.common_tags
}
output "terraform_state_kms_key_alias_arns" {
value = module.terraform_state.kms_key_alias_arns
}
output "terraform_state_kms_key_arns" {
value = module.terraform_state.kms_key_arns
}
output "terraform_state_iam_role_arns" {
value = module.terraform_state.iam_role_arns
}
terraform {
backend "s3" {
role_arn = "arn:aws:iam::123456789012:role/123456789012-terraform-state"
acl = "bucket-owner-full-control"
bucket = "mycompany-remote-state-backend-anm1587s49"
dynamodb_table = "mycompany-remote-state-backend"
encrypt = true
key = "123456789012/mycompany-account-organization-master/terraform.tfstate"
kms_key_id = "arn:aws:kms:us-east-1:123456789012:key/4ryh7htp-FAKE-ARNS-DUDE-777d88512345"
region = "us-east-1"
}
}
terraform init -backend-config="access_key=ABCDEFGHIJKLMNOPQR" -backend-config="secret_key=AbcDeFgHIJKlmnOPqRStUVwxyZ"
NOTE: The access and secret keys used must have rights to assume the role created by the module
- This is usually automatically the case for any keys that have full admin rights in the account whose state is to be stored, or in one of the global accounts specified.
- Otherwise, this will need to be assigned manually. You can use this module to help with mapping those trusts: https://registry.terraform.io/modules/StratusGrid/iam-cross-account-trust-maps/aws
- Use trusting_arn to map a single trust (like for a standard account assumption policy)
- Use trusting_arns to map multiple trusts (like for a global account assumption policy)
# This should have each terraform state role if you want a user to be able to apply terraform manually
locals {
mycompany_organization_terraform_state_account_roles = [
"arn:aws:iam::123456789012:role/210987654321-terraform-state",
"arn:aws:iam::123456789012:role/123456789012-terraform-state"
]
}
# When require_mfa is set to true, terraform init and terraform apply would need to be run with your STS acquired temporary token
module "mycompany_organization_terraform_state_trust_maps" {
source = "StratusGrid/iam-role-cross-account-trusting/aws"
version = "~> 2.1"
trusting_role_arns = local.mycompany_organization_terraform_state_account_roles
trusted_policy_name = "mycompany-organization-terraform-states"
trusted_group_names = [
"${aws_iam_group.mycompany_internal_admins.name}"
]
trusted_role_names = []
require_mfa = false
input_tags = local.common_tags
}
In this case, you just don't specific other accounts. Then, you use the default kms key along with the dynamodb table.
module "terraform_state" {
source = "StratusGrid/terraform-state-s3-bucket-centralized-with-roles/aws"
version = "~> 5.1"
name_prefix = var.name_prefix
name_suffix = local.name_suffix
log_bucket_id = module.s3_bucket_logging.bucket_id
log_bucket_target_prefix = "s3/"
log_bucket_target_object_key_format = {
partitioned_prefix = {
partition_date_source = "EventTime"
}
}
account_arns = []
global_account_arns = []
dynamodb_table_billing_type = "PROVISIONED"
dynamodb_table_read_capacity = 1
dynamodb_table_write_capacity = 1
input_tags = merge(local.common_tags, {})
}
output "terraform_state_kms_key_alias_arn" {
value = module.terraform_state.kms_default_key_alias_arn
}
output "terraform_state_kms_key_arn" {
value = module.terraform_state.kms_default_key_arn
}
Name | Type |
---|---|
aws_dynamodb_table.remote_state_backend | resource |
aws_iam_policy.account_state_policy | resource |
aws_iam_role.account_state_role | resource |
aws_iam_role_policy_attachment.account_state_role | resource |
aws_kms_alias.remote_state_backend | resource |
aws_kms_alias.specific_state_backend | resource |
aws_kms_key.remote_state_backend | resource |
aws_kms_key.specific_remote_state_backend | resource |
aws_s3_bucket.remote_state_backend | resource |
aws_s3_bucket_logging.remote_state_backend | resource |
aws_s3_bucket_policy.remote_state_backend | resource |
aws_s3_bucket_public_access_block.this | resource |
aws_s3_bucket_server_side_encryption_configuration.remote_state_backend | resource |
aws_s3_bucket_versioning.remote_state_backend | resource |
Name | Description | Type | Default | Required |
---|---|---|---|---|
account_arns | Arns for accounts / roles in accounts which are given a role they are able to assume to access their state. | list(string) |
[] |
no |
aws_s3_bucket_server_side_encryption_type | Selection of the bucket encryption type | string |
"SSE_KMS" |
no |
block_public_acls | Blocks public ACLs on the bucket. | bool |
true |
no |
block_public_policy | Whether Amazon S3 should block public bucket policies for this bucket. | bool |
true |
no |
dynamodb_table_billing_type | Defines whether the DynamoDB table used for state locking and consistency checking should use on-demand or provisioned capacity mode. | string |
"PAY_PER_REQUEST" |
no |
dynamodb_table_read_capacity | Defines the number of read units for the state locking and consistency table. If the dynamodb_table_billing_type is PROVISIONED, this field is required. | number |
0 |
no |
dynamodb_table_write_capacity | Defines the number of write units for the state locking and consistency table. If the dynamodb_table_billing_type is PROVISIONED, this field is required. | number |
0 |
no |
global_account_arns | Arns for a account(s) / roles in account(s) that would be allowed access to all account states, for instance a global users account. Restrictions of which of that accounts users were able to access a given state would need to be further restricted inside of the global account(s) themselves. | list(string) |
[] |
no |
ignore_public_acls | Whether Amazon S3 should ignore public ACLs for this bucket. Causes Amazon S3 to ignore public ACLs on this bucket and any objects that it contains. | bool |
true |
no |
input_tags | Map of tags to apply to resources | map(string) |
{} |
no |
log_bucket_id | ID of logging bucket to be targeted for S3 bucket logs | string |
n/a | yes |
log_bucket_target_object_key_format | Map containing logging bucket target object key format configuration. | any |
{} |
no |
log_bucket_target_prefix | The prefix for all log object keys. Define this varible to override the default. | string |
"" |
no |
name_prefix | String to use as prefix on object names | string |
n/a | yes |
name_suffix | String to append to object names. This is optional, so start with dash if using | string |
"" |
no |
restrict_public_buckets | Whether Amazon S3 should restrict public bucket policies for this bucket. Enabling this setting does not affect the previously stored bucket policy, except that public and cross-account access within the public bucket policy, including non-public delegation to specific accounts, is blocked. | bool |
true |
no |
Name | Description |
---|---|
bucket | bucket friendly name |
dynamodb_table | dynamodb friendly name |
iam_role_arns | arns for each IAM role that can be assumend for the corresponding account's terraform state |
kms_default_key_alias_arn | kms key arn that is created by default. Use this when just using this for a state bucket and not from other accounts. |
kms_default_key_arn | kms key alias arn that is created by default. Use this when just using this for a state bucket and not from other accounts. |
kms_key_alias_arns | kms key alias arns for each specific account |
kms_key_arns | kms key arns for each specific account |
- Chris Hurst GenesisChris
- Ivan Casco ivancasco-sg
- Jason Drouhard jason-drouhard
- Matt Barlow mattbarlow-sg
- Chris Childress chrischildresssg
Note: Manual changes to the README will be overwritten when the documentation is updated. To update the documentation, run terraform-docs -c .config/.terraform-docs.yml .