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.5k stars 3.85k forks source link

(CDK Pipelines): allow passing a Role to `CodePipeline` #18549

Open skinny85 opened 2 years ago

skinny85 commented 2 years ago

Description

Because of https://github.com/aws/aws-cdk/issues/16244, customers have to sometimes create a Role manually and control its permissions.

We should make that easy in CodePipeline.

Use Case

See above.

Proposed Solution

Add a new property role to the CodePipeline construct.

Other information

No response

Acknowledge

rix0rrr commented 2 years ago

You can pass a codepipeline.Pipeline to CodePipeline. It can be initialized with the role you need.

skinny85 commented 2 years ago

Yep, that's what I recommended the customer do, but it's pretty non-trivial to figure out. A property in the construct props would make it more discoverable.

rix0rrr commented 2 years ago

Still don't really agree. We should control better for policy size, or injecting, instead.

pfried commented 2 years ago

For reference: I just deployed a fix following the advice by @skinny85 which essentially (besides a narrower policy) looks like the code below:

The stack redeployed and kept its resources. I had to pull out the cross account property tough.

        // Oversimplified policy
        const codePipelineRole = new Role(this, 'CodePipelineRole', {
            assumedBy: new ServicePrincipal('codepipeline.amazonaws.com'),
            roleName: cdk.PhysicalName.GENERATE_IF_NEEDED,
            inlinePolicies: {
                rootPermissions: new PolicyDocument({
                    statements: [
                        new PolicyStatement({
                            resources: ['*'],
                            actions: ['*'],
                        }),
                    ],
                }),
            }
        })

       // Need to pull out `crossAccountKeys`
        const codePipeline = new Pipeline(this, 'CodePipeline', {
            crossAccountKeys: true,
            role: codePipelineRole.withoutPolicyUpdates()
        })

        const pipeline = new CodePipeline(this, 'Pipeline', {
            codePipeline: codePipeline,
            ...
        })

Update: Just found the docs for that: AWS CDK V1: https://docs.aws.amazon.com/cdk/api/v1/docs/aws-iam-readme.html#opting-out-of-automatic-permissions-management AWS_CDK V2: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam-readme.html#opting-out-of-automatic-permissions-management

Update 2: I somehow broke stuff, so not sure if it actually works

ac259 commented 1 year ago

Hello @rix0rrr ,

I am trying to solve for the same problem; i.e to pass a role to the pipelines.CodePipeline. I am trying to do this in python. the official cdk documentation for CDK Pipeline Here there seems to be a role parameter. But in the class definition it does not seem to have it and throws and error when I cdk deploy

codepipeline-site-package-function-def

Code Snippet.

class WorkshopPipelineStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        codepipeline_role = iam.Role.from_role_arn(self, "Role", "arn:aws:iam::<account>:role/<pre-existing-role>",
        # Set 'mutable' to 'false' to use the role as-is and prevent adding new
        # policies to it. The default is 'true', which means the role may be
        # modified as part of the deployment.
        mutable=False
        )

        kms_key = aws_kms.Key.from_key_arn(self,"<kms-key>", "arn:aws:kms:us-east-1:account-number:key/<key>")
        pipeline_bucket = aws_s3.Bucket(self, '<bucket-name>',encryption_key=kms_key)

        pipeline = pipelines.CodePipeline(self,
        "<pipeline-name>",
        synth=pipelines.ShellStep(
            "Synth",
            input=pipelines.CodePipelineSource.connection("<org/repo>", "<branch>",
                connection_arn="arn:aws:codestar-connections:<connection>"
            ),
            commands=[
                "npm install -g aws-cdk",  # Installs the cdk cli on Codebuild
                "pip install -r requirements.txt",  # Instructs Codebuild to install required packages
                "cdk synth",
            ]
        ),
        role = codepipeline_role
        )

Error

Traceback (most recent call last):
  File "C:\Users\aramji\Desktop\aws-cdk\app.py", line 7, in <module>
    WorkshopPipelineStack(app, "cmg-datasvc-cdk-codepipeline-test",
  File "C:\Users\aramji\Envs\aws-cdk\lib\site-packages\jsii\_runtime.py", line 86, in __call__
    inst = super().__call__(*args, **kwargs)
  File "C:\Users\aramji\aws-cdk\cdk_workshop\pipeline_stack.py", line 41, in __init__
    pipeline = pipelines.CodePipeline(self,
  File "C:\Users\aramji\Envs\aws-cdk\lib\site-packages\jsii\_runtime.py", line 86, in __call__
    inst = super().__call__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'role'

Subprocess exited with error 1

Could you kindly help on the same?

Thanks, Ani

skinny85 commented 1 year ago

@ac259 what version of CDK are you using?

ac259 commented 1 year ago

@skinny85 I was using an older 2.x version but I upgraded to the 2.47.0 and tested again.

(aws-cdk) C:\Users\aramji\Desktop\aws-cdk>cdk --version
2.47.0 (build 3528e3d)
skinny85 commented 1 year ago

I'm asking about the libraries, though; not the CDK CLI version. You'll find their version in the requirements.txt (or just execute pip list). The libraries determine whether you have access to this feature or not.

It was released in version 2.35.0, so you need your libraries to be at least at that version.

ac259 commented 1 year ago

@skinny85 thank you so much - I was on an earlier version of the library. Was able to get it to work!