Skip to content

Instantly share code, notes, and snippets.

@alukach
Created May 15, 2024 21:53
Show Gist options
  • Save alukach/8842bdf2d9fefaa2212ce2b2573272b1 to your computer and use it in GitHub Desktop.
Save alukach/8842bdf2d9fefaa2212ce2b2573272b1 to your computer and use it in GitHub Desktop.
MCP CDK Bootstrap

To successfully bootstrap into an MCP account, we need to do the following:

  1. Dump the boostrap template to a local file: npx cdk bootstrap --show-template > template.yaml. Manually append a permission boundary to every role created within the template (see change.diff below). Use this updated template when deploying: npx cdk bootstrap --template template.yaml
  2. Use the custom permissions boundary flag: --custom-permissions-boundary mcp-tenantOperator-APIG
  3. Disable setting the public access block configuration on the S3 assets bucket: --public-access-block-configuration false

Putting it all together, bootstrapping will look something like this:

npx cdk bootstrap \
  --public-access-block-configuration false \
  --custom-permissions-boundary mcp-tenantOperator-APIG \
  --template template.yaml
290a291,295
> PermissionsBoundary:
> Fn::If:
> - PermissionsBoundarySet
> - Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
> - Ref: AWS::NoValue
313a319,323
> PermissionsBoundary:
> Fn::If:
> - PermissionsBoundarySet
> - Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
> - Ref: AWS::NoValue
356a367,371
> PermissionsBoundary:
> Fn::If:
> - PermissionsBoundarySet
> - Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
> - Ref: AWS::NoValue
513a529,533
> PermissionsBoundary:
> Fn::If:
> - PermissionsBoundarySet
> - Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
> - Ref: AWS::NoValue
Description: This stack includes resources needed to deploy AWS CDK apps into this environment
Parameters:
TrustedAccounts:
Description: List of AWS accounts that are trusted to publish assets and deploy stacks to this environment
Default: ""
Type: CommaDelimitedList
TrustedAccountsForLookup:
Description: List of AWS accounts that are trusted to look up values in this environment
Default: ""
Type: CommaDelimitedList
CloudFormationExecutionPolicies:
Description: List of the ManagedPolicy ARN(s) to attach to the CloudFormation deployment role
Default: ""
Type: CommaDelimitedList
FileAssetsBucketName:
Description: The name of the S3 bucket used for file assets
Default: ""
Type: String
FileAssetsBucketKmsKeyId:
Description: Empty to create a new key (default), 'AWS_MANAGED_KEY' to use a managed S3 key, or the ID/ARN of an existing key.
Default: ""
Type: String
ContainerAssetsRepositoryName:
Description: A user-provided custom name to use for the container assets ECR repository
Default: ""
Type: String
Qualifier:
Description: An identifier to distinguish multiple bootstrap stacks in the same environment
Default: hnb659fds
Type: String
AllowedPattern: "[A-Za-z0-9_-]{1,10}"
ConstraintDescription: Qualifier must be an alphanumeric identifier of at most 10 characters
PublicAccessBlockConfiguration:
Description: Whether or not to enable S3 Staging Bucket Public Access Block Configuration
Default: "true"
Type: String
AllowedValues:
- "true"
- "false"
InputPermissionsBoundary:
Description: Whether or not to use either the CDK supplied or custom permissions boundary
Default: ""
Type: String
UseExamplePermissionsBoundary:
Default: "false"
AllowedValues:
- "true"
- "false"
Type: String
BootstrapVariant:
Type: String
Default: "AWS CDK: Default Resources"
Description: Describe the provenance of the resources in this bootstrap stack. Change this when you customize the template. To prevent accidents, the CDK CLI will not overwrite bootstrap stacks with a different variant.
Conditions:
HasTrustedAccounts:
Fn::Not:
- Fn::Equals:
- ""
- Fn::Join:
- ""
- Ref: TrustedAccounts
HasTrustedAccountsForLookup:
Fn::Not:
- Fn::Equals:
- ""
- Fn::Join:
- ""
- Ref: TrustedAccountsForLookup
HasCloudFormationExecutionPolicies:
Fn::Not:
- Fn::Equals:
- ""
- Fn::Join:
- ""
- Ref: CloudFormationExecutionPolicies
HasCustomFileAssetsBucketName:
Fn::Not:
- Fn::Equals:
- ""
- Ref: FileAssetsBucketName
CreateNewKey:
Fn::Equals:
- ""
- Ref: FileAssetsBucketKmsKeyId
UseAwsManagedKey:
Fn::Equals:
- AWS_MANAGED_KEY
- Ref: FileAssetsBucketKmsKeyId
ShouldCreatePermissionsBoundary:
Fn::Equals:
- "true"
- Ref: UseExamplePermissionsBoundary
PermissionsBoundarySet:
Fn::Not:
- Fn::Equals:
- ""
- Ref: InputPermissionsBoundary
HasCustomContainerAssetsRepositoryName:
Fn::Not:
- Fn::Equals:
- ""
- Ref: ContainerAssetsRepositoryName
UsePublicAccessBlockConfiguration:
Fn::Equals:
- "true"
- Ref: PublicAccessBlockConfiguration
Resources:
FileAssetsBucketEncryptionKey:
Type: AWS::KMS::Key
Properties:
KeyPolicy:
Statement:
- Action:
- kms:Create*
- kms:Describe*
- kms:Enable*
- kms:List*
- kms:Put*
- kms:Update*
- kms:Revoke*
- kms:Disable*
- kms:Get*
- kms:Delete*
- kms:ScheduleKeyDeletion
- kms:CancelKeyDeletion
- kms:GenerateDataKey
- kms:TagResource
- kms:UntagResource
Effect: Allow
Principal:
AWS:
Ref: AWS::AccountId
Resource: "*"
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS: "*"
Resource: "*"
Condition:
StringEquals:
kms:CallerAccount:
Ref: AWS::AccountId
kms:ViaService:
- Fn::Sub: s3.${AWS::Region}.amazonaws.com
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS:
Fn::Sub: ${FilePublishingRole.Arn}
Resource: "*"
Condition: CreateNewKey
FileAssetsBucketEncryptionKeyAlias:
Condition: CreateNewKey
Type: AWS::KMS::Alias
Properties:
AliasName:
Fn::Sub: alias/cdk-${Qualifier}-assets-key
TargetKeyId:
Ref: FileAssetsBucketEncryptionKey
StagingBucket:
Type: AWS::S3::Bucket
Properties:
BucketName:
Fn::If:
- HasCustomFileAssetsBucketName
- Fn::Sub: ${FileAssetsBucketName}
- Fn::Sub: cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}
AccessControl: Private
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: aws:kms
KMSMasterKeyID:
Fn::If:
- CreateNewKey
- Fn::Sub: ${FileAssetsBucketEncryptionKey.Arn}
- Fn::If:
- UseAwsManagedKey
- Ref: AWS::NoValue
- Fn::Sub: ${FileAssetsBucketKmsKeyId}
PublicAccessBlockConfiguration:
Fn::If:
- UsePublicAccessBlockConfiguration
- BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
- Ref: AWS::NoValue
VersioningConfiguration:
Status: Enabled
LifecycleConfiguration:
Rules:
- Id: CleanupOldVersions
Status: Enabled
NoncurrentVersionExpiration:
NoncurrentDays: 365
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
StagingBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket:
Ref: StagingBucket
PolicyDocument:
Id: AccessControl
Version: "2012-10-17"
Statement:
- Sid: AllowSSLRequestsOnly
Action: s3:*
Effect: Deny
Resource:
- Fn::Sub: ${StagingBucket.Arn}
- Fn::Sub: ${StagingBucket.Arn}/*
Condition:
Bool:
aws:SecureTransport: "false"
Principal: "*"
ContainerAssetsRepository:
Type: AWS::ECR::Repository
Properties:
ImageTagMutability: IMMUTABLE
LifecyclePolicy:
LifecyclePolicyText: |
{
"rules": [
{
"rulePriority": 1,
"description": "Untagged images should not exist, but expire any older than one year",
"selection": {
"tagStatus": "untagged",
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 365
},
"action": { "type": "expire" }
}
]
}
RepositoryName:
Fn::If:
- HasCustomContainerAssetsRepositoryName
- Fn::Sub: ${ContainerAssetsRepositoryName}
- Fn::Sub: cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}
RepositoryPolicyText:
Version: "2012-10-17"
Statement:
- Sid: LambdaECRImageRetrievalPolicy
Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- ecr:BatchGetImage
- ecr:GetDownloadUrlForLayer
Condition:
StringLike:
aws:sourceArn:
Fn::Sub: arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*
FilePublishingRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: AWS::AccountId
- Fn::If:
- HasTrustedAccounts
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: TrustedAccounts
- Ref: AWS::NoValue
RoleName:
Fn::Sub: cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}
Tags:
- Key: aws-cdk:bootstrap-role
Value: file-publishing
PermissionsBoundary:
Fn::If:
- PermissionsBoundarySet
- Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
- Ref: AWS::NoValue
ImagePublishingRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: AWS::AccountId
- Fn::If:
- HasTrustedAccounts
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: TrustedAccounts
- Ref: AWS::NoValue
RoleName:
Fn::Sub: cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}
Tags:
- Key: aws-cdk:bootstrap-role
Value: image-publishing
PermissionsBoundary:
Fn::If:
- PermissionsBoundarySet
- Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
- Ref: AWS::NoValue
LookupRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: AWS::AccountId
- Fn::If:
- HasTrustedAccountsForLookup
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: TrustedAccountsForLookup
- Ref: AWS::NoValue
- Fn::If:
- HasTrustedAccounts
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: TrustedAccounts
- Ref: AWS::NoValue
RoleName:
Fn::Sub: cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}
ManagedPolicyArns:
- Fn::Sub: arn:${AWS::Partition}:iam::aws:policy/ReadOnlyAccess
Policies:
- PolicyDocument:
Statement:
- Sid: DontReadSecrets
Effect: Deny
Action:
- kms:Decrypt
Resource: "*"
Version: "2012-10-17"
PolicyName: LookupRolePolicy
Tags:
- Key: aws-cdk:bootstrap-role
Value: lookup
PermissionsBoundary:
Fn::If:
- PermissionsBoundarySet
- Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
- Ref: AWS::NoValue
FilePublishingRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- s3:GetObject*
- s3:GetBucket*
- s3:GetEncryptionConfiguration
- s3:List*
- s3:DeleteObject*
- s3:PutObject*
- s3:Abort*
Resource:
- Fn::Sub: ${StagingBucket.Arn}
- Fn::Sub: ${StagingBucket.Arn}/*
Effect: Allow
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Resource:
Fn::If:
- CreateNewKey
- Fn::Sub: ${FileAssetsBucketEncryptionKey.Arn}
- Fn::Sub: arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/${FileAssetsBucketKmsKeyId}
Version: "2012-10-17"
Roles:
- Ref: FilePublishingRole
PolicyName:
Fn::Sub: cdk-${Qualifier}-file-publishing-role-default-policy-${AWS::AccountId}-${AWS::Region}
ImagePublishingRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- ecr:PutImage
- ecr:InitiateLayerUpload
- ecr:UploadLayerPart
- ecr:CompleteLayerUpload
- ecr:BatchCheckLayerAvailability
- ecr:DescribeRepositories
- ecr:DescribeImages
- ecr:BatchGetImage
- ecr:GetDownloadUrlForLayer
Resource:
Fn::Sub: ${ContainerAssetsRepository.Arn}
Effect: Allow
- Action:
- ecr:GetAuthorizationToken
Resource: "*"
Effect: Allow
Version: "2012-10-17"
Roles:
- Ref: ImagePublishingRole
PolicyName:
Fn::Sub: cdk-${Qualifier}-image-publishing-role-default-policy-${AWS::AccountId}-${AWS::Region}
DeploymentActionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: AWS::AccountId
- Fn::If:
- HasTrustedAccounts
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: TrustedAccounts
- Ref: AWS::NoValue
Policies:
- PolicyDocument:
Statement:
- Sid: CloudFormationPermissions
Effect: Allow
Action:
- cloudformation:CreateChangeSet
- cloudformation:DeleteChangeSet
- cloudformation:DescribeChangeSet
- cloudformation:DescribeStacks
- cloudformation:ExecuteChangeSet
- cloudformation:CreateStack
- cloudformation:UpdateStack
Resource: "*"
- Sid: PipelineCrossAccountArtifactsBucket
Effect: Allow
Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
- s3:Abort*
- s3:DeleteObject*
- s3:PutObject*
Resource: "*"
Condition:
StringNotEquals:
s3:ResourceAccount:
Ref: AWS::AccountId
- Sid: PipelineCrossAccountArtifactsKey
Effect: Allow
Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Resource: "*"
Condition:
StringEquals:
kms:ViaService:
Fn::Sub: s3.${AWS::Region}.amazonaws.com
- Action: iam:PassRole
Resource:
Fn::Sub: ${CloudFormationExecutionRole.Arn}
Effect: Allow
- Sid: CliPermissions
Action:
- cloudformation:DescribeStackEvents
- cloudformation:GetTemplate
- cloudformation:DeleteStack
- cloudformation:UpdateTerminationProtection
- sts:GetCallerIdentity
- cloudformation:GetTemplateSummary
Resource: "*"
Effect: Allow
- Sid: CliStagingBucket
Effect: Allow
Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
Resource:
- Fn::Sub: ${StagingBucket.Arn}
- Fn::Sub: ${StagingBucket.Arn}/*
- Sid: ReadVersion
Effect: Allow
Action:
- ssm:GetParameter
- ssm:GetParameters
Resource:
- Fn::Sub: arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${CdkBootstrapVersion}
Version: "2012-10-17"
PolicyName: default
RoleName:
Fn::Sub: cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}
Tags:
- Key: aws-cdk:bootstrap-role
Value: deploy
PermissionsBoundary:
Fn::If:
- PermissionsBoundarySet
- Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
- Ref: AWS::NoValue
CloudFormationExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Version: "2012-10-17"
ManagedPolicyArns:
Fn::If:
- HasCloudFormationExecutionPolicies
- Ref: CloudFormationExecutionPolicies
- Fn::If:
- HasTrustedAccounts
- Ref: AWS::NoValue
- - Fn::Sub: arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess
RoleName:
Fn::Sub: cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}
PermissionsBoundary:
Fn::If:
- PermissionsBoundarySet
- Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
- Ref: AWS::NoValue
CdkBoostrapPermissionsBoundaryPolicy:
Condition: ShouldCreatePermissionsBoundary
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
Statement:
- Sid: ExplicitAllowAll
Action:
- "*"
Effect: Allow
Resource: "*"
- Sid: DenyAccessIfRequiredPermBoundaryIsNotBeingApplied
Action:
- iam:CreateUser
- iam:CreateRole
- iam:PutRolePermissionsBoundary
- iam:PutUserPermissionsBoundary
Condition:
StringNotEquals:
iam:PermissionsBoundary:
Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/cdk-${Qualifier}-permissions-boundary-${AWS::AccountId}-${AWS::Region}
Effect: Deny
Resource: "*"
- Sid: DenyPermBoundaryIAMPolicyAlteration
Action:
- iam:CreatePolicyVersion
- iam:DeletePolicy
- iam:DeletePolicyVersion
- iam:SetDefaultPolicyVersion
Effect: Deny
Resource:
Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/cdk-${Qualifier}-permissions-boundary-${AWS::AccountId}-${AWS::Region}
- Sid: DenyRemovalOfPermBoundaryFromAnyUserOrRole
Action:
- iam:DeleteUserPermissionsBoundary
- iam:DeleteRolePermissionsBoundary
Effect: Deny
Resource: "*"
Version: "2012-10-17"
Description: Bootstrap Permission Boundary
ManagedPolicyName:
Fn::Sub: cdk-${Qualifier}-permissions-boundary-${AWS::AccountId}-${AWS::Region}
Path: /
CdkBootstrapVersion:
Type: AWS::SSM::Parameter
Properties:
Type: String
Name:
Fn::Sub: /cdk-bootstrap/${Qualifier}/version
Value: "20"
Outputs:
BucketName:
Description: The name of the S3 bucket owned by the CDK toolkit stack
Value:
Fn::Sub: ${StagingBucket}
BucketDomainName:
Description: The domain name of the S3 bucket owned by the CDK toolkit stack
Value:
Fn::Sub: ${StagingBucket.RegionalDomainName}
FileAssetKeyArn:
Description: The ARN of the KMS key used to encrypt the asset bucket (deprecated)
Value:
Fn::If:
- CreateNewKey
- Fn::Sub: ${FileAssetsBucketEncryptionKey.Arn}
- Fn::Sub: ${FileAssetsBucketKmsKeyId}
Export:
Name:
Fn::Sub: CdkBootstrap-${Qualifier}-FileAssetKeyArn
ImageRepositoryName:
Description: The name of the ECR repository which hosts docker image assets
Value:
Fn::Sub: ${ContainerAssetsRepository}
BootstrapVersion:
Description: The version of the bootstrap resources that are currently mastered in this stack
Value:
Fn::GetAtt:
- CdkBootstrapVersion
- Value
Description: This stack includes resources needed to deploy AWS CDK apps into this environment
Parameters:
TrustedAccounts:
Description: List of AWS accounts that are trusted to publish assets and deploy stacks to this environment
Default: ""
Type: CommaDelimitedList
TrustedAccountsForLookup:
Description: List of AWS accounts that are trusted to look up values in this environment
Default: ""
Type: CommaDelimitedList
CloudFormationExecutionPolicies:
Description: List of the ManagedPolicy ARN(s) to attach to the CloudFormation deployment role
Default: ""
Type: CommaDelimitedList
FileAssetsBucketName:
Description: The name of the S3 bucket used for file assets
Default: ""
Type: String
FileAssetsBucketKmsKeyId:
Description: Empty to create a new key (default), 'AWS_MANAGED_KEY' to use a managed S3 key, or the ID/ARN of an existing key.
Default: ""
Type: String
ContainerAssetsRepositoryName:
Description: A user-provided custom name to use for the container assets ECR repository
Default: ""
Type: String
Qualifier:
Description: An identifier to distinguish multiple bootstrap stacks in the same environment
Default: hnb659fds
Type: String
AllowedPattern: "[A-Za-z0-9_-]{1,10}"
ConstraintDescription: Qualifier must be an alphanumeric identifier of at most 10 characters
PublicAccessBlockConfiguration:
Description: Whether or not to enable S3 Staging Bucket Public Access Block Configuration
Default: "true"
Type: String
AllowedValues:
- "true"
- "false"
InputPermissionsBoundary:
Description: Whether or not to use either the CDK supplied or custom permissions boundary
Default: ""
Type: String
UseExamplePermissionsBoundary:
Default: "false"
AllowedValues:
- "true"
- "false"
Type: String
BootstrapVariant:
Type: String
Default: "AWS CDK: Default Resources"
Description: Describe the provenance of the resources in this bootstrap stack. Change this when you customize the template. To prevent accidents, the CDK CLI will not overwrite bootstrap stacks with a different variant.
Conditions:
HasTrustedAccounts:
Fn::Not:
- Fn::Equals:
- ""
- Fn::Join:
- ""
- Ref: TrustedAccounts
HasTrustedAccountsForLookup:
Fn::Not:
- Fn::Equals:
- ""
- Fn::Join:
- ""
- Ref: TrustedAccountsForLookup
HasCloudFormationExecutionPolicies:
Fn::Not:
- Fn::Equals:
- ""
- Fn::Join:
- ""
- Ref: CloudFormationExecutionPolicies
HasCustomFileAssetsBucketName:
Fn::Not:
- Fn::Equals:
- ""
- Ref: FileAssetsBucketName
CreateNewKey:
Fn::Equals:
- ""
- Ref: FileAssetsBucketKmsKeyId
UseAwsManagedKey:
Fn::Equals:
- AWS_MANAGED_KEY
- Ref: FileAssetsBucketKmsKeyId
ShouldCreatePermissionsBoundary:
Fn::Equals:
- "true"
- Ref: UseExamplePermissionsBoundary
PermissionsBoundarySet:
Fn::Not:
- Fn::Equals:
- ""
- Ref: InputPermissionsBoundary
HasCustomContainerAssetsRepositoryName:
Fn::Not:
- Fn::Equals:
- ""
- Ref: ContainerAssetsRepositoryName
UsePublicAccessBlockConfiguration:
Fn::Equals:
- "true"
- Ref: PublicAccessBlockConfiguration
Resources:
FileAssetsBucketEncryptionKey:
Type: AWS::KMS::Key
Properties:
KeyPolicy:
Statement:
- Action:
- kms:Create*
- kms:Describe*
- kms:Enable*
- kms:List*
- kms:Put*
- kms:Update*
- kms:Revoke*
- kms:Disable*
- kms:Get*
- kms:Delete*
- kms:ScheduleKeyDeletion
- kms:CancelKeyDeletion
- kms:GenerateDataKey
- kms:TagResource
- kms:UntagResource
Effect: Allow
Principal:
AWS:
Ref: AWS::AccountId
Resource: "*"
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS: "*"
Resource: "*"
Condition:
StringEquals:
kms:CallerAccount:
Ref: AWS::AccountId
kms:ViaService:
- Fn::Sub: s3.${AWS::Region}.amazonaws.com
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS:
Fn::Sub: ${FilePublishingRole.Arn}
Resource: "*"
Condition: CreateNewKey
FileAssetsBucketEncryptionKeyAlias:
Condition: CreateNewKey
Type: AWS::KMS::Alias
Properties:
AliasName:
Fn::Sub: alias/cdk-${Qualifier}-assets-key
TargetKeyId:
Ref: FileAssetsBucketEncryptionKey
StagingBucket:
Type: AWS::S3::Bucket
Properties:
BucketName:
Fn::If:
- HasCustomFileAssetsBucketName
- Fn::Sub: ${FileAssetsBucketName}
- Fn::Sub: cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}
AccessControl: Private
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: aws:kms
KMSMasterKeyID:
Fn::If:
- CreateNewKey
- Fn::Sub: ${FileAssetsBucketEncryptionKey.Arn}
- Fn::If:
- UseAwsManagedKey
- Ref: AWS::NoValue
- Fn::Sub: ${FileAssetsBucketKmsKeyId}
PublicAccessBlockConfiguration:
Fn::If:
- UsePublicAccessBlockConfiguration
- BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
- Ref: AWS::NoValue
VersioningConfiguration:
Status: Enabled
LifecycleConfiguration:
Rules:
- Id: CleanupOldVersions
Status: Enabled
NoncurrentVersionExpiration:
NoncurrentDays: 365
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
StagingBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket:
Ref: StagingBucket
PolicyDocument:
Id: AccessControl
Version: "2012-10-17"
Statement:
- Sid: AllowSSLRequestsOnly
Action: s3:*
Effect: Deny
Resource:
- Fn::Sub: ${StagingBucket.Arn}
- Fn::Sub: ${StagingBucket.Arn}/*
Condition:
Bool:
aws:SecureTransport: "false"
Principal: "*"
ContainerAssetsRepository:
Type: AWS::ECR::Repository
Properties:
ImageTagMutability: IMMUTABLE
LifecyclePolicy:
LifecyclePolicyText: |
{
"rules": [
{
"rulePriority": 1,
"description": "Untagged images should not exist, but expire any older than one year",
"selection": {
"tagStatus": "untagged",
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 365
},
"action": { "type": "expire" }
}
]
}
RepositoryName:
Fn::If:
- HasCustomContainerAssetsRepositoryName
- Fn::Sub: ${ContainerAssetsRepositoryName}
- Fn::Sub: cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}
RepositoryPolicyText:
Version: "2012-10-17"
Statement:
- Sid: LambdaECRImageRetrievalPolicy
Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- ecr:BatchGetImage
- ecr:GetDownloadUrlForLayer
Condition:
StringLike:
aws:sourceArn:
Fn::Sub: arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*
FilePublishingRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: AWS::AccountId
- Fn::If:
- HasTrustedAccounts
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: TrustedAccounts
- Ref: AWS::NoValue
RoleName:
Fn::Sub: cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}
Tags:
- Key: aws-cdk:bootstrap-role
Value: file-publishing
ImagePublishingRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: AWS::AccountId
- Fn::If:
- HasTrustedAccounts
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: TrustedAccounts
- Ref: AWS::NoValue
RoleName:
Fn::Sub: cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}
Tags:
- Key: aws-cdk:bootstrap-role
Value: image-publishing
LookupRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: AWS::AccountId
- Fn::If:
- HasTrustedAccountsForLookup
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: TrustedAccountsForLookup
- Ref: AWS::NoValue
- Fn::If:
- HasTrustedAccounts
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: TrustedAccounts
- Ref: AWS::NoValue
RoleName:
Fn::Sub: cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}
ManagedPolicyArns:
- Fn::Sub: arn:${AWS::Partition}:iam::aws:policy/ReadOnlyAccess
Policies:
- PolicyDocument:
Statement:
- Sid: DontReadSecrets
Effect: Deny
Action:
- kms:Decrypt
Resource: "*"
Version: "2012-10-17"
PolicyName: LookupRolePolicy
Tags:
- Key: aws-cdk:bootstrap-role
Value: lookup
FilePublishingRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- s3:GetObject*
- s3:GetBucket*
- s3:GetEncryptionConfiguration
- s3:List*
- s3:DeleteObject*
- s3:PutObject*
- s3:Abort*
Resource:
- Fn::Sub: ${StagingBucket.Arn}
- Fn::Sub: ${StagingBucket.Arn}/*
Effect: Allow
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Resource:
Fn::If:
- CreateNewKey
- Fn::Sub: ${FileAssetsBucketEncryptionKey.Arn}
- Fn::Sub: arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/${FileAssetsBucketKmsKeyId}
Version: "2012-10-17"
Roles:
- Ref: FilePublishingRole
PolicyName:
Fn::Sub: cdk-${Qualifier}-file-publishing-role-default-policy-${AWS::AccountId}-${AWS::Region}
ImagePublishingRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- ecr:PutImage
- ecr:InitiateLayerUpload
- ecr:UploadLayerPart
- ecr:CompleteLayerUpload
- ecr:BatchCheckLayerAvailability
- ecr:DescribeRepositories
- ecr:DescribeImages
- ecr:BatchGetImage
- ecr:GetDownloadUrlForLayer
Resource:
Fn::Sub: ${ContainerAssetsRepository.Arn}
Effect: Allow
- Action:
- ecr:GetAuthorizationToken
Resource: "*"
Effect: Allow
Version: "2012-10-17"
Roles:
- Ref: ImagePublishingRole
PolicyName:
Fn::Sub: cdk-${Qualifier}-image-publishing-role-default-policy-${AWS::AccountId}-${AWS::Region}
DeploymentActionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: AWS::AccountId
- Fn::If:
- HasTrustedAccounts
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Ref: TrustedAccounts
- Ref: AWS::NoValue
Policies:
- PolicyDocument:
Statement:
- Sid: CloudFormationPermissions
Effect: Allow
Action:
- cloudformation:CreateChangeSet
- cloudformation:DeleteChangeSet
- cloudformation:DescribeChangeSet
- cloudformation:DescribeStacks
- cloudformation:ExecuteChangeSet
- cloudformation:CreateStack
- cloudformation:UpdateStack
Resource: "*"
- Sid: PipelineCrossAccountArtifactsBucket
Effect: Allow
Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
- s3:Abort*
- s3:DeleteObject*
- s3:PutObject*
Resource: "*"
Condition:
StringNotEquals:
s3:ResourceAccount:
Ref: AWS::AccountId
- Sid: PipelineCrossAccountArtifactsKey
Effect: Allow
Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Resource: "*"
Condition:
StringEquals:
kms:ViaService:
Fn::Sub: s3.${AWS::Region}.amazonaws.com
- Action: iam:PassRole
Resource:
Fn::Sub: ${CloudFormationExecutionRole.Arn}
Effect: Allow
- Sid: CliPermissions
Action:
- cloudformation:DescribeStackEvents
- cloudformation:GetTemplate
- cloudformation:DeleteStack
- cloudformation:UpdateTerminationProtection
- sts:GetCallerIdentity
- cloudformation:GetTemplateSummary
Resource: "*"
Effect: Allow
- Sid: CliStagingBucket
Effect: Allow
Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
Resource:
- Fn::Sub: ${StagingBucket.Arn}
- Fn::Sub: ${StagingBucket.Arn}/*
- Sid: ReadVersion
Effect: Allow
Action:
- ssm:GetParameter
- ssm:GetParameters
Resource:
- Fn::Sub: arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${CdkBootstrapVersion}
Version: "2012-10-17"
PolicyName: default
RoleName:
Fn::Sub: cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}
Tags:
- Key: aws-cdk:bootstrap-role
Value: deploy
CloudFormationExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Version: "2012-10-17"
ManagedPolicyArns:
Fn::If:
- HasCloudFormationExecutionPolicies
- Ref: CloudFormationExecutionPolicies
- Fn::If:
- HasTrustedAccounts
- Ref: AWS::NoValue
- - Fn::Sub: arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess
RoleName:
Fn::Sub: cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}
PermissionsBoundary:
Fn::If:
- PermissionsBoundarySet
- Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
- Ref: AWS::NoValue
CdkBoostrapPermissionsBoundaryPolicy:
Condition: ShouldCreatePermissionsBoundary
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
Statement:
- Sid: ExplicitAllowAll
Action:
- "*"
Effect: Allow
Resource: "*"
- Sid: DenyAccessIfRequiredPermBoundaryIsNotBeingApplied
Action:
- iam:CreateUser
- iam:CreateRole
- iam:PutRolePermissionsBoundary
- iam:PutUserPermissionsBoundary
Condition:
StringNotEquals:
iam:PermissionsBoundary:
Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/cdk-${Qualifier}-permissions-boundary-${AWS::AccountId}-${AWS::Region}
Effect: Deny
Resource: "*"
- Sid: DenyPermBoundaryIAMPolicyAlteration
Action:
- iam:CreatePolicyVersion
- iam:DeletePolicy
- iam:DeletePolicyVersion
- iam:SetDefaultPolicyVersion
Effect: Deny
Resource:
Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/cdk-${Qualifier}-permissions-boundary-${AWS::AccountId}-${AWS::Region}
- Sid: DenyRemovalOfPermBoundaryFromAnyUserOrRole
Action:
- iam:DeleteUserPermissionsBoundary
- iam:DeleteRolePermissionsBoundary
Effect: Deny
Resource: "*"
Version: "2012-10-17"
Description: Bootstrap Permission Boundary
ManagedPolicyName:
Fn::Sub: cdk-${Qualifier}-permissions-boundary-${AWS::AccountId}-${AWS::Region}
Path: /
CdkBootstrapVersion:
Type: AWS::SSM::Parameter
Properties:
Type: String
Name:
Fn::Sub: /cdk-bootstrap/${Qualifier}/version
Value: "20"
Outputs:
BucketName:
Description: The name of the S3 bucket owned by the CDK toolkit stack
Value:
Fn::Sub: ${StagingBucket}
BucketDomainName:
Description: The domain name of the S3 bucket owned by the CDK toolkit stack
Value:
Fn::Sub: ${StagingBucket.RegionalDomainName}
FileAssetKeyArn:
Description: The ARN of the KMS key used to encrypt the asset bucket (deprecated)
Value:
Fn::If:
- CreateNewKey
- Fn::Sub: ${FileAssetsBucketEncryptionKey.Arn}
- Fn::Sub: ${FileAssetsBucketKmsKeyId}
Export:
Name:
Fn::Sub: CdkBootstrap-${Qualifier}-FileAssetKeyArn
ImageRepositoryName:
Description: The name of the ECR repository which hosts docker image assets
Value:
Fn::Sub: ${ContainerAssetsRepository}
BootstrapVersion:
Description: The version of the bootstrap resources that are currently mastered in this stack
Value:
Fn::GetAtt:
- CdkBootstrapVersion
- Value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment