Skip to content

v2.1.0: add kms admin roles, key policy and allow them to be passed in #27

Merged
merged 8 commits into from
May 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@
* v2.0.1 -- 20210325
- make bucket policies denying missing encryption header optional
- add variable: `require_explicit_encryption` default = false

* v2.1.0 -- 20210511
- add kms_policy to be used for custom kms key policy and kms_admin_roles
8 changes: 8 additions & 0 deletions common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ No modules.
| [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.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

Expand All @@ -37,7 +43,9 @@ No modules.
| <a name="input_bucket_folders"></a> [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 |
| <a name="input_bucket_name"></a> [bucket\_name](#input\_bucket\_name) | AWS Bucket Name. Standard prefix will be applied here, do not include here. | `string` | n/a | yes |
| <a name="input_force_destroy"></a> [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 |
| <a name="input_kms_admin_roles"></a> [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 |
| <a name="input_kms_key_id"></a> [kms\_key\_id](#input\_kms\_key\_id) | AWS KMS Key ID (one per bucket). This is currently ignored. | `string` | `""` | no |
| <a name="input_kms_policy_document"></a> [kms\_policy\_document](#input\_kms\_policy\_document) | AWS KMS Key Policy Document JSON, merged with admin policy document | `string` | `""` | no |
| <a name="input_metadata_tags"></a> [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 |
| <a name="input_require_explicit_encryption"></a> [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 |
| <a name="input_tags"></a> [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 |
Expand Down
7 changes: 7 additions & 0 deletions common/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
data "aws_caller_identity" "current" {}

data "aws_arn" "current" {
arn = data.aws_caller_identity.current.arn
}

data "aws_region" "current" {}
40 changes: 38 additions & 2 deletions common/resources.tf
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
locals {

account_id = data.aws_caller_identity.current.account_id
current_user_arn = data.aws_caller_identity.current.arn
partition = data.aws_arn.current.partition
region = data.aws_region.current.name
}

locals {
base_name = var.bucket_name
name = replace(var.bucket_name, local._prefixes["s3"], "")
bucket_name = format("%s%s", local._prefixes["s3"], local.name)

# 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)

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

condition_allowed_cidr = {
"test" : "NotIpAddress"
"variable" : "aws:sourceIp"
Expand Down Expand Up @@ -210,17 +223,40 @@ resource "aws_s3_bucket_object" "this_objects" {
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
policy = data.aws_iam_policy_document.key_policy_combined.json

tags = merge(
local.base_tags,
var.tags,
local.enforced_tags,
map("Name", local.bucket_name)
map("Name", local.kms_key_name)
)
}

resource "aws_kms_alias" "key" {
name = "alias/${local.kms_key_name}"
target_key_id = aws_kms_key.key.key_id
}

# 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" "empty" {}
16 changes: 16 additions & 0 deletions common/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ variable "kms_key_id" {
default = ""
}

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 = []
}

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)
Expand Down Expand Up @@ -62,3 +74,7 @@ variable "require_explicit_encryption" {
type = bool
default = false
}

# TBD
# variable "kms_policy_read_arns" { }
# variable "kms_policy_write_arns" { }
2 changes: 1 addition & 1 deletion common/version.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
locals {
_module_version = "2.0.1"
_module_version = "2.1.0"
}
23 changes: 23 additions & 0 deletions standard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,26 @@ module "mybucket" {
bucket_name = "mynormalbucket"
access_log_bucket = "mylogbucket"
kms_admin_roles = [ aws_iam_role.cloud-admin.arn ]
## optional
# kms_policy_document = data.aws_iam_policy_document.mypolicy.json
}
data "aws_iam_policy_document" "mypolicy" {
statement { }
}
```

This automaticaly creates an AWS KMS key used just for this bucket.

It will set a key usage/management policy by default with the `root` account, along with any other
roles in the variable `kms_admin_roles` list. This is **full** access to the KMS key.

If `kms_policy_document` is provided it needs to be a valid IAM policy as would apply to key usage,
such as read access (decrypt) or write access (encrypt, re-encrypt). A later enhancement may be
to provide variables granting read and write access to the key.

## Requirements

No requirements.
Expand All @@ -45,7 +60,13 @@ No modules.
| [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.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

Expand All @@ -60,7 +81,9 @@ No modules.
| <a name="input_data_safeguards"></a> [data\_safeguards](#input\_data\_safeguards) | Selected available safeguards which apply to the data in the bucket | `list(string)` | `[]` | no |
| <a name="input_enable_title26"></a> [enable\_title26](#input\_enable\_title26) | Flag to enable bucket with Title 26 (FTI) settings | `bool` | `false` | no |
| <a name="input_force_destroy"></a> [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 |
| <a name="input_kms_admin_roles"></a> [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 |
| <a name="input_kms_key_id"></a> [kms\_key\_id](#input\_kms\_key\_id) | AWS KMS Key ID (one per bucket). This is currently ignored. | `string` | `""` | no |
| <a name="input_kms_policy_document"></a> [kms\_policy\_document](#input\_kms\_policy\_document) | AWS KMS Key Policy Document JSON, merged with admin policy document | `string` | `""` | no |
| <a name="input_metadata_tags"></a> [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 |
| <a name="input_require_explicit_encryption"></a> [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 |
| <a name="input_tags"></a> [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 |
Expand Down
1 change: 1 addition & 0 deletions standard/data.tf
15 changes: 15 additions & 0 deletions standard/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,25 @@
*
* bucket_name = "mynormalbucket"
* access_log_bucket = "mylogbucket"
* kms_admin_roles = [ aws_iam_role.cloud-admin.arn ]
*
* ## optional
* # kms_policy_document = data.aws_iam_policy_document.mypolicy.json
* }
*
* data "aws_iam_policy_document" "mypolicy" {
* statement { }
* }
* ```
*
* This automaticaly creates an AWS KMS key used just for this bucket.
*
* It will set a key usage/management policy by default with the `root` account, along with any other
* roles in the variable `kms_admin_roles` list. This is **full** access to the KMS key.
*
* If `kms_policy_document` is provided it needs to be a valid IAM policy as would apply to key usage,
* such as read access (decrypt) or write access (encrypt, re-encrypt). A later enhancement may be
* to provide variables granting read and write access to the key.
*/

locals {
Expand Down
23 changes: 23 additions & 0 deletions title26/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ module "mybucket" {
bucket_name = "myt26bucket"
access_log_bucket = "mylogbucket"
# enable_title26 = true
kms_admin_roles = [ aws_iam_role.cloud-admin.arn ]
## optional
# kms_policy_document = data.aws_iam_policy_document.mypolicy.json
}
data "aws_iam_policy_document" "mypolicy" {
statement { }
}
```

Expand All @@ -24,6 +32,13 @@ to make a comma separated list.

This automaticaly creates an AWS KMS key used just for this bucket.

It will set a key usage/management policy by default with the `root` account, along with any other
roles in the variable `kms_admin_roles` list. This is **full** access to the KMS key.

If `kms_policy_document` is provided it needs to be a valid IAM policy as would apply to key usage,
such as read access (decrypt) or write access (encrypt, re-encrypt). A later enhancement may be
to provide variables granting read and write access to the key.

## Requirements

No requirements.
Expand All @@ -50,7 +65,13 @@ No modules.
| [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.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

Expand All @@ -65,7 +86,9 @@ No modules.
| <a name="input_data_safeguards"></a> [data\_safeguards](#input\_data\_safeguards) | Selected available safeguards which apply to the data in the bucket | `list(string)` | <pre>[<br> "title26"<br>]</pre> | no |
| <a name="input_enable_title26"></a> [enable\_title26](#input\_enable\_title26) | Flag to enable bucket with Title 26 (FTI) settings | `bool` | `true` | no |
| <a name="input_force_destroy"></a> [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 |
| <a name="input_kms_admin_roles"></a> [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 |
| <a name="input_kms_key_id"></a> [kms\_key\_id](#input\_kms\_key\_id) | AWS KMS Key ID (one per bucket). This is currently ignored. | `string` | `""` | no |
| <a name="input_kms_policy_document"></a> [kms\_policy\_document](#input\_kms\_policy\_document) | AWS KMS Key Policy Document JSON, merged with admin policy document | `string` | `""` | no |
| <a name="input_metadata_tags"></a> [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 |
| <a name="input_require_explicit_encryption"></a> [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 |
| <a name="input_tags"></a> [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 |
Expand Down
1 change: 1 addition & 0 deletions title26/data.tf
15 changes: 15 additions & 0 deletions title26/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@
* bucket_name = "myt26bucket"
* access_log_bucket = "mylogbucket"
* # enable_title26 = true
* kms_admin_roles = [ aws_iam_role.cloud-admin.arn ]
*
* ## optional
* # kms_policy_document = data.aws_iam_policy_document.mypolicy.json
* }
*
* data "aws_iam_policy_document" "mypolicy" {
* statement { }
* }
* ```
*
Expand All @@ -24,6 +32,13 @@
* to make a comma separated list.
*
* This automaticaly creates an AWS KMS key used just for this bucket.
*
* It will set a key usage/management policy by default with the `root` account, along with any other
* roles in the variable `kms_admin_roles` list. This is **full** access to the KMS key.
*
* If `kms_policy_document` is provided it needs to be a valid IAM policy as would apply to key usage,
* such as read access (decrypt) or write access (encrypt, re-encrypt). A later enhancement may be
* to provide variables granting read and write access to the key.
*/

locals {
Expand Down