aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code

Home Page:https://aws.amazon.com/cdk

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

pipelines: default behavior created overly permissive policy

andreprawira opened this issue · comments

Describe the bug

im using the pipelines construct to deploy resources cross account through the pipelines. When the pipeline kicks in, it will create 2 roles (1 in the account where the pipeline is created, and another 1 in the account where we deploy the resources), one of the resources the pipeline deploy is an IAM role named xxxxx-deploy-role-<account-id>-<region-> that has an inline policy named default

this is what is inside the default inline policy (along with other stuff)

{
            "Condition": {
                "StringEquals": {
                    "kms:ViaService": "s3.us-east-2.amazonaws.com"
                }
            },
            "Action": [
                "kms:Decrypt",
                "kms:DescribeKey",
                "kms:Encrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*"
            ],
            "Resource": "*",
            "Effect": "Allow",
            "Sid": "PipelineCrossAccountArtifactsKey"
        },

The problem of this policy is that it creates a problem in our SecurityHub findings

image

My question is, is there a way to make this policy not overly permissive instead of supressing the finding in the SecurityHub? Or other alternatives that i cant think of? Thx

Expected Behavior

The default inline policy isnt overly permissive

Current Behavior

The overly permissive default inline policy is found to be a problem in SecurityHub findings

Reproduction Steps

please view the description above

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.143.0

Framework Version

No response

Node.js Version

20.13.0

OS

windows

Language

Python

Language Version

3.9.16

Other information

No response

@andreprawira , thanks for reporting this.

Default role is created by CDK to assume to initiate a deployment in this environment- Code ref - and which adds the KMS:Decrypt policy.
AFAIK, the default role policy can't be changed. One has to take measures to bypass it.
I have checked the feature flags but did not notice any flag which could help restrict the policies created.
cc : @pahud

@khushail how do i bypass it in cdk?

Hi @andreprawira

This role seems to be the deploy-role created when you first cdk bootstrap the account/region and it should be

cdk-hnb659fds-deploy-role-<YOUR_ACCOUNT_ID>-<REGION>

Can you confirm if it's the role you mentioned?

What’s happening for x-account deployment pipeline:

  1. pipeline account A would have a codebuild phase that run cdk synth and another phase for cdk deploy using the synthesized cloudassembly.

  2. In that deploy phase, codebuild would run cdk deploy as a role from Account A

  3. What’s happening here is this role would assume the cdk-hnb659fds-deploy-role-<YOUR_ACCOUNT_ID>-<REGION> of account B so it could run the cloudformation SDK calls to deploy account B as that deploy-role.

  4. cdk-hnb659fds-deploy-role-<YOUR_ACCOUNT_ID>-<REGION> this role is provisioned when you cdk bootstrap account B, not created by the pipeline.

@pahud its not that role, its the role that is created by CDK in account B (Where we deploy the actual resources, not the pipeline, the pipeline is in account A), in my end the role name is cdk-<@aws-cdk/core:bootstrapQualifier>-deploy-role-<account-number>-us-east-1 and below is the full default inline policy that it has

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "cloudformation:CreateChangeSet",
                "cloudformation:DeleteChangeSet",
                "cloudformation:DescribeChangeSet",
                "cloudformation:DescribeStacks",
                "cloudformation:ExecuteChangeSet",
                "cloudformation:CreateStack",
                "cloudformation:UpdateStack"
            ],
            "Resource": "*",
            "Effect": "Allow",
            "Sid": "CloudFormationPermissions"
        },
        {
            "Condition": {
                "StringNotEquals": {
                    "s3:ResourceAccount": "<my-account-id>"
                }
            },
            "Action": [
                "s3:GetObject*",
                "s3:GetBucket*",
                "s3:List*",
                "s3:Abort*",
                "s3:DeleteObject*",
                "s3:PutObject*"
            ],
            "Resource": "*",
            "Effect": "Allow",
            "Sid": "PipelineCrossAccountArtifactsBucket"
        },
        {
            "Condition": {
                "StringEquals": {
                    "kms:ViaService": "s3.us-east-1.amazonaws.com"
                }
            },
            "Action": [
                "kms:Decrypt",
                "kms:DescribeKey",
                "kms:Encrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*"
            ],
            "Resource": "*",
            "Effect": "Allow",
            "Sid": "PipelineCrossAccountArtifactsKey"
        },
        {
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::<my-account-id>:role/cdk-<@aws-cdk/core:bootstrapQualifier>-cfn-exec-role-<my-account-id>-us-east-1",
            "Effect": "Allow"
        },
        {
            "Action": [
                "cloudformation:DescribeStackEvents",
                "cloudformation:GetTemplate",
                "cloudformation:DeleteStack",
                "cloudformation:UpdateTerminationProtection",
                "sts:GetCallerIdentity"
            ],
            "Resource": "*",
            "Effect": "Allow",
            "Sid": "CliPermissions"
        },
        {
            "Action": [
                "s3:GetObject*",
                "s3:GetBucket*",
                "s3:List*"
            ],
            "Resource": [
                "arn:aws:s3:::cdk-<@aws-cdk/core:bootstrapQualifier>-assets-<my-account-id>-us-east-1",
                "arn:aws:s3:::cdk-<@aws-cdk/core:bootstrapQualifier>-assets-<my-account-id>-us-east-1/*"
            ],
            "Effect": "Allow",
            "Sid": "CliStagingBucket"
        },
        {
            "Action": [
                "ssm:GetParameter"
            ],
            "Resource": [
                "arn:aws:ssm:us-east-1:<my-account-id>:parameter/cdk-bootstrap/<@aws-cdk/core:bootstrapQualifier>/version"
            ],
            "Effect": "Allow",
            "Sid": "ReadVersion"
        }
    ]
}

that inline rule is what triggers securityhub findings

its the role that is created by CDK in account B (Where we deploy the actual resources, not the pipeline, the pipeline is in account A), in my end the role name is cdk-<@aws-cdk/core:bootstrapQualifier>-deploy-role--us-east-1 and below is the full default inline policy that it has

Hi,

The cdk-<@aws-cdk/core:bootstrapQualifier>-deploy-role-<account-number>-us-east-1 role you mentioned in account B is created when you cdk bootstrap on account B, which is defined here.

Per How does bootstrapping work:

Resources and their configuration that are used by the CDK are defined in an AWS CloudFormation template. This template is created and managed by the CDK team. For the latest version of this template, see bootstrap-template.yaml in the aws-cdk GitHub repository.

To bootstrap an environment, you use the AWS CDK Command Line Interface (AWS CDK CLI) cdk bootstrap command. The CDK CLI retrieves the template and deploys it to AWS CloudFormation as a stack, known as the bootstrap stack. By default, the stack name is CDKToolkit. By deploying this template, CloudFormation provisions the resources in your environment. After deployment, the bootstrap stack will appear in the AWS CloudFormation console of your environment.

You can also customize bootstrapping by modifying the template or by using CDK CLI options with the cdk bootstrap command.

My questions:

  1. Why do you believe cdk-<@aws-cdk/core:bootstrapQualifier>-deploy-role-<account-number>-us-east-1 of account B is actually created by account A?
  2. Can you check the cloudformation console on Account B, view the Resources of the CDKToolkit stack and see if you can find this IAM role resource in the CDKToolkit stack?

You can use AWS CLI to check that as well.

From Account B:

aws cloudformation list-stack-resources \
    --stack-name CDKToolkit \
    --query 'StackResourceSummaries[?ResourceType==`AWS::IAM::Role`].[ResourceType, PhysicalResourceId]' \
    --output text

You should see this

AWS::IAM::Role  cdk-hnb659fds-cfn-exec-role-<AWS_ACCOUNT_ID>-us-east-1
AWS::IAM::Role  cdk-hnb659fds-deploy-role-<AWS_ACCOUNT_ID>-us-east-1
AWS::IAM::Role  cdk-hnb659fds-file-publishing-role-<AWS_ACCOUNT_ID>-us-east-1
AWS::IAM::Role  cdk-hnb659fds-image-publishing-role-<AWS_ACCOUNT_ID>-us-east-1
AWS::IAM::Role  cdk-hnb659fds-lookup-role-<AWS_ACCOUNT_ID>-us-east-1

They are the IAM roles created when you cdk bootstrap Account B.

This issue has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.

Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.