From a138cf2930996d900f1d6012186af1520581d80e Mon Sep 17 00:00:00 2001 From: badra001 Date: Wed, 17 Nov 2021 13:08:11 -0500 Subject: [PATCH] factor out kms code --- common/README.md | 64 ---------------------------------- common/kms.tf | 66 ++++++++++++++++++++++++++++++++++++ common/outputs.kms.tf | 18 ++++++++++ common/outputs.s3.tf | 12 +++++++ common/variables.common.tf | 6 ++++ common/variables.kms.tf | 23 +++++++++++++ common/variables.s3.tf | 62 +++++++++++++++++++++++++++++++++ examples/policy/README.md | 28 +++++++++++++++ standard/kms.tf | 1 + standard/outputs.kms.tf | 1 + standard/outputs.s3.tf | 1 + standard/variables.common.tf | 1 + standard/variables.kms.tf | 1 + standard/variables.s3.tf | 1 + title26/kms.tf | 1 + title26/outputs.kms.tf | 1 + title26/outputs.s3.tf | 1 + title26/variables.common.tf | 1 + title26/variables.kms.tf | 1 + title26/variables.s3.tf | 1 + 20 files changed, 227 insertions(+), 64 deletions(-) delete mode 100644 common/README.md create mode 100644 common/kms.tf create mode 100644 common/outputs.kms.tf create mode 100644 common/outputs.s3.tf create mode 100644 common/variables.common.tf create mode 100644 common/variables.kms.tf create mode 100644 common/variables.s3.tf create mode 100644 examples/policy/README.md create mode 120000 standard/kms.tf create mode 120000 standard/outputs.kms.tf create mode 120000 standard/outputs.s3.tf create mode 120000 standard/variables.common.tf create mode 120000 standard/variables.kms.tf create mode 120000 standard/variables.s3.tf create mode 120000 title26/kms.tf create mode 120000 title26/outputs.kms.tf create mode 120000 title26/outputs.s3.tf create mode 120000 title26/variables.common.tf create mode 120000 title26/variables.kms.tf create mode 120000 title26/variables.s3.tf diff --git a/common/README.md b/common/README.md deleted file mode 100644 index 41623d7..0000000 --- a/common/README.md +++ /dev/null @@ -1,64 +0,0 @@ -## Requirements - -No requirements. - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | n/a | -| [null](#provider\_null) | n/a | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [aws_kms_alias.key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | -| [aws_kms_key.key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | -| [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket_object.this_objects](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_object) | resource | -| [aws_s3_bucket_policy.policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | -| [aws_s3_bucket_public_access_block.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | -| [null_resource.policy_delay](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | -| [aws_arn.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source | -| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_iam_policy_document.bucket_policy_combined](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.empty](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.key_admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.key_policy_combined](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [access\_log\_bucket](#input\_access\_log\_bucket) | Server Access Logging Bucket ID | `string` | n/a | yes | -| [access\_log\_bucket\_prefix](#input\_access\_log\_bucket\_prefix) | Access log bucket prefix, to which the bucket name will be appended to make the target\_prefix | `string` | `"s3"` | no | -| [allowed\_cidr](#input\_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](#input\_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](#input\_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](#input\_bucket\_name) | AWS Bucket Name. Standard prefix will be applied here, do not include here. | `string` | n/a | yes | -| [bucket\_policy\_document](#input\_bucket\_policy\_document) | IAM Policy document describing additiona policy to be attached to the bucket beyond the default | `string` | `""` | no | -| [force\_destroy](#input\_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\_admin\_roles](#input\_kms\_admin\_roles) | AWS KMS Key administrative role(s) which have full access to the key. The root user is included by default. | `list(string)` | `[]` | no | -| [kms\_key\_arn](#input\_kms\_key\_arn) | AWS KMS Key ARN, a key created external to this module call. | `string` | `null` | no | -| [kms\_key\_id](#input\_kms\_key\_id) | AWS KMS Key ID (one per bucket). This is currently ignored (and deprecated). | `string` | `null` | no | -| [kms\_policy\_document](#input\_kms\_policy\_document) | AWS KMS Key Policy Document JSON, merged with admin policy document | `string` | `""` | no | -| [metadata\_tags](#input\_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 | -| [require\_explicit\_encryption](#input\_require\_explicit\_encryption) | When enabled, adds bucket policy to Deny unencrypted uploads and incorrect encryption header. Should not normally be needed. | `bool` | `false` | no | -| [tags](#input\_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 | - -## Outputs - -| Name | Description | -|------|-------------| -| [kms\_key\_alias](#output\_kms\_key\_alias) | Created KMS Key Alias name | -| [kms\_key\_arn](#output\_kms\_key\_arn) | Created KMS Key ARN | -| [kms\_key\_id](#output\_kms\_key\_id) | Created KMS Key ID | -| [s3\_bucket\_arn](#output\_s3\_bucket\_arn) | Created S3 Bucket ARN | -| [s3\_bucket\_id](#output\_s3\_bucket\_id) | Created S3 Bucket ID | diff --git a/common/kms.tf b/common/kms.tf new file mode 100644 index 0000000..b42ca3e --- /dev/null +++ b/common/kms.tf @@ -0,0 +1,66 @@ +# data "aws_kms_key" "incoming_key" { +# count = var.kms_key_arn != null ? 1 : 0 +# key_id = var.kms_key_arn +# } +# +locals { + kms_key_arn = var.kms_key_arn != null ? var.kms_key_arn : aws_kms_key.key.arn + kms_key_name = format("%s%s", local._prefixes["kms"], local.name) + + kms_admin_root = [format("arn:%v:iam::%v:root", local.partition, local.account_id)] + kms_admin_roles = compact(concat(local.kms_admin_root, var.kms_admin_roles)) + kms_policy_document = length(var.kms_policy_document) > 0 ? var.kms_policy_document : data.aws_iam_policy_document.empty.json +} + +#--- +# create a key and alias if not specified +#--- +resource "aws_kms_key" "key" { + count = var.kms_key_arn == null ? 1 : 0 + description = "KMS CMK for S3 bucket ${local.name}" + enable_key_rotation = true + policy = data.aws_iam_policy_document.key_policy_combined.json + + tags = merge( + local.base_tags, + var.tags, + local.enforced_tags, + map("Name", local.kms_key_name) + ) +} + +resource "aws_kms_alias" "key" { + count = var.kms_key_arn == null ? 1 : 0 + name = "alias/${local.kms_key_name}" + target_key_id = var.kms_key_arn == null ? aws_kms_key.key[0].key_id : null +} + +# auto includes root +data "aws_iam_policy_document" "key_admin" { + statement { + sid = "BuiltinKMSAdminRoles" + effect = "Allow" + actions = ["kms:*"] + resources = ["*"] + principals { + type = "AWS" + identifiers = local.kms_admin_roles + } + } +} + +data "aws_iam_policy_document" "key_policy_combined" { + source_policy_documents = [ + data.aws_iam_policy_document.key_admin.json, + local.kms_policy_document + ] +} + +data "aws_iam_policy_document" "bucket_policy_combined" { + source_policy_documents = [ + data.aws_iam_policy_document.this.json, + local.bucket_policy_document + ] +} + +data "aws_iam_policy_document" "empty" {} diff --git a/common/outputs.kms.tf b/common/outputs.kms.tf new file mode 100644 index 0000000..4ad613a --- /dev/null +++ b/common/outputs.kms.tf @@ -0,0 +1,18 @@ +#--- +# 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/outputs.s3.tf b/common/outputs.s3.tf new file mode 100644 index 0000000..a29a743 --- /dev/null +++ b/common/outputs.s3.tf @@ -0,0 +1,12 @@ +#--- +# 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 +} diff --git a/common/variables.common.tf b/common/variables.common.tf new file mode 100644 index 0000000..010acce --- /dev/null +++ b/common/variables.common.tf @@ -0,0 +1,6 @@ +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 = {} +} + diff --git a/common/variables.kms.tf b/common/variables.kms.tf new file mode 100644 index 0000000..3fe6f33 --- /dev/null +++ b/common/variables.kms.tf @@ -0,0 +1,23 @@ +variable "kms_key_id" { + description = "AWS KMS Key ID (one per bucket). This is currently ignored (and deprecated)." + type = string + default = null +} + +variable "kms_key_arn" { + description = "AWS KMS Key ARN, a key created external to this module call." + type = string + default = null +} + +variable "kms_policy_document" { + description = "AWS KMS Key Policy Document JSON, merged with admin policy document" + type = string + default = "" +} + +variable "kms_admin_roles" { + description = "AWS KMS Key administrative role(s) which have full access to the key. The root user is included by default." + type = list(string) + default = [] +} diff --git a/common/variables.s3.tf b/common/variables.s3.tf new file mode 100644 index 0000000..6f15cf3 --- /dev/null +++ b/common/variables.s3.tf @@ -0,0 +1,62 @@ +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 "bucket_policy_document" { + description = "IAM Policy document describing additiona policy to be attached to the bucket beyond the default" + 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 "require_explicit_encryption" { + description = "When enabled, adds bucket policy to Deny unencrypted uploads and incorrect encryption header. Should not normally be needed." + type = bool + default = false +} + +# TBD +# variable "kms_policy_read_arns" { } +# variable "kms_policy_write_arns" { } diff --git a/examples/policy/README.md b/examples/policy/README.md new file mode 100644 index 0000000..0acfbad --- /dev/null +++ b/examples/policy/README.md @@ -0,0 +1,28 @@ +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_policy.policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy_document.policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +No inputs. + +## Outputs + +No outputs. diff --git a/standard/kms.tf b/standard/kms.tf new file mode 120000 index 0000000..b0b3f29 --- /dev/null +++ b/standard/kms.tf @@ -0,0 +1 @@ +../common/kms.tf \ No newline at end of file diff --git a/standard/outputs.kms.tf b/standard/outputs.kms.tf new file mode 120000 index 0000000..74a8d7b --- /dev/null +++ b/standard/outputs.kms.tf @@ -0,0 +1 @@ +../common/outputs.kms.tf \ No newline at end of file diff --git a/standard/outputs.s3.tf b/standard/outputs.s3.tf new file mode 120000 index 0000000..594685a --- /dev/null +++ b/standard/outputs.s3.tf @@ -0,0 +1 @@ +../common/outputs.s3.tf \ No newline at end of file diff --git a/standard/variables.common.tf b/standard/variables.common.tf new file mode 120000 index 0000000..7439ed8 --- /dev/null +++ b/standard/variables.common.tf @@ -0,0 +1 @@ +../common/variables.common.tf \ No newline at end of file diff --git a/standard/variables.kms.tf b/standard/variables.kms.tf new file mode 120000 index 0000000..08cab47 --- /dev/null +++ b/standard/variables.kms.tf @@ -0,0 +1 @@ +../common/variables.kms.tf \ No newline at end of file diff --git a/standard/variables.s3.tf b/standard/variables.s3.tf new file mode 120000 index 0000000..49213df --- /dev/null +++ b/standard/variables.s3.tf @@ -0,0 +1 @@ +../common/variables.s3.tf \ No newline at end of file diff --git a/title26/kms.tf b/title26/kms.tf new file mode 120000 index 0000000..b0b3f29 --- /dev/null +++ b/title26/kms.tf @@ -0,0 +1 @@ +../common/kms.tf \ No newline at end of file diff --git a/title26/outputs.kms.tf b/title26/outputs.kms.tf new file mode 120000 index 0000000..74a8d7b --- /dev/null +++ b/title26/outputs.kms.tf @@ -0,0 +1 @@ +../common/outputs.kms.tf \ No newline at end of file diff --git a/title26/outputs.s3.tf b/title26/outputs.s3.tf new file mode 120000 index 0000000..594685a --- /dev/null +++ b/title26/outputs.s3.tf @@ -0,0 +1 @@ +../common/outputs.s3.tf \ No newline at end of file diff --git a/title26/variables.common.tf b/title26/variables.common.tf new file mode 120000 index 0000000..7439ed8 --- /dev/null +++ b/title26/variables.common.tf @@ -0,0 +1 @@ +../common/variables.common.tf \ No newline at end of file diff --git a/title26/variables.kms.tf b/title26/variables.kms.tf new file mode 120000 index 0000000..08cab47 --- /dev/null +++ b/title26/variables.kms.tf @@ -0,0 +1 @@ +../common/variables.kms.tf \ No newline at end of file diff --git a/title26/variables.s3.tf b/title26/variables.s3.tf new file mode 120000 index 0000000..49213df --- /dev/null +++ b/title26/variables.s3.tf @@ -0,0 +1 @@ +../common/variables.s3.tf \ No newline at end of file