From 595385d96393e08b94038a3ffb7b6480355ce243 Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 12 Nov 2021 14:23:09 -0500 Subject: [PATCH 01/59] exclude cloudtrail_orig --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2056df3..d0a6e69 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,6 +10,7 @@ repos: exclude: version.tf - id: terraform_tflint args: [ "--args=--config=__GIT_WORKING_DIR__/.tflint.hcl"] + exclude: cloudtrail_orig - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.0.1 hooks: From 95f2d5fab6c82b79b7bb8bce07eea6ce8013fed0 Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 12 Nov 2021 14:23:29 -0500 Subject: [PATCH 02/59] 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" } From ac1b0652da5d76593a6d7d02ed5f68473759af25 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 09:15:49 -0500 Subject: [PATCH 03/59] ignore examples --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d0a6e69..91a733b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,6 +11,7 @@ repos: - id: terraform_tflint args: [ "--args=--config=__GIT_WORKING_DIR__/.tflint.hcl"] exclude: cloudtrail_orig + exclude: examples - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.0.1 hooks: From efa4b2d221aa5c6db260d97c322aacbdb58922f5 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 09:21:39 -0500 Subject: [PATCH 04/59] ignore examples for tfdocs --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 91a733b..f146357 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,6 +8,7 @@ repos: args: ['table'] exclude: common/*.tf exclude: version.tf + exclude: examples - id: terraform_tflint args: [ "--args=--config=__GIT_WORKING_DIR__/.tflint.hcl"] exclude: cloudtrail_orig From b74e494dff8857849298c28af20dbe06f73a5c41 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 09:22:35 -0500 Subject: [PATCH 05/59] add cloudtrail-key --- CHANGELOG.md | 4 + cloudtrail-key/README.md | 95 ++++++++ cloudtrail-key/base_tags.tf | 6 + cloudtrail-key/data.tf | 1 + cloudtrail-key/defaults.tf | 1 + cloudtrail-key/main.tf | 218 ++++++++++++++++++ cloudtrail-key/outputs.tf | 14 ++ cloudtrail-key/prefixes.tf | 1 + cloudtrail-key/variables.common.tf | 1 + cloudtrail-key/variables.tf | 23 ++ cloudtrail-key/version.tf | 1 + common/version.tf | 2 +- .../cloudtrail-key/cloudtrail_key_full.tf | 18 ++ .../cloudtrail-key/cloudtrail_key_simple.tf | 7 + 14 files changed, 391 insertions(+), 1 deletion(-) create mode 100644 cloudtrail-key/README.md create mode 100644 cloudtrail-key/base_tags.tf create mode 120000 cloudtrail-key/data.tf create mode 120000 cloudtrail-key/defaults.tf create mode 100644 cloudtrail-key/main.tf create mode 100644 cloudtrail-key/outputs.tf create mode 120000 cloudtrail-key/prefixes.tf create mode 120000 cloudtrail-key/variables.common.tf create mode 100644 cloudtrail-key/variables.tf create mode 120000 cloudtrail-key/version.tf create mode 100644 examples/cloudtrail-key/cloudtrail_key_full.tf create mode 100644 examples/cloudtrail-key/cloudtrail_key_simple.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index a5b2f4e..ec89428 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -122,3 +122,7 @@ * v1.13.2 -- 20210713 - general - change ip_restriction to be a dynamic condition block to also include VpcSourceIp + +* v1.14.0 -- 20211115 + - cloudtrail-key + - create module to setup a KMS ke per region for cloudtrail diff --git a/cloudtrail-key/README.md b/cloudtrail-key/README.md new file mode 100644 index 0000000..ad1aabe --- /dev/null +++ b/cloudtrail-key/README.md @@ -0,0 +1,95 @@ +# aws-inf-setup :: cloudtrail-keys + +This set up the KMS key used by Cloudtrail for the ts S3 bucket, CloudTrail, and SQS (if possible). + +* Cloudtrail +* S3 bucket +* SQS + +## Usage, Simple Example +Here is a simple example, the one most commonly expected to be used. + +```hcl +module "cloudtrail_key_simple" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" + + tags = { + Environment = "csvd:infrastructure" + } +} +``` + +## Usage, Longer Example +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_key_full" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" + + name = "mycloudtrail" + kms_admin_roles = ["arn:aws:iam::079788916859:role/r-inf-cloud-admin"] + kms_policy_document = data.aws_iam_policy_document.myct_policy.json + + tags = { + Environment = "csvd:infrastructure" + } + + component_tags = { + "kms" = { + "SpecialTag1" = "something" + "SpecialTag2" = "somethingElse" + } + } +} +``` + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 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_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](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_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [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 | +| [component\_tags](#input\_component\_tags) | Additional tags for Components (s3, kms, ddb) | `map(map(string))` |
{
"ddb": {},
"kms": {},
"s3": {}
}
| 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\_policy\_document](#input\_kms\_policy\_document) | AWS KMS Key Policy Document JSON, merged with admin policy document | `string` | `null` | no | +| [name](#input\_name) | Name to apply to Cloudtrail KMS Key (default: k-inf-cloudtrail) | `string` | `null` | 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) | 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\_aliase\_nam](#output\_kms\_aliase\_nam) | Cloudtrail Key Alias name | +| [kms\_key\_arn](#output\_kms\_key\_arn) | Cloudtrail Key ARN | +| [kms\_key\_id](#output\_kms\_key\_id) | Cloudtrail Key ID | diff --git a/cloudtrail-key/base_tags.tf b/cloudtrail-key/base_tags.tf new file mode 100644 index 0000000..602b87a --- /dev/null +++ b/cloudtrail-key/base_tags.tf @@ -0,0 +1,6 @@ +locals { + base_tags = { + "boc:tf_module_version" = local._module_version + "boc:created_by" = "terraform" + } +} diff --git a/cloudtrail-key/data.tf b/cloudtrail-key/data.tf new file mode 120000 index 0000000..995624d --- /dev/null +++ b/cloudtrail-key/data.tf @@ -0,0 +1 @@ +../common/data.tf \ No newline at end of file diff --git a/cloudtrail-key/defaults.tf b/cloudtrail-key/defaults.tf new file mode 120000 index 0000000..a5556ac --- /dev/null +++ b/cloudtrail-key/defaults.tf @@ -0,0 +1 @@ +../common/defaults.tf \ No newline at end of file diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf new file mode 100644 index 0000000..088adbf --- /dev/null +++ b/cloudtrail-key/main.tf @@ -0,0 +1,218 @@ +/* +* # aws-inf-setup :: cloudtrail-keys +* +* This set up the KMS key used by Cloudtrail for the ts S3 bucket, CloudTrail, and SQS (if possible). +* +* * Cloudtrail +* * S3 bucket +* * SQS +* +* ## Usage, Simple Example +* Here is a simple example, the one most commonly expected to be used. +* +* ```hcl +* module "cloudtrail_key_simple" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" +* +* tags = { +* Environment = "csvd:infrastructure" +* } +* } +* ``` +* +* ## Usage, Longer Example +* 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_key_full" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" +* +* name = "mycloudtrail" +* kms_admin_roles = ["arn:aws:iam::079788916859:role/r-inf-cloud-admin"] +* kms_policy_document = data.aws_iam_policy_document.myct_policy.json +* +* tags = { +* Environment = "csvd:infrastructure" +* } +* +* component_tags = { +* "kms" = { +* "SpecialTag1" = "something" +* "SpecialTag2" = "somethingElse" +* } +* } +* } +* ``` +*/ + +locals { + # basic details about the env + 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 + + name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name + kms_key_name = format("k-%v", 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 + +} + +resource "aws_kms_key" "key" { + description = "KMS CMK for cloudtrail" + enable_key_rotation = true + policy = data.aws_iam_policy_document.key_policy_combined.json + + tags = merge( + local.base_tags, + var.tags, + map("boc:aws:region", local.region), + 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 +} + +data "aws_iam_policy_document" "key_policy_combined" { + source_policy_documents = [ + data.aws_iam_policy_document.key.json, + data.aws_iam_policy_document.key_admin.json, + local.kms_policy_document + ] +} + +data "aws_iam_policy_document" "key" { + policy_id = "Cloudtrail KMS Access" + statement { + sid = "EnableIAMUserPermissions" + effect = "Allow" + actions = ["kms:*"] + resources = ["*"] + principals { + type = "AWS" + identifiers = [local.kms_admin_root] + } + } + statement { + sid = "AllowCloudTrailEncryptLogs" + effect = "Allow" + actions = ["kms:GenerateDataKey*"] + resources = ["*"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com", "logs.amazonaws.com", "logs.${local.region}.amazonaws.com"] + } + condition { + test = "StringLike" + variable = "kms:EncryptionContext:aws:cloudtrail:arn" + # values = [format("arn:%v:cloudtrail:%v:%v:trail/*",local.partition,local.region,local.account_id] + values = [format("arn:%v:cloudtrail:*:%v:trail/*", local.partition, local.account_id)] + } + } + 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 = [format("arn:%v:cloudtrail:%v:%v:trail/*",local.partition,local.region,local.account_id] + values = [format("arn:%v:cloudtrail:*:%v:trail/*", local.partition, local.account_id)] + } + } + 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 = [format("arn:%v:cloudtrail:%v:%v:trail/*",local.partition,local.region,local.account_id] + values = [format("arn:%v:cloudtrail:*:%v:trail/*", local.partition, local.account_id)] + } + } + 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 = [format("ec2.%v.amazonaws.com", local.region)] + } + } +} + +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" "empty" {} diff --git a/cloudtrail-key/outputs.tf b/cloudtrail-key/outputs.tf new file mode 100644 index 0000000..bb73d2e --- /dev/null +++ b/cloudtrail-key/outputs.tf @@ -0,0 +1,14 @@ +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 +} + +output "kms_aliase_nam" { + description = "Cloudtrail Key Alias name" + value = aws_kms_alias.key.arn +} diff --git a/cloudtrail-key/prefixes.tf b/cloudtrail-key/prefixes.tf new file mode 120000 index 0000000..7e265d5 --- /dev/null +++ b/cloudtrail-key/prefixes.tf @@ -0,0 +1 @@ +../common/prefixes.tf \ No newline at end of file diff --git a/cloudtrail-key/variables.common.tf b/cloudtrail-key/variables.common.tf new file mode 120000 index 0000000..7439ed8 --- /dev/null +++ b/cloudtrail-key/variables.common.tf @@ -0,0 +1 @@ +../common/variables.common.tf \ No newline at end of file diff --git a/cloudtrail-key/variables.tf b/cloudtrail-key/variables.tf new file mode 100644 index 0000000..9f58d60 --- /dev/null +++ b/cloudtrail-key/variables.tf @@ -0,0 +1,23 @@ +variable "name" { + description = "Name to apply to Cloudtrail KMS Key (default: k-inf-cloudtrail)" + type = string + default = null +} + +variable "kms_policy_document" { + description = "AWS KMS Key Policy Document JSON, merged with admin policy document" + type = string + default = null +} + +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 "component_tags" { + description = "Additional tags for Components (s3, kms, ddb)" + type = map(map(string)) + default = { "s3" = {}, "kms" = {}, "ddb" = {} } +} diff --git a/cloudtrail-key/version.tf b/cloudtrail-key/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/cloudtrail-key/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file diff --git a/common/version.tf b/common/version.tf index 0d97837..cf6531c 100644 --- a/common/version.tf +++ b/common/version.tf @@ -1,3 +1,3 @@ locals { - _module_version = "1.13.2" + _module_version = "1.14.0" } diff --git a/examples/cloudtrail-key/cloudtrail_key_full.tf b/examples/cloudtrail-key/cloudtrail_key_full.tf new file mode 100644 index 0000000..a1fdd69 --- /dev/null +++ b/examples/cloudtrail-key/cloudtrail_key_full.tf @@ -0,0 +1,18 @@ +module "cloudtrail_key_full" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" + + name = "mycloudtrail" + kms_admin_roles = ["arn:aws:iam::079788916859:role/r-inf-cloud-admin"] + kms_policy_document = data.aws_iam_policy_document.myct_policy.json + + tags = { + Environment = "csvd:infrastructure" + } + + component_tags = { + "kms" = { + "SpecialTag1" = "something" + "SpecialTag2" = "somethingElse" + } + } +} diff --git a/examples/cloudtrail-key/cloudtrail_key_simple.tf b/examples/cloudtrail-key/cloudtrail_key_simple.tf new file mode 100644 index 0000000..c5124d2 --- /dev/null +++ b/examples/cloudtrail-key/cloudtrail_key_simple.tf @@ -0,0 +1,7 @@ +module "cloudtrail_key_simple" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" + + tags = { + Environment = "csvd:infrastructure" + } +} From be8bee9eeb607d9da8339230ffd28e79ee2aa3ae Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 12:51:38 -0500 Subject: [PATCH 06/59] update kms_admin_root --- cloudtrail-key/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf index 088adbf..0f9bf43 100644 --- a/cloudtrail-key/main.tf +++ b/cloudtrail-key/main.tf @@ -56,8 +56,8 @@ locals { name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name kms_key_name = format("k-%v", 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_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 } From aa233ae9ee68d19eb9b185228cb7b33df90916df Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 12:53:02 -0500 Subject: [PATCH 07/59] fix policy doc --- cloudtrail-key/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf index 0f9bf43..a76b2af 100644 --- a/cloudtrail-key/main.tf +++ b/cloudtrail-key/main.tf @@ -58,7 +58,7 @@ locals { kms_key_name = format("k-%v", 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 + kms_policy_document = var.kms_policy_document != null ? var.kms_policy_document : data.aws_iam_policy_document.empty.json } From 82a4186e049b19310a834eef4d9131f8676916e2 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 13:10:29 -0500 Subject: [PATCH 08/59] add files (initial) --- cloudtrail/README.md | 97 ++++++++ cloudtrail/TODO | 10 + cloudtrail/base_tags.tf | 1 + cloudtrail/cloudtrail.tf.off | 20 ++ cloudtrail/data.policies.tf | 31 +++ cloudtrail/data.tf | 1 + cloudtrail/defaults.tf | 1 + cloudtrail/edl.cloudtrail.sns.txt | 179 +++++++++++++++ cloudtrail/edl.cloudtrail.txt | 342 +++++++++++++++++++++++++++++ cloudtrail/main.tf | 174 +++++++++++++++ cloudtrail/prefixes.tf | 1 + cloudtrail/role.tf | 141 ++++++++++++ cloudtrail/s3.tf2 | 57 +++++ cloudtrail/stuff | 353 ++++++++++++++++++++++++++++++ cloudtrail/variables.common.tf | 1 + cloudtrail/variables.tf | 69 ++++++ cloudtrail/version.tf | 1 + 17 files changed, 1479 insertions(+) create mode 100644 cloudtrail/README.md create mode 100644 cloudtrail/TODO create mode 120000 cloudtrail/base_tags.tf create mode 100644 cloudtrail/cloudtrail.tf.off create mode 100644 cloudtrail/data.policies.tf create mode 120000 cloudtrail/data.tf create mode 120000 cloudtrail/defaults.tf create mode 100644 cloudtrail/edl.cloudtrail.sns.txt create mode 100644 cloudtrail/edl.cloudtrail.txt create mode 100644 cloudtrail/main.tf create mode 120000 cloudtrail/prefixes.tf create mode 100644 cloudtrail/role.tf create mode 100644 cloudtrail/s3.tf2 create mode 100644 cloudtrail/stuff create mode 120000 cloudtrail/variables.common.tf create mode 100644 cloudtrail/variables.tf create mode 120000 cloudtrail/version.tf diff --git a/cloudtrail/README.md b/cloudtrail/README.md new file mode 100644 index 0000000..a5f32ab --- /dev/null +++ b/cloudtrail/README.md @@ -0,0 +1,97 @@ +# 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.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | +| [aws_cloudtrail.trail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | +| [aws_cloudwatch_log_group.inf-cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_policy.cloudtrail_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_kms_key.cloudtrail_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_s3_bucket.trail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | 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.cloudtrail_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.cloudtrail_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | 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.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 | +| [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) | 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 + +No outputs. diff --git a/cloudtrail/TODO b/cloudtrail/TODO new file mode 100644 index 0000000..adc6571 --- /dev/null +++ b/cloudtrail/TODO @@ -0,0 +1,10 @@ +- cloudtrail +- cloudtrail key +- cloudwatch log stream +- s3 bucket +- s3 bucket policy +- iam role +- sqs +- sns + + diff --git a/cloudtrail/base_tags.tf b/cloudtrail/base_tags.tf new file mode 120000 index 0000000..91c15aa --- /dev/null +++ b/cloudtrail/base_tags.tf @@ -0,0 +1 @@ +../common/base_tags.tf \ No newline at end of file diff --git a/cloudtrail/cloudtrail.tf.off b/cloudtrail/cloudtrail.tf.off new file mode 100644 index 0000000..2614c6e --- /dev/null +++ b/cloudtrail/cloudtrail.tf.off @@ -0,0 +1,20 @@ + +#--- +# 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] +} diff --git a/cloudtrail/data.policies.tf b/cloudtrail/data.policies.tf new file mode 100644 index 0000000..e092555 --- /dev/null +++ b/cloudtrail/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/data.tf b/cloudtrail/data.tf new file mode 120000 index 0000000..995624d --- /dev/null +++ b/cloudtrail/data.tf @@ -0,0 +1 @@ +../common/data.tf \ No newline at end of file diff --git a/cloudtrail/defaults.tf b/cloudtrail/defaults.tf new file mode 120000 index 0000000..a5556ac --- /dev/null +++ b/cloudtrail/defaults.tf @@ -0,0 +1 @@ +../common/defaults.tf \ No newline at end of file diff --git a/cloudtrail/edl.cloudtrail.sns.txt b/cloudtrail/edl.cloudtrail.sns.txt new file mode 100644 index 0000000..381f530 --- /dev/null +++ b/cloudtrail/edl.cloudtrail.sns.txt @@ -0,0 +1,179 @@ +#--- +# sns: cloudtrail, one global one (us-gov-east-1) +#--- +resource "aws_sns_topic" "cloudtrail" { + name = "inf-cloudtrail" + display_name = "DO3MA3GC" +} + +resource "aws_sns_topic_policy" "cloudtrail" { + arn = aws_sns_topic.cloudtrail.arn + policy = data.aws_iam_policy_document.cloudtrail_topic.json +} + +data "aws_iam_policy_document" "cloudtrail_topic" { + policy_id = "inf-cloudtrail_topic" + + statement { + sid = "CloudtrailSNSPermissions" + effect = "Allow" + + principals { + type = "AWS" + identifiers = ["*"] + } + + actions = [ + "sns:Subscribe", + "sns:SetTopicAttributes", + "sns:RemovePermission", + "sns:Receive", + "sns:Publish", + "sns:ListSubscriptionsByTopic", + "sns:GetTopicAttributes", + "sns:DeleteTopic", + "sns:AddPermission", + ] + + condition { + test = "StringEquals" + variable = "AWS:SourceOwner" + values = [var.account_id] + } + + resources = [aws_sns_topic.cloudtrail.arn] + } + + statement { + sid = "CloudTrailSNSPolicy" + effect = "Allow" + + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + + actions = ["sns:Publish"] + resources = [aws_sns_topic.cloudtrail.arn] + } +} + + +#--- +# sqs (from splunk) +#--- +# one per region we are using +#--- +# cloudtrail +#--- +resource "aws_sqs_queue" "cloudtrail_deadletter" { + # delay=0 retention=4d max=256k visibility=1h + count = length(var.regions) + name = "inf-cloudtrail-${var.regions[count.index]}-deadletter" + delay_seconds = 0 + max_message_size = 262144 + message_retention_seconds = 345600 + receive_wait_time_seconds = 15 + visibility_timeout_seconds = 3600 + + # disable kms, doesn't seem to work with splunk + # kms_master_key_id = "alias/${var.kms_inf_key}" + # kms_data_key_reuse_period_seconds = 300 + + tags = merge( + local.common_tags, + map("Name", "inf-cloudtrail-${var.regions[count.index]}-deadletter"), + ) +} + +resource "aws_sqs_queue_policy" "cloudtrail_deadletter" { + count = length(var.regions) + queue_url = aws_sqs_queue.cloudtrail_deadletter[count.index].id + policy = data.aws_iam_policy_document.cloudtrail_deadletter[count.index].json +} + +data "aws_iam_policy_document" "cloudtrail_deadletter" { + count = length(var.regions) + policy_id = "SQSDefaultPolicy" + + statement { + sid = "AllowSNSSendMessage" + effect = "Allow" + actions = ["SQS:SendMessage"] + resources = [aws_sqs_queue.cloudtrail_deadletter[count.index].arn] + + principals { + type = "AWS" + identifiers = ["*"] + } + + condition { + test = "ArnEquals" + variable = "aws:SourceArn" + values = [aws_sns_topic.cloudtrail.arn] + } + } +} + +resource "aws_sqs_queue" "cloudtrail" { + # delay=0 retention=7d max=256k visibity=2h + count = length(var.regions) + name = "inf-cloudtrail-${var.regions[count.index]}" + delay_seconds = 0 + max_message_size = 262144 + message_retention_seconds = 604800 + receive_wait_time_seconds = 15 + visibility_timeout_seconds = 7200 + + redrive_policy = < Date: Mon, 15 Nov 2021 14:09:57 -0500 Subject: [PATCH 09/59] fix --- cloudtrail/README.md | 10 +- cloudtrail/cloudtrail.tf | 20 ++++ cloudtrail/cloudwatch.tf | 29 +++++ cloudtrail/kms.tf.off | 166 +++++++++++++++++++++++++++++ cloudtrail/main.tf | 112 +------------------ cloudtrail/s3-bucket-policy.tf.off | 31 ++++++ cloudtrail/s3.tf | 88 +++++++++++++++ cloudtrail/s3.tf.off | 92 ++++++++++++++++ cloudtrail/variables.tf | 5 + 9 files changed, 441 insertions(+), 112 deletions(-) create mode 100644 cloudtrail/cloudtrail.tf create mode 100644 cloudtrail/cloudwatch.tf create mode 100644 cloudtrail/kms.tf.off create mode 100644 cloudtrail/s3-bucket-policy.tf.off create mode 100644 cloudtrail/s3.tf create mode 100644 cloudtrail/s3.tf.off diff --git a/cloudtrail/README.md b/cloudtrail/README.md index a5f32ab..37b4092 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -58,21 +58,24 @@ No modules. | Name | Type | |------|------| | [aws_cloudtrail.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | -| [aws_cloudtrail.trail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | +| [aws_cloudtrail.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | | [aws_cloudwatch_log_group.inf-cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_iam_policy.cloudtrail_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_kms_key.cloudtrail_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | -| [aws_s3_bucket.trail](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.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](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cloudtrail_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cloudtrail_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | 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.policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.cloudwatch_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_kms_key.incoming_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_key) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs @@ -87,6 +90,7 @@ No modules. | [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\_arn](#input\_kms\_key\_arn) | AWS CloudTrail KMS ARN to be used for encrypting the ClouldTrail, S3 Bucket, and SQS | `string` | n/a | yes | | [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 | | [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 | diff --git a/cloudtrail/cloudtrail.tf b/cloudtrail/cloudtrail.tf new file mode 100644 index 0000000..2661a1c --- /dev/null +++ b/cloudtrail/cloudtrail.tf @@ -0,0 +1,20 @@ +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 = true + is_multi_region_trail = false + enable_log_file_validation = true + enable_logging = true + kms_key_id = var.kms_key_arn + # sns_topic_name = aws_sns_topic.cloudtrail.arn + # cloud_watch_logs_group_arn = aws_cloudwatch_log_group.inf-cloudtrail.arn + # cloud_watch_logs_role_arn = aws_iam_role.inf-cloudtrail.arn + + tags = merge( + local.base_tags, + var.tags, + { "Name" = local.name }, + ) + depends_on = [aws_s3_bucket_policy.bucket_policy] +} diff --git a/cloudtrail/cloudwatch.tf b/cloudtrail/cloudwatch.tf new file mode 100644 index 0000000..f885d17 --- /dev/null +++ b/cloudtrail/cloudwatch.tf @@ -0,0 +1,29 @@ +data "aws_iam_policy_document" "cloudwatch_policy" { + statement { + sid = "AWSCloudTrailCreateLogStream" + effect = "Allow" + actions = ["logs:CreateLogStream"] + resources = [local.cloudwatch_resources] + } + + statement { + sid = "AWSCloudTrailPutLogEvents" + effect = "Allow" + actions = ["logs:PutLogEvents"] + resources = [local.cloudwatch_resources] + } +} + +resource "aws_cloudwatch_log_group" "this" { + name = local.name + + # kms_key_id = var.kms_key_id + # kms_key_id = var.kms_key_arn + kms_key_id = data.aws_kms_key.incoming_key.id + retention_in_days = 7 + + tags = merge( + local.common_tags, + map("Name", local.name), + ) +} diff --git a/cloudtrail/kms.tf.off b/cloudtrail/kms.tf.off new file mode 100644 index 0000000..63f49fa --- /dev/null +++ b/cloudtrail/kms.tf.off @@ -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/main.tf b/cloudtrail/main.tf index 1157b2a..e6df390 100644 --- a/cloudtrail/main.tf +++ b/cloudtrail/main.tf @@ -55,120 +55,14 @@ locals { partition = data.aws_arn.current.partition name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name - kms_key_arn = var.kms_key_arn kms_key_name = format("k-%v", 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_admin_roles = compact(concat([var.kms_admin_root], var.kms_admin_roles)) kms_policy_document = var.kms_policy_document != null ? var.kms_policy_document : data.aws_iam_policy_document.empty.json bucket_name = var.name == null ? format("%v-%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.account_id, local.region) : var.name } - -resource "aws_cloudtrail" "trail" { - name = local.name - s3_bucket_name = aws_s3_bucket.trail.id - s3_key_prefix = var.cloudtrail_bucket_prefix - include_global_service_events = rue - is_multi_region_trail = false - kms_key_id = local.kms_key_arn - enable_log_file_validation = true - - tags = merge( - local.base_tags, - var.tags, - { "Name" = local.name }, - ) - depends_on = [aws_s3_bucket_policy.policy] -} - - -resource "aws_s3_bucket" "trail" { - bucket = local.bucket_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.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" - } +data "aws_kms_key" "incoming_key" { + key_id = var.kms_key_arn } diff --git a/cloudtrail/s3-bucket-policy.tf.off b/cloudtrail/s3-bucket-policy.tf.off new file mode 100644 index 0000000..e092555 --- /dev/null +++ b/cloudtrail/s3-bucket-policy.tf.off @@ -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/s3.tf b/cloudtrail/s3.tf new file mode 100644 index 0000000..134b874 --- /dev/null +++ b/cloudtrail/s3.tf @@ -0,0 +1,88 @@ +resource "aws_s3_bucket" "this" { + bucket = local.bucket_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 = var.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" "bucket_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 = [format("%v/%v/*", 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.bucket_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 + } + provisioner "local-exec" { + when = create + command = "sleep 180" + } +} diff --git a/cloudtrail/s3.tf.off b/cloudtrail/s3.tf.off new file mode 100644 index 0000000..dc5ee5b --- /dev/null +++ b/cloudtrail/s3.tf.off @@ -0,0 +1,92 @@ +#--- +# 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" + } +} diff --git a/cloudtrail/variables.tf b/cloudtrail/variables.tf index b8cb955..3775f86 100644 --- a/cloudtrail/variables.tf +++ b/cloudtrail/variables.tf @@ -49,6 +49,11 @@ variable "kms_key_management_identifiers" { default = [] } +variable "kms_key_arn" { + description = "AWS CloudTrail KMS ARN to be used for encrypting the ClouldTrail, S3 Bucket, and SQS" + type = string +} + variable "enable_sns" { description = "Flag to enable or disable the creation of SNS for Cloudtrail (TBD)" type = bool From a6c3b99175ec3d7cecaf6b836cad015cbe9b2600 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 14:10:49 -0500 Subject: [PATCH 10/59] update base --- cloudtrail-key/base_tags.tf | 7 +------ common/base_tags.tf | 6 ++++++ 2 files changed, 7 insertions(+), 6 deletions(-) mode change 100644 => 120000 cloudtrail-key/base_tags.tf create mode 100644 common/base_tags.tf diff --git a/cloudtrail-key/base_tags.tf b/cloudtrail-key/base_tags.tf deleted file mode 100644 index 602b87a..0000000 --- a/cloudtrail-key/base_tags.tf +++ /dev/null @@ -1,6 +0,0 @@ -locals { - base_tags = { - "boc:tf_module_version" = local._module_version - "boc:created_by" = "terraform" - } -} diff --git a/cloudtrail-key/base_tags.tf b/cloudtrail-key/base_tags.tf new file mode 120000 index 0000000..91c15aa --- /dev/null +++ b/cloudtrail-key/base_tags.tf @@ -0,0 +1 @@ +../common/base_tags.tf \ No newline at end of file diff --git a/common/base_tags.tf b/common/base_tags.tf new file mode 100644 index 0000000..602b87a --- /dev/null +++ b/common/base_tags.tf @@ -0,0 +1,6 @@ +locals { + base_tags = { + "boc:tf_module_version" = local._module_version + "boc:created_by" = "terraform" + } +} From 541359b08c73b5682017d4e846067b85048b40bf Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 14:13:37 -0500 Subject: [PATCH 11/59] remove role --- cloudtrail/role.tf | 141 --------------------------------------------- 1 file changed, 141 deletions(-) delete mode 100644 cloudtrail/role.tf diff --git a/cloudtrail/role.tf b/cloudtrail/role.tf deleted file mode 100644 index c443d4e..0000000 --- a/cloudtrail/role.tf +++ /dev/null @@ -1,141 +0,0 @@ -locals { - cloudwatch_prefix = replace(aws_cloudwatch_log_group.inf-cloudtrail.arn, "/:\\*$/", "") - cloudwatch_suffix = "${var.account_id}_CloudTrail_${var.region}*" - cloudwatch_resources = join(":", list(local.cloudwatch_prefix, "log-stream", local.cloudwatch_suffix)) - cloudtrail_policies = list(data.terraform_remote_state.common.outputs.policy_deny_billing_arn, aws_iam_policy.inf-cloudtrail.arn) - cloudtrail_bucket_arn = aws_s3_bucket.cloudtrail.arn - - cloudtrail_role_name = format("%v%v", local._prefixes["role"], local.role_name) - cloudtrail_policy_name = format("%v%v", local._prefixes["policy"], local.role_name) - -} - -resource "aws_iam_role" "cloudtrail" { - name = local.cloudtrail_role_name - assume_role_policy = data.aws_iam_policy_document.cloudtrail_assume.json - description = "AWS CloudTrail Role for ${local.region}" - force_detach_policies = false - max_session_duration = 3600 - # add deny billing - attached_policies = [aws_iam_policy.cloudtrail_policy.arn] - path = "/" - - tags = merge( - local.base_tags, - var.tags, - ) -} - - -data "aws_iam_policy_document" "cloudtrail_assume" { - statement { - sid = "AWSCloudTrailServiceAssumeRole" - effect = "Allow" - actions = ["sts:AssumeRole"] - - principals { - type = "Service" - identifiers = ["cloudtrail.amazonaws.com"] - } - } -} - -resource "aws_iam_policy" "cloudtrail_policy" { - name = local.cloudtrail_policy_name - policy = data.aws_iam_policy_document.cloudtrail_cloudwatch.json -} - - -resource "aws_kms_key" "cloudtrail_key" { - description = "encrypt inf-cloudtrail objects and streams" - enable_key_rotation = true - policy = data.aws_iam_policy_document.cloudtrail_key.json - - tags = merge( - local.common_tags, - map("Name", var.kms_cloudtrail_key) - ) -} - -data "aws_iam_policy_document" "cloudtrail_cloudwatch" { - statement { - sid = "AWSCloudTrailCreateLogStream" - effect = "Allow" - actions = ["logs:CreateLogStream"] - resources = [local.cloudwatch_resources] - } - - statement { - sid = "AWSCloudTrailPutLogEvents" - effect = "Allow" - actions = ["logs:PutLogEvents"] - resources = [local.cloudwatch_resources] - } -} - -resource "aws_cloudtrail" "cloudtrail" { - name = "inf-cloudtrail" - s3_bucket_name = aws_s3_bucket.cloudtrail.id - - # s3_key_prefix = - include_global_service_events = true - is_multi_region_trail = true - enable_log_file_validation = true - enable_logging = true - - kms_key_id = aws_kms_key.cloudtrail_key.arn - sns_topic_name = aws_sns_topic.cloudtrail.arn - cloud_watch_logs_group_arn = aws_cloudwatch_log_group.inf-cloudtrail.arn - cloud_watch_logs_role_arn = aws_iam_role.inf-cloudtrail.arn - - tags = merge( - local.common_tags, - { - "Project Role" = local.project_role["inf"] - }, - map("Name", "inf-cloudtrail-cloudwatch"), - ) -} - -resource "aws_cloudwatch_log_group" "inf-cloudtrail" { - name = "inf-cloudtrail" - - # kms_key_id = aws_kms_key.cloudtrail_key.arn - retention_in_days = 7 - - tags = merge( - local.common_tags, - map("Name", "inf-cloudtrail-cloudwatch-log"), - ) -} - -## # add this later after creating additional buckets for applications -## # or, create an app-specific bucket for the cloudtrail logs -## resource "aws_cloudtrail" "inf-cloudtrail-s3" { -## name = "inf-cloudtrail-s3" -## s3_bucket_name = aws_s3_bucket.cloudtrail.id -## s3_key_prefix = "inf-s3" -## -## include_global_service_events = true -## is_multi_region_trail = true -## enable_log_file_validation = true -## enable_logging = true -## -## kms_key_id = aws_kms_key.cloudtrail_key.arn -## -## tags = merge( -## local.common_tags, -## map("Name", "inf-cloudtrail-s3"), -## ) -## -## event_selector { -## read_write_type = "All" -## include_management_events = true -## -## data_resource { -## type = "AWS::S3::Object" -## values = [ "${aws_s3_bucket.edl-poc-dl-versioned.arn}/" ] -## } -## } -## } -## From 158c55ded0d8c220909e9d1ea1c1ffe5f2fe629d Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 14:26:26 -0500 Subject: [PATCH 12/59] fix --- cloudtrail/README.md | 7 ------- cloudtrail/main.tf | 10 +++++----- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/cloudtrail/README.md b/cloudtrail/README.md index 37b4092..9aae33a 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -57,13 +57,8 @@ No modules. | Name | Type | |------|------| -| [aws_cloudtrail.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | | [aws_cloudtrail.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | -| [aws_cloudwatch_log_group.inf-cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_iam_policy.cloudtrail_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_role.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_kms_key.cloudtrail_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_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 | @@ -71,8 +66,6 @@ No modules. | [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](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.cloudtrail_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.cloudtrail_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | 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.cloudwatch_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_kms_key.incoming_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_key) | data source | diff --git a/cloudtrail/main.tf b/cloudtrail/main.tf index e6df390..5822348 100644 --- a/cloudtrail/main.tf +++ b/cloudtrail/main.tf @@ -54,11 +54,11 @@ locals { account_environment = data.aws_arn.current.partition == "aws-us-gov" ? "gov" : "ew" partition = data.aws_arn.current.partition - name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name - kms_key_name = format("k-%v", local.name) - kms_admin_root = format("arn:%v:iam::%v:root", local.partition, local.account_id) - kms_admin_roles = compact(concat([var.kms_admin_root], var.kms_admin_roles)) - kms_policy_document = var.kms_policy_document != null ? var.kms_policy_document : data.aws_iam_policy_document.empty.json + name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name + kms_key_name = format("k-%v", local.name) + kms_admin_root = format("arn:%v:iam::%v:root", local.partition, local.account_id) + # kms_admin_roles = compact(concat([var.kms_admin_root], var.kms_admin_roles)) + # kms_policy_document = var.kms_policy_document != null ? var.kms_policy_document : data.aws_iam_policy_document.empty.json bucket_name = var.name == null ? format("%v-%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.account_id, local.region) : var.name } From 66fef813292675ce79f7b51cac5ebdfd30051452 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 14:27:00 -0500 Subject: [PATCH 13/59] fix --- cloudtrail/data.policies.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail/data.policies.tf b/cloudtrail/data.policies.tf index e092555..7a99e9c 100644 --- a/cloudtrail/data.policies.tf +++ b/cloudtrail/data.policies.tf @@ -2,7 +2,7 @@ data "aws_iam_policy_document" "cloudtrail_s3" { statement { sid = "AWSCloudTrailWrite" effect = "Allow" - resources = ["${aws_s3_bucket.cloudtrail.arn}/*"] + resources = ["${aws_s3_bucket.this.arn}/*"] actions = ["s3:PutObject"] principals { @@ -20,7 +20,7 @@ data "aws_iam_policy_document" "cloudtrail_s3" { statement { sid = "AWSCloudTrailAclCheck" effect = "Allow" - resources = [aws_s3_bucket.cloudtrail.arn] + resources = [aws_s3_bucket.this.arn] actions = ["s3:GetBucketAcl"] principals { From ee78dd620a4a3a26c7b55e9a36f3c13870388d92 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 15 Nov 2021 16:10:51 -0500 Subject: [PATCH 14/59] update --- cloudtrail/cloudwatch.tf | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cloudtrail/cloudwatch.tf b/cloudtrail/cloudwatch.tf index f885d17..6d2b6d3 100644 --- a/cloudtrail/cloudwatch.tf +++ b/cloudtrail/cloudwatch.tf @@ -1,3 +1,9 @@ +locals { + cloudwatch_prefix = replace(aws_cloudwatch_log_group.this.arn, "/:\\*$/", "") + cloudwatch_suffix = format("%v_CloudTrail_%v", local.account_id, local.region) + cloudwatch_resources = join(":", list(local.cloudwatch_prefix, "log-stream", local.cloudwatch_suffix)) +} + data "aws_iam_policy_document" "cloudwatch_policy" { statement { sid = "AWSCloudTrailCreateLogStream" @@ -23,7 +29,8 @@ resource "aws_cloudwatch_log_group" "this" { retention_in_days = 7 tags = merge( - local.common_tags, + local.base_tags, + var.tags, map("Name", local.name), ) } From 4d5dc8ccadaf5a45b4badbd3032830a73311b574 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 10:49:32 -0500 Subject: [PATCH 15/59] fix --- cloudtrail/cloudtrail.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail/cloudtrail.tf b/cloudtrail/cloudtrail.tf index 2661a1c..b231279 100644 --- a/cloudtrail/cloudtrail.tf +++ b/cloudtrail/cloudtrail.tf @@ -16,5 +16,5 @@ resource "aws_cloudtrail" "this" { var.tags, { "Name" = local.name }, ) - depends_on = [aws_s3_bucket_policy.bucket_policy] + depends_on = [aws_s3_bucket_policy.policy] } From 864e4207792ddee878063e77447ccdebb2faf2cb Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 10:53:23 -0500 Subject: [PATCH 16/59] fix --- cloudtrail-key/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf index a76b2af..5489854 100644 --- a/cloudtrail-key/main.tf +++ b/cloudtrail-key/main.tf @@ -55,7 +55,7 @@ locals { partition = data.aws_arn.current.partition name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name - kms_key_name = format("k-%v", local.name) + kms_key_name = format("%v%v", local._defaults["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 = var.kms_policy_document != null ? var.kms_policy_document : data.aws_iam_policy_document.empty.json @@ -71,7 +71,7 @@ resource "aws_kms_key" "key" { local.base_tags, var.tags, map("boc:aws:region", local.region), - map("Name", local.kms_key_name), + map("Name", local.name), ) } From 9381371f69843d70fa5078a0731d0edfe18b7c76 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 10:56:05 -0500 Subject: [PATCH 17/59] fix --- cloudtrail-key/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf index 5489854..6b780e4 100644 --- a/cloudtrail-key/main.tf +++ b/cloudtrail-key/main.tf @@ -55,7 +55,7 @@ locals { partition = data.aws_arn.current.partition name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name - kms_key_name = format("%v%v", local._defaults["kms"], local.name) + kms_key_name = format("%v%v", 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 = var.kms_policy_document != null ? var.kms_policy_document : data.aws_iam_policy_document.empty.json From 433ae6ecdbf30918ff4e8bd6d9992914a8b58aef Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 11:45:33 -0500 Subject: [PATCH 18/59] setup for enable_sns --- cloudtrail/README.md | 10 +++++ cloudtrail/sns.tf | 54 +++++++++++++++++++++++++ cloudtrail/sqs.tf | 96 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 cloudtrail/sns.tf create mode 100644 cloudtrail/sqs.tf diff --git a/cloudtrail/README.md b/cloudtrail/README.md index 9aae33a..b2daffb 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -62,11 +62,21 @@ No modules. | [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | 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 | +| [aws_sns_topic.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | +| [aws_sns_topic_policy.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource | +| [aws_sns_topic_subscription.cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | +| [aws_sqs_queue.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_sqs_queue.cloudtrail_deadletter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_sqs_queue_policy.cloudtrail_deadletter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | +| [aws_sqs_queue_policy.cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | 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](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.cloudtrail_deadletter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | 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.cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.cloudtrail_topic](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cloudwatch_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_kms_key.incoming_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_key) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | diff --git a/cloudtrail/sns.tf b/cloudtrail/sns.tf new file mode 100644 index 0000000..e511782 --- /dev/null +++ b/cloudtrail/sns.tf @@ -0,0 +1,54 @@ +resource "aws_sns_topic" "cloudtrail" { + count = var.enable_sns ? 1 : 0 + name = local.name + + tags = merge( + local.base_tags, + local.tags + ) +} + +resource "aws_sns_topic_policy" "cloudtrail" { + count = var.enable_sns ? 1 : 0 + arn = aws_sns_topic.cloudtrail.arn + policy = data.aws_iam_policy_document.cloudtrail_topic.json +} + +data "aws_iam_policy_document" "cloudtrail_topic" { + policy_id = format("%v_topic", local.name) + statement { + sid = "CloudtrailSNSPermissions" + effect = "Allow" + principals { + type = "AWS" + identifiers = ["*"] + } + actions = [ + "sns:Subscribe", + "sns:SetTopicAttributes", + "sns:RemovePermission", + "sns:Receive", + "sns:Publish", + "sns:ListSubscriptionsByTopic", + "sns:GetTopicAttributes", + "sns:DeleteTopic", + "sns:AddPermission", + ] + condition { + test = "StringEquals" + variable = "AWS:SourceOwner" + values = [loal.account_id] + } + resources = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null] + } + statement { + sid = "CloudTrailSNSPolicy" + effect = "Allow" + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + actions = ["sns:Publish"] + resources = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null] + } +} diff --git a/cloudtrail/sqs.tf b/cloudtrail/sqs.tf new file mode 100644 index 0000000..a5b3840 --- /dev/null +++ b/cloudtrail/sqs.tf @@ -0,0 +1,96 @@ +resource "aws_sqs_queue" "cloudtrail_deadletter" { + # delay=0 retention=4d max=256k visibility=1h + name = format("%v-deadletter", local.name) + delay_seconds = 0 + max_message_size = 262144 + message_retention_seconds = 345600 + receive_wait_time_seconds = 15 + visibility_timeout_seconds = 3600 + + kms_master_key_id = data.aws_kms_key.incoming_key.id + kms_data_key_reuse_period_seconds = 300 + + tags = merge( + local.base_tags, + var.tags, + map("Name", format("%v-deadletter", local.name)), + ) +} + +resource "aws_sqs_queue_policy" "cloudtrail_deadletter" { + queue_url = aws_sqs_queue.cloudtrail_deadletter.id + policy = data.aws_iam_policy_document.cloudtrail_deadletter.json +} + +data "aws_iam_policy_document" "cloudtrail_deadletter" { + policy_id = "SQSDefaultPolicy" + statement { + sid = "AllowSNSSendMessage" + effect = "Allow" + actions = ["SQS:SendMessage"] + resources = [aws_sqs_queue.cloudtrail_deadletter.arn] + principals { + type = "AWS" + identifiers = ["*"] + } + condition { + test = "ArnEquals" + variable = "aws:SourceArn" + values = [aws_sns_topic.cloudtrail.arn] + } + } +} + +resource "aws_sqs_queue" "cloudtrail" { + # delay=0 retention=7d max=256k visibity=2h + name = local.name + delay_seconds = 0 + max_message_size = 262144 + message_retention_seconds = 604800 + receive_wait_time_seconds = 15 + visibility_timeout_seconds = 7200 + + redrive_policy = jsonencode({ + deadLetterTargetArn = aws_sqs_queue.cloudtrail_deadletter.arn + maxReceiveCount = 100 + }) + + kms_master_key_id = data.aws_kms_key.incoming_key.id + kms_data_key_reuse_period_seconds = 300 + + tags = merge( + local.base_tags, + var.tags, + map("Name", local.name), + ) +} + +resource "aws_sqs_queue_policy" "cloudtrail_sqs" { + queue_url = aws_sqs_queue.cloudtrail.id + policy = data.aws_iam_policy_document.cloudtrail_sqs.json +} + +data "aws_iam_policy_document" "cloudtrail_sqs" { + policy_id = "SQSDefaultPolicy" + statement { + sid = "AllowSNSSendMessage" + effect = "Allow" + actions = ["SQS:SendMessage"] + resources = [aws_sqs_queue.cloudtrail.arn] + principals { + type = "AWS" + identifiers = ["*"] + } + condition { + test = "ArnEquals" + variable = "aws:SourceArn" + values = [aws_sns_topic.cloudtrail.arn] + } + } +} + +resource "aws_sns_topic_subscription" "cloudtrail_sqs" { + protocol = "sqs" + topic_arn = aws_sns_topic.cloudtrail.arn + endpoint = aws_sqs_queue.cloudtrail.arn +} From 183fbe8dffd5781e3cac60a46be5ed7ca5880bb8 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 11:50:17 -0500 Subject: [PATCH 19/59] fix --- cloudtrail/sns.tf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cloudtrail/sns.tf b/cloudtrail/sns.tf index e511782..8f947cf 100644 --- a/cloudtrail/sns.tf +++ b/cloudtrail/sns.tf @@ -4,7 +4,8 @@ resource "aws_sns_topic" "cloudtrail" { tags = merge( local.base_tags, - local.tags + var.tags, + map("Name", local.name), ) } From 2ec53a3b38a4754f3302eaeae09ae396f3abbbfb Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 11:59:36 -0500 Subject: [PATCH 20/59] make enable_sqs first pass --- cloudtrail/sqs.tf | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/cloudtrail/sqs.tf b/cloudtrail/sqs.tf index a5b3840..25ee60a 100644 --- a/cloudtrail/sqs.tf +++ b/cloudtrail/sqs.tf @@ -1,4 +1,5 @@ resource "aws_sqs_queue" "cloudtrail_deadletter" { + count = var.enable_sqs ? 1 : 0 # delay=0 retention=4d max=256k visibility=1h name = format("%v-deadletter", local.name) delay_seconds = 0 @@ -18,7 +19,8 @@ resource "aws_sqs_queue" "cloudtrail_deadletter" { } resource "aws_sqs_queue_policy" "cloudtrail_deadletter" { - queue_url = aws_sqs_queue.cloudtrail_deadletter.id + count = var.enable_sqs ? 1 : 0 + queue_url = var.enable_sqs ? aws_sqs_queue.cloudtrail_deadletter[0].id : null policy = data.aws_iam_policy_document.cloudtrail_deadletter.json } @@ -28,7 +30,7 @@ data "aws_iam_policy_document" "cloudtrail_deadletter" { sid = "AllowSNSSendMessage" effect = "Allow" actions = ["SQS:SendMessage"] - resources = [aws_sqs_queue.cloudtrail_deadletter.arn] + resources = [var.enable_sqs ? aws_sqs_queue.cloudtrail_deadletter[0].arn : null] principals { type = "AWS" identifiers = ["*"] @@ -36,12 +38,13 @@ data "aws_iam_policy_document" "cloudtrail_deadletter" { condition { test = "ArnEquals" variable = "aws:SourceArn" - values = [aws_sns_topic.cloudtrail.arn] + values = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null] } } } resource "aws_sqs_queue" "cloudtrail" { + count = var.enable_sqs ? 1 : 0 # delay=0 retention=7d max=256k visibity=2h name = local.name delay_seconds = 0 @@ -51,7 +54,7 @@ resource "aws_sqs_queue" "cloudtrail" { visibility_timeout_seconds = 7200 redrive_policy = jsonencode({ - deadLetterTargetArn = aws_sqs_queue.cloudtrail_deadletter.arn + deadLetterTargetArn = var.enable_sqs ? aws_sqs_queue.cloudtrail_deadletter[0].arn : null maxReceiveCount = 100 }) @@ -66,7 +69,8 @@ resource "aws_sqs_queue" "cloudtrail" { } resource "aws_sqs_queue_policy" "cloudtrail_sqs" { - queue_url = aws_sqs_queue.cloudtrail.id + count = var.enable_sqs ? 1 : 0 + queue_url = var.enable_sqs ? aws_sqs_queue.cloudtrail[0].id : null policy = data.aws_iam_policy_document.cloudtrail_sqs.json } @@ -76,7 +80,7 @@ data "aws_iam_policy_document" "cloudtrail_sqs" { sid = "AllowSNSSendMessage" effect = "Allow" actions = ["SQS:SendMessage"] - resources = [aws_sqs_queue.cloudtrail.arn] + resources = [var.enable_sqs ? aws_sqs_queue.cloudtrail[0].arn : null] principals { type = "AWS" identifiers = ["*"] @@ -84,13 +88,14 @@ data "aws_iam_policy_document" "cloudtrail_sqs" { condition { test = "ArnEquals" variable = "aws:SourceArn" - values = [aws_sns_topic.cloudtrail.arn] + values = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null] } } } resource "aws_sns_topic_subscription" "cloudtrail_sqs" { + count = var.enable_sqs && var.enable_sns ? 1 : 0 protocol = "sqs" - topic_arn = aws_sns_topic.cloudtrail.arn - endpoint = aws_sqs_queue.cloudtrail.arn + topic_arn = var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null + endpoint = var.enable_sqs ? aws_sqs_queue.cloudtrail[0].arn : null } From ab14f2e9525ff091543e287fc56de1367da7641c Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 12:20:20 -0500 Subject: [PATCH 21/59] fix --- cloudtrail/sns.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail/sns.tf b/cloudtrail/sns.tf index 8f947cf..5734a14 100644 --- a/cloudtrail/sns.tf +++ b/cloudtrail/sns.tf @@ -38,7 +38,7 @@ data "aws_iam_policy_document" "cloudtrail_topic" { condition { test = "StringEquals" variable = "AWS:SourceOwner" - values = [loal.account_id] + values = [local.account_id] } resources = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null] } From 9e0b36de187dec99d540a138766dbc3984967281 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 12:22:59 -0500 Subject: [PATCH 22/59] fix --- cloudtrail/sns.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail/sns.tf b/cloudtrail/sns.tf index 5734a14..2a49760 100644 --- a/cloudtrail/sns.tf +++ b/cloudtrail/sns.tf @@ -11,7 +11,7 @@ resource "aws_sns_topic" "cloudtrail" { resource "aws_sns_topic_policy" "cloudtrail" { count = var.enable_sns ? 1 : 0 - arn = aws_sns_topic.cloudtrail.arn + arn = var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null policy = data.aws_iam_policy_document.cloudtrail_topic.json } From 8b934404ff9f36f92c8ee73d38877be23489f630 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 12:31:16 -0500 Subject: [PATCH 23/59] fix log target prefix --- cloudtrail/s3.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail/s3.tf b/cloudtrail/s3.tf index 134b874..47596e6 100644 --- a/cloudtrail/s3.tf +++ b/cloudtrail/s3.tf @@ -5,7 +5,7 @@ resource "aws_s3_bucket" "this" { logging { target_bucket = var.access_log_bucket - target_prefix = format("%s/%s/", var.access_log_bucket_prefix, local.name) + target_prefix = format("%s/%s/", var.access_log_bucket_prefix, local.bucket_name) } tags = merge( From 1f30c36b60a87eda0617af46c8a98831a380ad3a Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 12:50:41 -0500 Subject: [PATCH 24/59] add role --- cloudtrail/README.md | 5 +++ cloudtrail/cloudtrail.tf | 71 +++++++++++++++++++++++++++++++++++++--- cloudtrail/main.tf | 3 ++ 3 files changed, 75 insertions(+), 4 deletions(-) diff --git a/cloudtrail/README.md b/cloudtrail/README.md index b2daffb..ed9c045 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -58,7 +58,10 @@ No modules. | Name | Type | |------|------| | [aws_cloudtrail.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | +| [aws_cloudwatch_log_group.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_policy.cloudtrail_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | 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 | @@ -73,6 +76,8 @@ No modules. | [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](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.cloudtrail_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.cloudtrail_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cloudtrail_deadletter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | 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.cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | diff --git a/cloudtrail/cloudtrail.tf b/cloudtrail/cloudtrail.tf index b231279..a0a051a 100644 --- a/cloudtrail/cloudtrail.tf +++ b/cloudtrail/cloudtrail.tf @@ -7,14 +7,77 @@ resource "aws_cloudtrail" "this" { enable_log_file_validation = true enable_logging = true kms_key_id = var.kms_key_arn - # sns_topic_name = aws_sns_topic.cloudtrail.arn - # cloud_watch_logs_group_arn = aws_cloudwatch_log_group.inf-cloudtrail.arn - # cloud_watch_logs_role_arn = aws_iam_role.inf-cloudtrail.arn + sns_topic_name = var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null + cloud_watch_logs_group_arn = aws_cloudwatch_log_group.cloudtrail.arn + cloud_watch_logs_role_arn = aws_iam_role.cloudtrail.arn tags = merge( local.base_tags, var.tags, - { "Name" = local.name }, + map("Name", local.name), ) depends_on = [aws_s3_bucket_policy.policy] } + +resource "aws_iam_role" "cloudtrail" { + name = local.role_name + assume_role_policy = data.aws_iam_policy_document.cloudtrail_assume.json + description = "AWS CloudTrail Role for ${local.name}" + force_detach_policies = false + max_session_duration = 3600 + # add deny billing + attached_policies = [aws_iam_policy.cloudtrail_policy.arn] + path = "/" + + tags = merge( + local.base_tags, + var.tags, + map("Name", local.role_name), + ) +} + +data "aws_iam_policy_document" "cloudtrail_assume" { + statement { + sid = "AWSCloudTrailServiceAssumeRole" + effect = "Allow" + actions = ["sts:AssumeRole"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + } +} + +resource "aws_iam_policy" "cloudtrail_policy" { + name = local.policy_name + policy = data.aws_iam_policy_document.cloudtrail_cloudwatch.json +} + + +data "aws_iam_policy_document" "cloudtrail_cloudwatch" { + statement { + sid = "AWSCloudTrailCreateLogStream" + effect = "Allow" + actions = ["logs:CreateLogStream"] + resources = [local.cloudwatch_resources] + } + statement { + sid = "AWSCloudTrailPutLogEvents" + effect = "Allow" + actions = ["logs:PutLogEvents"] + resources = [local.cloudwatch_resources] + } +} + +resource "aws_cloudwatch_log_group" "cloudtrail" { + name = local.name + + kms_key_id = var.kms_key_arn + retention_in_days = 7 + + tags = merge( + local.base_tags, + var.tags, + map("Name", format("%v-log", local.name)), + ) +} diff --git a/cloudtrail/main.tf b/cloudtrail/main.tf index 5822348..9228d37 100644 --- a/cloudtrail/main.tf +++ b/cloudtrail/main.tf @@ -61,6 +61,9 @@ locals { # kms_policy_document = var.kms_policy_document != null ? var.kms_policy_document : data.aws_iam_policy_document.empty.json bucket_name = var.name == null ? format("%v-%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.account_id, local.region) : var.name + + role_name = format("%v%v", local._prefixes["role"], local.name) + policy_name = format("%v%v", local._prefixes["policy"], local.name) } data "aws_kms_key" "incoming_key" { From c49613750268a203393b11da45e22668b927453a Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 12:53:41 -0500 Subject: [PATCH 25/59] fix --- cloudtrail/cloudtrail.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail/cloudtrail.tf b/cloudtrail/cloudtrail.tf index a0a051a..69703a4 100644 --- a/cloudtrail/cloudtrail.tf +++ b/cloudtrail/cloudtrail.tf @@ -26,8 +26,8 @@ resource "aws_iam_role" "cloudtrail" { force_detach_policies = false max_session_duration = 3600 # add deny billing - attached_policies = [aws_iam_policy.cloudtrail_policy.arn] - path = "/" + managed_policy_arns = [aws_iam_policy.cloudtrail_policy.arn] + path = "/" tags = merge( local.base_tags, From 259c2ff11b616a646f040c75b77fefbb16dd89c3 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 13:46:45 -0500 Subject: [PATCH 26/59] add splunk generation --- cloudtrail/README.md | 5 ++++ cloudtrail/generate_splunk.cloudtrail.tf | 30 +++++++++++++++++++ .../templates/inputs.cloudtrail.conf.tpl | 10 +++++++ 3 files changed, 45 insertions(+) create mode 100644 cloudtrail/generate_splunk.cloudtrail.tf create mode 100644 cloudtrail/templates/inputs.cloudtrail.conf.tpl diff --git a/cloudtrail/README.md b/cloudtrail/README.md index ed9c045..99eea12 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -48,6 +48,8 @@ No requirements. |------|---------| | [aws](#provider\_aws) | n/a | | [null](#provider\_null) | n/a | +| [random](#provider\_random) | n/a | +| [template](#provider\_template) | n/a | ## Modules @@ -73,6 +75,8 @@ No modules. | [aws_sqs_queue_policy.cloudtrail_deadletter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | | [aws_sqs_queue_policy.cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | | [null_resource.policy_delay](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [null_resource.splunk_cloudtrail](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [random_uuid.splunk_cloudtrail](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | 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](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -85,6 +89,7 @@ No modules. | [aws_iam_policy_document.cloudwatch_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_kms_key.incoming_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_key) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | +| [template_file.splunk_cloudtrail](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) | data source | ## Inputs diff --git a/cloudtrail/generate_splunk.cloudtrail.tf b/cloudtrail/generate_splunk.cloudtrail.tf new file mode 100644 index 0000000..a052406 --- /dev/null +++ b/cloudtrail/generate_splunk.cloudtrail.tf @@ -0,0 +1,30 @@ +#--- +# generate splunk inputs file +#--- +data "template_file" "splunk_cloudtrail" { + template = file("${path.module}/templates/inputs.cloudtrail.conf.tpl") + vars = { + account_id = local.account_id + account_alias = local.account_alias + entry_uuid = random_uuid.splunk_cloudtrail.result + region = local.cloudtrail_region + queue_url = var.enable_sqs ? aws_sqs_queue.cloudtrail[0].id : null + } +} + +resource "random_uuid" "splunk_cloudtrail" { + keepers = { + queue_url = var.enable_sqs ? aws_sqs_queue.cloudtrail[0].id : null + } +} + +resource "null_resource" "splunk_cloudtrail" { + count = var.enable_sqs ? 1 : 0 + provisioner "local-exec" { + command = "test -d setup || mkdir setup" + } + provisioner "local-exec" { + working_dir = "setup" + command = "echo '${data.template_file.splunk_cloudtrail.rendered}' > inputs.cloudtrail.${local.account_id}.${local.cloudtrail_region}.conf" + } +} diff --git a/cloudtrail/templates/inputs.cloudtrail.conf.tpl b/cloudtrail/templates/inputs.cloudtrail.conf.tpl new file mode 100644 index 0000000..78390d9 --- /dev/null +++ b/cloudtrail/templates/inputs.cloudtrail.conf.tpl @@ -0,0 +1,10 @@ +[aws_sqs_based_s3://${account_alias}-cloudtrail-${region}] +account = ${account_alias} +index = aws +polling_interval = 300 +s3_file_decoder = CloudTrail +sourcetype = aws:cloudtrail +sqs_batch_size = 10 +sqs_queue_region = ${region} +sqs_queue_url = ${queue_url} + From 3f623d8d9613e9636b0641c13fadc759aba48a52 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 13:50:33 -0500 Subject: [PATCH 27/59] add organization --- cloudtrail/README.md | 1 + cloudtrail/main.tf | 3 ++- cloudtrail/variables.tf | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cloudtrail/README.md b/cloudtrail/README.md index 99eea12..a5227ef 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -101,6 +101,7 @@ No modules. | [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\_organization](#input\_enable\_organization) | Enable CloudTrail as an organization trail. This will only work in the organization master account | `bool` | `false` | 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\_arn](#input\_kms\_key\_arn) | AWS CloudTrail KMS ARN to be used for encrypting the ClouldTrail, S3 Bucket, and SQS | `string` | n/a | yes | diff --git a/cloudtrail/main.tf b/cloudtrail/main.tf index 9228d37..4cf1853 100644 --- a/cloudtrail/main.tf +++ b/cloudtrail/main.tf @@ -54,7 +54,8 @@ locals { account_environment = data.aws_arn.current.partition == "aws-us-gov" ? "gov" : "ew" partition = data.aws_arn.current.partition - name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name + _name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name + name = var.enable_organization ? lookup(local._defaults["org_cloudtrail"], "name") : local._name kms_key_name = format("k-%v", local.name) kms_admin_root = format("arn:%v:iam::%v:root", local.partition, local.account_id) # kms_admin_roles = compact(concat([var.kms_admin_root], var.kms_admin_roles)) diff --git a/cloudtrail/variables.tf b/cloudtrail/variables.tf index 3775f86..c588afb 100644 --- a/cloudtrail/variables.tf +++ b/cloudtrail/variables.tf @@ -72,3 +72,9 @@ variable "component_tags" { default = { "s3" = {}, "kms" = {}, "ddb" = {} } } + +variable "enable_organization" { + description = "Enable CloudTrail as an organization trail. This will only work in the organization master account" + type = bool + default = false +} From dfdb34b0d53d9ee0ea202f5004f3707df72a3344 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 14:21:01 -0500 Subject: [PATCH 28/59] replace null with empty string --- cloudtrail/sns.tf | 4 ++-- cloudtrail/sqs.tf | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cloudtrail/sns.tf b/cloudtrail/sns.tf index 2a49760..194a93c 100644 --- a/cloudtrail/sns.tf +++ b/cloudtrail/sns.tf @@ -40,7 +40,7 @@ data "aws_iam_policy_document" "cloudtrail_topic" { variable = "AWS:SourceOwner" values = [local.account_id] } - resources = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null] + resources = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : ""] } statement { sid = "CloudTrailSNSPolicy" @@ -50,6 +50,6 @@ data "aws_iam_policy_document" "cloudtrail_topic" { identifiers = ["cloudtrail.amazonaws.com"] } actions = ["sns:Publish"] - resources = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null] + resources = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : ""] } } diff --git a/cloudtrail/sqs.tf b/cloudtrail/sqs.tf index 25ee60a..42f2442 100644 --- a/cloudtrail/sqs.tf +++ b/cloudtrail/sqs.tf @@ -30,7 +30,7 @@ data "aws_iam_policy_document" "cloudtrail_deadletter" { sid = "AllowSNSSendMessage" effect = "Allow" actions = ["SQS:SendMessage"] - resources = [var.enable_sqs ? aws_sqs_queue.cloudtrail_deadletter[0].arn : null] + resources = [var.enable_sqs ? aws_sqs_queue.cloudtrail_deadletter[0].arn : ""] principals { type = "AWS" identifiers = ["*"] @@ -38,7 +38,7 @@ data "aws_iam_policy_document" "cloudtrail_deadletter" { condition { test = "ArnEquals" variable = "aws:SourceArn" - values = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null] + values = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : ""] } } } @@ -80,7 +80,7 @@ data "aws_iam_policy_document" "cloudtrail_sqs" { sid = "AllowSNSSendMessage" effect = "Allow" actions = ["SQS:SendMessage"] - resources = [var.enable_sqs ? aws_sqs_queue.cloudtrail[0].arn : null] + resources = [var.enable_sqs ? aws_sqs_queue.cloudtrail[0].arn : ""] principals { type = "AWS" identifiers = ["*"] @@ -88,7 +88,7 @@ data "aws_iam_policy_document" "cloudtrail_sqs" { condition { test = "ArnEquals" variable = "aws:SourceArn" - values = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null] + values = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : ""] } } } From b6ca1466f3c934007c78fdc2abebbfe8c8cb0b49 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 14:23:26 -0500 Subject: [PATCH 29/59] fix --- cloudtrail/generate_splunk.cloudtrail.tf | 2 +- cloudtrail/main.tf | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cloudtrail/generate_splunk.cloudtrail.tf b/cloudtrail/generate_splunk.cloudtrail.tf index a052406..ad18e86 100644 --- a/cloudtrail/generate_splunk.cloudtrail.tf +++ b/cloudtrail/generate_splunk.cloudtrail.tf @@ -7,7 +7,7 @@ data "template_file" "splunk_cloudtrail" { account_id = local.account_id account_alias = local.account_alias entry_uuid = random_uuid.splunk_cloudtrail.result - region = local.cloudtrail_region + region = local.region queue_url = var.enable_sqs ? aws_sqs_queue.cloudtrail[0].id : null } } diff --git a/cloudtrail/main.tf b/cloudtrail/main.tf index 4cf1853..ff26375 100644 --- a/cloudtrail/main.tf +++ b/cloudtrail/main.tf @@ -53,6 +53,7 @@ locals { region = data.aws_region.current.name account_environment = data.aws_arn.current.partition == "aws-us-gov" ? "gov" : "ew" partition = data.aws_arn.current.partition + account_alias = var.account_alias == "" ? "MISSING" : var.account_alias _name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name name = var.enable_organization ? lookup(local._defaults["org_cloudtrail"], "name") : local._name From cb541eacfa92d46d0f4ccc6fa78e5f69d2e62765 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 14:23:40 -0500 Subject: [PATCH 30/59] fix --- common/defaults.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/defaults.tf b/common/defaults.tf index 7e84a52..237ca24 100644 --- a/common/defaults.tf +++ b/common/defaults.tf @@ -17,7 +17,7 @@ locals { "ses" = { "event_types" = ["bounce", "delivery", "complaint"] } - "organization-cloudtrail" = { + "org_cloudtrail" = { "name" = "inf-org-cloudtrail" } "cloudtrail" = { From 60ca74f8a1d676bbc6f6b48e87e5f0a7b305eaa4 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 16 Nov 2021 14:26:52 -0500 Subject: [PATCH 31/59] fix --- cloudtrail/generate_splunk.cloudtrail.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail/generate_splunk.cloudtrail.tf b/cloudtrail/generate_splunk.cloudtrail.tf index ad18e86..159e9dd 100644 --- a/cloudtrail/generate_splunk.cloudtrail.tf +++ b/cloudtrail/generate_splunk.cloudtrail.tf @@ -25,6 +25,6 @@ resource "null_resource" "splunk_cloudtrail" { } provisioner "local-exec" { working_dir = "setup" - command = "echo '${data.template_file.splunk_cloudtrail.rendered}' > inputs.cloudtrail.${local.account_id}.${local.cloudtrail_region}.conf" + command = "echo '${data.template_file.splunk_cloudtrail.rendered}' > inputs.cloudtrail.${local.account_id}.${local.region}.conf" } } From b6512f2fa98ed96b9cb2bf266e79888d2e99d22d Mon Sep 17 00:00:00 2001 From: badra001 Date: Thu, 18 Nov 2021 13:55:58 -0500 Subject: [PATCH 32/59] more org change --- cloudtrail/main.tf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cloudtrail/main.tf b/cloudtrail/main.tf index ff26375..dc18bf9 100644 --- a/cloudtrail/main.tf +++ b/cloudtrail/main.tf @@ -62,7 +62,8 @@ locals { # kms_admin_roles = compact(concat([var.kms_admin_root], var.kms_admin_roles)) # kms_policy_document = var.kms_policy_document != null ? var.kms_policy_document : data.aws_iam_policy_document.empty.json - bucket_name = var.name == null ? format("%v-%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.account_id, local.region) : var.name + _bucket_name = var.name == null ? format("%v-%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.account_id, local.region) : var.name + bucket_name = var.enable_organization ? format("%v-%v-%v", lookup(local._defaults["org_cloudtrail"], "name"), local.account_id, local.region) : local._bucket_name role_name = format("%v%v", local._prefixes["role"], local.name) policy_name = format("%v%v", local._prefixes["policy"], local.name) From ecd32512df7872589f70c7d8c42d6a05323d037e Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 11:28:05 -0500 Subject: [PATCH 33/59] add org trail variable --- cloudtrail/cloudtrail.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/cloudtrail/cloudtrail.tf b/cloudtrail/cloudtrail.tf index 69703a4..da06709 100644 --- a/cloudtrail/cloudtrail.tf +++ b/cloudtrail/cloudtrail.tf @@ -10,6 +10,7 @@ resource "aws_cloudtrail" "this" { sns_topic_name = var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null cloud_watch_logs_group_arn = aws_cloudwatch_log_group.cloudtrail.arn cloud_watch_logs_role_arn = aws_iam_role.cloudtrail.arn + is_organization_trail = var.enable_organization tags = merge( local.base_tags, From bbcda8ede193b2a967784ffba5b56dfdf894d621 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 11:43:47 -0500 Subject: [PATCH 34/59] remove policy_id --- cloudtrail/sqs.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail/sqs.tf b/cloudtrail/sqs.tf index 42f2442..cc15c2c 100644 --- a/cloudtrail/sqs.tf +++ b/cloudtrail/sqs.tf @@ -25,7 +25,7 @@ resource "aws_sqs_queue_policy" "cloudtrail_deadletter" { } data "aws_iam_policy_document" "cloudtrail_deadletter" { - policy_id = "SQSDefaultPolicy" + # policy_id = "SQSDefaultPolicy" statement { sid = "AllowSNSSendMessage" effect = "Allow" @@ -75,7 +75,7 @@ resource "aws_sqs_queue_policy" "cloudtrail_sqs" { } data "aws_iam_policy_document" "cloudtrail_sqs" { - policy_id = "SQSDefaultPolicy" + # policy_id = "SQSDefaultPolicy" statement { sid = "AllowSNSSendMessage" effect = "Allow" From d51267b77c377009f2c06f973cd0b0e095369887 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 13:32:06 -0500 Subject: [PATCH 35/59] replace key policy with that from s3 objct logging --- cloudtrail-key/README.md | 1 + cloudtrail-key/main.tf | 58 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/cloudtrail-key/README.md b/cloudtrail-key/README.md index ad1aabe..176d26d 100644 --- a/cloudtrail-key/README.md +++ b/cloudtrail-key/README.md @@ -70,6 +70,7 @@ No modules. | [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](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_orig](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_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf index 6b780e4..dc888d7 100644 --- a/cloudtrail-key/main.tf +++ b/cloudtrail-key/main.tf @@ -54,10 +54,11 @@ locals { account_environment = data.aws_arn.current.partition == "aws-us-gov" ? "gov" : "ew" partition = data.aws_arn.current.partition - name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name - kms_key_name = format("%v%v", 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)) + name = var.name == null ? format("%v-%v", lookup(local._defaults["cloudtrail"], "name"), local.region) : var.name + kms_key_name = format("%v%v", 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_admin_roles = var.kms_admin_roles kms_policy_document = var.kms_policy_document != null ? var.kms_policy_document : data.aws_iam_policy_document.empty.json } @@ -88,7 +89,7 @@ data "aws_iam_policy_document" "key_policy_combined" { ] } -data "aws_iam_policy_document" "key" { +data "aws_iam_policy_document" "key_orig" { policy_id = "Cloudtrail KMS Access" statement { sid = "EnableIAMUserPermissions" @@ -216,3 +217,50 @@ data "aws_iam_policy_document" "key_admin" { } data "aws_iam_policy_document" "empty" {} + + +#--- +# 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 +# +# from aws-setup-s3-object-logging +#--- +data "aws_iam_policy_document" "key" { + policy_id = "object-logging-cloud-trail" + statement { + sid = "IAMPermissionsAccessKMSManagement" + effect = "Allow" + actions = ["kms:*"] + resources = ["*"] + principals { + type = "AWS" + identifiers = [local.kms_admin_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:%v:cloudtrail:*:%v:trail/*", local.partition, local.account_id)] + } + } +} From 6472786954658756cb9cdfdaff28d4765e57fb51 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 13:38:40 -0500 Subject: [PATCH 36/59] fix --- cloudtrail-key/main.tf | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf index dc888d7..00f070a 100644 --- a/cloudtrail-key/main.tf +++ b/cloudtrail-key/main.tf @@ -204,14 +204,17 @@ data "aws_iam_policy_document" "key_orig" { } data "aws_iam_policy_document" "key_admin" { - statement { - sid = "BuiltinKMSAdminRoles" - effect = "Allow" - actions = ["kms:*"] - resources = ["*"] - principals { - type = "AWS" - identifiers = local.kms_admin_roles + dynamic "statement" { + for_each = length(local.kms_admin_roles) > 0 ? [1] : [] + content { + sid = "BuiltinKMSAdminRoles" + effect = "Allow" + actions = ["kms:*"] + resources = ["*"] + principals { + type = "AWS" + identifiers = local.kms_admin_roles + } } } } From 85309a66c0b58c0a24a5a72c0fbe376a63e540d9 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 13:51:29 -0500 Subject: [PATCH 37/59] add cw log key policy --- cloudtrail-key/main.tf | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf index 00f070a..45acd75 100644 --- a/cloudtrail-key/main.tf +++ b/cloudtrail-key/main.tf @@ -266,4 +266,26 @@ data "aws_iam_policy_document" "key" { values = [format("arn:%v:cloudtrail:*:%v:trail/*", local.partition, local.account_id)] } } + # https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html + statement { + sid = "Cloudwatch" + effect = "Allow" + actions = [ + "kms:Encrypt*", + "kms:Decrypt*", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:Describe*" + ] + resources = ["*"] + principals { + type = "Service" + identifiers = ["logs.amazonaws.com", "logs.${local.region}.amazonaws.com"] + } + condition { + test = "StringLike" + variable = "kms:EncryptionContext:aws:logs:arn" + values = [format("arn:%v:logs:%v:%v:log-group:*", local.partition, local.region, local.account_id)] + } + } } From b71aa2fa504eaed42e16f9a68f14b196e600b4a4 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 13:56:10 -0500 Subject: [PATCH 38/59] fix key --- cloudtrail/cloudwatch.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail/cloudwatch.tf b/cloudtrail/cloudwatch.tf index 6d2b6d3..d533b05 100644 --- a/cloudtrail/cloudwatch.tf +++ b/cloudtrail/cloudwatch.tf @@ -24,8 +24,8 @@ resource "aws_cloudwatch_log_group" "this" { name = local.name # kms_key_id = var.kms_key_id - # kms_key_id = var.kms_key_arn - kms_key_id = data.aws_kms_key.incoming_key.id + kms_key_id = var.kms_key_arn + # kms_key_id = data.aws_kms_key.incoming_key.id retention_in_days = 7 tags = merge( From 3d13ad78e8029cc60b9699f072e35b8d8c784771 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 14:07:43 -0500 Subject: [PATCH 39/59] fix cw arn --- cloudtrail/cloudtrail.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail/cloudtrail.tf b/cloudtrail/cloudtrail.tf index da06709..a36774c 100644 --- a/cloudtrail/cloudtrail.tf +++ b/cloudtrail/cloudtrail.tf @@ -8,7 +8,7 @@ resource "aws_cloudtrail" "this" { enable_logging = true kms_key_id = var.kms_key_arn sns_topic_name = var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null - cloud_watch_logs_group_arn = aws_cloudwatch_log_group.cloudtrail.arn + cloud_watch_logs_group_arn = format("%v:*", aws_cloudwatch_log_group.cloudtrail.arn) cloud_watch_logs_role_arn = aws_iam_role.cloudtrail.arn is_organization_trail = var.enable_organization From f0d9f88bc21972bc67b5beaeb6790233d3520f18 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 14:30:50 -0500 Subject: [PATCH 40/59] add to policy for CW logs for org --- cloudtrail/README.md | 1 + cloudtrail/cloudwatch.tf | 13 ++++++++----- cloudtrail/main.tf | 3 +++ cloudtrail/variables.tf | 7 ++++++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/cloudtrail/README.md b/cloudtrail/README.md index a5227ef..d1a9a0d 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -107,6 +107,7 @@ No modules. | [kms\_key\_arn](#input\_kms\_key\_arn) | AWS CloudTrail KMS ARN to be used for encrypting the ClouldTrail, S3 Bucket, and SQS | `string` | n/a | yes | | [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 | +| [organization\_id](#input\_organization\_id) | AWS Organization ID | `string` | `""` | 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) | 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 | diff --git a/cloudtrail/cloudwatch.tf b/cloudtrail/cloudwatch.tf index d533b05..835aad1 100644 --- a/cloudtrail/cloudwatch.tf +++ b/cloudtrail/cloudwatch.tf @@ -1,7 +1,10 @@ locals { - cloudwatch_prefix = replace(aws_cloudwatch_log_group.this.arn, "/:\\*$/", "") - cloudwatch_suffix = format("%v_CloudTrail_%v", local.account_id, local.region) - cloudwatch_resources = join(":", list(local.cloudwatch_prefix, "log-stream", local.cloudwatch_suffix)) + cloudwatch_prefix = replace(aws_cloudwatch_log_group.this.arn, "/:\\*$/", "") + cloudwatch_suffix = format("%v_CloudTrail_%v", local.account_id, local.region) + org_cloudwatch_suffix = format("o-%v_*", var.organization_id) + cloudwatch_resources = join(":", list(local.cloudwatch_prefix, "log-stream", local.cloudwatch_suffix)) + org_cloudwatch_resources = var.enable_organization ? join(":", list(local.cloudwatch_prefix, "log-stream", local.org_cloudwatch_suffix)) : "" + resources = compact(concat(local.cloudwatch_resoures, local.org_cloudwatch_resources)) } data "aws_iam_policy_document" "cloudwatch_policy" { @@ -9,14 +12,14 @@ data "aws_iam_policy_document" "cloudwatch_policy" { sid = "AWSCloudTrailCreateLogStream" effect = "Allow" actions = ["logs:CreateLogStream"] - resources = [local.cloudwatch_resources] + resources = [local.resources] } statement { sid = "AWSCloudTrailPutLogEvents" effect = "Allow" actions = ["logs:PutLogEvents"] - resources = [local.cloudwatch_resources] + resources = [local.resources] } } diff --git a/cloudtrail/main.tf b/cloudtrail/main.tf index dc18bf9..83f5c6f 100644 --- a/cloudtrail/main.tf +++ b/cloudtrail/main.tf @@ -72,3 +72,6 @@ locals { data "aws_kms_key" "incoming_key" { key_id = var.kms_key_arn } + +# data "aws_organizations_organization" "org" {} + diff --git a/cloudtrail/variables.tf b/cloudtrail/variables.tf index c588afb..65a5a1e 100644 --- a/cloudtrail/variables.tf +++ b/cloudtrail/variables.tf @@ -72,9 +72,14 @@ variable "component_tags" { default = { "s3" = {}, "kms" = {}, "ddb" = {} } } - variable "enable_organization" { description = "Enable CloudTrail as an organization trail. This will only work in the organization master account" type = bool default = false } + +variable "organization_id" { + description = "AWS Organization ID" + type = string + default = "" +} From f6b755279a1a463efc94e3afdbdf42964dd37ff7 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 14:32:27 -0500 Subject: [PATCH 41/59] fix --- cloudtrail/cloudwatch.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail/cloudwatch.tf b/cloudtrail/cloudwatch.tf index 835aad1..55143b9 100644 --- a/cloudtrail/cloudwatch.tf +++ b/cloudtrail/cloudwatch.tf @@ -4,7 +4,7 @@ locals { org_cloudwatch_suffix = format("o-%v_*", var.organization_id) cloudwatch_resources = join(":", list(local.cloudwatch_prefix, "log-stream", local.cloudwatch_suffix)) org_cloudwatch_resources = var.enable_organization ? join(":", list(local.cloudwatch_prefix, "log-stream", local.org_cloudwatch_suffix)) : "" - resources = compact(concat(local.cloudwatch_resoures, local.org_cloudwatch_resources)) + resources = compact(concat(local.cloudwatch_resources, local.org_cloudwatch_resources)) } data "aws_iam_policy_document" "cloudwatch_policy" { From a0be9718549d84ae4dc110187e6882dcfb24182f Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 14:36:52 -0500 Subject: [PATCH 42/59] fix --- cloudtrail/cloudwatch.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail/cloudwatch.tf b/cloudtrail/cloudwatch.tf index 55143b9..4affd1d 100644 --- a/cloudtrail/cloudwatch.tf +++ b/cloudtrail/cloudwatch.tf @@ -3,8 +3,8 @@ locals { cloudwatch_suffix = format("%v_CloudTrail_%v", local.account_id, local.region) org_cloudwatch_suffix = format("o-%v_*", var.organization_id) cloudwatch_resources = join(":", list(local.cloudwatch_prefix, "log-stream", local.cloudwatch_suffix)) - org_cloudwatch_resources = var.enable_organization ? join(":", list(local.cloudwatch_prefix, "log-stream", local.org_cloudwatch_suffix)) : "" - resources = compact(concat(local.cloudwatch_resources, local.org_cloudwatch_resources)) + org_cloudwatch_resources = var.enable_organization ? join(":", list(local.cloudwatch_prefix, "log-stream", local.org_cloudwatch_suffix)) : null + resources = compact([local.cloudwatch_resources, local.org_cloudwatch_resources]) } data "aws_iam_policy_document" "cloudwatch_policy" { From 71ae191fad36090154932ba028c1944c19c67826 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 23 Nov 2021 14:39:20 -0500 Subject: [PATCH 43/59] fix --- cloudtrail/cloudwatch.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail/cloudwatch.tf b/cloudtrail/cloudwatch.tf index 4affd1d..3b3c00c 100644 --- a/cloudtrail/cloudwatch.tf +++ b/cloudtrail/cloudwatch.tf @@ -12,14 +12,14 @@ data "aws_iam_policy_document" "cloudwatch_policy" { sid = "AWSCloudTrailCreateLogStream" effect = "Allow" actions = ["logs:CreateLogStream"] - resources = [local.resources] + resources = local.resources } statement { sid = "AWSCloudTrailPutLogEvents" effect = "Allow" actions = ["logs:PutLogEvents"] - resources = [local.resources] + resources = local.resources } } From 5570fc7c12a15a1b90ce73bea7da78991579c10e Mon Sep 17 00:00:00 2001 From: badra001 Date: Wed, 24 Nov 2021 16:06:33 -0500 Subject: [PATCH 44/59] move policy to cloudtrail, fix --- cloudtrail/README.md | 1 - cloudtrail/cloudtrail.tf | 4 ++-- cloudtrail/cloudwatch.tf | 34 +++++++++++++++++----------------- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/cloudtrail/README.md b/cloudtrail/README.md index d1a9a0d..2ddc7ca 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -86,7 +86,6 @@ No modules. | [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.cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cloudtrail_topic](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.cloudwatch_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_kms_key.incoming_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_key) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | | [template_file.splunk_cloudtrail](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) | data source | diff --git a/cloudtrail/cloudtrail.tf b/cloudtrail/cloudtrail.tf index a36774c..212bca7 100644 --- a/cloudtrail/cloudtrail.tf +++ b/cloudtrail/cloudtrail.tf @@ -60,13 +60,13 @@ data "aws_iam_policy_document" "cloudtrail_cloudwatch" { sid = "AWSCloudTrailCreateLogStream" effect = "Allow" actions = ["logs:CreateLogStream"] - resources = [local.cloudwatch_resources] + resources = [local.resources] } statement { sid = "AWSCloudTrailPutLogEvents" effect = "Allow" actions = ["logs:PutLogEvents"] - resources = [local.cloudwatch_resources] + resources = [local.resources] } } diff --git a/cloudtrail/cloudwatch.tf b/cloudtrail/cloudwatch.tf index 3b3c00c..cea791d 100644 --- a/cloudtrail/cloudwatch.tf +++ b/cloudtrail/cloudwatch.tf @@ -7,25 +7,8 @@ locals { resources = compact([local.cloudwatch_resources, local.org_cloudwatch_resources]) } -data "aws_iam_policy_document" "cloudwatch_policy" { - statement { - sid = "AWSCloudTrailCreateLogStream" - effect = "Allow" - actions = ["logs:CreateLogStream"] - resources = local.resources - } - - statement { - sid = "AWSCloudTrailPutLogEvents" - effect = "Allow" - actions = ["logs:PutLogEvents"] - resources = local.resources - } -} - resource "aws_cloudwatch_log_group" "this" { name = local.name - # kms_key_id = var.kms_key_id kms_key_id = var.kms_key_arn # kms_key_id = data.aws_kms_key.incoming_key.id @@ -37,3 +20,20 @@ resource "aws_cloudwatch_log_group" "this" { map("Name", local.name), ) } + +## data "aws_iam_policy_document" "cloudwatch_policy" { +## statement { +## sid = "AWSCloudTrailCreateLogStream" +## effect = "Allow" +## actions = ["logs:CreateLogStream"] +## resources = local.resources +## } +## +## statement { +## sid = "AWSCloudTrailPutLogEvents" +## effect = "Allow" +## actions = ["logs:PutLogEvents"] +## resources = local.resources +## } +## } +## From f609ce98b72851c273a513b821fcc41c30749a6a Mon Sep 17 00:00:00 2001 From: badra001 Date: Wed, 24 Nov 2021 16:08:15 -0500 Subject: [PATCH 45/59] fix --- cloudtrail/cloudtrail.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail/cloudtrail.tf b/cloudtrail/cloudtrail.tf index 212bca7..2efd5bd 100644 --- a/cloudtrail/cloudtrail.tf +++ b/cloudtrail/cloudtrail.tf @@ -60,13 +60,13 @@ data "aws_iam_policy_document" "cloudtrail_cloudwatch" { sid = "AWSCloudTrailCreateLogStream" effect = "Allow" actions = ["logs:CreateLogStream"] - resources = [local.resources] + resources = local.resources } statement { sid = "AWSCloudTrailPutLogEvents" effect = "Allow" actions = ["logs:PutLogEvents"] - resources = [local.resources] + resources = local.resources } } From 3362c30232ef8306e2e6936f9dad48baba395cd6 Mon Sep 17 00:00:00 2001 From: badra001 Date: Wed, 24 Nov 2021 16:10:38 -0500 Subject: [PATCH 46/59] fix prefix --- cloudtrail/cloudwatch.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail/cloudwatch.tf b/cloudtrail/cloudwatch.tf index cea791d..db4dd95 100644 --- a/cloudtrail/cloudwatch.tf +++ b/cloudtrail/cloudwatch.tf @@ -1,7 +1,7 @@ locals { cloudwatch_prefix = replace(aws_cloudwatch_log_group.this.arn, "/:\\*$/", "") cloudwatch_suffix = format("%v_CloudTrail_%v", local.account_id, local.region) - org_cloudwatch_suffix = format("o-%v_*", var.organization_id) + org_cloudwatch_suffix = format("%v_*", var.organization_id) cloudwatch_resources = join(":", list(local.cloudwatch_prefix, "log-stream", local.cloudwatch_suffix)) org_cloudwatch_resources = var.enable_organization ? join(":", list(local.cloudwatch_prefix, "log-stream", local.org_cloudwatch_suffix)) : null resources = compact([local.cloudwatch_resources, local.org_cloudwatch_resources]) From b31c37e077036d0606fe14b649c2bca4cfa4d480 Mon Sep 17 00:00:00 2001 From: badra001 Date: Wed, 24 Nov 2021 16:18:28 -0500 Subject: [PATCH 47/59] add splunk_name for configs --- cloudtrail/generate_splunk.cloudtrail.tf | 2 +- cloudtrail/main.tf | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cloudtrail/generate_splunk.cloudtrail.tf b/cloudtrail/generate_splunk.cloudtrail.tf index 159e9dd..a61110a 100644 --- a/cloudtrail/generate_splunk.cloudtrail.tf +++ b/cloudtrail/generate_splunk.cloudtrail.tf @@ -25,6 +25,6 @@ resource "null_resource" "splunk_cloudtrail" { } provisioner "local-exec" { working_dir = "setup" - command = "echo '${data.template_file.splunk_cloudtrail.rendered}' > inputs.cloudtrail.${local.account_id}.${local.region}.conf" + command = "echo '${data.template_file.splunk_cloudtrail.rendered}' > inputs.${local.splunk_name}.${local.account_id}.${local.region}.conf" } } diff --git a/cloudtrail/main.tf b/cloudtrail/main.tf index 83f5c6f..be9b9af 100644 --- a/cloudtrail/main.tf +++ b/cloudtrail/main.tf @@ -67,6 +67,8 @@ locals { role_name = format("%v%v", local._prefixes["role"], local.name) policy_name = format("%v%v", local._prefixes["policy"], local.name) + + splunk_name = var.enable_organization ? "org-cloudtrail" : "cloudtrail" } data "aws_kms_key" "incoming_key" { From d75fe3125e7b7e169dd8a1b9d7d1d821759af90c Mon Sep 17 00:00:00 2001 From: badra001 Date: Wed, 24 Nov 2021 16:26:46 -0500 Subject: [PATCH 48/59] fix name in template --- cloudtrail/generate_splunk.cloudtrail.tf | 11 ++++++----- cloudtrail/templates/inputs.cloudtrail.conf.tpl | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cloudtrail/generate_splunk.cloudtrail.tf b/cloudtrail/generate_splunk.cloudtrail.tf index a61110a..06063a3 100644 --- a/cloudtrail/generate_splunk.cloudtrail.tf +++ b/cloudtrail/generate_splunk.cloudtrail.tf @@ -4,11 +4,12 @@ data "template_file" "splunk_cloudtrail" { template = file("${path.module}/templates/inputs.cloudtrail.conf.tpl") vars = { - account_id = local.account_id - account_alias = local.account_alias - entry_uuid = random_uuid.splunk_cloudtrail.result - region = local.region - queue_url = var.enable_sqs ? aws_sqs_queue.cloudtrail[0].id : null + account_id = local.account_id + account_alias = local.account_alias + entry_uuid = random_uuid.splunk_cloudtrail.result + region = local.region + cloudtrail_name = local.splunk_name + queue_url = var.enable_sqs ? aws_sqs_queue.cloudtrail[0].id : null } } diff --git a/cloudtrail/templates/inputs.cloudtrail.conf.tpl b/cloudtrail/templates/inputs.cloudtrail.conf.tpl index 78390d9..5154a94 100644 --- a/cloudtrail/templates/inputs.cloudtrail.conf.tpl +++ b/cloudtrail/templates/inputs.cloudtrail.conf.tpl @@ -1,4 +1,4 @@ -[aws_sqs_based_s3://${account_alias}-cloudtrail-${region}] +[aws_sqs_based_s3://${account_alias}-%{cloudtrail_name}-${region}] account = ${account_alias} index = aws polling_interval = 300 From ec1040a2dffa6fec3ace93c16ed0d6bb315750b1 Mon Sep 17 00:00:00 2001 From: badra001 Date: Wed, 24 Nov 2021 16:29:13 -0500 Subject: [PATCH 49/59] fix --- cloudtrail/templates/inputs.cloudtrail.conf.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudtrail/templates/inputs.cloudtrail.conf.tpl b/cloudtrail/templates/inputs.cloudtrail.conf.tpl index 5154a94..51d0fde 100644 --- a/cloudtrail/templates/inputs.cloudtrail.conf.tpl +++ b/cloudtrail/templates/inputs.cloudtrail.conf.tpl @@ -1,4 +1,4 @@ -[aws_sqs_based_s3://${account_alias}-%{cloudtrail_name}-${region}] +[aws_sqs_based_s3://${account_alias}-${cloudtrail_name}-${region}] account = ${account_alias} index = aws polling_interval = 300 From d069fb498f4964bd6bab172c3b5f63f65169e3aa Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 26 Nov 2021 08:56:26 -0500 Subject: [PATCH 50/59] update key perms --- cloudtrail-key/main.tf | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf index 45acd75..65e1e12 100644 --- a/cloudtrail-key/main.tf +++ b/cloudtrail-key/main.tf @@ -231,6 +231,7 @@ data "aws_iam_policy_document" "empty" {} #--- data "aws_iam_policy_document" "key" { policy_id = "object-logging-cloud-trail" + # manage key by root and other principals statement { sid = "IAMPermissionsAccessKMSManagement" effect = "Allow" @@ -241,20 +242,25 @@ data "aws_iam_policy_document" "key" { identifiers = [local.kms_admin_root] } } + # let cloudtrial, logs, sns, and sqs find key statement { - sid = "CloudTrailKMSAccess" + sid = "KMSDescribeKeyFromServices" effect = "Allow" actions = ["kms:DescribeKey"] resources = ["*"] principals { type = "Service" - identifiers = ["cloudtrail.amazonaws.com"] + identifiers = ["cloudtrail.amazonaws.com", "sns.amazonaws.com", "sqs.amazonaws.com"] } } statement { - sid = "CloudTrailKMSEncryptAccess" - effect = "Allow" - actions = ["kms:GenerateDataKey"] + sid = "CloudTrailKMSEncryptAccess" + effect = "Allow" + actions = [ + "kms:Encrypt*", + "kms:ReEncrypt*", + "kms:GenerateDataKey", + ] resources = ["*"] principals { type = "Service" @@ -288,4 +294,21 @@ data "aws_iam_policy_document" "key" { values = [format("arn:%v:logs:%v:%v:log-group:*", local.partition, local.region, local.account_id)] } } + # https://aws.amazon.com/blogs/compute/encrypting-messages-published-to-amazon-sns-with-aws-kms/ + # https://docs.aws.amazon.com/sns/latest/dg/sns-key-management.html#sns-what-permissions-for-sse + # https://docs.aws.amazon.com/sns/latest/dg/sns-enable-encryption-for-topic-sqs-queue-subscriptions.html + statement { + sid = "ServiceMSAccess" + effect = "Allow" + actions = [ + "kms:Decrypt*", + "kms:GenerateDataKey*", + "kms:Describe*" + ] + resources = ["*"] + principals { + type = "Service" + identifiers = ["sns.amazonaws.com", "sqs.amazonaws.com"] + } + } } From f79e3f5aefa36e1996519362804e34944ae2d1ba Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 26 Nov 2021 08:58:11 -0500 Subject: [PATCH 51/59] add comments --- cloudtrail-key/main.tf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf index 65e1e12..518a947 100644 --- a/cloudtrail-key/main.tf +++ b/cloudtrail-key/main.tf @@ -312,3 +312,6 @@ data "aws_iam_policy_document" "key" { } } } + +# producers and consumers +# https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-key-management.html#compatibility-with-aws-services From f84ddb6892ac4e3af4f3de2c2efd7b8e5e013d37 Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 26 Nov 2021 08:59:00 -0500 Subject: [PATCH 52/59] change case --- cloudtrail/sqs.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail/sqs.tf b/cloudtrail/sqs.tf index cc15c2c..67a3525 100644 --- a/cloudtrail/sqs.tf +++ b/cloudtrail/sqs.tf @@ -29,7 +29,7 @@ data "aws_iam_policy_document" "cloudtrail_deadletter" { statement { sid = "AllowSNSSendMessage" effect = "Allow" - actions = ["SQS:SendMessage"] + actions = ["sqs:SendMessage"] resources = [var.enable_sqs ? aws_sqs_queue.cloudtrail_deadletter[0].arn : ""] principals { type = "AWS" @@ -79,7 +79,7 @@ data "aws_iam_policy_document" "cloudtrail_sqs" { statement { sid = "AllowSNSSendMessage" effect = "Allow" - actions = ["SQS:SendMessage"] + actions = ["sqs:SendMessage"] resources = [var.enable_sqs ? aws_sqs_queue.cloudtrail[0].arn : ""] principals { type = "AWS" From d98ef7974627be7ec3744d6fb11805d134e0f256 Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 26 Nov 2021 09:00:13 -0500 Subject: [PATCH 53/59] add encryption to sns --- cloudtrail/sns.tf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cloudtrail/sns.tf b/cloudtrail/sns.tf index 194a93c..6960207 100644 --- a/cloudtrail/sns.tf +++ b/cloudtrail/sns.tf @@ -1,6 +1,7 @@ resource "aws_sns_topic" "cloudtrail" { - count = var.enable_sns ? 1 : 0 - name = local.name + count = var.enable_sns ? 1 : 0 + name = local.name + kms_master_key_id = data.aws_kms_key.incoming_key.id tags = merge( local.base_tags, From 7ef9fb99dfcbe402ba3b5a4527bd5f35beae0985 Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 26 Nov 2021 09:15:26 -0500 Subject: [PATCH 54/59] add cw retention into defaults --- cloudtrail/cloudwatch.tf | 8 +++----- common/defaults.tf | 3 +++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cloudtrail/cloudwatch.tf b/cloudtrail/cloudwatch.tf index db4dd95..355eed2 100644 --- a/cloudtrail/cloudwatch.tf +++ b/cloudtrail/cloudwatch.tf @@ -8,11 +8,9 @@ locals { } resource "aws_cloudwatch_log_group" "this" { - name = local.name - # kms_key_id = var.kms_key_id - kms_key_id = var.kms_key_arn - # kms_key_id = data.aws_kms_key.incoming_key.id - retention_in_days = 7 + name = local.name + kms_key_id = var.kms_key_arn + retention_in_days = lookup(local._defaults["cloudwatch"], "retention_in_days", 7) tags = merge( local.base_tags, diff --git a/common/defaults.tf b/common/defaults.tf index 237ca24..2d08c8d 100644 --- a/common/defaults.tf +++ b/common/defaults.tf @@ -26,6 +26,9 @@ locals { "config" = { "name" = "inf-config" } + "cloudwatch" = { + "retention_in_days" = 14 + } "splunk_description" = { "api_list" = [ "ec2_volumes", "ec2_instances", "ec2_reserved_instances", "ec2_key_pairs", "ec2_security_groups", "ec2_images", "ec2_addresses", From 6169822e7c4d4532f237a262fd9c714279afbee7 Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 26 Nov 2021 09:18:07 -0500 Subject: [PATCH 55/59] fix --- cloudtrail/README.md | 1 - cloudtrail/cloudtrail.tf | 26 +++++++++++++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/cloudtrail/README.md b/cloudtrail/README.md index 2ddc7ca..7beb7af 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -60,7 +60,6 @@ No modules. | Name | Type | |------|------| | [aws_cloudtrail.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail) | resource | -| [aws_cloudwatch_log_group.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_iam_policy.cloudtrail_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | diff --git a/cloudtrail/cloudtrail.tf b/cloudtrail/cloudtrail.tf index 2efd5bd..0052076 100644 --- a/cloudtrail/cloudtrail.tf +++ b/cloudtrail/cloudtrail.tf @@ -8,7 +8,7 @@ resource "aws_cloudtrail" "this" { enable_logging = true kms_key_id = var.kms_key_arn sns_topic_name = var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null - cloud_watch_logs_group_arn = format("%v:*", aws_cloudwatch_log_group.cloudtrail.arn) + cloud_watch_logs_group_arn = format("%v:*", aws_cloudwatch_log_group.this.arn) cloud_watch_logs_role_arn = aws_iam_role.cloudtrail.arn is_organization_trail = var.enable_organization @@ -70,15 +70,15 @@ data "aws_iam_policy_document" "cloudtrail_cloudwatch" { } } -resource "aws_cloudwatch_log_group" "cloudtrail" { - name = local.name - - kms_key_id = var.kms_key_arn - retention_in_days = 7 - - tags = merge( - local.base_tags, - var.tags, - map("Name", format("%v-log", local.name)), - ) -} +# resource "aws_cloudwatch_log_group" "cloudtrail" { +# name = local.name +# +# kms_key_id = var.kms_key_arn +# retention_in_days = 7 +# +# tags = merge( +# local.base_tags, +# var.tags, +# map("Name", format("%v-log", local.name)), +# ) +# } From accc566633d25215af2474d04226720559c23dcb Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 26 Nov 2021 09:28:59 -0500 Subject: [PATCH 56/59] change retention --- cloudtrail/sqs.tf | 18 ++++++++++-------- common/defaults.tf | 6 ++++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/cloudtrail/sqs.tf b/cloudtrail/sqs.tf index 67a3525..9593422 100644 --- a/cloudtrail/sqs.tf +++ b/cloudtrail/sqs.tf @@ -1,10 +1,11 @@ resource "aws_sqs_queue" "cloudtrail_deadletter" { count = var.enable_sqs ? 1 : 0 # delay=0 retention=4d max=256k visibility=1h - name = format("%v-deadletter", local.name) - delay_seconds = 0 - max_message_size = 262144 - message_retention_seconds = 345600 + name = format("%v-deadletter", local.name) + delay_seconds = 0 + max_message_size = 262144 + message_retention_seconds = lookup(locals._defaults["sqs_deadletter"], "message_retention_seconds", 1 * 86400) + # message_retention_seconds = 345600 receive_wait_time_seconds = 15 visibility_timeout_seconds = 3600 @@ -46,10 +47,11 @@ data "aws_iam_policy_document" "cloudtrail_deadletter" { resource "aws_sqs_queue" "cloudtrail" { count = var.enable_sqs ? 1 : 0 # delay=0 retention=7d max=256k visibity=2h - name = local.name - delay_seconds = 0 - max_message_size = 262144 - message_retention_seconds = 604800 + name = local.name + delay_seconds = 0 + max_message_size = 262144 + message_retention_seconds = lookup(locals._defaults["sqs_deadletter"], "message_retention_seconds", 7 * 86400) + # message_retention_seconds = 604800 receive_wait_time_seconds = 15 visibility_timeout_seconds = 7200 diff --git a/common/defaults.tf b/common/defaults.tf index 2d08c8d..6a1f087 100644 --- a/common/defaults.tf +++ b/common/defaults.tf @@ -29,6 +29,12 @@ locals { "cloudwatch" = { "retention_in_days" = 14 } + "sqs" = { + "message_retention_seconds" = 14 * 86400 + } + "sqs_deadletter" = { + "message_retention_seconds" = 7 * 86400 + } "splunk_description" = { "api_list" = [ "ec2_volumes", "ec2_instances", "ec2_reserved_instances", "ec2_key_pairs", "ec2_security_groups", "ec2_images", "ec2_addresses", From 918785d21cd695e1703f925d3a5a3aed27f28ed6 Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 26 Nov 2021 09:33:01 -0500 Subject: [PATCH 57/59] fix --- cloudtrail/sqs.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudtrail/sqs.tf b/cloudtrail/sqs.tf index 9593422..223ae33 100644 --- a/cloudtrail/sqs.tf +++ b/cloudtrail/sqs.tf @@ -4,7 +4,7 @@ resource "aws_sqs_queue" "cloudtrail_deadletter" { name = format("%v-deadletter", local.name) delay_seconds = 0 max_message_size = 262144 - message_retention_seconds = lookup(locals._defaults["sqs_deadletter"], "message_retention_seconds", 1 * 86400) + message_retention_seconds = lookup(local._defaults["sqs_deadletter"], "message_retention_seconds", 1 * 86400) # message_retention_seconds = 345600 receive_wait_time_seconds = 15 visibility_timeout_seconds = 3600 @@ -50,7 +50,7 @@ resource "aws_sqs_queue" "cloudtrail" { name = local.name delay_seconds = 0 max_message_size = 262144 - message_retention_seconds = lookup(locals._defaults["sqs_deadletter"], "message_retention_seconds", 7 * 86400) + message_retention_seconds = lookup(local._defaults["sqs_deadletter"], "message_retention_seconds", 7 * 86400) # message_retention_seconds = 604800 receive_wait_time_seconds = 15 visibility_timeout_seconds = 7200 From 98eb0723f8df8509fb6d4e9e9569479efe5e596d Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 26 Nov 2021 10:13:42 -0500 Subject: [PATCH 58/59] add decrypt to cloudtrail policy --- cloudtrail-key/main.tf | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cloudtrail-key/main.tf b/cloudtrail-key/main.tf index 518a947..a8e3fc1 100644 --- a/cloudtrail-key/main.tf +++ b/cloudtrail-key/main.tf @@ -257,6 +257,7 @@ data "aws_iam_policy_document" "key" { sid = "CloudTrailKMSEncryptAccess" effect = "Allow" actions = [ + "kms:Decrypt*", "kms:Encrypt*", "kms:ReEncrypt*", "kms:GenerateDataKey", @@ -266,19 +267,19 @@ data "aws_iam_policy_document" "key" { type = "Service" identifiers = ["cloudtrail.amazonaws.com"] } - condition { - test = "StringLike" - variable = "kms:EncryptionContext:aws:cloudtrail:arn" - values = [format("arn:%v:cloudtrail:*:%v:trail/*", local.partition, local.account_id)] - } + # condition { + # test = "StringLike" + # variable = "kms:EncryptionContext:aws:cloudtrail:arn" + # values = [format("arn:%v:cloudtrail:*:%v:trail/*", local.partition, local.account_id)] + # } } # https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html statement { sid = "Cloudwatch" effect = "Allow" actions = [ - "kms:Encrypt*", "kms:Decrypt*", + "kms:Encrypt*", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:Describe*" From 6b398bd067518d82865f6504018a4b85de861140 Mon Sep 17 00:00:00 2001 From: badra001 Date: Fri, 26 Nov 2021 10:51:06 -0500 Subject: [PATCH 59/59] update readme --- CHANGELOG.md | 4 +- README.md | 19 ++- cloudtrail-key/README.md | 7 +- cloudtrail-key/versions.tf | 14 +++ cloudtrail/README.md | 113 +++++++++++++++--- cloudtrail/main.tf | 119 ++++++++++++++++--- cloudtrail/versions.tf | 14 +++ examples/cloudtrail/cloudtrail_full.tf | 38 ++++++ examples/cloudtrail/cloudtrail_simple.tf | 18 +++ examples/cloudtrail/org_cloudtrail_simple.tf | 23 ++++ 10 files changed, 329 insertions(+), 40 deletions(-) create mode 100644 cloudtrail-key/versions.tf create mode 100644 cloudtrail/versions.tf create mode 100644 examples/cloudtrail/cloudtrail_full.tf create mode 100644 examples/cloudtrail/cloudtrail_simple.tf create mode 100644 examples/cloudtrail/org_cloudtrail_simple.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index b17f01c..a72b45a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -129,4 +129,6 @@ * v1.14.0 -- 20211115 - cloudtrail-key - - create module to setup a KMS ke per region for cloudtrail + - create module to setup a KMS key per region for cloudtrail + - cloudtrail + - create module to setup needed resources for cloudtrail, cloudwatch logs, sns, sqs, and splunk diff --git a/README.md b/README.md index dccaf0b..f852f84 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,23 @@ This sets the SES domain of the form `{account_id}.aws.mail.census.gov`. At this so be sure run it in the west region for govcloud. ### object-logging -### cloudtrail -### config + +This is in its own module [aws-setup-s3-object-logging](https://github.e.it.census.gov/terraform-modules/aws-setup-s3-object-logging). + +### [cloudtrail-key](cloudtrail-key) + +This creates a KMS key (region specific) for use by CloudTrail and all its resources (Cloudwatch Log, SNS, SQS, S3). + +### [cloudtrail](cloudtrail) + +This creates a CloudTrail (region specific) and supporing resources Cloudwatch Log, SNS, SQS, S3. It requires a KMS +key created specifically for this, from [cloudtrail-key](cloudtrail-key) above. It also creates Splunk input +configuration files. + +### [config](config) + +This creates the Config setup, a few Config Rules, SNS and SQS and Splunk input configurations files. + ### gpg-key ## Submodules :: Common diff --git a/cloudtrail-key/README.md b/cloudtrail-key/README.md index 176d26d..61a86d0 100644 --- a/cloudtrail-key/README.md +++ b/cloudtrail-key/README.md @@ -47,13 +47,16 @@ module "cloudtrail_key_full" { ## Requirements -No requirements. +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.12 | +| [aws](#requirement\_aws) | >= 3.66.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | n/a | +| [aws](#provider\_aws) | >= 3.66.0 | ## Modules diff --git a/cloudtrail-key/versions.tf b/cloudtrail-key/versions.tf new file mode 100644 index 0000000..3d116e6 --- /dev/null +++ b/cloudtrail-key/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 3.66.0" + } + # ldap = { + # source = "trevex/ldap" + # version = ">= 0.5.4" + # } + } + required_version = ">= 0.12" + # required_version = ">= 0.13" +} diff --git a/cloudtrail/README.md b/cloudtrail/README.md index 7beb7af..a3af4b0 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -5,48 +5,129 @@ cloudwatch log groups, and associated permissions. It also generates a splunk c for pulling cloudtrail events. * S3 bucket -* S3 bucket policy +* SNS Topic +* SQS Queue (and Deadletter queue) +* Cloudwatch Log +* setup/*.conf files for Splunk + * inputs.{name}.{account}.{region}.conf -# Usage -Here is a simple example, the one most commonly expected to be used. +Once setup, the gnerated Splunk configuration files can be provided to the Splunk team for ingesting +as CloudTrail. + +## Usage: Simple + +This siomple configuration is how it will typically be deployed. ```hcl +module "cloudtrail_key" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" + + tags = local.common_tags +} + 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" ] + account_alias = var.account_alias + access_log_bucket = module.logs.bucket_id + kms_key_arn = module.cloudtrail_key.kms_key_arn + + enable_sns = true + enable_sqs = true + + tags = local.common_tags } ``` -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. +## Usage: Extended + +This shows the creation of a key with additional variables, along with a policy for key access (currently +just a placholder), and the cloudtrail with more variables offered. ```hcl -module "cloudtrail_full" { +module "cloudtrail_key" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" + + name = "mycloudtrail" + kms_admin_roles = ["arn:aws:iam::079788916859:role/r-inf-cloud-admin"] + kms_policy_document = data.aws_iam_policy_document.myct_policy.json - # logs is generally not needed and not recommended - component_tags = { - "s3" = { + tags = { + Environment = "csvd:infrastructure" + } + + component_tags = { + "kms" = { "SpecialTag1" = "something" "SpecialTag2" = "somethingElse" } } } + +data "aws_iam_policy_document" "myct_policy" {} + +module "cloudtrail" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail" + + name = "mycloudtrail" + account_alias = var.account_alias + access_log_bucket = module.logs.bucket_id + kms_key_arn = module.cloudtrail_key.kms_key_arn + + enable_organization = false + enable_sns = true + enable_sqs = true + + tags = merge( + local.common_tags, + tomap({ Environment = "csvd:infrastructure" }), + ) +} +```hcl + +## Usage: Organization Cloudtrail + +This can be used for creation of an organization cloud trail. It is only applicable to the master +account of the organization, so you won't see this one used very often. + +```hcl +data "aws_organizations_organization" "org" {} + +module "org_cloudtrail_key" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" + + name = "org-cloudtrail" + tags = local.common_tags +} + +module "org_cloudtrail" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail" + + account_alias = var.account_alias + enable_organization = true + access_log_bucket = module.logs.bucket_id + kms_key_arn = module.org_cloudtrail_key.kms_key_arn + organization_id = data.aws_organizations_organization.org.id + + enable_sns = true + enable_sqs = true + + tags = local.common_tags +} ``` ## Requirements -No requirements. +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.12 | +| [aws](#requirement\_aws) | >= 3.66.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | n/a | +| [aws](#provider\_aws) | >= 3.66.0 | | [null](#provider\_null) | n/a | | [random](#provider\_random) | n/a | | [template](#provider\_template) | n/a | diff --git a/cloudtrail/main.tf b/cloudtrail/main.tf index be9b9af..31682eb 100644 --- a/cloudtrail/main.tf +++ b/cloudtrail/main.tf @@ -4,39 +4,118 @@ * 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 +* * SNS Topic +* * SQS Queue (and Deadletter queue) +* * Cloudwatch Log +* * setup/*.conf files for Splunk +* * inputs.{name}.{account}.{region}.conf * -* # Usage -* Here is a simple example, the one most commonly expected to be used. +* Once setup, the gnerated Splunk configuration files can be provided to the Splunk team for ingesting +* as CloudTrail. * +* ## Usage: Simple +* +* This siomple configuration is how it will typically be deployed. +* * ```hcl +* module "cloudtrail_key" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" +* +* tags = local.common_tags +* } +* * 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" ] +* +* account_alias = var.account_alias +* access_log_bucket = module.logs.bucket_id +* kms_key_arn = module.cloudtrail_key.kms_key_arn +* +* enable_sns = true +* enable_sqs = true +* +* tags = local.common_tags * } * ``` -* -* 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. -* +* +* ## Usage: Extended +* +* This shows the creation of a key with additional variables, along with a policy for key access (currently +* just a placholder), and the cloudtrail with more variables offered. +* * ```hcl -* module "cloudtrail_full" { -* -* # logs is generally not needed and not recommended -* component_tags = { -* "s3" = { +* module "cloudtrail_key" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" +* +* name = "mycloudtrail" +* kms_admin_roles = ["arn:aws:iam::079788916859:role/r-inf-cloud-admin"] +* kms_policy_document = data.aws_iam_policy_document.myct_policy.json +* +* tags = { +* Environment = "csvd:infrastructure" +* } +* +* component_tags = { +* "kms" = { * "SpecialTag1" = "something" * "SpecialTag2" = "somethingElse" * } * } * } +* +* data "aws_iam_policy_document" "myct_policy" {} +* +* module "cloudtrail" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail" +* +* name = "mycloudtrail" +* account_alias = var.account_alias +* access_log_bucket = module.logs.bucket_id +* kms_key_arn = module.cloudtrail_key.kms_key_arn +* +* enable_organization = false +* enable_sns = true +* enable_sqs = true +* +* tags = merge( +* local.common_tags, +* tomap({ Environment = "csvd:infrastructure" }), +* ) +* } +* ```hcl +* +* +* ## Usage: Organization Cloudtrail +* +* This can be used for creation of an organization cloud trail. It is only applicable to the master +* account of the organization, so you won't see this one used very often. +* +* ```hcl +* data "aws_organizations_organization" "org" {} +* +* module "org_cloudtrail_key" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" +* +* name = "org-cloudtrail" +* tags = local.common_tags +* } +* +* module "org_cloudtrail" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail" +* +* account_alias = var.account_alias +* enable_organization = true +* access_log_bucket = module.logs.bucket_id +* kms_key_arn = module.org_cloudtrail_key.kms_key_arn +* organization_id = data.aws_organizations_organization.org.id +* +* enable_sns = true +* enable_sqs = true +* +* tags = local.common_tags +* } * ``` */ @@ -77,3 +156,5 @@ data "aws_kms_key" "incoming_key" { # data "aws_organizations_organization" "org" {} + + diff --git a/cloudtrail/versions.tf b/cloudtrail/versions.tf new file mode 100644 index 0000000..3d116e6 --- /dev/null +++ b/cloudtrail/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 3.66.0" + } + # ldap = { + # source = "trevex/ldap" + # version = ">= 0.5.4" + # } + } + required_version = ">= 0.12" + # required_version = ">= 0.13" +} diff --git a/examples/cloudtrail/cloudtrail_full.tf b/examples/cloudtrail/cloudtrail_full.tf new file mode 100644 index 0000000..d70f5c0 --- /dev/null +++ b/examples/cloudtrail/cloudtrail_full.tf @@ -0,0 +1,38 @@ +module "cloudtrail_key" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" + + name = "mycloudtrail" + kms_admin_roles = ["arn:aws:iam::079788916859:role/r-inf-cloud-admin"] + kms_policy_document = data.aws_iam_policy_document.myct_policy.json + + tags = { + Environment = "csvd:infrastructure" + } + + component_tags = { + "kms" = { + "SpecialTag1" = "something" + "SpecialTag2" = "somethingElse" + } + } +} + +data "aws_iam_policy_document" "myct_policy" {} + +module "cloudtrail" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail" + + name = "mycloudtrail" + account_alias = var.account_alias + access_log_bucket = module.logs.bucket_id + kms_key_arn = module.cloudtrail_key.kms_key_arn + + enable_organization = false + enable_sns = true + enable_sqs = true + + tags = merge( + local.common_tags, + tomap({ Environment = "csvd:infrastructure" }), + ) +} diff --git a/examples/cloudtrail/cloudtrail_simple.tf b/examples/cloudtrail/cloudtrail_simple.tf new file mode 100644 index 0000000..329599a --- /dev/null +++ b/examples/cloudtrail/cloudtrail_simple.tf @@ -0,0 +1,18 @@ +module "cloudtrail_key" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" + + tags = local.common_tags +} + +module "cloudtrail" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail" + + account_alias = var.account_alias + access_log_bucket = module.logs.bucket_id + kms_key_arn = module.cloudtrail_key.kms_key_arn + + enable_sns = true + enable_sqs = true + + tags = local.common_tags +} diff --git a/examples/cloudtrail/org_cloudtrail_simple.tf b/examples/cloudtrail/org_cloudtrail_simple.tf new file mode 100644 index 0000000..409f0ef --- /dev/null +++ b/examples/cloudtrail/org_cloudtrail_simple.tf @@ -0,0 +1,23 @@ +data "aws_organizations_organization" "org" {} + +module "org_cloudtrail_key" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail-key" + + name = "org-cloudtrail" + tags = local.common_tags +} + +module "org_cloudtrail" { + source = "git@github.e.it.census.gov:terraform-modules/aws-inf-setup.git//cloudtrail" + + account_alias = var.account_alias + enable_organization = true + access_log_bucket = module.logs.bucket_id + kms_key_arn = module.org_cloudtrail_key.kms_key_arn + organization_id = data.aws_organizations_organization.org.id + + enable_sns = true + enable_sqs = true + + tags = local.common_tags +}