diff --git a/CHANGELOG.md b/CHANGELOG.md index c9f44a5..c6f6219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## 0.11.0 (2021-09-22) + +- Add additional IAM activity monitors ([#119](https://github.com/schubergphilis/terraform-aws-mcaf-landing-zone/pull/119)) + ## 0.10.6 (2021-09-13) - Upgrade Datadog MCAF module used in core accounts to latest version ([#118](https://github.com/schubergphilis/terraform-aws-mcaf-landing-zone/pull/118)) diff --git a/README.md b/README.md index 5e1b20c..1434e5e 100644 --- a/README.md +++ b/README.md @@ -313,6 +313,7 @@ module "landing_zone" { | kms\_key\_policy | A valid KMS key policy JSON document | `string` | `""` | no | | monitor\_iam\_activity | Whether IAM activity should be monitored | `bool` | `true` | no | | monitor\_iam\_activity\_sns\_subscription | Subscription options for the LandingZone-IAMActivity SNS topic |
map(object({
endpoint = string
protocol = string
}))
| `{}` | no | +| security\_hub\_create\_cis\_metric\_filters | Enable the creation of metric filters related to the CIS AWS Foundation Security Hub Standard | `bool` | `true` | no | | security\_hub\_standards\_arns | A list of the ARNs of the standards you want to enable in Security Hub | `list(string)` | `null` | no | ## Outputs diff --git a/audit.tf b/audit.tf index 02265fe..a36f243 100644 --- a/audit.tf +++ b/audit.tf @@ -22,7 +22,7 @@ module "kms_key_audit" { } resource "aws_cloudwatch_log_metric_filter" "iam_activity_audit" { - for_each = var.monitor_iam_activity ? local.iam_activity : {} + for_each = var.monitor_iam_activity ? merge(local.iam_activity, local.cloudtrail_activity_cis_aws_foundations) : {} provider = aws.audit name = "LandingZone-IAMActivity-${each.key}" @@ -173,7 +173,7 @@ resource "aws_sns_topic" "security_hub_findings" { resource "aws_sns_topic_policy" "security_hub_findings" { provider = aws.audit arn = aws_sns_topic.security_hub_findings.arn - policy = templatefile("${path.module}/files/sns/topic_policy.json.tpl", { + policy = templatefile("${path.module}/files/sns/security_hub_topic_policy.json.tpl", { account_id = data.aws_caller_identity.audit.account_id services_allowed_publish = jsonencode("events.amazonaws.com") sns_topic = aws_sns_topic.security_hub_findings.arn @@ -209,10 +209,14 @@ resource "aws_sns_topic" "iam_activity" { resource "aws_sns_topic_policy" "iam_activity" { provider = aws.audit arn = aws_sns_topic.iam_activity.arn - policy = templatefile("${path.module}/files/sns/topic_policy.json.tpl", { + policy = templatefile("${path.module}/files/sns/iam_activity_topic_policy.json.tpl", { account_id = data.aws_caller_identity.audit.account_id services_allowed_publish = jsonencode("cloudwatch.amazonaws.com") sns_topic = aws_sns_topic.iam_activity.arn + security_hub_roles = local.security_hub_has_cis_aws_foundations_enabled ? sort([ + for account_id, _ in local.aws_account_emails : "\"arn:aws:sts::${account_id}:assumed-role/AWSServiceRoleForSecurityHub/securityhub\"" + if account_id != var.control_tower_account_ids.audit + ]) : [] }) } diff --git a/files/sns/iam_activity_topic_policy.json.tpl b/files/sns/iam_activity_topic_policy.json.tpl new file mode 100644 index 0000000..3ad3daf --- /dev/null +++ b/files/sns/iam_activity_topic_policy.json.tpl @@ -0,0 +1,50 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "__default_statement_ID", + "Effect": "Allow", + "Principal": { + "AWS": "*" + }, + "Action": [ + "SNS:Subscribe", + "SNS:SetTopicAttributes", + "SNS:RemovePermission", + "SNS:Receive", + "SNS:Publish", + "SNS:ListSubscriptionsByTopic", + "SNS:GetTopicAttributes", + "SNS:DeleteTopic", + "SNS:AddPermission" + ], + "Resource": "${sns_topic}", + "Condition": { + "StringEquals": { + "AWS:SourceOwner": "${account_id}" + } + } + }, + { + "Sid": "__services_allowed_publish", + "Effect": "Allow", + "Principal": { + "Service": ${services_allowed_publish} + }, + "Action": "sns:Publish", + "Resource": "${sns_topic}" + } + %{ if length(security_hub_roles) > 0 ~} + , + { + "Sid": "AllowListSubscribersBySecurityHub", + "Effect": "Allow", + "Principal": { + "AWS": [ ${join(", ", security_hub_roles)} ] + }, + "Action": "sns:ListSubscriptionsByTopic", + "Resource": "${sns_topic}" + } + %{ endif ~} + ] +} diff --git a/files/sns/topic_policy.json.tpl b/files/sns/security_hub_topic_policy.json.tpl similarity index 100% rename from files/sns/topic_policy.json.tpl rename to files/sns/security_hub_topic_policy.json.tpl diff --git a/locals.tf b/locals.tf index 2858afb..fdf2f68 100644 --- a/locals.tf +++ b/locals.tf @@ -31,12 +31,29 @@ locals { ] ]) iam_activity = { - Root = "{$.userIdentity.type=\"Root\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \"AwsServiceEvent\"}" - SSO = "{$.readOnly IS FALSE && $.userIdentity.sessionContext.sessionIssuer.userName = \"AWSReservedSSO_*\" && $.eventName != \"ConsoleLogin\"}" + SSO = "{$.readOnly IS FALSE && $.userIdentity.sessionContext.sessionIssuer.userName = \"AWSReservedSSO_*\" && $.eventName != \"ConsoleLogin\"}" } + cloudtrail_activity_cis_aws_foundations = (local.security_hub_has_cis_aws_foundations_enabled && var.security_hub_create_cis_metric_filters) ? { + RootActivity = "{$.userIdentity.type=\"Root\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \"AwsServiceEvent\"}" + UnauthorizedApiCalls = "{($.errorCode=\"*UnauthorizedOperation\") || ($.errorCode=\"AccessDenied*\")}" + IamPolicyChanges = "{($.eventName=DeleteGroupPolicy) || ($.eventName=DeleteRolePolicy) || ($.eventName=DeleteUserPolicy) || ($.eventName=PutGroupPolicy) || ($.eventName=PutRolePolicy) || ($.eventName=PutUserPolicy) || ($.eventName=CreatePolicy) || ($.eventName=DeletePolicy) || ($.eventName=CreatePolicyVersion) || ($.eventName=DeletePolicyVersion) || ($.eventName=AttachRolePolicy) || ($.eventName=DetachRolePolicy) || ($.eventName=AttachUserPolicy) || ($.eventName=DetachUserPolicy) || ($.eventName=AttachGroupPolicy) || ($.eventName=DetachGroupPolicy)}" + CloudTrailConfigChange = "{($.eventName=CreateTrail) || ($.eventName=UpdateTrail) || ($.eventName=DeleteTrail) || ($.eventName=StartLogging) || ($.eventName=StopLogging)}" + ManagementConsoleAuthFailure = "{($.eventName=ConsoleLogin) && ($.errorMessage=\"Failed authentication\")}" + KmsKeyDisableOrDeletion = "{($.eventSource=kms.amazonaws.com) && (($.eventName=DisableKey) || ($.eventName=ScheduleKeyDeletion))}" + S3BucketPolicyChange = "{($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))}" + AwsConfigConfigChange = "{($.eventSource=config.amazonaws.com) && (($.eventName=StopConfigurationRecorder) || ($.eventName=DeleteDeliveryChannel) || ($.eventName=PutDeliveryChannel) || ($.eventName=PutConfigurationRecorder))}" + SecurityGroupChange = "{($.eventName=AuthorizeSecurityGroupIngress) || ($.eventName=AuthorizeSecurityGroupEgress) || ($.eventName=RevokeSecurityGroupIngress) || ($.eventName=RevokeSecurityGroupEgress) || ($.eventName=CreateSecurityGroup) || ($.eventName=DeleteSecurityGroup)}" + NaclChange = "{($.eventName=CreateNetworkAcl) || ($.eventName=CreateNetworkAclEntry) || ($.eventName=DeleteNetworkAcl) || ($.eventName=DeleteNetworkAclEntry) || ($.eventName=ReplaceNetworkAclEntry) || ($.eventName=ReplaceNetworkAclAssociation)}" + NetworkGatewayChange = "{($.eventName=CreateCustomerGateway) || ($.eventName=DeleteCustomerGateway) || ($.eventName=AttachInternetGateway) || ($.eventName=CreateInternetGateway) || ($.eventName=DeleteInternetGateway) || ($.eventName=DetachInternetGateway)}" + RouteTableChange = "{($.eventName=CreateRoute) || ($.eventName=CreateRouteTable) || ($.eventName=ReplaceRoute) || ($.eventName=ReplaceRouteTableAssociation) || ($.eventName=DeleteRouteTable) || ($.eventName=DeleteRoute) || ($.eventName=DisassociateRouteTable)}" + VpcChange = "{($.eventName=CreateVpc) || ($.eventName=DeleteVpc) || ($.eventName=ModifyVpcAttribute) || ($.eventName=AcceptVpcPeeringConnection) || ($.eventName=CreateVpcPeeringConnection) || ($.eventName=DeleteVpcPeeringConnection) || ($.eventName=RejectVpcPeeringConnection) || ($.eventName=AttachClassicLinkVpc) || ($.eventName=DetachClassicLinkVpc) || ($.eventName=DisableVpcClassicLink) || ($.eventName=EnableVpcClassicLink)}" + } : {} security_hub_standards_arns = var.security_hub_standards_arns != null ? var.security_hub_standards_arns : [ "arn:aws:securityhub:${data.aws_region.current.name}::standards/aws-foundational-security-best-practices/v/1.0.0", "arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0", "arn:aws:securityhub:${data.aws_region.current.name}::standards/pci-dss/v/3.2.1" ] + security_hub_has_cis_aws_foundations_enabled = length(regexall( + "ruleset/cis-aws-foundations-benchmark/v", join(",", local.security_hub_standards_arns) + )) > 0 ? true : false } diff --git a/logging.tf b/logging.tf index 479d4bc..c08f70c 100644 --- a/logging.tf +++ b/logging.tf @@ -7,7 +7,7 @@ provider "aws" { } resource "aws_cloudwatch_log_metric_filter" "iam_activity_logging" { - for_each = var.monitor_iam_activity ? local.iam_activity : {} + for_each = var.monitor_iam_activity ? merge(local.iam_activity, local.cloudtrail_activity_cis_aws_foundations) : {} provider = aws.logging name = "LandingZone-IAMActivity-${each.key}" diff --git a/main.tf b/main.tf index 3f231a9..52beee1 100644 --- a/main.tf +++ b/main.tf @@ -10,7 +10,7 @@ resource "aws_cloudtrail" "additional_auditing_trail" { } resource "aws_cloudwatch_log_metric_filter" "iam_activity_master" { - for_each = var.monitor_iam_activity ? local.iam_activity : {} + for_each = var.monitor_iam_activity ? merge(local.iam_activity, local.cloudtrail_activity_cis_aws_foundations) : {} name = "LandingZone-IAMActivity-${each.key}" pattern = each.value diff --git a/variables.tf b/variables.tf index bf87fd5..43d207d 100644 --- a/variables.tf +++ b/variables.tf @@ -130,6 +130,12 @@ variable "security_hub_standards_arns" { description = "A list of the ARNs of the standards you want to enable in Security Hub" } +variable "security_hub_create_cis_metric_filters" { + type = bool + default = true + description = "Enable the creation of metric filters related to the CIS AWS Foundation Security Hub Standard" +} + variable "aws_sso_permission_sets" { type = map(object({ assignments = list(map(list(string)))