Skip to content

Commit

Permalink
Feat add kms cloudtrail (#362)
Browse files Browse the repository at this point in the history
  • Loading branch information
bcarranza authored Jul 18, 2022
1 parent 3db7add commit 666deaf
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ No requirements.
| <a name="module_cis_alarms"></a> [cis\_alarms](#module\_cis\_alarms) | cloudposse/cloudtrail-cloudwatch-alarms/aws | 0.14.3 |
| <a name="module_cloudtrail"></a> [cloudtrail](#module\_cloudtrail) | cloudposse/cloudtrail/aws | 0.17.0 |
| <a name="module_cloudtrail_s3_bucket"></a> [cloudtrail\_s3\_bucket](#module\_cloudtrail\_s3\_bucket) | github.com/ManagedKube/terraform-aws-cloudtrail-s3-bucket.git// | 0.24.0 |
| <a name="module_kms_cloudtrail"></a> [kms\_cloudtrail](#module\_kms\_cloudtrail) | github.com/ManagedKube/kubernetes-ops.git//terraform-modules/aws/kms/cloudtrail | feat-kms-cloudtrail |
| <a name="module_kms_cloudwatch_log_group"></a> [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 |
| <a name="module_metric_configs"></a> [metric\_configs](#module\_metric\_configs) | cloudposse/config/yaml | 0.7.0 |
| <a name="module_this"></a> [this](#module\_this) | cloudposse/label/null | 0.25.0 |

Expand All @@ -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

Expand All @@ -47,6 +51,12 @@ No requirements.
| <a name="input_force_destroy"></a> [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 |
| <a name="input_id_length_limit"></a> [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).<br>Set to `0` for unlimited length.<br>Set to `null` for keep the existing setting, which defaults to `0`.<br>Does not affect `id_full`. | `number` | `null` | no |
| <a name="input_is_multi_region_trail"></a> [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 |
| <a name="input_kms_cloudtrail_deletion_window_in_days"></a> [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 |
| <a name="input_kms_cloudtrail_enable"></a> [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 |
| <a name="input_kms_cloudtrail_kms_enable_key_rotation"></a> [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 |
| <a name="input_kms_cloudwatch_loggroup_deletion_window_in_days"></a> [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 |
| <a name="input_kms_cloudwatch_loggroup_enable"></a> [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 |
| <a name="input_kms_cloudwatch_loggroup_kms_enable_key_rotation"></a> [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 |
| <a name="input_label_key_case"></a> [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.<br>Does not affect keys of tags passed in via the `tags` input.<br>Possible values: `lower`, `title`, `upper`.<br>Default value: `title`. | `string` | `null` | no |
| <a name="input_label_order"></a> [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.<br>Defaults to ["namespace", "environment", "stage", "name", "attributes"].<br>You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no |
| <a name="input_label_value_case"></a> [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,<br>set as tag values, and output by this module individually.<br>Does not affect values of tags passed in via the `tags` input.<br>Possible values: `lower`, `title`, `upper` and `none` (no transformation).<br>Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.<br>Default value: `lower`. | `string` | `null` | no |
Expand All @@ -70,51 +80,3 @@ No requirements.
| <a name="output_dashboard_combined"></a> [dashboard\_combined](#output\_dashboard\_combined) | n/a |
| <a name="output_dashboard_individual"></a> [dashboard\_individual](#output\_dashboard\_individual) | n/a |
| <a name="output_sns_topic_arn"></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"
```
Original file line number Diff line number Diff line change
@@ -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" {
Expand All @@ -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" {
Expand Down Expand Up @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
}
39 changes: 39 additions & 0 deletions terraform-modules/aws/kms/cloudtrail/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
## Requirements

No requirements.

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [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 |
|------|-------------|------|---------|:--------:|
| <a name="input_cloudtrail_name"></a> [cloudtrail\_name](#input\_cloudtrail\_name) | Cloudtrail/trail for attaching currently kms | `string` | `"cloudtrail-default"` | no |
| <a name="input_kms_deletion_window_in_days"></a> [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 |
| <a name="input_kms_enable_key_rotation"></a> [kms\_enable\_key\_rotation](#input\_kms\_enable\_key\_rotation) | Specifies whether key rotation is enabled. Defaults to false. | `bool` | `true` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | n/a | `map(any)` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_kms_arn"></a> [kms\_arn](#output\_kms\_arn) | Arn of kms created |
81 changes: 81 additions & 0 deletions terraform-modules/aws/kms/cloudtrail/main.tf
Original file line number Diff line number Diff line change
@@ -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
}
4 changes: 4 additions & 0 deletions terraform-modules/aws/kms/cloudtrail/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output "kms_arn" {
description = "Arn of kms created"
value = aws_kms_key.kms.arn
}
Loading

0 comments on commit 666deaf

Please sign in to comment.