From 95f2d5fab6c82b79b7bb8bce07eea6ce8013fed0 Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 12 Nov 2021 14:23:29 -0500 Subject: [PATCH] rename --- cloudtrail_orig/README.md | 100 ++++++++ cloudtrail_orig/data.policies.tf | 31 +++ cloudtrail_orig/data.tf | 1 + cloudtrail_orig/defaults.tf | 1 + cloudtrail_orig/kms.tf | 166 +++++++++++++ cloudtrail_orig/m | 6 + cloudtrail_orig/main.tf | 272 +++++++++++++++++++++ cloudtrail_orig/ol.tf | 252 +++++++++++++++++++ cloudtrail_orig/olv.tf | 68 ++++++ cloudtrail_orig/prefixes.tf | 1 + cloudtrail_orig/s3.tf | 57 +++++ cloudtrail_orig/variables.common.tf | 1 + cloudtrail_orig/variables.tf | 75 ++++++ {cloudtrail => cloudtrail_orig}/version.tf | 0 common/defaults.tf | 6 + 15 files changed, 1037 insertions(+) create mode 100644 cloudtrail_orig/README.md create mode 100644 cloudtrail_orig/data.policies.tf create mode 120000 cloudtrail_orig/data.tf create mode 120000 cloudtrail_orig/defaults.tf create mode 100644 cloudtrail_orig/kms.tf create mode 100644 cloudtrail_orig/m create mode 100644 cloudtrail_orig/main.tf create mode 100644 cloudtrail_orig/ol.tf create mode 100644 cloudtrail_orig/olv.tf create mode 120000 cloudtrail_orig/prefixes.tf create mode 100644 cloudtrail_orig/s3.tf create mode 120000 cloudtrail_orig/variables.common.tf create mode 100644 cloudtrail_orig/variables.tf rename {cloudtrail => cloudtrail_orig}/version.tf (100%) diff --git a/cloudtrail_orig/README.md b/cloudtrail_orig/README.md new file mode 100644 index 0000000..d6eef0c --- /dev/null +++ b/cloudtrail_orig/README.md @@ -0,0 +1,100 @@ +# aws-inf-setup :: cloudtrail + +This set up the needed components for cloudtrail in a region: S3, KMS key, SNS, SQS, cloudtrail, +cloudwatch log groups, and associated permissions. It also generates a splunk configuration to be used +for pulling cloudtrail events. + +* S3 bucket +* S3 bucket policy + +# Usage +Here is a simple example, the one most commonly expected to be used. + +```hcl +module "cloudtrail" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail" + + # account_alias = "do2-govcloud" + name = "mycloudtrail" + access_log_bucket = "myaccesslogbucket" + kms_key_management_identifiers = [ "arn:aws:iam::079788916859:role/r-inf-cloud-admin" ] +} +``` + +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 "cloudtrail_full" { + + # logs is generally not needed and not recommended + component_tags = { + "s3" = { + "SpecialTag1" = "something" + "SpecialTag2" = "somethingElse" + } + } +} +``` + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | n/a | +| [null](#provider\_null) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudtrail.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | +| [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.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_policy.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | 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.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | 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.cloudtrail_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.policy](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) | Server Access Log bucket prefix, to which the Object Logging bucket name will be appended to make the target\_prefix | `string` | `"s3"` | no | +| [account\_alias](#input\_account\_alias) | AWS Account Alias | `string` | `""` | no | +| [account\_id](#input\_account\_id) | AWS Account ID (default will pull from current user) | `string` | `""` | no | +| [cloudtrail\_bucket\_prefix](#input\_cloudtrail\_bucket\_prefix) | Access log bucket prefix, to which the bucket name will be appended to make the target\_prefix | `string` | `"cloudtrail"` | no | +| [component\_tags](#input\_component\_tags) | Additional tags for Components (s3, kms, ddb) | `map(map(string))` |
{
"ddb": {},
"kms": {},
"s3": {}
}
| no | +| [enable\_sns](#input\_enable\_sns) | Flag to enable or disable the creation of SNS for Cloudtrail (TBD) | `bool` | `false` | no | +| [enable\_sqs](#input\_enable\_sqs) | Flag to enable or disable the creation of SQS attached to SNS for Cloudtrail, used for Splunk ingestion (TBD) | `bool` | `false` | no | +| [kms\_key\_management\_identifiers](#input\_kms\_key\_management\_identifiers) | AWS IAM ARNs (roles, groups, users) for full access to the created KMS Key for this bucket | `list(string)` | `[]` | no | +| [name](#input\_name) | Name to apply to Cloudtrail, S3, SNS and SQS | `string` | `null` | no | +| [object\_log\_bucket\_prefix](#input\_object\_log\_bucket\_prefix) | Access log bucket prefix, to which the bucket name will be appended to make the target\_prefix | `string` | `"s3_object_logs"` | no | +| [override\_prefixes](#input\_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](#input\_tags) | Tags to apply to all resources | `map(string)` | `{}` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [kms\_key\_arn](#output\_kms\_key\_arn) | Cloudtrail Key ARN | +| [kms\_key\_id](#output\_kms\_key\_id) | Cloudtrail Key ID | diff --git a/cloudtrail_orig/data.policies.tf b/cloudtrail_orig/data.policies.tf new file mode 100644 index 0000000..e092555 --- /dev/null +++ b/cloudtrail_orig/data.policies.tf @@ -0,0 +1,31 @@ +data "aws_iam_policy_document" "cloudtrail_s3" { + statement { + sid = "AWSCloudTrailWrite" + effect = "Allow" + resources = ["${aws_s3_bucket.cloudtrail.arn}/*"] + actions = ["s3:PutObject"] + + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + + condition { + test = "StringLike" + variable = "s3:x-amz-acl" + values = ["bucket-owner-full-control"] + } + } + + statement { + sid = "AWSCloudTrailAclCheck" + effect = "Allow" + resources = [aws_s3_bucket.cloudtrail.arn] + actions = ["s3:GetBucketAcl"] + + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + } +} diff --git a/cloudtrail_orig/data.tf b/cloudtrail_orig/data.tf new file mode 120000 index 0000000..995624d --- /dev/null +++ b/cloudtrail_orig/data.tf @@ -0,0 +1 @@ +../common/data.tf \ No newline at end of file diff --git a/cloudtrail_orig/defaults.tf b/cloudtrail_orig/defaults.tf new file mode 120000 index 0000000..a5556ac --- /dev/null +++ b/cloudtrail_orig/defaults.tf @@ -0,0 +1 @@ +../common/defaults.tf \ No newline at end of file diff --git a/cloudtrail_orig/kms.tf b/cloudtrail_orig/kms.tf new file mode 100644 index 0000000..63f49fa --- /dev/null +++ b/cloudtrail_orig/kms.tf @@ -0,0 +1,166 @@ +#--- +# kms key +#--- +resource "aws_kms_key" "key" { + description = "Encrypt CloudTrail objects and streams" + enable_key_rotation = true + policy = data.aws_iam_policy_document.key.json + + tags = merge( + local.common_tags, + map("boc:aws:region", local.region), + map("Name", var.kms_key), + ) + lifecycle { + ignore_changes = [tags["boc:tf_module_version"]] + } +} + +resource "aws_kms_alias" "key" { + name = "alias/${var.kms_key}" + target_key_id = aws_kms_key.key.key_id +} + +output "kms_key_id" { + description = "Cloudtrail Key ID" + value = aws_kms_key.key.id +} +output "kms_key_arn" { + description = "Cloudtrail Key ARN" + value = aws_kms_key.key.arn +} + +data "aws_iam_policy_document" "key" { + policy_id = "inf-cloudtrail KMS access" + statement { + sid = "EnableIAMUserPermissions" + effect = "Allow" + actions = ["kms:*"] + resources = ["*"] + principals { + type = "AWS" + + identifiers = [ + # data.aws_caller_identity.current.arn, + "arn:${data.aws_arn.current.partition}:iam::${var.account_id}:root", + # "arn:${data.aws_arn.current.partition}:sts::${var.account_id}:assumed-role/r-inf-cloud-admin/${var.tag_creator}", + ] + } + } + + statement { + sid = "AllowCloudTrailEncryptLogs" + effect = "Allow" + actions = ["kms:GenerateDataKey*"] + resources = ["*"] + + principals { + type = "Service" + # identifiers = ["cloudtrail.amazonaws.com"] + identifiers = ["cloudtrail.amazonaws.com", "logs.amazonaws.com", "logs.${local.region}.amazonaws.com"] + } + + condition { + test = "StringLike" + variable = "kms:EncryptionContext:aws:cloudtrail:arn" + values = ["arn:${data.aws_arn.current.partition}:cloudtrail:*:${var.account_id}:trail/*"] + } + } + + statement { + sid = "AllowCloudTrailKeyActivities" + effect = "Allow" + actions = [ + "kms:Describe*", + "log:AssociateKmsKey", + "log:DisassociateKmsKey" + ] + resources = ["*"] + + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com", "logs.amazonaws.com", "logs.${local.region}.amazonaws.com"] + } + } + + statement { + sid = "AllowPrincipalsDecryptLogFiles" + effect = "Allow" + + principals { + type = "AWS" + identifiers = ["*"] + } + actions = [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncryptFrom" + ] + resources = ["*"] + + condition { + test = "StringEquals" + variable = "kms:CallerAccount" + values = [var.account_id] + } + + condition { + test = "StringLike" + variable = "kms:EncryptionContext:aws:cloudtrail:arn" + values = ["arn:${data.aws_arn.current.partition}:cloudtrail:*:${var.account_id}:trail/*"] + } + } + + statement { + sid = "EnableCrossAccountDecryptLogFiles" + effect = "Allow" + + principals { + type = "AWS" + identifiers = ["*"] + } + + actions = [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncryptFrom" + ] + resources = ["*"] + + condition { + test = "StringEquals" + variable = "kms:CallerAccount" + values = [var.account_id] + } + + condition { + test = "StringLike" + variable = "kms:EncryptionContext:aws:cloudtrail:arn" + values = ["arn:${data.aws_arn.current.partition}:cloudtrail:*:${var.account_id}:trail/*"] + } + } + + statement { + sid = "AllowAliasCreationDuringSetup" + effect = "Allow" + actions = ["kms:CreateAlias"] + resources = ["*"] + + principals { + type = "AWS" + identifiers = ["*"] + } + + condition { + test = "StringEquals" + variable = "kms:CallerAccount" + values = [var.account_id] + } + + condition { + test = "StringEquals" + variable = "kms:ViaService" + values = ["ec2.${local.region}.amazonaws.com}"] + } + } +} diff --git a/cloudtrail_orig/m b/cloudtrail_orig/m new file mode 100644 index 0000000..2797179 --- /dev/null +++ b/cloudtrail_orig/m @@ -0,0 +1,6 @@ +/* +* +* cloudtrail +* sqs, dead letter +* sns +* diff --git a/cloudtrail_orig/main.tf b/cloudtrail_orig/main.tf new file mode 100644 index 0000000..e90fa70 --- /dev/null +++ b/cloudtrail_orig/main.tf @@ -0,0 +1,272 @@ +/* +* # aws-inf-setup :: cloudtrail +* +* This set up the needed components for cloudtrail in a region: S3, KMS key, SNS, SQS, cloudtrail, +* cloudwatch log groups, and associated permissions. It also generates a splunk configuration to be used +* for pulling cloudtrail events. +* +* * S3 bucket +* * S3 bucket policy +* +* # Usage +* Here is a simple example, the one most commonly expected to be used. +* +* ```hcl +* module "cloudtrail" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail" +* +* # account_alias = "do2-govcloud" +* name = "mycloudtrail" +* access_log_bucket = "myaccesslogbucket" +* kms_key_management_identifiers = [ "arn:aws:iam::079788916859:role/r-inf-cloud-admin" ] +* } +* ``` +* +* 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 "cloudtrail_full" { +* +* # logs 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 + region = data.aws_region.current.name + account_environment = data.aws_arn.current.partition == "aws-us-gov" ? "gov" : "ew" + partition = data.aws_arn.current.partition + + + # remap do2 to do1 for govcloud (undo this later when accounts are renamed in splunk) + # account_alias = replace(var.account_alias, "do2", "do1") + + name = (var.name != "" && var.name != null) ? var.name : format("%v-%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.account_id, local.region) + + bucket_id = aws_s3_bucket.cloudtrail.id + bucket_arn = aws_s3_bucket.cloudtrail.arn + + # 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) + + base_tags = { + "boc:tf_module_version" = local._module_version + "boc:created_by" = "terraform" + } +} + +#@@@ + +#--- +# cloudtrail, with encryption +#--- +resource "aws_cloudtrail" "this" { + name = local.name + s3_bucket_name = aws_s3_bucket.this.id + s3_key_prefix = var.cloudtrail_bucket_prefix + include_global_service_events = false + is_multi_region_trail = false + kms_key_id = aws_kms_key.key.arn + enable_log_file_validation = true + + tags = merge( + local.base_tags, + var.tags, + { "Name" = local.name }, + ) + depends_on = [aws_s3_bucket_policy.policy] +} + +#--- +# s3 object logging bucket, with encryption +#--- +resource "aws_s3_bucket" "this" { + bucket = local.name + acl = "private" + force_destroy = false + + logging { + target_bucket = var.access_log_bucket + target_prefix = format("%s/%s/", var.access_log_bucket_prefix, local.name) + } + + tags = merge( + local.base_tags, + var.tags, + { "Name" = local.name }, + ) + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.key.arn + sse_algorithm = "aws:kms" + } + } + } +} + +#--- +# bucket policy (apply also encryption key usage here?) +# deny unencrypted uploads policy statement removed for default encryption +#--- +data "aws_iam_policy_document" "policy" { + statement { + sid = "AWSCloudTrailAclCheck" + effect = "Allow" + actions = ["s3:GetBucketAcl"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + resources = [aws_s3_bucket.this.arn] + } + statement { + sid = "AWSCloudTrailWrite" + effect = "Allow" + actions = ["s3:PutObject"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + resources = ["${aws_s3_bucket.this.arn}/${var.cloudtrail_bucket_prefix}/*"] + condition { + test = "StringEquals" + variable = "s3:x-amz-acl" + values = ["bucket-owner-full-control"] + } + } +} + +#--- +# 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.policy.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 +} + +#--- +# 180s delay needed for bucket to create and policy to apply, before +# creating a cloudtrail to point to it +#--- +resource "null_resource" "policy_delay" { + triggers = { + bucket = aws_s3_bucket.this.id + # policy = aws_s3_bucket_policy.policy.id + } + provisioner "local-exec" { + when = create + command = "sleep 180" + } +} + +#--- +# create a key and alias if not specified +#--- +resource "aws_kms_key" "key" { + description = "KMS CMK for Cloudtrail and S3 bucket ${local.name}" + enable_key_rotation = true + policy = data.aws_iam_policy_document.key.json + + tags = merge( + local.base_tags, + { "Name" = local.kms_key_name }, + var.tags + ) +} + +resource "aws_kms_alias" "key" { + name = "alias/${local.kms_key_name}" + target_key_id = aws_kms_key.key.key_id +} + + +#--- +# key policy for clodutrail +# https://docs.aws.amazon.com/awscloudtrail/latest/userguide/create-kms-key-policy-for-cloudtrail.html +# can't use aws_cloudtrail.this.arn as it makes for a circular reference +#--- +data "aws_iam_policy_document" "key" { + policy_id = "object-logging-cloud-trail" + statement { + sid = "IAMPermissionsAccessKMSManagement" + effect = "Allow" + actions = ["kms:*"] + resources = ["*"] + principals { + type = "AWS" + identifiers = compact(concat(list(format("arn:%s:iam::%s:root", local.partition, local.account_id)), var.kms_key_management_identifiers)) + # data.aws_caller_identity.current.arn, + # aws_iam_role.inf-cloud-admin.arn, + # "arn:${data.aws_arn.current.partition}:iam::${var.account_id}:root", + } + } + statement { + sid = "CloudTrailKMSAccess" + effect = "Allow" + actions = ["kms:DescribeKey"] + resources = ["*"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + } + statement { + sid = "CloudTrailKMSEncryptAccess" + effect = "Allow" + actions = ["kms:GenerateDataKey"] + resources = ["*"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + condition { + test = "StringLike" + variable = "kms:EncryptionContext:aws:cloudtrail:arn" + values = [format("arn:%s:cloudtrail:*:%s:trail/%s", local.partition, local.account_id, local.name)] + } + } +} + + +## { +## "Sid": "Enable CloudTrail log decrypt permissions", +## "Effect": "Allow", +## "Principal": { +## "AWS": "arn:aws:iam::111111111111:user/Bob" +## }, +## "Action": "kms:Decrypt", +## "Resource": "*", +## "Condition": { +## "Null": { +## "kms:EncryptionContext:aws:cloudtrail:arn": "false" +## } +## } +## } +## +## +## +## + +#@@@ + diff --git a/cloudtrail_orig/ol.tf b/cloudtrail_orig/ol.tf new file mode 100644 index 0000000..7470898 --- /dev/null +++ b/cloudtrail_orig/ol.tf @@ -0,0 +1,252 @@ +/* +* ```hcl +* module "cloudtrail" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail" +* +* name = "mycloudtrail" +* access_log_bucket = "myaccesslogbucket" +* kms_key_management_identifiers = [ "arn:aws:iam::079788916859:role/r-inf-cloud-admin" ] +* } +* ``` +* +*/ + +#--- +# get account and partition values from caller +#--- +data "aws_caller_identity" "current" {} +data "aws_arn" "current" { + arn = data.aws_caller_identity.current.arn +} +data "aws_region" "current" {} + +#--- +# setup name, if missing +# setup key, if missing +# set base tags +#--- +locals { + account_id = data.aws_caller_identity.current.account_id + aws_region = data.aws_region.current.name + partition = data.aws_arn.current.partition + name = (var.name != "" && var.name != null) ? var.name : format("inf-objectlogging-%v-%v", local.account_id, local.aws_region) + + # 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) + + base_tags = { + "boc:tf_module_version" = var._module_version + "boc:created_by" = "terraform" + } +} + +#--- +# cloudtrail, with encryption +#--- +resource "aws_cloudtrail" "this" { + name = local.name + s3_bucket_name = aws_s3_bucket.this.id + s3_key_prefix = var.object_log_bucket_prefix + include_global_service_events = false + is_multi_region_trail = false + kms_key_id = local.kms_key_arn + enable_log_file_validation = true + + event_selector { + read_write_type = "All" + include_management_events = false + + data_resource { + type = "AWS::S3::Object" + values = ["arn:${local.partition}:s3:::"] + } + } + tags = merge( + local.base_tags, + var.tags, + { "Name" = local.name }, + ) + depends_on = [aws_s3_bucket_policy.policy] +} + +#--- +# s3 object logging bucket, with encryption +#--- +resource "aws_s3_bucket" "this" { + bucket = local.name + acl = "private" + force_destroy = false + + logging { + target_bucket = var.access_log_bucket + target_prefix = format("%s/%s/", var.access_log_bucket_prefix, local.name) + } + + tags = merge( + local.base_tags, + var.tags, + { "Name" = local.name }, + ) + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = local.kms_key_arn + sse_algorithm = "aws:kms" + } + } + } +} + +#--- +# bucket policy (apply also encryption key usage here?) +# deny unencrypted uploads policy statement removed for default encryption +#--- +data "aws_iam_policy_document" "policy" { + statement { + sid = "AWSCloudTrailAclCheck" + effect = "Allow" + actions = ["s3:GetBucketAcl"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + resources = [aws_s3_bucket.this.arn] + } + statement { + sid = "AWSCloudTrailWrite" + effect = "Allow" + actions = ["s3:PutObject"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + resources = ["${aws_s3_bucket.this.arn}/${var.object_log_bucket_prefix}/*"] + condition { + test = "StringEquals" + variable = "s3:x-amz-acl" + values = ["bucket-owner-full-control"] + } + } +} + +#--- +# 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.policy.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 +} + +#--- +# 180s delay needed for bucket to create and policy to apply, before +# creating a cloudtrail to point to it +#--- +resource "null_resource" "policy_delay" { + triggers = { + bucket = aws_s3_bucket.this.id + # policy = aws_s3_bucket_policy.policy.id + } + provisioner "local-exec" { + when = create + command = "sleep 180" + } +} + +#--- +# create a key and alias if not specified +#--- +resource "aws_kms_key" "key" { + description = "KMS CMK for Cloudtrail and S3 bucket ${local.name}" + enable_key_rotation = true + policy = data.aws_iam_policy_document.key.json + + tags = merge( + local.base_tags, + { "Name" = local.kms_key_name }, + var.tags + ) +} + +resource "aws_kms_alias" "key" { + name = "alias/${local.kms_key_name}" + target_key_id = aws_kms_key.key.key_id +} + + +#--- +# key policy for clodutrail +# https://docs.aws.amazon.com/awscloudtrail/latest/userguide/create-kms-key-policy-for-cloudtrail.html +# can't use aws_cloudtrail.this.arn as it makes for a circular reference +#--- +data "aws_iam_policy_document" "key" { + policy_id = "object-logging-cloud-trail" + statement { + sid = "IAMPermissionsAccessKMSManagement" + effect = "Allow" + actions = ["kms:*"] + resources = ["*"] + principals { + type = "AWS" + identifiers = compact(concat(list(format("arn:%s:iam::%s:root", local.partition, local.account_id)), var.kms_key_management_identifiers)) + # data.aws_caller_identity.current.arn, + # aws_iam_role.inf-cloud-admin.arn, + # "arn:${data.aws_arn.current.partition}:iam::${var.account_id}:root", + } + } + statement { + sid = "CloudTrailKMSAccess" + effect = "Allow" + actions = ["kms:DescribeKey"] + resources = ["*"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + } + statement { + sid = "CloudTrailKMSEncryptAccess" + effect = "Allow" + actions = ["kms:GenerateDataKey"] + resources = ["*"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + condition { + test = "StringLike" + variable = "kms:EncryptionContext:aws:cloudtrail:arn" + values = [format("arn:%s:cloudtrail:*:%s:trail/%s", local.partition, local.account_id, local.name)] + } + } +} + + +## { +## "Sid": "Enable CloudTrail log decrypt permissions", +## "Effect": "Allow", +## "Principal": { +## "AWS": "arn:aws:iam::111111111111:user/Bob" +## }, +## "Action": "kms:Decrypt", +## "Resource": "*", +## "Condition": { +## "Null": { +## "kms:EncryptionContext:aws:cloudtrail:arn": "false" +## } +## } +## } +## +## +## +## diff --git a/cloudtrail_orig/olv.tf b/cloudtrail_orig/olv.tf new file mode 100644 index 0000000..26fdd59 --- /dev/null +++ b/cloudtrail_orig/olv.tf @@ -0,0 +1,68 @@ +# enable_sns +# enable_sqs +# name (default = inf-objectlogging-{account}-{region}) +# cloudtrail_name (name) +# log_bucket (existing bucket; if empty, will create one) +# sns_name (name) +# sqs_name (name) + +variable "name" { + description = "Name to apply to Cloudtrail, S3, SNS and SQS" + type = string + default = null +} + +variable "object_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_object_logs" +} + +# required +variable "access_log_bucket" { + description = "Server Access Logging Bucket ID" + type = string + # default = null +} + +variable "access_log_bucket_prefix" { + description = "Server Access Log bucket prefix, to which the Object Logging bucket name will be appended to make the target_prefix" + type = string + default = "s3" +} + +# variable "bucket_folders" { +# description = "List of folders (keys) to create after creation of Object Logging bucket" +# type = list(string) +# default = [] +# } + +# variable "kms_key_arn" { +# description = "AWS KMS Key ARN for cloudtrail and bucket" +# type = string +# default = null +# } + +variable "kms_key_management_identifiers" { + description = "AWS IAM ARNs (roles, groups, users) for full access to the created KMS Key for this bucket" + type = list(string) + default = [] +} + +variable "tags" { + description = "Tags to apply to all resources" + type = map(string) + default = {} +} + +variable "enable_sns" { + description = "Flag to enable or disable the creation of SNS for Cloudtrail (TBD)" + type = bool + default = false +} + +variable "enable_sqs" { + description = "Flag to enable or disable the creation of SQS attached to SNS for Cloudtrail, used for Splunk ingestion (TBD)" + type = bool + default = false +} diff --git a/cloudtrail_orig/prefixes.tf b/cloudtrail_orig/prefixes.tf new file mode 120000 index 0000000..7e265d5 --- /dev/null +++ b/cloudtrail_orig/prefixes.tf @@ -0,0 +1 @@ +../common/prefixes.tf \ No newline at end of file diff --git a/cloudtrail_orig/s3.tf b/cloudtrail_orig/s3.tf new file mode 100644 index 0000000..287b161 --- /dev/null +++ b/cloudtrail_orig/s3.tf @@ -0,0 +1,57 @@ +#--- +# s3 +#--- +resource "aws_s3_bucket" "cloudtrail" { + bucket = local.bucket_name + acl = "private" + + server_side_encryption_cloudtrailuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.cloudtrail_key.arn + sse_algorithm = "aws:kms" + } + } + } + + versioning { + enabled = false + } + + logging { + target_bucket = aws_s3_bucket.logs.id + target_prefix = "s3/{local.cloudtrail_bucket}/" + } + + lifecycle { + prevent_destroy = true + ignore_changes = [tags["boc:tf_module_version"]] + } + + # probably want some migration of old data to some other location + # like glacier + + tags = merge( + var.tags, + local.base_tags, + lookup(var.component_tags, "s3", {}), + map("Name", local.bucket_name), + ) + + provisioner "local-exec" { + command = "sleep 30" + } +} + +resource "aws_s3_bucket_public_access_block" "cloudtrail" { + bucket = aws_s3_bucket.cloudtrail.id + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +resource "aws_s3_bucket_policy" "cloudtrail" { + bucket = aws_s3_bucket.cloudtrail.id + policy = data.aws_iam_policy_document.cloudtrail_s3.json +} diff --git a/cloudtrail_orig/variables.common.tf b/cloudtrail_orig/variables.common.tf new file mode 120000 index 0000000..7439ed8 --- /dev/null +++ b/cloudtrail_orig/variables.common.tf @@ -0,0 +1 @@ +../common/variables.common.tf \ No newline at end of file diff --git a/cloudtrail_orig/variables.tf b/cloudtrail_orig/variables.tf new file mode 100644 index 0000000..bce9464 --- /dev/null +++ b/cloudtrail_orig/variables.tf @@ -0,0 +1,75 @@ +## variable "bucket_name" { +## description = "Cloudtrail S3 bucket name" +## type = string +## default = "" +## } +## +## variable "bucket_name_prefix" { +## description = "Cloudtrail S3 bucket prefix, prepended to the AWS account ID and region to make the bucket name." +## type = string +## default = "" +## } + +# enable_sns +# enable_sqs +# name (default = inf-cloudtrail-{account}-{region}) +# cloudtrail_name (name) +# log_bucket (existing bucket; if empty, will create one) +# sns_name (name) +# sqs_name (name) + +variable "name" { + description = "Name to apply to Cloudtrail, S3, SNS and SQS" + type = string + default = null +} + +variable "cloudtrail_bucket_prefix" { + description = "Access log bucket prefix, to which the bucket name will be appended to make the target_prefix" + type = string + default = "cloudtrail" +} + +# required +variable "access_log_bucket" { + description = "Server Access Logging Bucket ID" + type = string + # default = null +} + +variable "access_log_bucket_prefix" { + description = "Server Access Log bucket prefix, to which the Object Logging bucket name will be appended to make the target_prefix" + type = string + default = "s3" +} + +variable "kms_key_management_identifiers" { + description = "AWS IAM ARNs (roles, groups, users) for full access to the created KMS Key for this bucket" + type = list(string) + default = [] +} + +variable "tags" { + description = "Tags to apply to all resources" + type = map(string) + default = {} +} + +variable "enable_sns" { + description = "Flag to enable or disable the creation of SNS for Cloudtrail (TBD)" + type = bool + default = false +} + +variable "enable_sqs" { + description = "Flag to enable or disable the creation of SQS attached to SNS for Cloudtrail, used for Splunk ingestion (TBD)" + type = bool + default = false +} + +variable "component_tags" { + description = "Additional tags for Components (s3, kms, ddb)" + type = map(map(string)) + default = { "s3" = {}, "kms" = {}, "ddb" = {} } +} + diff --git a/cloudtrail/version.tf b/cloudtrail_orig/version.tf similarity index 100% rename from cloudtrail/version.tf rename to cloudtrail_orig/version.tf diff --git a/common/defaults.tf b/common/defaults.tf index 91dc82b..7e84a52 100644 --- a/common/defaults.tf +++ b/common/defaults.tf @@ -17,6 +17,12 @@ locals { "ses" = { "event_types" = ["bounce", "delivery", "complaint"] } + "organization-cloudtrail" = { + "name" = "inf-org-cloudtrail" + } + "cloudtrail" = { + "name" = "inf-cloudtrail" + } "config" = { "name" = "inf-config" }