-
Notifications
You must be signed in to change notification settings - Fork 4k
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): Reduce template size by combining IAM roles and policies #9243
Conversation
This change combines the two roles (and policies) per pipeline asset into a single role + policy for all assets in a pipeline. In a small pipeline with only 3 assets, this reduced the overall template size by a third. With a pipeline stack with 30 assets, this change reduces the template size from 363111 bytes to 190223 bytes. Tested on a cross-account pipeline to verify permissions were retained. fixes #9066 mitigates #9225 mitigates #9237
// Modeled after the CodePipeline role and 'CodePipelineActionRole' roles. | ||
// Late-binding here to prevent creating the role in cases where no asset actions are created. | ||
if (!this.assetRole) { | ||
this.assetRole = new iam.Role(this, 'Role', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the eventual IAM policy that will be generated for this role?
We need to be careful here because this role is an important component of our security model so the policy must be least privilege.
The main risk is docker builds in which arbitrary 3rd party code can run.
There are a few things that we should ensure (ideally enforce through unit tests):
- Docker publishing roles must not be able to access the s3 assets bucket in order to mitigate the threat of injecting compromised templates that can deploy malicious resources through nested stacks.
- The role must be able to assume only the specific cross-account roles in the specified target environments in which it needs to publish into to mitigate the blast radius of a compromised publisher).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this change breaks point 1 above; point 2 I believe is already broken, given the overly-permissive sts:AssumeRole statement in the pipeline asset policy (assuming arn:*:iam::*:role/*-file-publishing-role-*
).
Here is a gist with the before/after of the relevant roles and policies: https://gist.github.com/njlynch/b3364ace98559757a1ca4a1a3aab2f6d
I've replaced my account ID with __$PIPELINEACCOUNT__
in the output, but otherwise it's exactly as it appears in the synthesized output. As you can see, there are no other account(s)/environment(s) explicitly referenced, despite this template being for a cross-account, multi-region pipeline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should raise an issue to fix this policy. The remote role ARNs should actually come from the user app and not be hard coded in the pipelines library. Users are allowed to specify any role ARNs they want for publishing.
I can't seem to find the s3:PutObject permissions in the referenced gist. Are these policies for publishing both docker & s3 assets? We should still separate these into two policies in order to ensure that docker publishers cannot upload files to the S3 asset store.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should raise an issue to fix this policy.
Ok. I created #9271 to address this.
I can't seem to find the s3:PutObject permissions in the referenced gist.
s3:PutObject appears as an action on both the "PipelineRoleDefaultPolicy" (used by CodePipeline), the "PipelineBuildSynthCdkBuildProjectRoleDefaultPolicy" (used by CodeBuild as part of the build action), as well as in the policy attached to the *-file-publishing-role-*
Role. I believe it's the latter that enables the actual asset publishing here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The roles being touched in this PR are not the ones that do the actual publishing; instead, they are the roles that enable the roles that do the actual publishing.
The first role/policy (PipelineAssetsFileAssetNCodePipelineActionRole*
in the "before" example) is used by CodePipeline to start/stop the CodeBuild builds. This role is the one assumed by the CodePipeline CodeBuild action. Lumping these all together means there is a single role with the ability to start/stop the CodeBuild builds; I don't think there's a security risk here.
The second role is the one used by CodeBuild itself (PipelineAssetsFileAssetNCodePipelineActionRoleDefaultPolicy*
in the "before" example). This role has permissions to create asset-named log groups, CodeBuild report groups, has S3 and KMS get permissions on the entire asset bucket to read and decrypt the manifest, and lastly has permissions to assume the bootstrapped file and image publishing roles. The only elements of this policy that are in any way asset-specific are the named log groups and report groups. So risks here would be a malicious build writing to the wrong logs, maybe?
The main risk is docker builds in which arbitrary 3rd party code can run.
There are a few things that we should ensure (ideally enforce through unit tests):
- Docker publishing roles must not be able to access the s3 assets bucket in order to mitigate the threat of injecting compromised templates that can deploy malicious resources through nested stacks.
- The role must be able to assume only the specific cross-account roles in the specified target environments in which it needs to publish into to mitigate the blast radius of a compromised publisher).
So the actual asset publishing is controlled by the PublishAssetsAction
class, which creates a CodeBuild project that installs cdk-assets, and then executes a series of publish commands. For example:
cdk-assets --path "assembly-CdkpipelinesDemoPipelineStack-PreProdAccount1/CdkpipelinesDemoPipelineStackPreProdAccount1WebService1F433423.assets.json" --verbose publish "0a1ddcc82faef3c47aaafb9516057a34961187be09202edaf14bb4b28a6cb115:ACCOUNT1-eu-west-1"
This reads from the generated *.assets.json
files, which have encoded within them the source asset name, destination bucket, object, region, and environment-specific (account & region) role ARN to assume to do the publishing. cdk-assets
itself does the STS AssumeRole call, gets environment-specific credentials, and then does the publishing. This is where the above two restrictions are being enforced; a combination of the code that generates the assets.json files and cdk-asset executing it. I don't see a path here for combining the initial two roles causing a breakdown in that chain.
Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
…ies (aws#9243) This change combines the two roles (and policies) per pipeline asset into a single role + policy for all assets in a pipeline. In a small pipeline with only 3 assets, this reduced the overall template size by a third. With a pipeline stack with 30 assets, this change reduces the template size from 363111 bytes to 190223 bytes. Tested on a cross-account pipeline to verify permissions were retained. fixes aws#9066 mitigates aws#9225 mitigates aws#9237 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
This change combines the two roles (and policies) per pipeline asset into a
single role + policy for all assets in a pipeline. In a small pipeline with only
3 assets, this reduced the overall template size by a third.
With a pipeline stack with 30 assets, this change reduces the template size from
363111 bytes to 190223 bytes.
Tested on a cross-account pipeline to verify permissions were retained.
fixes #9066
mitigates #9225
mitigates #9237
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license