From 138dd66f7004401528714fe7eb25efa325376c12 Mon Sep 17 00:00:00 2001 From: badra001 Date: Thu, 18 Feb 2021 14:44:19 -0500 Subject: [PATCH 01/20] setup initial structure --- .gitignore | 12 ++ .pre-commit-config.yaml | 17 ++ CHANGELOG.md | 6 + README.md | 27 ++- access-logging-bucket/version.tf | 1 + cloudtrail/version.tf | 1 + common/defaults.tf | 5 + common/outputs.tf | 30 ++++ common/prefixes.tf | 12 ++ common/resources.tf | 271 +++++++++++++++++++++++++++++++ common/variables.tf | 70 ++++++++ common/version.tf | 3 + config/version.tf | 1 + gpg-key/version.tf | 1 + object-logging/version.tf | 1 + terraform-state/version.tf | 1 + 16 files changed, 458 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 CHANGELOG.md create mode 120000 access-logging-bucket/version.tf create mode 120000 cloudtrail/version.tf create mode 100644 common/defaults.tf create mode 100644 common/outputs.tf create mode 100644 common/prefixes.tf create mode 100644 common/resources.tf create mode 100644 common/variables.tf create mode 100644 common/version.tf create mode 120000 config/version.tf create mode 120000 gpg-key/version.tf create mode 120000 object-logging/version.tf create mode 120000 terraform-state/version.tf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4df0dc1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# .tfvars files +*.tfvars + +.terraform/* +logs diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..85f5ae4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,17 @@ +repos: +- repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.31.0 + hooks: +# - id: terraform_validate + - id: terraform_fmt + - id: terraform_docs_replace + args: ['table'] + exclude: common/*.tf + exclude: version.tf + +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.1.0 + hooks: + - id: check-symlinks + - id: detect-aws-credentials + - id: detect-private-key diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..72de437 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +# Versions + +* v1.0 -- 20210218 + - initial creation + - module: terraform-state + diff --git a/README.md b/README.md index 97f16ee..dc81bdb 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,27 @@ # aws-inf-setup -AWS Infrastructure Setup + +This contains a bunch of submodules used for setting up an AWS account, to the standard configurations we use +at Census. + +## Submodules + +### [terraform-state](terraform-state) + +This creates an S3 bucket, KMS key, and DynamoDB table for use with an AWS account. The bucket region is important +for connection to the remote state. Key ARN and ID, S3 bucket ID, and DDB tables are exportet, but they follow a standard +structure so they are not really needed. The bucket is `inf-tfstate-{account_id}`. + +This has no other dependencies, since it has to be created first. Only one is needed per account. + +### splunk-user + +### access-logging-bucket + +This sets up the S3 bucket used for access logs. One is needed per region, and the region and account are included +in the bucket names: `inf-log-{account_id}-{region}`. + +### object-logging +### cloudtrail +### config +### gpg-key + diff --git a/access-logging-bucket/version.tf b/access-logging-bucket/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/access-logging-bucket/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file diff --git a/cloudtrail/version.tf b/cloudtrail/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/cloudtrail/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file diff --git a/common/defaults.tf b/common/defaults.tf new file mode 100644 index 0000000..c67478b --- /dev/null +++ b/common/defaults.tf @@ -0,0 +1,5 @@ + +locals { + _defaults = { + } +} diff --git a/common/outputs.tf b/common/outputs.tf new file mode 100644 index 0000000..254a87e --- /dev/null +++ b/common/outputs.tf @@ -0,0 +1,30 @@ +#--- +# bucket +#--- +output "s3_bucket_arn" { + description = "Created S3 Bucket ARN" + value = aws_s3_bucket.this.arn +} + +output "s3_bucket_id" { + description = "Created S3 Bucket ID" + value = aws_s3_bucket.this.id +} + +#--- +# key +#--- +output "kms_key_id" { + description = "Created KMS Key ID" + value = aws_kms_key.key.id +} + +output "kms_key_arn" { + description = "Created KMS Key ARN" + value = aws_kms_key.key.arn +} + +output "kms_key_alias" { + description = "Created KMS Key Alias name" + value = aws_kms_alias.key.name +} diff --git a/common/prefixes.tf b/common/prefixes.tf new file mode 100644 index 0000000..fafcbde --- /dev/null +++ b/common/prefixes.tf @@ -0,0 +1,12 @@ +locals { + _prefixes = { + "efs" = "v-efs-" + "s3" = "v-s3-" + "ebs" = "v-ebs-" + "kms" = "k-kms-" + "role" = "r-" + "policy" = "p-" + "security-group" = "" + # "security-group" = "sg-" + } +} diff --git a/common/resources.tf b/common/resources.tf new file mode 100644 index 0000000..016ecb6 --- /dev/null +++ b/common/resources.tf @@ -0,0 +1,271 @@ +locals { + name = replace(var.bucket_name, local._prefixes["s3"], "") + bucket_name = format("%s%s", local._prefixes["s3"], local.name) + __prefixes = merge(local._prefixes, var.override_prefixes) + + # kms_key_arn_exists = var.kms_key_arn != "" && var.kms_key_arn != null + kms_key_arn = aws_kms_key.key.arn + kms_key_name = format("%s%s", local.__prefixes["kms"], local.name) + + condition_allowed_cidr = { + "test" : "NotIpAddress" + "variable" : "aws:sourceIp" + "values" : var.allowed_cidr + } + condition_allowed_endpoints = { + "test" : "StringNotEquals" + "variable" : "aws:sourceVpce" + "values" : var.allowed_endpoints + } + s3_bucket_conditions_list = list(local.condition_allowed_cidr, local.condition_allowed_endpoints) + s3_bucket_conditions = [for x in local.s3_bucket_conditions_list : x if length(x.values) > 0] + + # enforced_tags = { + # "boc:safeguard" = "title26" + # } + base_tags = { + "boc:tf_module_version" = local._module_version + "boc:created_by" = "terraform" + } + # strip spaces, convert to lowercase, make distinct, sort. Remove those not in the _defaults + add_safeguard_tags = local.enable_title26 ? ["title26"] : [] + _default_safeguard_tags = { for d in local._defaults["data_safeguards"] : d => d } + safeguard_tags = sort(distinct(compact(concat([for t in var.data_safeguards : lookup(local._default_safeguard_tags, lower(replace(t, " ", "")), "")], local.add_safeguard_tags)))) + add_tags = { + safeguard = { + "exists" = { "boc:safeguard" = join(",", local.safeguard_tags) } + "not_exists" = {} + } + } + enforced_tags = merge( + local.add_tags["safeguard"][length(local.safeguard_tags) > 0 ? "exists" : "not_exists"] + ) + metadata_tags = merge( + var.metadata_tags, + { for k, v in local.enforced_tags : format("x-amzn-meta-%v", replace(k, "/\\W/", "_")) => v } + ) +} + +#--- +# s3 bucket +#--- +resource "aws_s3_bucket" "this" { + bucket = local.bucket_name + acl = "private" + force_destroy = var.force_destroy + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.key.key_id + sse_algorithm = "aws:kms" + } + } + } + + versioning { + enabled = local.versioning + } + + logging { + target_bucket = var.access_log_bucket + target__prefix = format("%s/%s/", var.access_log_bucket__prefix, local.bucket_name) + } + + lifecycle { + prevent_destroy = false + } + + tags = merge( + local.base_tags, + var.tags, + local.enforced_tags, + map("Name", local.bucket_name) + ) +} + +data "aws_iam_policy_document" "this" { + statement { + sid = "DenyIncorrectEncryptionHeader" + effect = "Deny" + actions = ["s3:PutObject"] + principals { + type = "AWS" + identifiers = ["*"] + } + resources = ["${aws_s3_bucket.this.arn}/*"] + condition { + test = "StringNotEquals" + variable = "s3:x-amz-server-side-encryption" + values = ["aws:kms"] + } + } + statement { + sid = "DenyUnEncryptedObjectUploads" + effect = "Deny" + actions = ["s3:PutObject"] + principals { + type = "AWS" + identifiers = ["*"] + } + resources = ["${aws_s3_bucket.this.arn}/*"] + condition { + test = "Null" + variable = "s3:x-amz-server-side-encryption" + values = ["true"] + } + } + statement { + sid = "enforceSSL" + effect = "Deny" + actions = ["s3:*"] + principals { + type = "AWS" + identifiers = ["*"] + } + resources = [aws_s3_bucket.this.arn, "${aws_s3_bucket.this.arn}/*"] + condition { + test = "Bool" + variable = "aws:SecureTransport" + values = ["false"] + } + } + dynamic "statement" { + for_each = length(local.s3_bucket_conditions) > 0 ? toset(["1"]) : toset([]) + iterator = s + content { + sid = "RemoteAccessBucketRestrictions" + effect = "Deny" + actions = ["s3:*"] + principals { + type = "AWS" + identifiers = ["*"] + } + resources = [aws_s3_bucket.this.arn, "${aws_s3_bucket.this.arn}/*"] + dynamic "condition" { + for_each = local.s3_bucket_conditions + iterator = c + content { + test = c.value.test + variable = c.value.variable + values = c.value.values + } + } + } + } +} +#--- +# apply policy to bucket and public access block policy to bucket +#--- +resource "aws_s3_bucket_policy" "policy" { + bucket = aws_s3_bucket.this.bucket + policy = data.aws_iam_policy_document.this.json + depends_on = [null_resource.policy_delay] +} + +resource "aws_s3_bucket_public_access_block" "this" { + bucket = aws_s3_bucket.this.id + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true + depends_on = [aws_s3_bucket_policy.policy] +} + +resource "null_resource" "policy_delay" { + triggers = { + bucket = aws_s3_bucket.this.id + } + provisioner "local-exec" { + when = create + command = "sleep 120" + } +} + +resource "aws_s3_bucket_object" "this_objects" { + for_each = toset(var.bucket_folders) + bucket = aws_s3_bucket.this.id + key = format("%s/", each.key) + source = "/dev/null" + metadata = local.metadata_tags + + depends_on = [null_resource.policy_delay] +} + +#--- +# create a key and alias if not specified +# right now, this can't use an external key, it has to create one per bucket +#--- +resource "aws_kms_key" "key" { + description = "KMS CMK for S3 bucket ${local.name}" + enable_key_rotation = true + # policy = data.aws_iam_policy_document.key.json + + tags = merge( + local.base_tags, + var.tags, + local.enforced_tags, + map("Name", local.bucket_name) + ) +} + +resource "aws_kms_alias" "key" { + name = "alias/${local.kms_key_name}" + target_key_id = aws_kms_key.key.key_id +} + +## ### +## +## locals { +## lifecycle_rules = [ +## { +## id = "Expiration Rule" +## enabled = true +## prefix = "reports/" +## expiration = { +## days = 30 +## } +## } +## ] +## } +## +## resource "aws_s3_bucket" "bucket-name" { +## bucket = "bucket-name" +## +## dynamic "lifecycle_rule" { +## for_each = local.lifecycle_rules +## +## content { +## id = lifecycle_rule.each.id +## enabled = lifecycle_rule.each.enabled +## prefix = lifecycle_rule.each.prefix +## +## expiration { +## days = lifecycle_rule.each.expiration.days +## } +## } +## } +## } +## +## ## # lifecycle_rule { +## ## # id = "log" +## ## # enabled = true +## ## # prefix = "log/" +## ## # tags = { +## ## # "rule" = "log" +## ## # "autoclean" = "true" +## ## # } +## ## # transition { +## ## # days = 30 +## ## # storage_class = "STANDARD_IA" +## ## # } +## ## # +## ## # transition { +## ## # days = 60 +## ## # storage_class = "GLACIER" +## ## # } +## ## # +## ## # expiration { +## ## # days = 90 +## ## # } +## ## # } diff --git a/common/variables.tf b/common/variables.tf new file mode 100644 index 0000000..7d3b974 --- /dev/null +++ b/common/variables.tf @@ -0,0 +1,70 @@ +variable "bucket_name" { + description = "AWS Bucket Name. Standard prefix will be applied here, do not include here." + type = string +} + +variable "bucket_folders" { + description = "List of folders (keys) to create after creation of bucket. They will have object metadata provided based on metadata_tags and data_safeguard labels." + type = list(string) + default = [] +} + +variable "kms_key_id" { + description = "AWS KMS Key ID (one per bucket). This is currently ignored." + type = string + default = "" +} + +variable "tags" { + description = "AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data_safeguard field for such things." + type = map(string) + default = {} +} + +variable "metadata_tags" { + description = "AWS S3 Custom metadata (prefix x-amzn-meta- automatically included, not needed here). If data_safeguard labels are applied, they will be incorporated on any bucket objects created." + type = map(string) + default = {} +} + +variable "access_log_bucket_prefix" { + description = "Access log bucket prefix, to which the bucket name will be appended to make the target_prefix" + type = string + default = "s3" +} + +variable "access_log_bucket" { + description = "Server Access Logging Bucket ID" + type = string + # default = null +} + +variable "allowed_cidr" { + description = "List of allowed source IPs (NOT from within the VPC). If empty, there will be no restrictions on source IP. If provided, you must also use allowed_endpoints for access within a VPC." + type = list(string) + default = [] +} + +variable "allowed_endpoints" { + description = "List of allowed VPC endpoint IDs. If used, it will enable access to the bucket from the specific VPC endpoints." + type = list(string) + default = [] +} + +variable "force_destroy" { + description = "Sets force_destroy to allow the bucket and contents to be deleted. The deletion may take a very long time based on the number of objects. You normally want to update this to true, apply, and then destroy the resource." + type = bool + default = false +} + +# variable "lifecycle_rules" { +# description = "Setup lifecycle rules (in-progress, not working)" +# type = map() +# default = {} +# } + +variable "override_prefixes" { + description = "Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things" + type = map(string) + default = {} +} diff --git a/common/version.tf b/common/version.tf new file mode 100644 index 0000000..107272c --- /dev/null +++ b/common/version.tf @@ -0,0 +1,3 @@ +locals { + _module_version = "1.0" +} diff --git a/config/version.tf b/config/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/config/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file diff --git a/gpg-key/version.tf b/gpg-key/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/gpg-key/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file diff --git a/object-logging/version.tf b/object-logging/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/object-logging/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file diff --git a/terraform-state/version.tf b/terraform-state/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/terraform-state/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file From 0319f051cc373297bec74999a4d7c6845526acf6 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 14:23:52 -0500 Subject: [PATCH 02/20] update --- common/data.tf | 23 ++ common/outputs.tf | 30 -- common/resources.tf | 271 ------------------- common/{variables.tf => variables.common.tf} | 40 ++- 4 files changed, 52 insertions(+), 312 deletions(-) create mode 100644 common/data.tf delete mode 100644 common/outputs.tf delete mode 100644 common/resources.tf rename common/{variables.tf => variables.common.tf} (91%) diff --git a/common/data.tf b/common/data.tf new file mode 100644 index 0000000..30905b7 --- /dev/null +++ b/common/data.tf @@ -0,0 +1,23 @@ +data "aws_caller_identity" "current" {} + +data "aws_arn" "current" { + arn = data.aws_caller_identity.current.arn +} + +data "aws_region" "current" {} + +# output "caller_account_id" { +# value = data.aws_caller_identity.current.account_id +# } +# +# output "account_caller_arn" { +# value = data.aws_caller_identity.current.arn +# } +# +# output "account_caller_arn_partition" { +# value = data.aws_arn.current.partition +# } +# +# output "account_region"name" { +# value = data.aws_region.current.name +# } diff --git a/common/outputs.tf b/common/outputs.tf deleted file mode 100644 index 254a87e..0000000 --- a/common/outputs.tf +++ /dev/null @@ -1,30 +0,0 @@ -#--- -# bucket -#--- -output "s3_bucket_arn" { - description = "Created S3 Bucket ARN" - value = aws_s3_bucket.this.arn -} - -output "s3_bucket_id" { - description = "Created S3 Bucket ID" - value = aws_s3_bucket.this.id -} - -#--- -# key -#--- -output "kms_key_id" { - description = "Created KMS Key ID" - value = aws_kms_key.key.id -} - -output "kms_key_arn" { - description = "Created KMS Key ARN" - value = aws_kms_key.key.arn -} - -output "kms_key_alias" { - description = "Created KMS Key Alias name" - value = aws_kms_alias.key.name -} diff --git a/common/resources.tf b/common/resources.tf deleted file mode 100644 index 016ecb6..0000000 --- a/common/resources.tf +++ /dev/null @@ -1,271 +0,0 @@ -locals { - name = replace(var.bucket_name, local._prefixes["s3"], "") - bucket_name = format("%s%s", local._prefixes["s3"], local.name) - __prefixes = merge(local._prefixes, var.override_prefixes) - - # kms_key_arn_exists = var.kms_key_arn != "" && var.kms_key_arn != null - kms_key_arn = aws_kms_key.key.arn - kms_key_name = format("%s%s", local.__prefixes["kms"], local.name) - - condition_allowed_cidr = { - "test" : "NotIpAddress" - "variable" : "aws:sourceIp" - "values" : var.allowed_cidr - } - condition_allowed_endpoints = { - "test" : "StringNotEquals" - "variable" : "aws:sourceVpce" - "values" : var.allowed_endpoints - } - s3_bucket_conditions_list = list(local.condition_allowed_cidr, local.condition_allowed_endpoints) - s3_bucket_conditions = [for x in local.s3_bucket_conditions_list : x if length(x.values) > 0] - - # enforced_tags = { - # "boc:safeguard" = "title26" - # } - base_tags = { - "boc:tf_module_version" = local._module_version - "boc:created_by" = "terraform" - } - # strip spaces, convert to lowercase, make distinct, sort. Remove those not in the _defaults - add_safeguard_tags = local.enable_title26 ? ["title26"] : [] - _default_safeguard_tags = { for d in local._defaults["data_safeguards"] : d => d } - safeguard_tags = sort(distinct(compact(concat([for t in var.data_safeguards : lookup(local._default_safeguard_tags, lower(replace(t, " ", "")), "")], local.add_safeguard_tags)))) - add_tags = { - safeguard = { - "exists" = { "boc:safeguard" = join(",", local.safeguard_tags) } - "not_exists" = {} - } - } - enforced_tags = merge( - local.add_tags["safeguard"][length(local.safeguard_tags) > 0 ? "exists" : "not_exists"] - ) - metadata_tags = merge( - var.metadata_tags, - { for k, v in local.enforced_tags : format("x-amzn-meta-%v", replace(k, "/\\W/", "_")) => v } - ) -} - -#--- -# s3 bucket -#--- -resource "aws_s3_bucket" "this" { - bucket = local.bucket_name - acl = "private" - force_destroy = var.force_destroy - - server_side_encryption_configuration { - rule { - apply_server_side_encryption_by_default { - kms_master_key_id = aws_kms_key.key.key_id - sse_algorithm = "aws:kms" - } - } - } - - versioning { - enabled = local.versioning - } - - logging { - target_bucket = var.access_log_bucket - target__prefix = format("%s/%s/", var.access_log_bucket__prefix, local.bucket_name) - } - - lifecycle { - prevent_destroy = false - } - - tags = merge( - local.base_tags, - var.tags, - local.enforced_tags, - map("Name", local.bucket_name) - ) -} - -data "aws_iam_policy_document" "this" { - statement { - sid = "DenyIncorrectEncryptionHeader" - effect = "Deny" - actions = ["s3:PutObject"] - principals { - type = "AWS" - identifiers = ["*"] - } - resources = ["${aws_s3_bucket.this.arn}/*"] - condition { - test = "StringNotEquals" - variable = "s3:x-amz-server-side-encryption" - values = ["aws:kms"] - } - } - statement { - sid = "DenyUnEncryptedObjectUploads" - effect = "Deny" - actions = ["s3:PutObject"] - principals { - type = "AWS" - identifiers = ["*"] - } - resources = ["${aws_s3_bucket.this.arn}/*"] - condition { - test = "Null" - variable = "s3:x-amz-server-side-encryption" - values = ["true"] - } - } - statement { - sid = "enforceSSL" - effect = "Deny" - actions = ["s3:*"] - principals { - type = "AWS" - identifiers = ["*"] - } - resources = [aws_s3_bucket.this.arn, "${aws_s3_bucket.this.arn}/*"] - condition { - test = "Bool" - variable = "aws:SecureTransport" - values = ["false"] - } - } - dynamic "statement" { - for_each = length(local.s3_bucket_conditions) > 0 ? toset(["1"]) : toset([]) - iterator = s - content { - sid = "RemoteAccessBucketRestrictions" - effect = "Deny" - actions = ["s3:*"] - principals { - type = "AWS" - identifiers = ["*"] - } - resources = [aws_s3_bucket.this.arn, "${aws_s3_bucket.this.arn}/*"] - dynamic "condition" { - for_each = local.s3_bucket_conditions - iterator = c - content { - test = c.value.test - variable = c.value.variable - values = c.value.values - } - } - } - } -} -#--- -# apply policy to bucket and public access block policy to bucket -#--- -resource "aws_s3_bucket_policy" "policy" { - bucket = aws_s3_bucket.this.bucket - policy = data.aws_iam_policy_document.this.json - depends_on = [null_resource.policy_delay] -} - -resource "aws_s3_bucket_public_access_block" "this" { - bucket = aws_s3_bucket.this.id - block_public_acls = true - block_public_policy = true - ignore_public_acls = true - restrict_public_buckets = true - depends_on = [aws_s3_bucket_policy.policy] -} - -resource "null_resource" "policy_delay" { - triggers = { - bucket = aws_s3_bucket.this.id - } - provisioner "local-exec" { - when = create - command = "sleep 120" - } -} - -resource "aws_s3_bucket_object" "this_objects" { - for_each = toset(var.bucket_folders) - bucket = aws_s3_bucket.this.id - key = format("%s/", each.key) - source = "/dev/null" - metadata = local.metadata_tags - - depends_on = [null_resource.policy_delay] -} - -#--- -# create a key and alias if not specified -# right now, this can't use an external key, it has to create one per bucket -#--- -resource "aws_kms_key" "key" { - description = "KMS CMK for S3 bucket ${local.name}" - enable_key_rotation = true - # policy = data.aws_iam_policy_document.key.json - - tags = merge( - local.base_tags, - var.tags, - local.enforced_tags, - map("Name", local.bucket_name) - ) -} - -resource "aws_kms_alias" "key" { - name = "alias/${local.kms_key_name}" - target_key_id = aws_kms_key.key.key_id -} - -## ### -## -## locals { -## lifecycle_rules = [ -## { -## id = "Expiration Rule" -## enabled = true -## prefix = "reports/" -## expiration = { -## days = 30 -## } -## } -## ] -## } -## -## resource "aws_s3_bucket" "bucket-name" { -## bucket = "bucket-name" -## -## dynamic "lifecycle_rule" { -## for_each = local.lifecycle_rules -## -## content { -## id = lifecycle_rule.each.id -## enabled = lifecycle_rule.each.enabled -## prefix = lifecycle_rule.each.prefix -## -## expiration { -## days = lifecycle_rule.each.expiration.days -## } -## } -## } -## } -## -## ## # lifecycle_rule { -## ## # id = "log" -## ## # enabled = true -## ## # prefix = "log/" -## ## # tags = { -## ## # "rule" = "log" -## ## # "autoclean" = "true" -## ## # } -## ## # transition { -## ## # days = 30 -## ## # storage_class = "STANDARD_IA" -## ## # } -## ## # -## ## # transition { -## ## # days = 60 -## ## # storage_class = "GLACIER" -## ## # } -## ## # -## ## # expiration { -## ## # days = 90 -## ## # } -## ## # } diff --git a/common/variables.tf b/common/variables.common.tf similarity index 91% rename from common/variables.tf rename to common/variables.common.tf index 7d3b974..a1e04bc 100644 --- a/common/variables.tf +++ b/common/variables.common.tf @@ -1,3 +1,32 @@ +#--- +# account info +#--- +variable "account_id" { + description = "AWS Account ID" + type = string + default = "" +} + +variable "account_alias" { + description = "AWS Account Alias" + type = string + default = "" +} + +variable "override_prefixes" { + description = "Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things" + type = map(string) + default = {} +} + +variable "tags" { + description = "AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data_safeguard field for such things." + type = map(string) + default = {} +} + +# s3 + variable "bucket_name" { description = "AWS Bucket Name. Standard prefix will be applied here, do not include here." type = string @@ -15,12 +44,6 @@ variable "kms_key_id" { default = "" } -variable "tags" { - description = "AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data_safeguard field for such things." - type = map(string) - default = {} -} - variable "metadata_tags" { description = "AWS S3 Custom metadata (prefix x-amzn-meta- automatically included, not needed here). If data_safeguard labels are applied, they will be incorporated on any bucket objects created." type = map(string) @@ -63,8 +86,3 @@ variable "force_destroy" { # default = {} # } -variable "override_prefixes" { - description = "Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things" - type = map(string) - default = {} -} From 418e9a9101c696710bf9a18ffae5dacc9c36a100 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 14:24:07 -0500 Subject: [PATCH 03/20] add stuff for terraform-state --- terraform-state/data.tf | 1 + terraform-state/defaults.tf | 1 + terraform-state/main.tf | 151 ++++++++++++++++++++++++++++ terraform-state/outputs.tf | 25 +++++ terraform-state/prefixes.tf | 1 + terraform-state/variables.common.tf | 1 + terraform-state/variables.tf | 49 +++++++++ 7 files changed, 229 insertions(+) create mode 120000 terraform-state/data.tf create mode 120000 terraform-state/defaults.tf create mode 100644 terraform-state/main.tf create mode 100644 terraform-state/outputs.tf create mode 120000 terraform-state/prefixes.tf create mode 120000 terraform-state/variables.common.tf create mode 100644 terraform-state/variables.tf diff --git a/terraform-state/data.tf b/terraform-state/data.tf new file mode 120000 index 0000000..995624d --- /dev/null +++ b/terraform-state/data.tf @@ -0,0 +1 @@ +../common/data.tf \ No newline at end of file diff --git a/terraform-state/defaults.tf b/terraform-state/defaults.tf new file mode 120000 index 0000000..a5556ac --- /dev/null +++ b/terraform-state/defaults.tf @@ -0,0 +1 @@ +../common/defaults.tf \ No newline at end of file diff --git a/terraform-state/main.tf b/terraform-state/main.tf new file mode 100644 index 0000000..5d9b23d --- /dev/null +++ b/terraform-state/main.tf @@ -0,0 +1,151 @@ +/* +* # aws-inf-setup :: terraform-state +* +* This set up the needed components for the Terraform remote state: +* +* * S3 bucket +* * KMS key for the bucket +* * DynamoDB table for locking +* +* # Usage +* ```hcl +* module "tfstate" { +* source = ... +* +* tfstate_key_prefix = "do2-govcloud" +* +* kms_tfstate_key = "k-kms-inf-tfstate" +* tfstate_table = "tf_remote_state" +* tfstate_bucket = "inf-tfstate-123456789012" +* tfstate_bucket_prefix = "inf-tfstate" +* tfstate_key_suffix = "teraform.tfstate" +* +* # this is generally not needed and not recommended +* component_tags = { +* "s3" = { +* "SpecialTag1" = "something" +* "SpecialTag2" = "somethingElse" +* } +* } +* } +* ``` +*/ + +locals { + account_id = var.account_id != "" ? var.account_id : data.aws_caller_identity.current.account_id + tfstate_region = data.aws_region.current.name + + tfstate_key_arn = aws_kms_key.inf_tfstate.arn + tfstate_bucket = var.tfstate_bucket != "" ? var.tfstate_bucket : format("%v-%v", var.tfstate_bucket_prefix, local.account_id) +} + + +#--- +# dynamodb table +#--- +resource "aws_dynamodb_table" "tfstate" { + name = var.tfstate_table + hash_key = "LockID" + billing_mode = "PROVISIONED" + read_capacity = 1 + write_capacity = 1 + + attribute { + name = "LockID" + type = "S" + } + + server_side_encryption { + enabled = true + } + + tags = merge( + local.tags, + lookup(var.component_tags, "ddb", {}), + map("boc:tf_module_version",local._module_version), + map("Name", var.tfstate_table), + ) +} + +data "aws_iam_policy_document" "tfstate" { + statement { + sid = "TFRemoteStateList" + effect = "Allow" + resources = [aws_s3_bucket.tfstate.arn] + actions = ["s3:ListBucket"] + } + + statement { + sid = "TFRemoteState" + effect = "Allow" + resources = ["${aws_s3_bucket.tfstate.arn}/*"] + actions = ["s3:GetObject", "s3:PutObject"] + } + + statement { + sid = "TFRemoteStateDDB" + effect = "Allow" + resources = [aws_dynamodb_table.tfstate.arn] + actions = ["dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:DeleteItem"] + } +} + +#--- +# s3 +#--- +resource "aws_s3_bucket" "tfstate" { + bucket = local.tfstate_bucket + acl = "private" + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.inf_tfstate.arn + sse_algorithm = "aws:kms" + } + } + } + + versioning { + enabled = true + } + + lifecycle { + prevent_destroy = true + } + + tags = merge( + local.tags, + lookup(var.component_tags, "s3", {}), + map("boc:tf_module_version",local._module_version), + map("Name", local.tfstate_bucket), + ) +} + +resource "aws_s3_bucket_public_access_block" "tfstate" { + bucket = aws_s3_bucket.tfstate.id + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +#--- +# kms +#--- +resource "aws_kms_key" "tfstate_key" { + description = "inf-tfstate encryption key" + enable_key_rotation = true + + tags = merge( + local.tags, + lookup(var.component_tags, "kms", {}), + map("boc:tf_module_version",local._module_version), + map("Name", var.kms_tfstate_key) + ) +} + +resource "aws_kms_alias" "tfstate_key" { + name = "alias/${var.kms_tfstate_key}" + target_key_id = aws_kms_key.tfstate_key.key_id +} diff --git a/terraform-state/outputs.tf b/terraform-state/outputs.tf new file mode 100644 index 0000000..e5a5fcf --- /dev/null +++ b/terraform-state/outputs.tf @@ -0,0 +1,25 @@ +output "tfstate_key_arn" { + description = "inf-tfstate KMS key ARN" + value = aws_kms_key.tfstate_key.arn +} + +output "tfstate_bucket_id" { + description = "Terraform state S3 bucket ID" + value = aws_s3_bucket.tfstate.id +} + +output "tfstate_bucket_arn" { + description = "Terraform state S3 bucket ARN" + value = aws_s3_bucket.tfstate.arn +} + +output "tfstate_dynamodb_arn" { + description = "Terraform state DynamoDB table ARN" + value = aws_dynamodb_table.tfstate.arn +} + +output "tfstate_region" { + description = "Terraform state region" + value = local.tfstate_region +} + diff --git a/terraform-state/prefixes.tf b/terraform-state/prefixes.tf new file mode 120000 index 0000000..7e265d5 --- /dev/null +++ b/terraform-state/prefixes.tf @@ -0,0 +1 @@ +../common/prefixes.tf \ No newline at end of file diff --git a/terraform-state/variables.common.tf b/terraform-state/variables.common.tf new file mode 120000 index 0000000..7439ed8 --- /dev/null +++ b/terraform-state/variables.common.tf @@ -0,0 +1 @@ +../common/variables.common.tf \ No newline at end of file diff --git a/terraform-state/variables.tf b/terraform-state/variables.tf new file mode 100644 index 0000000..8fa962c --- /dev/null +++ b/terraform-state/variables.tf @@ -0,0 +1,49 @@ +variable "kms_tfstate_key" { + description = "Terraform remote state KMS key alias" + type = string + default = "k-kms-inf-tfstate" +} + +variable "tfstate_table" { + description = "Terraform remote state table" + type = string + default = "tf_remote_state" +} + +variable "tfstate_bucket" { + description = "Terraform remote state S3 bucket" + type = string + # default = "inf-tfstate-{{ tf_account }}" + default = "" +} + +variable "tfstate_bucket_prefix" { + description = "Terraform remote state S3 bucket prefix, prepended to the AWS account ID to make the bucket name." + type = string + default = "inf-tfstate" +} + +variable "tfstate_key_prefix" { + description = "Terraform remote state S3 bucket prefix (account alias)" + type = string + # default = "{{ tf_account_name | quote }}" +} + +variable "tfstate_key_suffix" { + description = "Terraform remote state S3 bucket suffix" + type = string + default = "terraform.tfstate" +} + +variable "tfstate_region" { + description = "Terraform remote state S3 bucket region" + type = string + # default = "{{ these_regions[0] | quote }}" + default = "" +} + +variable "component_tags" { + description = "Additional tags for Components (s3, kms, ddb)" + type = map(map(string)) + default = { "s3" = {}, "kms" = {}, "ddb" = {} } +} From 0eae7ad0f10ec6b19eb5bf5cf1480e7b9c50fc6e Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 14:55:28 -0500 Subject: [PATCH 04/20] add base_tags --- terraform-state/main.tf | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/terraform-state/main.tf b/terraform-state/main.tf index 5d9b23d..ffdeb8b 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -37,6 +37,11 @@ locals { tfstate_key_arn = aws_kms_key.inf_tfstate.arn tfstate_bucket = var.tfstate_bucket != "" ? var.tfstate_bucket : format("%v-%v", var.tfstate_bucket_prefix, local.account_id) + + base_tags = { + "boc:tf_module_version" = var._module_version + "boc:created_by" = "terraform" + } } @@ -61,8 +66,8 @@ resource "aws_dynamodb_table" "tfstate" { tags = merge( local.tags, + local.base_tags, lookup(var.component_tags, "ddb", {}), - map("boc:tf_module_version",local._module_version), map("Name", var.tfstate_table), ) } @@ -116,8 +121,8 @@ resource "aws_s3_bucket" "tfstate" { tags = merge( local.tags, + local.base_tags, lookup(var.component_tags, "s3", {}), - map("boc:tf_module_version",local._module_version), map("Name", local.tfstate_bucket), ) } @@ -139,8 +144,8 @@ resource "aws_kms_key" "tfstate_key" { tags = merge( local.tags, + local.base_tags, lookup(var.component_tags, "kms", {}), - map("boc:tf_module_version",local._module_version), map("Name", var.kms_tfstate_key) ) } From 288eaac6e88f700d02175ab9b33e0b07401eb50e Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 14:57:53 -0500 Subject: [PATCH 05/20] update docs --- terraform-state/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terraform-state/main.tf b/terraform-state/main.tf index ffdeb8b..cadef62 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -10,7 +10,7 @@ * # Usage * ```hcl * module "tfstate" { -* source = ... +* source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" * * tfstate_key_prefix = "do2-govcloud" * From fa79ff6469cb7bd970d699d65ba0e280979d3c1f Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 14:58:02 -0500 Subject: [PATCH 06/20] update docs --- terraform-state/README.md | 93 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 terraform-state/README.md diff --git a/terraform-state/README.md b/terraform-state/README.md new file mode 100644 index 0000000..8d43fd0 --- /dev/null +++ b/terraform-state/README.md @@ -0,0 +1,93 @@ +# aws-inf-setup :: terraform-state + +This set up the needed components for the Terraform remote state: + +* S3 bucket +* KMS key for the bucket +* DynamoDB table for locking + +# Usage +```hcl +module "tfstate" { + source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" + + tfstate_key_prefix = "do2-govcloud" + + kms_tfstate_key = "k-kms-inf-tfstate" + tfstate_table = "tf_remote_state" + tfstate_bucket = "inf-tfstate-123456789012" + tfstate_bucket_prefix = "inf-tfstate" + tfstate_key_suffix = "teraform.tfstate" + + # this is generally not needed and not recommended + component_tags = { + "s3" = { + "SpecialTag1" = "something" + "SpecialTag2" = "somethingElse" + } + } +} +``` + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| aws | n/a | + +## Modules + +No Modules. + +## Resources + +| Name | +|------| +| [aws_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | +| [aws_caller_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | +| [aws_dynamodb_table](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | +| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | +| [aws_kms_alias](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | +| [aws_kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | +| [aws_region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | +| [aws_s3_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | +| [aws_s3_bucket_public_access_block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| access\_log\_bucket | Server Access Logging Bucket ID | `string` | n/a | yes | +| access\_log\_bucket\_prefix | Access log bucket prefix, to which the bucket name will be appended to make the target\_prefix | `string` | `"s3"` | no | +| account\_alias | AWS Account Alias | `string` | `""` | no | +| account\_id | AWS Account ID | `string` | `""` | no | +| allowed\_cidr | List of allowed source IPs (NOT from within the VPC). If empty, there will be no restrictions on source IP. If provided, you must also use allowed\_endpoints for access within a VPC. | `list(string)` | `[]` | no | +| allowed\_endpoints | List of allowed VPC endpoint IDs. If used, it will enable access to the bucket from the specific VPC endpoints. | `list(string)` | `[]` | no | +| bucket\_folders | List of folders (keys) to create after creation of bucket. They will have object metadata provided based on metadata\_tags and data\_safeguard labels. | `list(string)` | `[]` | no | +| bucket\_name | AWS Bucket Name. Standard prefix will be applied here, do not include here. | `string` | n/a | yes | +| component\_tags | Additional tags for Components (s3, kms, ddb) | `map(map(string))` |
{
"ddb": {},
"kms": {},
"s3": {}
}
| no | +| force\_destroy | Sets force\_destroy to allow the bucket and contents to be deleted. The deletion may take a very long time based on the number of objects. You normally want to update this to true, apply, and then destroy the resource. | `bool` | `false` | no | +| kms\_key\_id | AWS KMS Key ID (one per bucket). This is currently ignored. | `string` | `""` | no | +| kms\_tfstate\_key | Terraform remote state KMS key alias | `string` | `"k-kms-inf-tfstate"` | no | +| metadata\_tags | AWS S3 Custom metadata (prefix x-amzn-meta- automatically included, not needed here). If data\_safeguard labels are applied, they will be incorporated on any bucket objects created. | `map(string)` | `{}` | no | +| override\_prefixes | Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things | `map(string)` | `{}` | no | +| tags | AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data\_safeguard field for such things. | `map(string)` | `{}` | no | +| tfstate\_bucket | Terraform remote state S3 bucket | `string` | `""` | no | +| tfstate\_bucket\_prefix | Terraform remote state S3 bucket prefix, prepended to the AWS account ID to make the bucket name. | `string` | `"inf-tfstate"` | no | +| tfstate\_key\_prefix | Terraform remote state S3 bucket prefix (account alias) | `string` | n/a | yes | +| tfstate\_key\_suffix | Terraform remote state S3 bucket suffix | `string` | `"terraform.tfstate"` | no | +| tfstate\_region | Terraform remote state S3 bucket region | `string` | `""` | no | +| tfstate\_table | Terraform remote state table | `string` | `"tf_remote_state"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| tfstate\_bucket\_arn | Terraform state S3 bucket ARN | +| tfstate\_bucket\_id | Terraform state S3 bucket ID | +| tfstate\_dynamodb\_arn | Terraform state DynamoDB table ARN | +| tfstate\_key\_arn | inf-tfstate KMS key ARN | From 9ceddbb403167c284018d5a7eb13e59d3da0d597 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:02:42 -0500 Subject: [PATCH 07/20] update usage --- terraform-state/README.md | 8 ++++++++ terraform-state/main.tf | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/terraform-state/README.md b/terraform-state/README.md index 8d43fd0..379098d 100644 --- a/terraform-state/README.md +++ b/terraform-state/README.md @@ -12,7 +12,15 @@ module "tfstate" { source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" tfstate_key_prefix = "do2-govcloud" +} + +module "tfstate_ful" { + source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" + + # required + tfstate_key_prefix = "do2-govcloud" + # optional, defaults kms_tfstate_key = "k-kms-inf-tfstate" tfstate_table = "tf_remote_state" tfstate_bucket = "inf-tfstate-123456789012" diff --git a/terraform-state/main.tf b/terraform-state/main.tf index cadef62..f7b603e 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -13,7 +13,15 @@ * source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" * * tfstate_key_prefix = "do2-govcloud" +* } +* +* module "tfstate_ful" { +* source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" +* +* # required +* tfstate_key_prefix = "do2-govcloud" * +* # optional, defaults * kms_tfstate_key = "k-kms-inf-tfstate" * tfstate_table = "tf_remote_state" * tfstate_bucket = "inf-tfstate-123456789012" From c42a98cd6c4c17f32a23d64a1d5ef2b75067e5e2 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:03:09 -0500 Subject: [PATCH 08/20] update doc --- terraform-state/README.md | 2 +- terraform-state/main.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/terraform-state/README.md b/terraform-state/README.md index 379098d..6598b73 100644 --- a/terraform-state/README.md +++ b/terraform-state/README.md @@ -14,7 +14,7 @@ module "tfstate" { tfstate_key_prefix = "do2-govcloud" } -module "tfstate_ful" { +module "tfstate_full" { source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" # required diff --git a/terraform-state/main.tf b/terraform-state/main.tf index f7b603e..8d70509 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -15,7 +15,7 @@ * tfstate_key_prefix = "do2-govcloud" * } * -* module "tfstate_ful" { +* module "tfstate_full" { * source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" * * # required From ded4a18d9955a7f1fe26ad2b209b23a956b8c732 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:04:50 -0500 Subject: [PATCH 09/20] update doc --- terraform-state/README.md | 32 ++------------------------------ terraform-state/main.tf | 8 ++++++++ 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/terraform-state/README.md b/terraform-state/README.md index 6598b73..3a1ac03 100644 --- a/terraform-state/README.md +++ b/terraform-state/README.md @@ -6,36 +6,8 @@ This set up the needed components for the Terraform remote state: * KMS key for the bucket * DynamoDB table for locking -# Usage -```hcl -module "tfstate" { - source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" - - tfstate_key_prefix = "do2-govcloud" -} - -module "tfstate_full" { - source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" - - # required - tfstate_key_prefix = "do2-govcloud" - - # optional, defaults - kms_tfstate_key = "k-kms-inf-tfstate" - tfstate_table = "tf_remote_state" - tfstate_bucket = "inf-tfstate-123456789012" - tfstate_bucket_prefix = "inf-tfstate" - tfstate_key_suffix = "teraform.tfstate" - - # this is generally not needed and not recommended - component_tags = { - "s3" = { - "SpecialTag1" = "something" - "SpecialTag2" = "somethingElse" - } - } -} -``` +# Usage +Here is a simple example, the one most commonly expected to be used. ## Requirements diff --git a/terraform-state/main.tf b/terraform-state/main.tf index 8d70509..188d1ab 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -8,13 +8,21 @@ * * DynamoDB table for locking * * # Usage +* Here is a simple example, the one most commonly expected to be used. + * ```hcl * module "tfstate" { * source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" * * tfstate_key_prefix = "do2-govcloud" * } +* ``` * +* This one can be used if you need to customize stuff, though really, the defaults are all built +* for a reason, and deployment code (i.e., Ansible) will expect these defaults to be used in +* variable file generation. +* +* ```hcl * module "tfstate_full" { * source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" * From c1e786c354a255c7833793752f18c12a897f57b8 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:05:53 -0500 Subject: [PATCH 10/20] update doc --- terraform-state/README.md | 36 ++++++++++++++++++++++++++++++++++++ terraform-state/main.tf | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/terraform-state/README.md b/terraform-state/README.md index 3a1ac03..4ba547d 100644 --- a/terraform-state/README.md +++ b/terraform-state/README.md @@ -9,6 +9,42 @@ This set up the needed components for the Terraform remote state: # Usage Here is a simple example, the one most commonly expected to be used. +```hcl +module "tfstate" { + source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" + + tfstate_key_prefix = "do2-govcloud" +} +``` + +This one can be used if you need to customize stuff, though really, the defaults are all built +for a reason, and deployment code (i.e., Ansible) will expect these defaults to be used in +variable file generation. + +```hcl +module "tfstate_full" { + source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" + + # required + tfstate_key_prefix = "do2-govcloud" + + # optional, defaults + kms_tfstate_key = "k-kms-inf-tfstate" + tfstate_table = "tf_remote_state" + tfstate_bucket = "inf-tfstate-123456789012" + tfstate_bucket_prefix = "inf-tfstate" + tfstate_key_suffix = "teraform.tfstate" + + # this is generally not needed and not recommended + component_tags = { + "s3" = { + "SpecialTag1" = "something" + "SpecialTag2" = "somethingElse" + } + } +} +``` + ## Requirements No requirements. diff --git a/terraform-state/main.tf b/terraform-state/main.tf index 188d1ab..2726e9c 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -9,7 +9,7 @@ * * # Usage * Here is a simple example, the one most commonly expected to be used. - +* * ```hcl * module "tfstate" { * source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" From 31c7660edc7300f1352309c925665ea01c917c58 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:08:06 -0500 Subject: [PATCH 11/20] remove some variables --- common/variables.common.tf | 121 ++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 61 deletions(-) diff --git a/common/variables.common.tf b/common/variables.common.tf index a1e04bc..4cc18af 100644 --- a/common/variables.common.tf +++ b/common/variables.common.tf @@ -25,64 +25,63 @@ variable "tags" { default = {} } -# s3 - -variable "bucket_name" { - description = "AWS Bucket Name. Standard prefix will be applied here, do not include here." - type = string -} - -variable "bucket_folders" { - description = "List of folders (keys) to create after creation of bucket. They will have object metadata provided based on metadata_tags and data_safeguard labels." - type = list(string) - default = [] -} - -variable "kms_key_id" { - description = "AWS KMS Key ID (one per bucket). This is currently ignored." - type = string - default = "" -} - -variable "metadata_tags" { - description = "AWS S3 Custom metadata (prefix x-amzn-meta- automatically included, not needed here). If data_safeguard labels are applied, they will be incorporated on any bucket objects created." - type = map(string) - default = {} -} - -variable "access_log_bucket_prefix" { - description = "Access log bucket prefix, to which the bucket name will be appended to make the target_prefix" - type = string - default = "s3" -} - -variable "access_log_bucket" { - description = "Server Access Logging Bucket ID" - type = string - # default = null -} - -variable "allowed_cidr" { - description = "List of allowed source IPs (NOT from within the VPC). If empty, there will be no restrictions on source IP. If provided, you must also use allowed_endpoints for access within a VPC." - type = list(string) - default = [] -} - -variable "allowed_endpoints" { - description = "List of allowed VPC endpoint IDs. If used, it will enable access to the bucket from the specific VPC endpoints." - type = list(string) - default = [] -} - -variable "force_destroy" { - description = "Sets force_destroy to allow the bucket and contents to be deleted. The deletion may take a very long time based on the number of objects. You normally want to update this to true, apply, and then destroy the resource." - type = bool - default = false -} - -# variable "lifecycle_rules" { -# description = "Setup lifecycle rules (in-progress, not working)" -# type = map() -# default = {} -# } - +## # s3 +## variable "bucket_name" { +## description = "AWS Bucket Name. Standard prefix will be applied here, do not include here." +## type = string +## } +## +## variable "bucket_folders" { +## description = "List of folders (keys) to create after creation of bucket. They will have object metadata provided based on metadata_tags and data_safeguard labels." +## type = list(string) +## default = [] +## } +## +## variable "kms_key_id" { +## description = "AWS KMS Key ID (one per bucket). This is currently ignored." +## type = string +## default = "" +## } +## +## variable "metadata_tags" { +## description = "AWS S3 Custom metadata (prefix x-amzn-meta- automatically included, not needed here). If data_safeguard labels are applied, they will be incorporated on any bucket objects created." +## type = map(string) +## default = {} +## } +## +## variable "access_log_bucket_prefix" { +## description = "Access log bucket prefix, to which the bucket name will be appended to make the target_prefix" +## type = string +## default = "s3" +## } +## +## variable "access_log_bucket" { +## description = "Server Access Logging Bucket ID" +## type = string +## # default = null +## } +## +## variable "allowed_cidr" { +## description = "List of allowed source IPs (NOT from within the VPC). If empty, there will be no restrictions on source IP. If provided, you must also use allowed_endpoints for access within a VPC." +## type = list(string) +## default = [] +## } +## +## variable "allowed_endpoints" { +## description = "List of allowed VPC endpoint IDs. If used, it will enable access to the bucket from the specific VPC endpoints." +## type = list(string) +## default = [] +## } +## +## variable "force_destroy" { +## description = "Sets force_destroy to allow the bucket and contents to be deleted. The deletion may take a very long time based on the number of objects. You normally want to update this to true, apply, and then destroy the resource." +## type = bool +## default = false +## } +## +## # variable "lifecycle_rules" { +## # description = "Setup lifecycle rules (in-progress, not working)" +## # type = map() +## # default = {} +## # } +## From 584744669e406dffa9c9030d5c2e6593ab2d101c Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:08:20 -0500 Subject: [PATCH 12/20] remove some variables --- terraform-state/README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/terraform-state/README.md b/terraform-state/README.md index 4ba547d..681a576 100644 --- a/terraform-state/README.md +++ b/terraform-state/README.md @@ -77,19 +77,10 @@ No Modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| access\_log\_bucket | Server Access Logging Bucket ID | `string` | n/a | yes | -| access\_log\_bucket\_prefix | Access log bucket prefix, to which the bucket name will be appended to make the target\_prefix | `string` | `"s3"` | no | | account\_alias | AWS Account Alias | `string` | `""` | no | | account\_id | AWS Account ID | `string` | `""` | no | -| allowed\_cidr | List of allowed source IPs (NOT from within the VPC). If empty, there will be no restrictions on source IP. If provided, you must also use allowed\_endpoints for access within a VPC. | `list(string)` | `[]` | no | -| allowed\_endpoints | List of allowed VPC endpoint IDs. If used, it will enable access to the bucket from the specific VPC endpoints. | `list(string)` | `[]` | no | -| bucket\_folders | List of folders (keys) to create after creation of bucket. They will have object metadata provided based on metadata\_tags and data\_safeguard labels. | `list(string)` | `[]` | no | -| bucket\_name | AWS Bucket Name. Standard prefix will be applied here, do not include here. | `string` | n/a | yes | | component\_tags | Additional tags for Components (s3, kms, ddb) | `map(map(string))` |
{
"ddb": {},
"kms": {},
"s3": {}
}
| no | -| force\_destroy | Sets force\_destroy to allow the bucket and contents to be deleted. The deletion may take a very long time based on the number of objects. You normally want to update this to true, apply, and then destroy the resource. | `bool` | `false` | no | -| kms\_key\_id | AWS KMS Key ID (one per bucket). This is currently ignored. | `string` | `""` | no | | kms\_tfstate\_key | Terraform remote state KMS key alias | `string` | `"k-kms-inf-tfstate"` | no | -| metadata\_tags | AWS S3 Custom metadata (prefix x-amzn-meta- automatically included, not needed here). If data\_safeguard labels are applied, they will be incorporated on any bucket objects created. | `map(string)` | `{}` | no | | override\_prefixes | Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things | `map(string)` | `{}` | no | | tags | AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data\_safeguard field for such things. | `map(string)` | `{}` | no | | tfstate\_bucket | Terraform remote state S3 bucket | `string` | `""` | no | From 8e5cc4738d6717b87d0fe60483f4029ac2b6bab8 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:13:06 -0500 Subject: [PATCH 13/20] update required things --- common/variables.common.tf | 5 ++--- terraform-state/README.md | 11 ++++++----- terraform-state/main.tf | 5 +++-- terraform-state/variables.tf | 1 + 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/common/variables.common.tf b/common/variables.common.tf index 4cc18af..2bc450a 100644 --- a/common/variables.common.tf +++ b/common/variables.common.tf @@ -2,15 +2,14 @@ # account info #--- variable "account_id" { - description = "AWS Account ID" + description = "AWS Account ID (default will pull from current user)" type = string default = "" } variable "account_alias" { - description = "AWS Account Alias" + description = "AWS Account Alias (required)" type = string - default = "" } variable "override_prefixes" { diff --git a/terraform-state/README.md b/terraform-state/README.md index 681a576..29d76ff 100644 --- a/terraform-state/README.md +++ b/terraform-state/README.md @@ -13,7 +13,7 @@ Here is a simple example, the one most commonly expected to be used. module "tfstate" { source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" - tfstate_key_prefix = "do2-govcloud" + account_alias = "do2-govcloud" } ``` @@ -26,9 +26,10 @@ module "tfstate_full" { source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" # required - tfstate_key_prefix = "do2-govcloud" + account_alias = "do2-govcloud" # optional, defaults + tfstate_key_prefix = "do2-govcloud" kms_tfstate_key = "k-kms-inf-tfstate" tfstate_table = "tf_remote_state" tfstate_bucket = "inf-tfstate-123456789012" @@ -77,15 +78,15 @@ No Modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| account\_alias | AWS Account Alias | `string` | `""` | no | -| account\_id | AWS Account ID | `string` | `""` | no | +| account\_alias | AWS Account Alias (required) | `string` | n/a | yes | +| account\_id | AWS Account ID (default will pull from current user) | `string` | `""` | no | | component\_tags | Additional tags for Components (s3, kms, ddb) | `map(map(string))` |
{
"ddb": {},
"kms": {},
"s3": {}
}
| no | | kms\_tfstate\_key | Terraform remote state KMS key alias | `string` | `"k-kms-inf-tfstate"` | no | | override\_prefixes | Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things | `map(string)` | `{}` | no | | tags | AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data\_safeguard field for such things. | `map(string)` | `{}` | no | | tfstate\_bucket | Terraform remote state S3 bucket | `string` | `""` | no | | tfstate\_bucket\_prefix | Terraform remote state S3 bucket prefix, prepended to the AWS account ID to make the bucket name. | `string` | `"inf-tfstate"` | no | -| tfstate\_key\_prefix | Terraform remote state S3 bucket prefix (account alias) | `string` | n/a | yes | +| tfstate\_key\_prefix | Terraform remote state S3 bucket prefix (account alias) | `string` | `""` | no | | tfstate\_key\_suffix | Terraform remote state S3 bucket suffix | `string` | `"terraform.tfstate"` | no | | tfstate\_region | Terraform remote state S3 bucket region | `string` | `""` | no | | tfstate\_table | Terraform remote state table | `string` | `"tf_remote_state"` | no | diff --git a/terraform-state/main.tf b/terraform-state/main.tf index 2726e9c..e0d9bf6 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -14,7 +14,7 @@ * module "tfstate" { * source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" * -* tfstate_key_prefix = "do2-govcloud" +* account_alias = "do2-govcloud" * } * ``` * @@ -27,9 +27,10 @@ * source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" * * # required -* tfstate_key_prefix = "do2-govcloud" +* account_alias = "do2-govcloud" * * # optional, defaults +* tfstate_key_prefix = "do2-govcloud" * kms_tfstate_key = "k-kms-inf-tfstate" * tfstate_table = "tf_remote_state" * tfstate_bucket = "inf-tfstate-123456789012" diff --git a/terraform-state/variables.tf b/terraform-state/variables.tf index 8fa962c..5430c4d 100644 --- a/terraform-state/variables.tf +++ b/terraform-state/variables.tf @@ -26,6 +26,7 @@ variable "tfstate_bucket_prefix" { variable "tfstate_key_prefix" { description = "Terraform remote state S3 bucket prefix (account alias)" type = string + default = "" # default = "{{ tf_account_name | quote }}" } From b80a2dad619974289bb41a984cffa9a03546fbae Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:15:29 -0500 Subject: [PATCH 14/20] ignore common/READMD.md --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4df0dc1..f4873d7 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ .terraform/* logs +common/README.md From b4cb8ef0efbb432603cead759f1f132e6b0b3f0d Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:22:22 -0500 Subject: [PATCH 15/20] fix typos --- terraform-state/README.md | 6 +++--- terraform-state/main.tf | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/terraform-state/README.md b/terraform-state/README.md index 29d76ff..4b93724 100644 --- a/terraform-state/README.md +++ b/terraform-state/README.md @@ -11,7 +11,7 @@ Here is a simple example, the one most commonly expected to be used. ```hcl module "tfstate" { - source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" + source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//terraform-state" account_alias = "do2-govcloud" } @@ -23,7 +23,7 @@ variable file generation. ```hcl module "tfstate_full" { - source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" + source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//terraform-state" # required account_alias = "do2-govcloud" @@ -34,7 +34,7 @@ module "tfstate_full" { tfstate_table = "tf_remote_state" tfstate_bucket = "inf-tfstate-123456789012" tfstate_bucket_prefix = "inf-tfstate" - tfstate_key_suffix = "teraform.tfstate" + tfstate_key_suffix = "terraform.tfstate" # this is generally not needed and not recommended component_tags = { diff --git a/terraform-state/main.tf b/terraform-state/main.tf index e0d9bf6..3d09062 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -12,7 +12,7 @@ * * ```hcl * module "tfstate" { -* source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" +* source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//terraform-state" * * account_alias = "do2-govcloud" * } @@ -24,7 +24,7 @@ * * ```hcl * module "tfstate_full" { -* source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//teraform-state" +* source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//terraform-state" * * # required * account_alias = "do2-govcloud" @@ -35,7 +35,7 @@ * tfstate_table = "tf_remote_state" * tfstate_bucket = "inf-tfstate-123456789012" * tfstate_bucket_prefix = "inf-tfstate" -* tfstate_key_suffix = "teraform.tfstate" +* tfstate_key_suffix = "terraform.tfstate" * * # this is generally not needed and not recommended * component_tags = { From cc59aad13085225e38e6c7065d8f3784ee3e5165 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:26:30 -0500 Subject: [PATCH 16/20] fix source --- terraform-state/README.md | 4 ++-- terraform-state/main.tf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/terraform-state/README.md b/terraform-state/README.md index 4b93724..e850cf5 100644 --- a/terraform-state/README.md +++ b/terraform-state/README.md @@ -11,7 +11,7 @@ Here is a simple example, the one most commonly expected to be used. ```hcl module "tfstate" { - source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//terraform-state" + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//terraform-state" account_alias = "do2-govcloud" } @@ -23,7 +23,7 @@ variable file generation. ```hcl module "tfstate_full" { - source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//terraform-state" + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//terraform-state" # required account_alias = "do2-govcloud" diff --git a/terraform-state/main.tf b/terraform-state/main.tf index 3d09062..5556baf 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -12,7 +12,7 @@ * * ```hcl * module "tfstate" { -* source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//terraform-state" +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//terraform-state" * * account_alias = "do2-govcloud" * } @@ -24,7 +24,7 @@ * * ```hcl * module "tfstate_full" { -* source = "git::https://vc1.csvd.census.gov/terraform-modules/aws-inf-setup.git//terraform-state" +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//terraform-state" * * # required * account_alias = "do2-govcloud" From e0f511a9cd5395881afd92d954a2020d30acad4a Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:28:04 -0500 Subject: [PATCH 17/20] fix tag --- terraform-state/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terraform-state/main.tf b/terraform-state/main.tf index 5556baf..233471a 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -56,7 +56,7 @@ locals { tfstate_bucket = var.tfstate_bucket != "" ? var.tfstate_bucket : format("%v-%v", var.tfstate_bucket_prefix, local.account_id) base_tags = { - "boc:tf_module_version" = var._module_version + "boc:tf_module_version" = local._module_version "boc:created_by" = "terraform" } } From 9d1d63f5ba656f87b9594758b1b709006d5f07e6 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 15:30:43 -0500 Subject: [PATCH 18/20] fix keys --- terraform-state/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/terraform-state/main.tf b/terraform-state/main.tf index 233471a..a424f45 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -52,7 +52,7 @@ locals { account_id = var.account_id != "" ? var.account_id : data.aws_caller_identity.current.account_id tfstate_region = data.aws_region.current.name - tfstate_key_arn = aws_kms_key.inf_tfstate.arn + tfstate_key_arn = aws_kms_key.tfstate_key.arn tfstate_bucket = var.tfstate_bucket != "" ? var.tfstate_bucket : format("%v-%v", var.tfstate_bucket_prefix, local.account_id) base_tags = { @@ -122,7 +122,7 @@ resource "aws_s3_bucket" "tfstate" { server_side_encryption_configuration { rule { apply_server_side_encryption_by_default { - kms_master_key_id = aws_kms_key.inf_tfstate.arn + kms_master_key_id = aws_kms_key.tfstate_key.arn sse_algorithm = "aws:kms" } } From d0c261fe285512b04ce05dfdaad671f303822eaa Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 17:25:09 -0500 Subject: [PATCH 19/20] change local.tags to var.tags --- terraform-state/main.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/terraform-state/main.tf b/terraform-state/main.tf index a424f45..80d33da 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -82,7 +82,7 @@ resource "aws_dynamodb_table" "tfstate" { } tags = merge( - local.tags, + var.tags, local.base_tags, lookup(var.component_tags, "ddb", {}), map("Name", var.tfstate_table), @@ -137,7 +137,7 @@ resource "aws_s3_bucket" "tfstate" { } tags = merge( - local.tags, + var.tags, local.base_tags, lookup(var.component_tags, "s3", {}), map("Name", local.tfstate_bucket), @@ -160,7 +160,7 @@ resource "aws_kms_key" "tfstate_key" { enable_key_rotation = true tags = merge( - local.tags, + var.tags, local.base_tags, lookup(var.component_tags, "kms", {}), map("Name", var.kms_tfstate_key) From d9658a04076be3a40738d5a05ab877372baedbfa Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 22 Feb 2021 17:51:57 -0500 Subject: [PATCH 20/20] add comment --- terraform-state/main.tf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/terraform-state/main.tf b/terraform-state/main.tf index 80d33da..886b96d 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -89,6 +89,8 @@ resource "aws_dynamodb_table" "tfstate" { ) } +# create iam policy for it, to apply to roles/groups as needed + data "aws_iam_policy_document" "tfstate" { statement { sid = "TFRemoteStateList"