-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
feat(app-delivery) IAM policy for deploy stack #1165
Conversation
478d1e8
to
ea9aac3
Compare
@skinny85 can you take a look please? |
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.
In general, looks good and thanks, just want to hear from @skinny85 about design decisions w.r.t. CFN capabitilies.
/** | ||
* The CloudFormation Capabilities enabled for the ChangeSet. | ||
* | ||
* @default None |
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 would default this to "anonymous" IAM capabilities, that should make 95% of all CDK templates work out of the box and doesn't introduce much appreciable risk.
People will then be able to opt out of IAM completely or opt-in to strongly-named IAM objects as they desire.
Also, an enum seems more ergonomic. I know it's not robust against future extension, but I do care about ergonomics today more than a hypothetical future extension, and we can always deal with that if it ever occurs (which I don't think it will any time soon).
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.
Also, fullPermissions implies named-IAM, I'm seeing in the source of the underlying construct:
Does named-IAM subsume anonymous IAM?
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 guess this is a request for upstream change then.
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 CloudFormation documentation states that NamedIAM
implies IAM
, and that you need not specify both.
I would agree with defaulting to IAM
in app-delivery
, while letting the CFN L2 default be nothing
. This is L3 so we can allow opinion in (and CDK applications will very often make use of IAM resources).
Now the fact that it's an array of CloudFormationCapabilities
is because that is what CloudFormation accepts (even though there is no apparent use for it just yet). Maybe it's future-proofing? But I guess if the API we use is future-proofed, maybe there's a reason and we should "leak" the future-proofing out to avoid a bad surprise later?
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.
That future-proofing is exactly what I'm opposing to.
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 would default this to "anonymous" IAM capabilities, that should make 95% of all CDK templates work out of the box and doesn't introduce much appreciable risk.
People will then be able to opt out of IAM completely or opt-in to strongly-named IAM objects as they desire.
Also, an enum seems more ergonomic. I know it's not robust against future extension, but I do care about ergonomics today more than a hypothetical future extension, and we can always deal with that if it ever occurs (which I don't think it will any time soon).
@rix0rrr I'm confused here. Is anonymous
an actual thing or are we saying just change the word none to anonymous
because that's a better description? Right now if you don't create IAM entities the capabilities is empty, so I'm confused on the wording?
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.
@moofish32, I believe @rix0rrr means "anonymous IAM permissions" (as opposed to "named IAM permissions").
I agree wholeheartedly with Rico and Romain here. In general, we don't do these kind of future proofing in the CDK - we try to give a nicer API for the common case.
So, I would proceed as follows here:
- Introduce a new
enum
in this module, with 3 values:None
,AnonymousIAM
,NamedIAM
. - Make
capabilities
inPipelineDeployStackActionProps
be of this newenum
type (not an array), with defaultAnonymousIAM
. - After this PR, open a separate PR to move this enum to the
aws-cloudformation
package, and change the API of the CFN Actions themselves to use it.
Does this make sense?
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.
If I can do it all in this PR should I? I haven't looked at how difficult this would be plumb.
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.
Probably easier to leave it out of this PR, as it's a breaking change. But knock yourself out if you want - I don't think it will be super difficult :).
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.
That's pretty good! There's a couple of things that I would like to have fixed (nothing major, really). I would also plan to give the README.md
example the .lit.ts
treatment (but don't you worry about this right now - I'll do it once this PR is merged) so we can make sure it at least compiles going forward.
``` | ||
|
||
#### `buildspec.yml` | ||
The repository should contain a file at the root level named `buildspec.yml`. |
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.
That's only true if you don't specify an inline buildspec with your CodeBuild project, so I wouldn't phrase it like so.
The `PipelineDeployStackAction` expects it's `inputArtifact` to contain the result of synthesizing a CDK App using the | ||
`cdk synth -o <directory>` command. | ||
|
||
For example, a *TypeScript* or *Javascript* CDK App can add the following `buildspec.yml` at the root of the repository | ||
configured in the `Source` stage: | ||
|
||
Example contents of `buildspec.yml` (note: `buildspec.yaml` is not compatible) |
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 precision on .yaml
is definitely a good one - I'd have moved it in the paragraph just above.
@@ -41,6 +41,29 @@ export interface PipelineDeployStackActionProps { | |||
* @default ``createChangeSetRunOrder + 1`` | |||
*/ | |||
executeChangeSetRunOrder?: number; | |||
|
|||
/** | |||
* The role to use when creating and executing the ChangeSet. |
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 would copy the comment from the PipelineCreateReplaceChangeSetActionProps
attribute (same for the other two). I think they're pretty detailed and they avoid insisting so much on the implementation detail here (customer is really just interesting at deploying a stack - the fact there is a ChangeSet being created, then executed, is mostly irrelevant).
new cfn.PipelineCreateReplaceChangeSetAction(this, 'ChangeSet', { | ||
this.stack = props.stack; | ||
|
||
const fullPermissions = props.fullPermissions === true; |
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 don't think this is needed. fullPermissions
defaults to false
in PipelineCreateReplaceChangeSetAction
(and I reckon we're quite unlikely to change this default, as it has pretty drastic security implications).
@@ -63,6 +65,8 @@ | |||
], | |||
"peerDependencies": { | |||
"@aws-cdk/aws-codepipeline-api": "^0.16.0", | |||
"@aws-cdk/aws-cloudformation": "^0.16.0", |
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.
You'll want to make sure you merge in the 0.17.0
version bump & update those :)
@@ -52,9 +52,13 @@ const source = new codepipeline.GitHubSourceAction(pipelineStack, 'GitHub', { | |||
/* ... */ | |||
}); | |||
const project = new codebuild.PipelineProject(pipelineStack, 'CodeBuild', { | |||
/* ... */ | |||
environment: { | |||
buildImage: codebuild.LinuxBuildImage.UBUNTU_14_04_NODEJS_10_1_0, |
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 wouldn't specify this in the README.md
, it could be distracting (or looking like it needs to be that).
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.
Made a comment instead as an example.
9dcfa2f
to
0d1fdb9
Compare
"@aws-cdk/aws-codepipeline": "^0.17.0", | ||
"@aws-cdk/aws-s3": "^0.17.0", | ||
"cdk-build-tools": "^0.17.0", | ||
"cdk-integ-tools": "^0.17.0", |
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.
Some dependencies are duplicated here (cdk-build-tools
, cdk-integ-tools
, @aws-cdk/aws-s3
, @aws-cdk/aws-codepipeline
) - I would remove the extra ones so that the @aws-cdk
namespace ones are grouped at the beginning.
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.
copy and paste on resolution -- my bad fixing and will alphabetize too
"@aws-cdk/aws-codebuild": "^0.17.0", | ||
"@aws-cdk/aws-codepipeline-api": "^0.17.0", | ||
"@aws-cdk/cdk": "^0.17.0", | ||
"@aws-cdk/cx-api": "^0.17.0", |
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.
Nit: alphabetic order.
@@ -63,6 +83,8 @@ | |||
], | |||
"peerDependencies": { | |||
"@aws-cdk/aws-codepipeline-api": "^0.17.0", | |||
"@aws-cdk/aws-iam": "^0.17.0", | |||
"@aws-cdk/aws-cloudformation": "^0.17.0", |
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.
Nit: alphabetic order.
/** | ||
* The CloudFormation Capabilities enabled for the ChangeSet. | ||
* | ||
* @default None |
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.
@moofish32, I believe @rix0rrr means "anonymous IAM permissions" (as opposed to "named IAM permissions").
I agree wholeheartedly with Rico and Romain here. In general, we don't do these kind of future proofing in the CDK - we try to give a nicer API for the common case.
So, I would proceed as follows here:
- Introduce a new
enum
in this module, with 3 values:None
,AnonymousIAM
,NamedIAM
. - Make
capabilities
inPipelineDeployStackActionProps
be of this newenum
type (not an array), with defaultAnonymousIAM
. - After this PR, open a separate PR to move this enum to the
aws-cloudformation
package, and change the API of the CFN Actions themselves to use it.
Does this make sense?
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.
Looks great. Other than the capabilities thing (which is not a problem in this PR, but something we actually want to change upstream), I only have minor nitpicks.
0d1fdb9
to
471008e
Compare
I will leave it to @RomainMuller and @skinny85 to merge this PR if they're satisfied. |
I think we'll be good to merge once @skinny85's suggestion with respects to defining an |
471008e
to
2a60d58
Compare
I have updated the commit (via squash/rebase) and included this breaking change. If we are going to break let's just get on with it.
|
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.
Related #286
packages/@aws-cdk/app-delivery/lib/pipeline-deploy-stack-action.ts
Outdated
Show resolved
Hide resolved
packages/@aws-cdk/app-delivery/lib/pipeline-deploy-stack-action.ts
Outdated
Show resolved
Hide resolved
* | ||
* @default false | ||
*/ | ||
fullPermissions?: boolean; |
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.
This should have the word admin
in it in my mind to ensure the extent of this grant is clear. I would even just call this administrator
. It's okay that this also implies "capabilities=NAMED_IAM"...
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 went with adminPermissions
because when I put in administrator
I asked my self of what? I thought adminPermissions
would be more clear, if you are set on administrator
let me know.
dfc4db7
to
9aa9eed
Compare
I'm not sure who has the final merge rights, but I've attempted to incorporate the feedback. Let me know if any further changes are needed. |
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.
LGTM @skinny85 you get the final approval
Resolved the conflicts in |
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.
Sorry @moofish32 , I still have comments here :(.
// Add the necessary permissions for you service deploy action. This role is | ||
// is passed to CloudFormation and needs the permissions necessary to deploy | ||
// stack. Alternatively you can enable [Administrator](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions.html#jf_administrator | ||
) permissions above, |
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.
Huh. This shows up as a new line without comments. Perhaps it's just GitHub's diff displaying it weirdly.
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.
legit mistake on me, GitHub doesn't lie
The `PipelineDeployStackAction` expects it's `inputArtifact` to contain the result of synthesizing a CDK App using the | ||
`cdk synth -o <directory>` command. | ||
|
||
For example, a *TypeScript* or *Javascript* CDK App can add the following `buildspec.yml` at the root of the repository | ||
configured in the `Source` stage: | ||
|
||
Example contents of `buildspec.yml`. |
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.
Example contents of buildspec.yml
:
// empty line here
version: 0.2
phases:
...
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.
👍
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 now clashes with the sentence above? "For example, a TypeScript or Javascript CDK App can add the following buildspec.yml
at the root of the repository configured in the Source
stage:". Perhaps it always did, I just never noticed ;p.
* Acknowledge certain changes made as part of deployment | ||
* | ||
* For stacks that contain certain resources, explicit acknowledgement that AWS CloudFormation | ||
* might create or update those resources. For example, you must specify CAPABILITY_IAM if your |
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 believe CAPABILITY_IAM
is not the correct constant name anymore?
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.
👍
addAction('ec2:DescribeSecurityGroups'). | ||
addAction('ec2:CreateSecurityGroup'). | ||
addAction('ec2:RevokeSecurityGroupEgress'). | ||
addAction('ec2:RevokeSecurityGroupIngress'). |
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.
Feel free to use the addActions
method here, that takes a varargs argument, will be more concise.
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.
OH... I didn't see there was one!
// else capabilities are defined use them | ||
return capabilities; | ||
} | ||
} |
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.
Sorry, maybe I wasn't clear before.
The capabilities should default to AnonymousIAM
only in the app-delivery
construct.
In the CFN Actions, the default should be undefined
(that is, none), like it is now.
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 wondered about this change. With adminPermissions
being required it seems a bit odd this default is allow IAM, but it's a pretty heavy coin flip considering it's rare not to deploy a role with a service.
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.
@skinny85 -- implementing changes requested in next push, if build passes I think I've incorporated the changes, if not I'll be fixing shortly.
The `PipelineDeployStackAction` expects it's `inputArtifact` to contain the result of synthesizing a CDK App using the | ||
`cdk synth -o <directory>` command. | ||
|
||
For example, a *TypeScript* or *Javascript* CDK App can add the following `buildspec.yml` at the root of the repository | ||
configured in the `Source` stage: | ||
|
||
Example contents of `buildspec.yml`. |
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.
👍
// Add the necessary permissions for you service deploy action. This role is | ||
// is passed to CloudFormation and needs the permissions necessary to deploy | ||
// stack. Alternatively you can enable [Administrator](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions.html#jf_administrator | ||
) permissions above, |
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.
legit mistake on me, GitHub doesn't lie
* Acknowledge certain changes made as part of deployment | ||
* | ||
* For stacks that contain certain resources, explicit acknowledgement that AWS CloudFormation | ||
* might create or update those resources. For example, you must specify CAPABILITY_IAM if your |
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.
👍
// else capabilities are defined use them | ||
return capabilities; | ||
} | ||
} |
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 wondered about this change. With adminPermissions
being required it seems a bit odd this default is allow IAM, but it's a pretty heavy coin flip considering it's rare not to deploy a role with a service.
f055eff
to
51401d3
Compare
Thanks for the conflict resolution @RomainMuller. @skinny85 did I get all the fixes in 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.
Can you revert the changes to the expected JSON files, and see if npm run test
still passes for the packages? I'm pretty sure none of the changes to those files are needed, and I'd rather not change them if there's no reason (they are our biggest line of defense against regressions).
Also, some optional minor comments.
// new iam.PolicyStatement(). | ||
// ... addAction('actions that you need'). | ||
// add resource | ||
); |
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 wouldn't comment out the whole thing, but instead just the usecase-specific part:
deployServiceAAction.addToRolePolicy(
new iam.PolicyStatement()
.addAction('service:SomeAction')
.addResource(myResource.myResourceArn)
// add more Action(s) and/or Resource(s) here, as needed
);
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 `PipelineDeployStackAction` expects it's `inputArtifact` to contain the result of synthesizing a CDK App using the | ||
`cdk synth -o <directory>` command. | ||
|
||
For example, a *TypeScript* or *Javascript* CDK App can add the following `buildspec.yml` at the root of the repository | ||
configured in the `Source` stage: | ||
|
||
Example contents of `buildspec.yml`. |
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 now clashes with the sentence above? "For example, a TypeScript or Javascript CDK App can add the following buildspec.yml
at the root of the repository configured in the Source
stage:". Perhaps it always did, I just never noticed ;p.
*/ | ||
NamedIAM = 'CAPABILITY_NAMED_IAM' | ||
None = '', |
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 would actually make None
the first enum value (I would sort them in the order of increasing capabilities).
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.
Just so we all know ... that enum was alphabetized, in accordance with multiple other nits
from @skinny85 😮
packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit-build.expected.json
Outdated
Show resolved
Hide resolved
packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit.expected.json
Outdated
Show resolved
Hide resolved
packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-deploy.expected.json
Outdated
Show resolved
Hide resolved
packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-events.expected.json
Outdated
Show resolved
Hide resolved
* The changeset and apply changeset can now apply role IAM permissions, and CloudFormation Capabilities * Updated CloudFormationCapabilities enum to include `None` * User must set adminPermissions boolean for pipeline action * app-delivery defaults pipelin-action capabilities to AnonymousIAM * Document updates for proper build stage configuration * Fixes aws#1151 BREAKING CHANGE: `CloudFormationCapabilities.IAM` renamed to `CloudFormation.AnonymousIAM` and `PipelineCloudFormationDeployActionProps.capabilities?: CloudFormationCapabilities[]` has been changed to `PipelineCloudFormationDeployActionProps.capabilities?: CloudFormationCapabilities` no longer an array. `PipelineCloudFormationDeployActionProps.fullPermissions?:` has been renamed to `PipelineCloudFormationDeployActionProps.adminPermissions:` and is required instead of optional.
5be9fa8
to
7754916
Compare
alright @skinny85 one more pass when ever you are back from the holiday. |
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.
Looks great. Thanks for the patience @moofish32 !
and the user can now customize them via
deployStackAction.role
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license.