diff --git a/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/README.md b/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/README.md index e93c96de4..5e83d5f22 100644 --- a/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/README.md +++ b/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/README.md @@ -15,6 +15,8 @@ No requirements. | [cis\_alarms](#module\_cis\_alarms) | cloudposse/cloudtrail-cloudwatch-alarms/aws | 0.14.3 | | [cloudtrail](#module\_cloudtrail) | cloudposse/cloudtrail/aws | 0.17.0 | | [cloudtrail\_s3\_bucket](#module\_cloudtrail\_s3\_bucket) | github.com/ManagedKube/terraform-aws-cloudtrail-s3-bucket.git// | 0.24.0 | +| [kms\_cloudtrail](#module\_kms\_cloudtrail) | github.com/ManagedKube/kubernetes-ops.git//terraform-modules/aws/kms/cloudtrail | feat-kms-cloudtrail | +| [kms\_cloudwatch\_log\_group](#module\_kms\_cloudwatch\_log\_group) | github.com/ManagedKube/kubernetes-ops.git//terraform-modules/aws/kms/cloudwatch_log_group | v2.0.37 | | [metric\_configs](#module\_metric\_configs) | cloudposse/config/yaml | 0.7.0 | | [this](#module\_this) | cloudposse/label/null | 0.25.0 | @@ -28,6 +30,8 @@ No requirements. | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.assume_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.log_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs @@ -47,6 +51,12 @@ No requirements. | [force\_destroy](#input\_force\_destroy) | (Optional, Default:false ) A boolean that indicates all objects should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable | `bool` | `false` | no | | [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for keep the existing setting, which defaults to `0`.
Does not affect `id_full`. | `number` | `null` | no | | [is\_multi\_region\_trail](#input\_is\_multi\_region\_trail) | Specifies whether the trail is created in the current region or in all regions | `bool` | `true` | no | +| [kms\_cloudtrail\_deletion\_window\_in\_days](#input\_kms\_cloudtrail\_deletion\_window\_in\_days) | The waiting period, specified in number of days. After the waiting period ends, AWS KMS deletes the KMS key. (cloudtrail-trails) | `number` | `30` | no | +| [kms\_cloudtrail\_enable](#input\_kms\_cloudtrail\_enable) | It will create for you a standard kms for cloudwatch that will free it from possible vulnerabilities.. (cloudwatch-loggroup) | `bool` | `true` | no | +| [kms\_cloudtrail\_kms\_enable\_key\_rotation](#input\_kms\_cloudtrail\_kms\_enable\_key\_rotation) | Specifies whether key rotation is enabled. Defaults to false. (cloudtrail-trails) | `bool` | `true` | no | +| [kms\_cloudwatch\_loggroup\_deletion\_window\_in\_days](#input\_kms\_cloudwatch\_loggroup\_deletion\_window\_in\_days) | The waiting period, specified in number of days. After the waiting period ends, AWS KMS deletes the KMS key. (cloudwatch-loggroup) | `number` | `30` | no | +| [kms\_cloudwatch\_loggroup\_enable](#input\_kms\_cloudwatch\_loggroup\_enable) | It will create for you a standard kms for cloudwatch that will free it from possible vulnerabilities. (cloudwatch-loggroup) | `bool` | `true` | no | +| [kms\_cloudwatch\_loggroup\_kms\_enable\_key\_rotation](#input\_kms\_cloudwatch\_loggroup\_kms\_enable\_key\_rotation) | Specifies whether key rotation is enabled. Defaults to false. (cloudwatch-loggroup) | `bool` | `true` | no | | [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | | [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no | | [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
Default value: `lower`. | `string` | `null` | no | @@ -70,51 +80,3 @@ No requirements. | [dashboard\_combined](#output\_dashboard\_combined) | n/a | | [dashboard\_individual](#output\_dashboard\_individual) | n/a | | [sns\_topic\_arn](#output\_sns\_topic\_arn) | n/a | - -## What does it solve? - -https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#cis-1.1-remediation -https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#cis-3.3-remediation -- 1.1 – Avoid the use of the "root" account -- 3.3 – Ensure a log metric filter and alarm exist for usage of "root" account -https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-3.8 -- 3.1 – Ensure a log metric filter and alarm exist for unauthorized API calls -- 3.2 – Ensure a log metric filter and alarm exist for AWS Management Console sign-in without MFA -- 3.4 – Ensure a log metric filter and alarm exist for IAM policy changes -- 3.5 – Ensure a log metric filter and alarm exist for CloudTrail configuration changes -- 3.6 – Ensure a log metric filter and alarm exist for AWS Management Console authentication failures -- 3.7 – Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs -- 3.8 – Ensure a log metric filter and alarm exist for S3 bucket policy changes -- 3.9 – Ensure a log metric filter and alarm exist for AWS Config configuration changes -- 3.10 – Ensure a log metric filter and alarm exist for security group changes -- 3.11 – Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) -- 3.12 – Ensure a log metric filter and alarm exist for changes to network gateways -- 3.13 – Ensure a log metric filter and alarm exist for route table changes -- 3.14 – Ensure a log metric filter and alarm exist for VPC changes - -## Best practice for adding alarms ? -We recommend adding this file through the input variable: ```input_metrics_paths``` -``` -metrics_paths = ["./cis_benchmark.yaml"] -``` -https://github.com/cloudposse/terraform-aws-cloudtrail-cloudwatch-alarms/blob/master/catalog/cis_benchmark.yaml - -If you want to add more alerts or modify existing alerts, you can use the following format: - -``` -ec2-instance-event-count: - metric_name: "EC2InstanceEventCount" - filter_pattern: - "{ ($.eventName = RunInstances) || ($.eventName = RebootInstances) || ($.eventName = StartInstances) || ($.eventName - = StopInstances) || ($.eventName = TerminateInstances) }" - metric_namespace: "CISBenchmark" - alarm_description: "Alarms when an API call is made to create, terminate, start, stop or reboot an EC2 instance." - metric_value: "1" - alarm_name: "EC2InstanceEventCountExceeded" - alarm_comparison_operator: "GreaterThanOrEqualToThreshold" - alarm_evaluation_periods: "1" - alarm_period: "300" - alarm_statistic: "Sum" - alarm_treat_missing_data: "notBreaching" - alarm_threshold: "1" -``` \ No newline at end of file diff --git a/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/main.tf b/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/main.tf index 040ff80ac..b7571ad64 100644 --- a/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/main.tf +++ b/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/main.tf @@ -1,95 +1,23 @@ -locals { - arn_format = "arn:${data.aws_partition.current.partition}" -} data "aws_partition" "current" {} data "aws_caller_identity" "current" {} data "aws_region" "current" {} -## Everything after this is standard cloudtrail setup -/*ToDo: We are collaborating with cloudposse to bring this solution to your project, we have the task of following up this pr to integrate it - and return to the direct version of cloudposse. - - Cloudposse' issue: New input variable s3_object_ownership cloudposse/terraform-aws-cloudtrail-s3-bucket#62 - Cloudposse' pr: add input var s3_object_ownership cloudposse/terraform-aws-cloudtrail-s3-bucket#63 -*/ - -# --------------------------------------------------------------------------------------------------------------------- -# CREATE A KMS -# We can attach KMS to CloudWatch Log. -# --------------------------------------------------------------------------------------------------------------------- -data "aws_iam_policy_document" "kms" { - statement { - sid = "Enable Root User Permissions" - effect = "Allow" - - actions = [ - "kms:Create*", - "kms:Describe*", - "kms:Enable*", - "kms:List*", - "kms:Put*", - "kms:Update*", - "kms:Revoke*", - "kms:Disable*", - "kms:Get*", - "kms:Delete*", - "kms:Tag*", - "kms:Untag*", - "kms:ScheduleKeyDeletion", - "kms:CancelKeyDeletion" - ] - - #bridgecrew:skip=CKV_AWS_109:This policy applies only to the key it is attached to - #bridgecrew:skip=CKV_AWS_111:This policy applies only to the key it is attached to - resources = [ - "*" - ] - - principals { - type = "AWS" - - identifiers = [ - "${local.arn_format}:iam::${data.aws_caller_identity.current.account_id}:root" - ] - } - } - - statement { - sid = "Allow KMS to CloudWatch Log Group ${element(var.attributes,0)}" - effect = "Allow" - - actions = [ - "kms:Encrypt*", - "kms:Decrypt*", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - "kms:Describe*" - ] - - resources = [ - "*" - ] - - principals { - type = "Service" - - identifiers = [ - "logs.${data.aws_region.current.name}.amazonaws.com" - ] - } - condition { - test = "ArnEquals" - variable = "kms:EncryptionContext:aws:logs:arn" - values = ["arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:${element(var.attributes,0)}"] - } - } +module "kms_cloudwatch_log_group" { + count = var.kms_cloudwatch_loggroup_enable ? 1 : 0 + source = "github.com/ManagedKube/kubernetes-ops.git//terraform-modules/aws/kms/cloudwatch_log_group?ref=v2.0.39" + log_group_name = element(var.attributes, 0) + kms_deletion_window_in_days = var.kms_cloudwatch_loggroup_deletion_window_in_days + kms_enable_key_rotation = var.kms_cloudwatch_loggroup_kms_enable_key_rotation + tags = var.tags } -resource "aws_kms_key" "kms" { - description = "KMS key for ${element(var.attributes,0)}" - deletion_window_in_days = 10 - enable_key_rotation = true - policy = join("", data.aws_iam_policy_document.kms.*.json) +module "kms_cloudtrail" { + count = var.kms_cloudtrail_enable ? 1 : 0 + source = "github.com/ManagedKube/kubernetes-ops.git//terraform-modules/aws/kms/cloudtrail?ref=v2.0.39" + cloudtrail_name = element(var.attributes, 0) + kms_deletion_window_in_days = var.kms_cloudtrail_deletion_window_in_days + kms_enable_key_rotation = var.kms_cloudtrail_kms_enable_key_rotation + tags = var.tags } module "cloudtrail_s3_bucket" { @@ -110,7 +38,7 @@ resource "aws_cloudwatch_log_group" "default" { tags = module.this.tags retention_in_days = 365 #prowler issue: https://github.com/prowler-cloud/prowler/issues/1229 - kms_key_id = aws_kms_key.kms.arn + kms_key_id = var.kms_cloudwatch_loggroup_enable ? module.kms_cloudwatch_log_group[0].kms_arn : null } data "aws_iam_policy_document" "log_policy" { @@ -169,6 +97,7 @@ module "cloudtrail" { cloud_watch_logs_group_arn = "${aws_cloudwatch_log_group.default.arn}:*" cloud_watch_logs_role_arn = aws_iam_role.cloudtrail_cloudwatch_events_role.arn event_selector = var.cloudtrail_event_selector + kms_key_arn = var.kms_cloudtrail_enable ? module.kms_cloudtrail[0].kms_arn : null context = module.this.context } diff --git a/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/variables.tf b/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/variables.tf index bec3030fd..65fd01d34 100644 --- a/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/variables.tf +++ b/terraform-modules/aws/cloudposse/aws-cloudtrail-cloudwatch-alarms/variables.tf @@ -69,4 +69,42 @@ variable "restrict_public_buckets" { type = bool default = true description = "Set to `false` to disable the restricting of making the bucket public" +} + + +#KMS Variables +variable "kms_cloudwatch_loggroup_enable" { + type = bool + default = true + description = "It will create for you a standard kms for cloudwatch that will free it from possible vulnerabilities. (cloudwatch-loggroup)" +} + +variable "kms_cloudtrail_enable" { + type = bool + default = true + description = "It will create for you a standard kms for cloudwatch that will free it from possible vulnerabilities.. (cloudwatch-loggroup)" +} + +variable "kms_cloudwatch_loggroup_deletion_window_in_days" { + type = number + default = 30 + description = "The waiting period, specified in number of days. After the waiting period ends, AWS KMS deletes the KMS key. (cloudwatch-loggroup)" +} + +variable "kms_cloudwatch_loggroup_kms_enable_key_rotation" { + type = bool + default = true + description = "Specifies whether key rotation is enabled. Defaults to false. (cloudwatch-loggroup)" +} + +variable "kms_cloudtrail_deletion_window_in_days" { + type = number + default = 30 + description = "The waiting period, specified in number of days. After the waiting period ends, AWS KMS deletes the KMS key. (cloudtrail-trails)" +} + +variable "kms_cloudtrail_kms_enable_key_rotation" { + type = bool + default = true + description = "Specifies whether key rotation is enabled. Defaults to false. (cloudtrail-trails)" } \ No newline at end of file diff --git a/terraform-modules/aws/kms/cloudtrail/README.md b/terraform-modules/aws/kms/cloudtrail/README.md new file mode 100644 index 000000000..8b9c92469 --- /dev/null +++ b/terraform-modules/aws/kms/cloudtrail/README.md @@ -0,0 +1,39 @@ +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_kms_alias.a](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | +| [aws_kms_key.kms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.kms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | 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 | +|------|-------------|------|---------|:--------:| +| [cloudtrail\_name](#input\_cloudtrail\_name) | Cloudtrail/trail for attaching currently kms | `string` | `"cloudtrail-default"` | no | +| [kms\_deletion\_window\_in\_days](#input\_kms\_deletion\_window\_in\_days) | The waiting period, specified in number of days. After the waiting period ends, AWS KMS deletes the KMS key. | `number` | `30` | no | +| [kms\_enable\_key\_rotation](#input\_kms\_enable\_key\_rotation) | Specifies whether key rotation is enabled. Defaults to false. | `bool` | `true` | no | +| [tags](#input\_tags) | n/a | `map(any)` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [kms\_arn](#output\_kms\_arn) | Arn of kms created | diff --git a/terraform-modules/aws/kms/cloudtrail/main.tf b/terraform-modules/aws/kms/cloudtrail/main.tf new file mode 100644 index 000000000..7ef9ed034 --- /dev/null +++ b/terraform-modules/aws/kms/cloudtrail/main.tf @@ -0,0 +1,81 @@ +# This is a standard kms that frees any cloudtrail/trails from vulnerabilities. +# Docs: https://dev.to/aws-builders/encrypt-cloudtrail-logs-with-multi-region-key-with-terraform-1hln + +locals { + arn_format = "arn:${data.aws_partition.current.partition}" +} + +data "aws_partition" "current" {} +data "aws_caller_identity" "current" {} +data "aws_region" "current" {} + +data "aws_iam_policy_document" "kms" { + statement { + sid = "Enable Root User Permissions" + effect = "Allow" + + actions = [ + "kms:Create*", + "kms:Describe*", + "kms:Enable*", + "kms:List*", + "kms:Put*", + "kms:Update*", + "kms:Revoke*", + "kms:Disable*", + "kms:Get*", + "kms:Delete*", + "kms:Tag*", + "kms:Untag*", + "kms:ScheduleKeyDeletion", + "kms:CancelKeyDeletion" + ] + + #bridgecrew:skip=CKV_AWS_109:This policy applies only to the key it is attached to + #bridgecrew:skip=CKV_AWS_111:This policy applies only to the key it is attached to + resources = [ + "*" + ] + + principals { + type = "AWS" + + identifiers = [ + "${local.arn_format}:iam::${data.aws_caller_identity.current.account_id}:root" + ] + } + } + statement { + sid = "Allow CloudTrail to encrypt - ${var.cloudtrail_name}" + effect = "Allow" + actions = ["kms:GenerateDataKey*"] + resources = ["*"] + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + condition { + test = "StringLike" + variable = "kms:EncryptionContext:aws:cloudtrail:arn" + values = ["arn:aws:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/${var.cloudtrail_name}"] + } + condition { + test = "StringEquals" + variable = "aws:SourceArn" + values = ["arn:aws:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/${var.cloudtrail_name}"] + } + } +} + +resource "aws_kms_alias" "a" { + name = "alias/${var.cloudtrail_name}" + target_key_id = aws_kms_key.kms.key_id +} + +resource "aws_kms_key" "kms" { + description = "KMS key for cloudtrail: ${var.cloudtrail_name}" + deletion_window_in_days = var.kms_deletion_window_in_days + enable_key_rotation = var.kms_enable_key_rotation + policy = join("", data.aws_iam_policy_document.kms.*.json) + tags = var.tags +} diff --git a/terraform-modules/aws/kms/cloudtrail/outputs.tf b/terraform-modules/aws/kms/cloudtrail/outputs.tf new file mode 100644 index 000000000..512e7b3d0 --- /dev/null +++ b/terraform-modules/aws/kms/cloudtrail/outputs.tf @@ -0,0 +1,4 @@ +output "kms_arn" { + description = "Arn of kms created" + value = aws_kms_key.kms.arn +} \ No newline at end of file diff --git a/terraform-modules/aws/kms/cloudtrail/variables.tf b/terraform-modules/aws/kms/cloudtrail/variables.tf new file mode 100644 index 000000000..1688752c6 --- /dev/null +++ b/terraform-modules/aws/kms/cloudtrail/variables.tf @@ -0,0 +1,21 @@ +variable "cloudtrail_name" { + type = string + default = "cloudtrail-default" + description = "Cloudtrail/trail for attaching currently kms" +} + +variable "kms_deletion_window_in_days" { + type = number + default = 30 + description = "The waiting period, specified in number of days. After the waiting period ends, AWS KMS deletes the KMS key." +} + +variable "kms_enable_key_rotation" { + type = bool + default = true + description = "Specifies whether key rotation is enabled. Defaults to false." +} + +variable "tags" { + type = map(any) +} \ No newline at end of file diff --git a/terraform-modules/aws/kms/cloudwatch_log_group/README.md b/terraform-modules/aws/kms/cloudwatch_log_group/README.md index 0d107aa32..39fd63a69 100644 --- a/terraform-modules/aws/kms/cloudwatch_log_group/README.md +++ b/terraform-modules/aws/kms/cloudwatch_log_group/README.md @@ -26,6 +26,8 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [kms\_deletion\_window\_in\_days](#input\_kms\_deletion\_window\_in\_days) | The waiting period, specified in number of days. After the waiting period ends, AWS KMS deletes the KMS key. | `number` | `30` | no | +| [kms\_enable\_key\_rotation](#input\_kms\_enable\_key\_rotation) | Specifies whether key rotation is enabled. Defaults to false. | `bool` | `true` | no | | [log\_group\_name](#input\_log\_group\_name) | Log group name of cloud watch | `string` | `"log-group-default"` | no | | [tags](#input\_tags) | n/a | `map(any)` | n/a | yes | diff --git a/terraform-modules/aws/kms/cloudwatch_log_group/main.tf b/terraform-modules/aws/kms/cloudwatch_log_group/main.tf index 29afbcfce..0373378a8 100644 --- a/terraform-modules/aws/kms/cloudwatch_log_group/main.tf +++ b/terraform-modules/aws/kms/cloudwatch_log_group/main.tf @@ -82,8 +82,8 @@ data "aws_iam_policy_document" "kms" { resource "aws_kms_key" "kms" { description = "KMS key for log-group: ${var.log_group_name}" - deletion_window_in_days = 10 - enable_key_rotation = true + deletion_window_in_days = var.kms_deletion_window_in_days + enable_key_rotation = var.kms_enable_key_rotation policy = join("", data.aws_iam_policy_document.kms.*.json) tags = var.tags } diff --git a/terraform-modules/aws/kms/cloudwatch_log_group/variables.tf b/terraform-modules/aws/kms/cloudwatch_log_group/variables.tf index d17d0f944..42ed7e677 100644 --- a/terraform-modules/aws/kms/cloudwatch_log_group/variables.tf +++ b/terraform-modules/aws/kms/cloudwatch_log_group/variables.tf @@ -4,6 +4,19 @@ variable "log_group_name" { description = "Log group name of cloud watch" } +variable "kms_deletion_window_in_days" { + type = number + default = 30 + description = "The waiting period, specified in number of days. After the waiting period ends, AWS KMS deletes the KMS key." +} + +variable "kms_enable_key_rotation" { + type = bool + default = true + description = "Specifies whether key rotation is enabled. Defaults to false." +} + + variable "tags" { type = map(any) } \ No newline at end of file