AWSTemplateFormatVersion: "2010-09-09" Description: This AWS CloudFormation template describes sample AWS resources with the purpose of testing the AwsCommunity::KMS::EncryptionSettings hook in an integration environment. Parameters: InstanceType: Description: Amazon EC2 instance type to use. Type: String AllowedValues: - t2.micro - t2.small Default: t2.micro LatestAmiId: Description: Region-specific image to use. Type: AWS::SSM::Parameter::Value Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 LaunchConfigurationInstanceType: Description: Amazon EC2 instance type to use for the LaunchConfiguration resource. Type: String AllowedValues: - a1.large Default: a1.large TagAppName: Description: 'Value for the AppName tag; minimum length: 0, maximum: 100.' Type: String Default: AwsCommunityKmsEncryptionSettingsInteg MaxLength: 100 MinLength: 0 TagEnv: Description: Value for the Env tag. Type: String AllowedValues: - dev - alpha - beta - prod Default: beta TagName: Description: 'Value for the Name tag; minimum length: 0, maximum: 100.' Type: String Default: AwsCommunityKmsEncryptionSettingsIntegResource MaxLength: 100 MinLength: 0 Resources: AutoScalingLaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Properties: BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: Encrypted: true VolumeSize: 1 VolumeType: gp3 - DeviceName: /dev/sdk Ebs: Encrypted: true VolumeSize: 1 VolumeType: gp3 ImageId: !Ref 'LatestAmiId' InstanceType: !Ref 'LaunchConfigurationInstanceType' CloudTrailTrail: Type: AWS::CloudTrail::Trail Properties: EventSelectors: - IncludeManagementEvents: true ReadWriteType: All IsLogging: false KMSKeyId: !Ref 'CloudTrailTrailKmsKey' S3BucketName: !Ref 'CloudTrailTrailS3Bucket' Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' TrailName: !Sub 'Trail-integ-succeed-awscommunity-kms-encryptionsettings-${AWS::Region}' CloudTrailTrailEmptyIntegS3PrefixCleanupCustomResource: Type: Custom::CloudTrailTrailEmptyIntegS3PrefixCleanup Properties: AccountId: !Ref 'AWS::AccountId' BucketName: !Ref 'CloudTrailTrailS3Bucket' ServiceToken: !GetAtt CloudTrailTrailEmptyIntegS3PrefixCleanupLambdaFunction.Arn CloudTrailTrailEmptyIntegS3PrefixCleanupLambdaFunction: Type: AWS::Lambda::Function DependsOn: CloudTrailTrailEmptyIntegS3PrefixCleanupLogsLogGroup Properties: Code: ZipFile: | """Deletes the `AWSLogs/YOUR_ACCOUNT_ID/CloudTrail/` empty prefix from the specified S3 bucket. """ import boto3 import cfnresponse import logging LOGGER = logging.getLogger("CloudTrailTrailEmptyIntegS3PrefixCleanup") LOGGER.setLevel(logging.INFO) S3_CLIENT = boto3.client("s3") def lambda_handler(event, context): """Handler function.""" try: if event["RequestType"] == "Delete": account_id = event["ResourceProperties"]["AccountId"] bucket_name = event["ResourceProperties"]["BucketName"] LOGGER.info(f"bucket_name: {bucket_name}") response = S3_CLIENT.list_objects_v2( Bucket=bucket_name, Prefix=f"AWSLogs/{account_id}/CloudTrail/", MaxKeys=2, ) if response["KeyCount"] > 1: LOGGER.error("Cannot continue, the prefix contains objects.") cfnresponse.send(event, context, cfnresponse.FAILED, {}, "") return False S3_CLIENT.delete_object( Bucket=bucket_name, Key=f"AWSLogs/{account_id}/CloudTrail/", ) S3_CLIENT.delete_object( Bucket=bucket_name, Key=f"AWSLogs/{account_id}/", ) S3_CLIENT.delete_object( Bucket=bucket_name, Key="AWSLogs/", ) cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, "") return True except Exception as e: LOGGER.error(e) cfnresponse.send(event, context, cfnresponse.FAILED, {}, "") return False Description: Deletes the `AWSLogs/YOUR_ACCOUNT_ID/CloudTrail/` empty prefix from the specified S3 bucket. FunctionName: CloudTrailTrailEmptyIntegS3PrefixCleanup Handler: index.lambda_handler MemorySize: 256 Role: !GetAtt CloudTrailTrailEmptyIntegS3PrefixCleanupLambdaFunctionExecutionRole.Arn Runtime: python3.9 Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' Timeout: 30 CloudTrailTrailEmptyIntegS3PrefixCleanupLambdaFunctionExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: - sts:AssumeRole Effect: Allow Principal: Service: - lambda.amazonaws.com Version: "2012-10-17" Path: / Policies: - PolicyDocument: Statement: - Action: - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/CloudTrailTrailEmptyIntegS3PrefixCleanup*' - Action: - s3:ListBucket Condition: StringLike: s3:prefix: - !Sub 'AWSLogs/${AWS::AccountId}/CloudTrail/*' Effect: Allow Resource: - !GetAtt CloudTrailTrailS3Bucket.Arn - Action: - s3:DeleteObject Effect: Allow Resource: - !Sub '${CloudTrailTrailS3Bucket.Arn}/AWSLogs/${AWS::AccountId}/CloudTrail/' - !Sub '${CloudTrailTrailS3Bucket.Arn}/AWSLogs/${AWS::AccountId}/' - !Sub '${CloudTrailTrailS3Bucket.Arn}/AWSLogs/' Version: "2012-10-17" PolicyName: CloudTrailTrailEmptyIntegS3PrefixCleanupLambdaFunctionExecutionRole RoleName: TrailS3Cleanup-integ-succeed-awscommunity-kms-encryptionsettings Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' CloudTrailTrailEmptyIntegS3PrefixCleanupLogsLogGroup: Type: AWS::Logs::LogGroup Properties: KmsKeyId: !GetAtt LogsLogGroupKmsKey.Arn LogGroupName: /aws/lambda/CloudTrailTrailEmptyIntegS3PrefixCleanup RetentionInDays: 365 Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' CloudTrailTrailKmsKey: Type: AWS::KMS::Key Properties: EnableKeyRotation: true KeyPolicy: Id: key-default-1 Statement: - Action: kms:* Effect: Allow Principal: AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' Resource: '*' Sid: Enable IAM User Permissions - Action: kms:GenerateDataKey* Condition: StringEquals: AWS:SourceArn: !Sub 'arn:${AWS::Partition}:cloudtrail:${AWS::Region}:${AWS::AccountId}:trail/Trail-integ-succeed-awscommunity-kms-encryptionsettings-${AWS::Region}' StringLike: kms:EncryptionContext:aws:cloudtrail:arn: !Sub 'arn:${AWS::Partition}:cloudtrail:*:${AWS::AccountId}:trail/*' Effect: Allow Principal: Service: cloudtrail.amazonaws.com Resource: '*' Sid: Allow CloudTrail to encrypt logs - Action: kms:DescribeKey Effect: Allow Principal: Service: cloudtrail.amazonaws.com Resource: '*' Sid: Allow CloudTrail to describe key - Action: - kms:Decrypt - kms:ReEncryptFrom Condition: StringEquals: kms:CallerAccount: !Ref 'AWS::AccountId' StringLike: kms:EncryptionContext:aws:cloudtrail:arn: !Sub 'arn:${AWS::Partition}:cloudtrail:*:${AWS::AccountId}:trail/*' Effect: Allow Principal: AWS: '*' Resource: '*' Sid: Allow principals in the account to decrypt log files Version: "2012-10-17" PendingWindowInDays: 7 Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' CloudTrailTrailS3Bucket: Type: AWS::S3::Bucket Properties: BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: aws:kms Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' CloudTrailTrailS3BucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref 'CloudTrailTrailS3Bucket' PolicyDocument: Statement: - Action: s3:GetBucketAcl Condition: StringEquals: AWS:SourceArn: !Sub 'arn:${AWS::Partition}:cloudtrail:${AWS::Region}:${AWS::AccountId}:trail/Trail-integ-succeed-awscommunity-kms-encryptionsettings-${AWS::Region}' Effect: Allow Principal: Service: cloudtrail.amazonaws.com Resource: !GetAtt CloudTrailTrailS3Bucket.Arn Sid: AWSCloudTrailAclCheck20150319 - Action: s3:PutObject Condition: StringEquals: AWS:SourceArn: !Sub 'arn:${AWS::Partition}:cloudtrail:${AWS::Region}:${AWS::AccountId}:trail/Trail-integ-succeed-awscommunity-kms-encryptionsettings-${AWS::Region}' s3:x-amz-acl: bucket-owner-full-control Effect: Allow Principal: Service: cloudtrail.amazonaws.com Resource: !Sub '${CloudTrailTrailS3Bucket.Arn}/AWSLogs/${AWS::AccountId}/*' Sid: AWSCloudTrailWrite20150319 Version: "2012-10-17" DynamoDbGlobalTable: Type: AWS::DynamoDB::GlobalTable Properties: AttributeDefinitions: - AttributeName: Book AttributeType: S - AttributeName: Author AttributeType: S BillingMode: PAY_PER_REQUEST KeySchema: - AttributeName: Book KeyType: HASH - AttributeName: Author KeyType: RANGE Replicas: - Region: !Ref 'AWS::Region' TableClass: STANDARD Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' SSESpecification: SSEEnabled: true SSEType: KMS DynamoDbTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: Book AttributeType: S - AttributeName: Author AttributeType: S KeySchema: - AttributeName: Book KeyType: HASH - AttributeName: Author KeyType: RANGE ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 SSESpecification: SSEEnabled: true SSEType: KMS Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' Ec2Instance: Type: AWS::EC2::Instance Properties: BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: Encrypted: true VolumeSize: 1 VolumeType: gp3 - DeviceName: /dev/sdk Ebs: Encrypted: true VolumeSize: 1 VolumeType: gp3 ImageId: !Ref 'LatestAmiId' InstanceType: !Ref 'InstanceType' PropagateTagsToVolumeOnCreation: true Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' Ec2LaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateData: BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: Encrypted: true VolumeSize: 1 VolumeType: gp3 - DeviceName: /dev/sdk Ebs: Encrypted: true VolumeSize: 1 VolumeType: gp3 ImageId: !Ref 'LatestAmiId' InstanceType: !Ref 'InstanceType' TagSpecifications: - ResourceType: launch-template Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' Ec2Volume: Type: AWS::EC2::Volume Properties: AvailabilityZone: !Sub '${AWS::Region}a' Encrypted: true Size: 1 Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' EfsFileSystem: Type: AWS::EFS::FileSystem Properties: Encrypted: true FileSystemTags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' KinesisStream: Type: AWS::Kinesis::Stream Properties: ShardCount: 1 StreamEncryption: EncryptionType: KMS KeyId: alias/aws/kinesis Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' LogsLogGroup: Type: AWS::Logs::LogGroup Properties: KmsKeyId: !GetAtt LogsLogGroupKmsKey.Arn RetentionInDays: 365 Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' LogsLogGroupKmsKey: Type: AWS::KMS::Key Properties: EnableKeyRotation: true KeyPolicy: Id: key-default-1 Statement: - Action: kms:* Effect: Allow Principal: AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' Resource: '*' Sid: Enable IAM User Permissions - Action: - kms:Decrypt* - kms:Describe* - kms:Encrypt* - kms:GenerateDataKey* - kms:ReEncrypt* Condition: ArnLike: kms:EncryptionContext:aws:logs:arn: !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*' Effect: Allow Principal: Service: !Sub 'logs.${AWS::Region}.amazonaws.com' Resource: '*' Version: "2012-10-17" PendingWindowInDays: 7 Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' RdsDbCluster: DeletionPolicy: Delete Type: AWS::RDS::DBCluster Properties: Engine: aurora-mysql MasterUserPassword: !Sub '{{resolve:secretsmanager:${RdsDbClusterSecretsManagerSecret}::password}}' MasterUsername: !Sub '{{resolve:secretsmanager:${RdsDbClusterSecretsManagerSecret}::username}}' StorageEncrypted: true Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' RdsDbClusterSecretsManagerSecret: Type: AWS::SecretsManager::Secret Properties: GenerateSecretString: ExcludeCharacters: '"@/' GenerateStringKey: password PasswordLength: 30 SecretStringTemplate: '{"username": "admin"}' Name: RdsDbClusterSecret-integ-succeed-awscommunity-kms-encryptionsettings Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' RdsDbClusterSecretsManagerSecretAttachment: Type: AWS::SecretsManager::SecretTargetAttachment Properties: SecretId: !Ref 'RdsDbClusterSecretsManagerSecret' TargetId: !Ref 'RdsDbCluster' TargetType: AWS::RDS::DBCluster RdsDbInstance: DeletionPolicy: Delete Type: AWS::RDS::DBInstance Properties: AllocatedStorage: 20 BackupRetentionPeriod: 0 DBInstanceClass: db.t3.small DBName: testdbinstance Engine: MySQL MasterUserPassword: !Sub '{{resolve:secretsmanager:${RdsDbInstanceSecretsManagerSecret}::password}}' MasterUsername: !Sub '{{resolve:secretsmanager:${RdsDbInstanceSecretsManagerSecret}::username}}' PubliclyAccessible: false StorageEncrypted: true Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' RdsDbInstanceSecretsManagerSecret: Type: AWS::SecretsManager::Secret Properties: GenerateSecretString: ExcludeCharacters: '"@/' GenerateStringKey: password PasswordLength: 30 SecretStringTemplate: '{"username": "admin"}' Name: RdsDbInstanceSecret-integ-succeed-awscommunity-kms-encryptionsettings Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' RdsDbInstanceSecretsManagerSecretAttachment: Type: AWS::SecretsManager::SecretTargetAttachment Properties: SecretId: !Ref 'RdsDbInstanceSecretsManagerSecret' TargetId: !Ref 'RdsDbInstance' TargetType: AWS::RDS::DBInstance RdsGlobalCluster: DeletionPolicy: Delete Type: AWS::RDS::GlobalCluster Properties: Engine: aurora-mysql StorageEncrypted: true RedshiftCluster: Type: AWS::Redshift::Cluster Properties: AutomatedSnapshotRetentionPeriod: 0 ClusterType: single-node DBName: testdb Encrypted: true MasterUserPassword: !Sub '{{resolve:secretsmanager:${RedshiftClusterSecretsManagerSecret}::password}}' MasterUsername: !Sub '{{resolve:secretsmanager:${RedshiftClusterSecretsManagerSecret}::username}}' NodeType: dc2.large PubliclyAccessible: false Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' RedshiftClusterSecretsManagerSecret: Type: AWS::SecretsManager::Secret Properties: GenerateSecretString: ExcludeCharacters: '"''@/\' GenerateStringKey: password PasswordLength: 64 SecretStringTemplate: '{"username": "admin"}' Name: RedshiftClusterSecret-integ-succeed-awscommunity-kms-encryptionsettings Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' RedshiftClusterSecretsManagerSecretAttachment: Type: AWS::SecretsManager::SecretTargetAttachment Properties: SecretId: !Ref 'RedshiftClusterSecretsManagerSecret' TargetId: !Ref 'RedshiftCluster' TargetType: AWS::Redshift::Cluster S3Bucket: Type: AWS::S3::Bucket Properties: BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: aws:kms Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' SnsTopic: Type: AWS::SNS::Topic Properties: KmsMasterKeyId: alias/aws/sns Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv' SqsQueue: Type: AWS::SQS::Queue Properties: KmsMasterKeyId: alias/aws/sqs SqsManagedSseEnabled: false Tags: - Key: Name Value: !Ref 'TagName' - Key: AppName Value: !Ref 'TagAppName' - Key: Env Value: !Ref 'TagEnv'