Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(pipelines): pipeline asset role trust policy has account root principal #30084

Merged
merged 12 commits into from
May 8, 2024
22 changes: 21 additions & 1 deletion packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Flags come in three types:
| [@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse](#aws-cdkaws-codepipelinecrossaccountkeysdefaultvaluetofalse) | Enables Pipeline to set the default value for crossAccountKeys to false. | 2.127.0 | (default) |
| [@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2](#aws-cdkaws-codepipelinedefaultpipelinetypetov2) | Enables Pipeline to set the default pipeline type to V2. | 2.133.0 | (default) |
| [@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope](#aws-cdkaws-kmsreducecrossaccountregionpolicyscope) | When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only. | 2.134.0 | (fix) |
| [@aws-cdk/pipelines:reduceAssetRoleTrustScope](#aws-cdkpipelinesreduceassetroletrustscope) | Remove the root account principal from PipelineAssetsFileRole trust policy | 2.141.0 | (default) |

<!-- END table -->

Expand Down Expand Up @@ -124,7 +125,8 @@ The following json shows the current recommended set of flags, as `cdk init` wou
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
"@aws-cdk/pipelines:reduceAssetRoleTrustScope": true
}
}
```
Expand Down Expand Up @@ -1265,4 +1267,22 @@ When this feature flag is enabled and calling KMS key grant method, the created
| 2.134.0 | `false` | `true` |


### @aws-cdk/pipelines:reduceAssetRoleTrustScope

*Remove the root account principal from PipelineAssetsFileRole trust policy* (default)

Remove the root account principal from the generated PipelineAssetsFileRole trust policy,
because it's only assumed by the codebuild.
Use a feature flag to make sure existing customers who might be relying
on the overly-broad trust policy are not broken.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of explaining why we add a feature flag here, can we explain the behaviour of the flag when it's true vs false, i.e. When this feature flag is enabled, the it will not add root account principal ...



| Since | Default | Recommended |
| ----- | ----- | ----- |
| (not in v1) | | |
| 2.141.0 | `false` | `true` |

**Compatibility with old behavior:** Disable the feature flag to add the root account principal back


<!-- END details -->
16 changes: 16 additions & 0 deletions packages/aws-cdk-lib/cx-api/lib/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export const LAMBDA_PERMISSION_LOGICAL_ID_FOR_LAMBDA_ACTION = '@aws-cdk/aws-clou
export const CODEPIPELINE_CROSS_ACCOUNT_KEYS_DEFAULT_VALUE_TO_FALSE = '@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse';
export const CODEPIPELINE_DEFAULT_PIPELINE_TYPE_TO_V2 = '@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2';
export const KMS_REDUCE_CROSS_ACCOUNT_REGION_POLICY_SCOPE = '@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope';
export const PIPELINE_REDUCE_ASSET_ROLE_TRUST_SCOPE = '@aws-cdk/pipelines:reduceAssetRoleTrustScope';

export const FLAGS: Record<string, FlagInfo> = {
//////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -1034,6 +1035,21 @@ export const FLAGS: Record<string, FlagInfo> = {
introducedIn: { v2: '2.134.0' },
recommendedValue: true,
},

//////////////////////////////////////////////////////////////////////
[PIPELINE_REDUCE_ASSET_ROLE_TRUST_SCOPE]: {
type: FlagType.ApiDefault,
summary: 'Remove the root account principal from PipelineAssetsFileRole trust policy',
detailsMd: `
Remove the root account principal from the generated PipelineAssetsFileRole trust policy,
because it's only assumed by the codebuild.
Use a feature flag to make sure existing customers who might be relying
on the overly-broad trust policy are not broken.
`,
introducedIn: { v2: '2.141.0' },
recommendedValue: true,
compatibilityWithOldBehaviorMd: 'Disable the feature flag to add the root account principal back',
},
};

const CURRENT_MV = 'v2';
Expand Down
19 changes: 13 additions & 6 deletions packages/aws-cdk-lib/pipelines/lib/codepipeline/codepipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import * as cpa from '../../../aws-codepipeline-actions';
import * as ec2 from '../../../aws-ec2';
import * as iam from '../../../aws-iam';
import * as s3 from '../../../aws-s3';
import { Aws, CfnCapabilities, Duration, PhysicalName, Stack, Names } from '../../../core';
import { Aws, CfnCapabilities, Duration, PhysicalName, Stack, Names, FeatureFlags } from '../../../core';
import * as cxapi from '../../../cx-api';
import { AssetType, FileSet, IFileSetProducer, ManualApprovalStep, ShellStep, StackAsset, StackDeployment, Step } from '../blueprint';
import { DockerCredential, dockerCredentialsInstallCommands, DockerCredentialUsage } from '../docker-credentials';
Expand Down Expand Up @@ -984,13 +984,20 @@ export class CodePipeline extends PipelineBase {

const stack = Stack.of(this);

const rolePrefix = assetType === AssetType.DOCKER_IMAGE ? 'Docker' : 'File';
const assetRole = new AssetSingletonRole(this.assetsScope, `${rolePrefix}Role`, {
roleName: PhysicalName.GENERATE_IF_NEEDED,
assumedBy: new iam.CompositePrincipal(
const removeRootPrincipal = FeatureFlags.of(this).isEnabled(cxapi.PIPELINE_REDUCE_ASSET_ROLE_TRUST_SCOPE);

const assumePrincipal = removeRootPrincipal ? new iam.CompositePrincipal(
new iam.ServicePrincipal('codebuild.amazonaws.com'),
) :
new iam.CompositePrincipal(
new iam.ServicePrincipal('codebuild.amazonaws.com'),
new iam.AccountPrincipal(stack.account),
),
);

const rolePrefix = assetType === AssetType.DOCKER_IMAGE ? 'Docker' : 'File';
let assetRole = new AssetSingletonRole(this.assetsScope, `${rolePrefix}Role`, {
roleName: PhysicalName.GENERATE_IF_NEEDED,
assumedBy: assumePrincipal,
});

// Grant pull access for any ECR registries and secrets that exist
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as s3 from '../../../aws-s3';
import * as sqs from '../../../aws-sqs';
import * as cdk from '../../../core';
import { Stack } from '../../../core';
import * as cxapi from '../../../cx-api';
import * as cdkp from '../../lib';
import { CodePipeline } from '../../lib';
import { PIPELINE_ENV, TestApp, ModernTestGitHubNpmPipeline, FileAssetApp, TwoStackApp, StageWithStackOutput } from '../testhelpers';
Expand Down Expand Up @@ -197,6 +198,27 @@ test('CodeBuild action role has the right AssumeRolePolicyDocument', () => {
});
});

test('CodeBuild asset role has the right Principal', () => {
xazhao marked this conversation as resolved.
Show resolved Hide resolved
const stack = new cdk.Stack();
stack.node.setContext(cxapi.PIPELINE_REDUCE_ASSET_ROLE_TRUST_SCOPE, true);
const pipelineStack = new cdk.Stack(stack, 'PipelineStack', { env: PIPELINE_ENV });
new ModernTestGitHubNpmPipeline(pipelineStack, 'Cdk');

const template = Template.fromStack(pipelineStack);
template.hasResourceProperties('AWS::IAM::Role', {
AssumeRolePolicyDocument: {
Statement: [
{
Action: 'sts:AssumeRole',
Principal: {
Service: 'codebuild.amazonaws.com',
},
},
],
},
});
});

test('CodePipeline throws when key rotation is enabled without enabling cross account keys', ()=>{
const pipelineStack = new cdk.Stack(app, 'PipelineStack', { env: PIPELINE_ENV });
const repo = new ccommit.Repository(pipelineStack, 'Repo', {
Expand Down
11 changes: 0 additions & 11 deletions packages/aws-cdk-lib/pipelines/test/compliance/assets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,17 +396,6 @@ describe('basic pipeline', () => {
Service: 'codebuild.amazonaws.com',
},
},
{
Action: 'sts:AssumeRole',
Effect: 'Allow',
Principal: {
AWS: {
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, `:iam::${PIPELINE_ENV.account}:root`,
]],
},
},
},
Comment on lines -400 to -409
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this test change when no feature flag is set?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the behavior has been tested with feature flag in the other test, we can use this to test default value.

],
},
});
Expand Down
Loading