aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.34k stars 3.76k forks source link

pipelines: default behavior created overly permissive policy #30598

Open andreprawira opened 1 week ago

andreprawira commented 1 week ago

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

khushail commented 4 days ago

@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

andreprawira commented 3 days ago

@khushail how do i bypass it in cdk?

pahud commented 3 days ago

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?

pahud commented 3 days ago

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.

andreprawira commented 2 days ago

@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