--- AWSTemplateFormatVersion: 2010-09-09 Description: Provides the base security, IAM, and access configuration for the AWS account (qs-1r6f0fdc6) Parameters: EnableLogFileValidation: Type: String Default: 'true' Description: Indicates whether CloudTrail validates the integrity of log files. AllowedValues: - 'true' - 'false' IncludeGlobalEvents: Type: String Default: 'true' Description: Indicates whether the trail is publishing events from global services, such as IAM, to the log files. AllowedValues: - 'true' - 'false' MultiRegion: Type: String Default: 'false' Description: Indicates whether the CloudTrail trail is created in the region in which you create the stack (false) or in all regions (true). AllowedValues: - 'true' - 'false' PublishToCloudWatchLogs: Type: String Default: 'true' Description: Indicates whether notifications are published to CloudWatch Logs. AllowedValues: - 'true' - 'false' CloudWatchLogsGroupName: Type: String Default: 'CloudTrail/K-ISMS-Logs' Description: CloudWatchLogs Group name. LogsRetentionInDays: Description: 'Specifies the number of days you want to retain CloudTrail log events in the CloudWatch Logs.' Type: Number Default: 14 AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653] QSS3BucketName: AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-.]*[0-9a-zA-Z])*$ ConstraintDescription: Quick Start bucket name can include numbers, lowercase letters, uppercase letters, periods (.), and hyphens (-). It cannot start or end with a hyphen (-). If you are unsure, do not change this value. Default: aws-quickstart Description: S3 bucket name for the Quick Start assets. Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). If you are unsure, do not change this value. Type: String QSS3BucketRegion: Default: 'us-east-1' Description: AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value. Type: String QSS3KeyPrefix: AllowedPattern: ^[0-9a-zA-Z-/]*$ ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). If you are unsure, do not change this value. Default: quickstart-korea-isms-p/ Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). If you are unsure, do not change this value. Type: String EnableGuardDuty: Type: String Default: enable AllowedValues: [ enable, disable ] Description: If you do not currently have Guard Duty enabled in your account. Conditions: IsMultiRegion: !Equals - !Ref MultiRegion - 'true' IsPublishToCloudWatchLogs: !Equals - !Ref PublishToCloudWatchLogs - 'true' UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] GuardDutyEnabled: !Equals [!Ref EnableGuardDuty, 'enable'] Resources: SysAdminGroup: Type: AWS::IAM::Group Properties: Path: / SysAdminPolicy: Type: AWS::IAM::ManagedPolicy Properties: PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow NotAction: iam:* Resource: '*' Condition: Bool: aws:MultiFactorAuthPresent: true - Effect: Deny Action: aws-portal:*Billing Resource: '*' - Effect: Deny Action: - cloudtrail:DeleteTrail - cloudtrail:StopLogging - cloudtrail:UpdateTrail Resource: '*' - Effect: Deny Action: - kms:Create* - kms:Revoke* - kms:Enable* - kms:Get* - kms:Disable* - kms:Delete* - kms:Put* - kms:Update* Resource: '*' Groups: - !Ref SysAdminGroup IAMAdminGroup: Type: AWS::IAM::Group Properties: Path: / IAMAdminPolicy: Type: AWS::IAM::ManagedPolicy Properties: PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: iam:* Resource: '*' Condition: Bool: aws:MultiFactorAuthPresent: true - Effect: Deny Action: aws-portal:*Billing Resource: '*' Groups: - !Ref IAMAdminGroup InstanceOpsGroup: Type: AWS::IAM::Group Properties: Path: / InstanceOpsPolicy: Type: AWS::IAM::ManagedPolicy Properties: PolicyDocument: Version: 2012-10-17 Statement: - Action: ec2:* Effect: Allow Resource: '*' - Effect: Allow Action: elasticloadbalancing:* Resource: '*' - Effect: Allow Action: cloudwatch:* Resource: '*' - Effect: Allow Action: autoscaling:* Resource: '*' - Effect: Deny Action: - ec2:CreateVpc* - ec2:DeleteVpc* - ec2:ModifyVpc* - ec2:CreateSubnet* - ec2:DeleteSubnet* - ec2:ModifySubnet* - ec2:Create*Route* - ec2:DeleteRoute* - ec2:AssociateRoute* - ec2:ReplaceRoute* - ec2:CreateVpn* - ec2:DeleteVpn* - ec2:AttachVpn* - ec2:DetachVpn* - ec2:CreateNetworkAcl* - ec2:DeleteNetworkAcl* - ec2:ReplaceNetworkAcl* - ec2:*Gateway* - ec2:*PeeringConnection* Resource: '*' - Effect: Deny Action: aws-portal:*Billing Resource: '*' - Effect: Deny Action: - kms:Create* - kms:Revoke* - kms:Enable* - kms:Get* - kms:Disable* - kms:Delete* - kms:Put* - kms:Update* Resource: '*' Groups: - !Ref InstanceOpsGroup ReadOnlyAdminGroup: Type: AWS::IAM::Group Properties: Path: / ReadOnlyAdminPolicy: Type: AWS::IAM::ManagedPolicy Properties: PolicyDocument: Version: 2012-10-17 Statement: - Action: - appstream:Get* - autoscaling:Describe* - cloudformation:DescribeStacks - cloudformation:DescribeStackEvents - cloudformation:DescribeStackResource - cloudformation:DescribeStackResources - cloudformation:GetTemplate - cloudformation:List* - cloudfront:Get* - cloudfront:List* - cloudtrail:DescribeTrails - cloudtrail:GetTrailStatus - cloudwatch:Describe* - cloudwatch:Get* - cloudwatch:List* - directconnect:Describe* - dynamodb:GetItem - dynamodb:BatchGetItem - dynamodb:Query - dynamodb:Scan - dynamodb:DescribeTable - dynamodb:ListTables - ec2:Describe* - elasticache:Describe* - elasticbeanstalk:Check* - elasticbeanstalk:Describe* - elasticbeanstalk:List* - elasticbeanstalk:RequestEnvironmentInfo - elasticbeanstalk:RetrieveEnvironmentInfo - elasticloadbalancing:Describe* - elastictranscoder:Read* - elastictranscoder:List* - iam:List* - iam:Get* - kinesis:Describe* - kinesis:Get* - kinesis:List* - opsworks:Describe* - opsworks:Get* - route53:Get* - route53:List* - redshift:Describe* - redshift:ViewQueriesInConsole - rds:Describe* - rds:ListTagsForResource - s3:Get* - s3:List* - sdb:GetAttributes - sdb:List* - sdb:Select* - ses:Get* - ses:List* - sns:Get* - sns:List* - sqs:GetQueueAttributes - sqs:ListQueues - sqs:ReceiveMessage - storagegateway:List* - storagegateway:Describe* - trustedadvisor:Describe* Effect: Allow Resource: '*' - Effect: Deny Action: aws-portal:*Billing Resource: '*' Groups: - !Ref ReadOnlyAdminGroup ReadOnlyBillingGroup: Type: AWS::IAM::Group Properties: Path: / ReadOnlyBillingPolicy: Type: AWS::IAM::ManagedPolicy Properties: PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: aws-portal:View* Resource: '*' - Effect: Deny Action: aws-portal:*Account Resource: '*' Groups: - !Ref ReadOnlyBillingGroup CloudTrail: DependsOn: - CloudTrailBucketPolicy Type: AWS::CloudTrail::Trail Properties: S3BucketName: !Ref CloudTrailS3Bucket KMSKeyId: !GetAtt CloudTrailKey.Arn IsLogging: True EnableLogFileValidation: !Ref EnableLogFileValidation IncludeGlobalServiceEvents: !If - IsMultiRegion - True - !Ref IncludeGlobalEvents IsMultiRegionTrail: !Ref MultiRegion CloudWatchLogsLogGroupArn: !If - IsPublishToCloudWatchLogs - !GetAtt TrailLogGroup.Arn - !Ref AWS::NoValue CloudWatchLogsRoleArn: !If - IsPublishToCloudWatchLogs - !GetAtt TrailLogGroupRole.Arn - !Ref AWS::NoValue TrailLogGroup: Type: 'AWS::Logs::LogGroup' Condition: IsPublishToCloudWatchLogs Properties: LogGroupName: !Ref CloudWatchLogsGroupName RetentionInDays: !Ref LogsRetentionInDays TrailLogGroupRole: Type: 'AWS::IAM::Role' Condition: IsPublishToCloudWatchLogs Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Sid: CloudTrailAssumeRole Effect: Allow Principal: Service: 'cloudtrail.amazonaws.com' Action: 'sts:AssumeRole' Policies: - PolicyName: 'cloudtrail-policy' PolicyDocument: Version: '2012-10-17' Statement: - Sid: AWSCloudTrailCreateLogStream Effect: Allow Action: 'logs:CreateLogStream' Resource: !GetAtt 'TrailLogGroup.Arn' - Sid: AWSCloudTrailPutLogEvents Effect: Allow Action: 'logs:PutLogEvents' Resource: !GetAtt 'TrailLogGroup.Arn' # Enable GuardDuty GuardDuty: Condition: GuardDutyEnabled Type: "AWS::GuardDuty::Detector" Properties: Enable: true FindingPublishingFrequency: FIFTEEN_MINUTES # Create KMS CloudTrail encryption key CloudTrailKey: Type: AWS::KMS::Key Properties: KeyPolicy: Version: 2012-10-17 Id: k-isms-key-cloudtrail Statement: - Sid: Enable IAM User Permissions Effect: Allow Principal: AWS: !Join - "" - - "arn:aws:iam::" - !Ref "AWS::AccountId" - ":root" Action: "kms:*" Resource: "*" - Sid: Allow CloudTrail to encrypt logs Effect: Allow Principal: Service: - cloudtrail.amazonaws.com Action: "kms:GenerateDataKey*" Resource: "*" Condition: StringLike: "kms:EncryptionContext:aws:cloudtrail:arn": !Sub "arn:aws:cloudtrail:*:${AWS::AccountId}:trail/*" - Sid: Allow CloudTrail to describe key Effect: Allow Principal: Service: - cloudtrail.amazonaws.com Action: "kms:DescribeKey" Resource: "*" - Sid: Allow principals in the account to decrypt log files Effect: Allow Principal: AWS: "*" Action: - "kms:Decrypt" - "kms:ReEncryptFrom" Resource: "*" Condition: StringEquals: "kms:CallerAccount": !Sub "${AWS::AccountId}" StringLike: "kms:EncryptionContext:aws:cloudtrail:arn": !Sub "arn:aws:cloudtrail:*:${AWS::AccountId}:trail/*" - Sid: Allow alias creation during setup Effect: Allow Principal: AWS: "*" Action: "kms:CreateAlias" Resource: "*" Condition: StringEquals: "kms:ViaService": ec2.region.amazonaws.com "kms:CallerAccount": !Sub "${AWS::AccountId}" - Sid: Enable cross account log decryption Effect: Allow Principal: AWS: "*" Action: - "kms:Decrypt" - "kms:ReEncryptFrom" Resource: "*" Condition: StringEquals: "kms:CallerAccount": !Sub "${AWS::AccountId}" StringLike: "kms:EncryptionContext:aws:cloudtrail:arn": !Sub "arn:aws:cloudtrail:*:${AWS::AccountId}:trail/*" CloudTrailKeyAlias: Type: AWS::KMS::Alias Properties: AliasName: alias/cloudtrail TargetKeyId: Ref: CloudTrailKey SecurityGroupChangesMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: "{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup) }" MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "SecurityGroupEventCount" MetricValue: "1" SecurityGroupChangesAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify K-ISMS Quick Start resources." Properties: #AlarmName: CloudTrailSecurityGroupChanges AlarmDescription: Alarms when an API call is made to create, update or delete a Security Group. MetricName: SecurityGroupEventCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching NetworkAclChangesMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: "{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }" MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "NetworkAclEventCount" MetricValue: "1" NetworkAclChangesAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify K-ISMS Quick Start resources." DependsOn: SecurityGroupChangesAlarm Properties: #AlarmName: CloudTrailNetworkAclChanges AlarmDescription: Alarms when an API call is made to create, update or delete a Network ACL. MetricName: NetworkAclEventCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching GatewayChangesMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: "{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }" MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "GatewayEventCount" MetricValue: "1" GatewayChangesAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify K-ISMS Quick Start resources." DependsOn: NetworkAclChangesAlarm Properties: #AlarmName: CloudTrailGatewayChanges AlarmDescription: Alarms when an API call is made to create, update or delete a Customer or Internet Gateway. MetricName: GatewayEventCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching VpcChangesMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: "{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }" MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "VpcEventCount" MetricValue: "1" VpcChangesAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify K-ISMS Quick Start resources." DependsOn: GatewayChangesAlarm Properties: #AlarmName: CloudTrailVpcChanges AlarmDescription: Alarms when an API call is made to create, update or delete a VPC, VPC peering connection or VPC connection to classic. MetricName: VpcEventCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching EC2InstanceChangesMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: "{ ($.eventName = RunInstances) || ($.eventName = RebootInstances) || ($.eventName = StartInstances) || ($.eventName = StopInstances) || ($.eventName = TerminateInstances) }" MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "EC2InstanceEventCount" MetricValue: "1" EC2InstanceChangesAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify AWS Landing Zone resources." DependsOn: VpcChangesAlarm Properties: #AlarmName: CloudTrailEC2InstanceChanges AlarmDescription: Alarms when an API call is made to create, terminate, start, stop or reboot an EC2 instance. MetricName: EC2InstanceEventCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching EC2LargeInstanceChangesMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: "{ (($.eventName = RunInstances) || ($.eventName = RebootInstances) || ($.eventName = StartInstances) || ($.eventName = StopInstances) || ($.eventName = TerminateInstances)) && (($.requestParameters.instanceType = *.32xlarge) || ($.requestParameters.instanceType = *.24xlarge) || ($.requestParameters.instanceType = *.18xlarge) || ($.requestParameters.instanceType = *.16xlarge) || ($.requestParameters.instanceType = *.12xlarge) || ($.requestParameters.instanceType = *.10xlarge) || ($.requestParameters.instanceType = *.9xlarge) || ($.requestParameters.instanceType = *.8xlarge) || ($.requestParameters.instanceType = *.4xlarge)) }" MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "EC2LargeInstanceEventCount" MetricValue: "1" EC2LargeInstanceChangesAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify AWS Landing Zone resources." DependsOn: EC2InstanceChangesAlarm Properties: #AlarmName: CloudTrailEC2LargeInstanceChanges AlarmDescription: Alarms when an API call is made to create, terminate, start, stop or reboot a 4x, 8x, 9x, 10x, 12x, 16x, 18x, 24x, 32x-large EC2 instance. MetricName: EC2LargeInstanceEventCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching CloudTrailChangesMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: "{ ($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging) }" MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "CloudTrailEventCount" MetricValue: "1" CloudTrailChangesAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify AWS Landing Zone resources." DependsOn: EC2LargeInstanceChangesAlarm Properties: #AlarmName: CloudTrailChanges AlarmDescription: Alarms when an API call is made to create, update or delete a CloudTrail trail, or to start or stop logging to a trail. MetricName: CloudTrailEventCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching ConsoleSignInFailuresMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: '{ ($.eventName = ConsoleLogin) && ($.errorMessage = "Failed authentication") }' MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "ConsoleSignInFailureCount" MetricValue: "1" ConsoleSignInFailuresAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify AWS Landing Zone resources." DependsOn: CloudTrailChangesAlarm Properties: #AlarmName: CloudTrailConsoleSignInFailures AlarmDescription: Alarms when an unauthenticated API call is made to sign into the console. MetricName: ConsoleSignInFailureCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 3 TreatMissingData: notBreaching AuthorizationFailuresMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: '{ ($.errorCode = "*UnauthorizedOperation") || ($.errorCode = "AccessDenied*") }' MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "AuthorizationFailureCount" MetricValue: "1" AuthorizationFailuresAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify AWS Landing Zone resources." DependsOn: ConsoleSignInFailuresAlarm Properties: #AlarmName: CloudTrailAuthorizationFailures AlarmDescription: Alarms when an unauthorized API call is made. MetricName: AuthorizationFailureCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching IAMPolicyChangesMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: "{($.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)}" MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "IAMPolicyEventCount" MetricValue: "1" IAMPolicyChangesAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify AWS Landing Zone resources." DependsOn: AuthorizationFailuresAlarm Properties: #AlarmName: IAMPolicyChanges AlarmDescription: Alarms when IAM policy changs are made. MetricName: IAMPolicyEventCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching RootLoginMetricFilter: Type: AWS::Logs::MetricFilter DependsOn: TrailLogGroup Properties: LogGroupName: !Ref CloudWatchLogsGroupName FilterPattern: '{ $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" }' MetricTransformations: - MetricNamespace: "CloudTrailMetrics" MetricName: "RootLoginEventCount" MetricValue: "1" RootLoginAlarm: Type: AWS::CloudWatch::Alarm Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "The alarm name is defined to identify AWS Landing Zone resources." DependsOn: IAMPolicyChangesAlarm Properties: #AlarmName: RootLogin AlarmDescription: Alarms when the root user logs in. MetricName: RootLoginEventCount Namespace: CloudTrailMetrics ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 Period: 300 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching # # Create KMS CloudTrail S3 bucket encryption key # S3CloudTrailKey: # Type: AWS::KMS::Key # Properties: # KeyPolicy: # Version: 2012-10-17 # Id: k-isms-key-cloudtrails3 # Statement: # - Sid: Enable IAM User Permissions # Effect: Allow # Principal: # AWS: !Join # - "" # - - "arn:aws:iam::" # - !Ref "AWS::AccountId" # - ":root" # Action: "kms:*" # Resource: "*" # - Sid: Allow VPC Flow Logs to use the key # Effect: Allow # Principal: # Service: # - delivery.logs.amazonaws.com # Action: "kms:GenerateDataKey*" # Resource: "*" # S3CloudTrailKeyAlias: # Type: AWS::KMS::Alias # Properties: # AliasName: alias/cloudtrails3 # TargetKeyId: # Ref: S3CloudTrailKey # Create CloudTrail encrypted S3 bucket for storage CloudTrailS3Bucket: # DependsOn: # - S3CloudTrailKey Type: AWS::S3::Bucket DeletionPolicy: Retain UpdateReplacePolicy: Retain # Properties: # BucketEncryption: # ServerSideEncryptionConfiguration: # - ServerSideEncryptionByDefault: # KMSMasterKeyID: !Sub "arn:aws:kms:${AWS::Region}:${AWS::AccountId}:${S3CloudTrailKeyAlias}" # SSEAlgorithm: "aws:kms" Properties: AccessControl: Private # Block Public Access Policy PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true # Versioning VersioningConfiguration: Status: Enabled BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 LifecycleConfiguration: Rules: - Id: GlacierRule Prefix: glacier Status: Enabled ExpirationInDays: 365 Transitions: - TransitionInDays: 180 StorageClass: GLACIER CloudTrailBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref CloudTrailS3Bucket PolicyDocument: Version: "2012-10-17" Statement: - Sid: "AWSCloudTrailAclCheck" Effect: Allow Principal: Service: "cloudtrail.amazonaws.com" Action: "s3:GetBucketAcl" Resource: !Sub arn:aws:s3:::${CloudTrailS3Bucket} - Sid: "AWSCloudTrailWrite" Effect: Allow Principal: Service: "cloudtrail.amazonaws.com" Action: "s3:PutObject" Resource: !Sub arn:aws:s3:::${CloudTrailS3Bucket}/AWSLogs/${AWS::AccountId}/* Condition: StringEquals: "s3:x-amz-acl": "bucket-owner-full-control" S3UploadBucket: DeletionPolicy: Retain UpdateReplacePolicy: Retain Type: AWS::S3::Bucket Properties: BucketName: !Sub - isms-conformance-delivery-${AWS::Region}-${X} - X: !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]] AccessControl: Private # Block Public Access Policy PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true # Versioning VersioningConfiguration: Status: Enabled BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 ConformanceServiceLinkedRole: Type: AWS::IAM::ServiceLinkedRole Properties: AWSServiceName: config-conforms.amazonaws.com Description: my service linked role for config-conforms S3UploadBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3UploadBucket PolicyDocument: Version: 2012-10-17 Statement: - Sid: EnforceHTTPSConnections Action: s3:* Effect: Deny Principal: '*' Resource: !Sub - arn:aws:s3:::isms-conformance-delivery-${AWS::Region}-${X}/* - X: !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]] Condition: Bool: aws:SecureTransport: false - Sid: AWSConfigConformsBucketPermissionsCheck Effect: Allow Principal: AWS: - !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/config-conforms.amazonaws.com/AWSServiceRoleForConfigConforms Action: s3:GetBucketAcl Resource: !Sub - arn:aws:s3:::isms-conformance-delivery-${AWS::Region}-${X} - X: !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]] - Sid: AWSConfigConformsBucketDelivery Effect: Allow Principal: AWS: - !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/config-conforms.amazonaws.com/AWSServiceRoleForConfigConforms Action: s3:PutObject Resource: !Sub - arn:aws:s3:::isms-conformance-delivery-${AWS::Region}-${X}/AWSLogs/${AWS::AccountId}/Config/* - X: !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]] Condition: StringEquals: s3:x-amz-acl: bucket-owner-full-control - Sid: AWSConfigConformsBucketReadAccess Effect: Allow Principal: AWS: - !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/config-conforms.amazonaws.com/AWSServiceRoleForConfigConforms Action: s3:GetObject Resource: !Sub - arn:aws:s3:::isms-conformance-delivery-${AWS::Region}-${X}/AWSLogs/${AWS::AccountId}/Config/* - X: !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]] ISMSConformancePack: Type: AWS::Config::ConformancePack DependsOn: S3UploadBucketPolicy Properties: ConformancePackName: !Sub ISMS-ConformancePackName-${AWS::StackName} DeliveryS3Bucket: !Ref S3UploadBucket TemplateS3Uri: !Sub s3://${QSS3BucketName}/${QSS3KeyPrefix}templates/config-rules.template.yaml # TemplateS3Uri: !Sub # - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/config-rules.template.yaml # - S3Region: !If [ UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion ] # S3Bucket: !If [ UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName ] Outputs: SysAdmin: Value: !Ref SysAdminGroup IAMAdminGroup: Value: !Ref IAMAdminGroup InstanceOpsGroup: Value: !Ref InstanceOpsGroup ReadOnlyBillingGroup: Value: !Ref ReadOnlyBillingGroup ReadOnlyAdminGroup: Value: !Ref ReadOnlyAdminGroup CloudTrailKMSKeyAlias: Description: "CloudTrail KMS Key Alias" Value: Ref: "CloudTrailKeyAlias" # S3KMSKeyAlias: # Description: "S3 KMS Key Alias" # Value: # Ref: "S3CloudTrailKeyAlias" CloudTrailS3Bucket: Description: "Encrypted S3 Bucket for CloudTrail Logs" Value: Ref: "CloudTrailS3Bucket" # CloudTrailS3BucketPolicy: # Description: "S3 Bucket Policy for CloudTrail Logs" # Value: # Ref: "CloudTrailBucketPolicy" CloudTrail: Description: "CloudTrail" Value: Ref: "CloudTrail"