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

CodeBuild: Associating an existing IAM role to a CodeBuild project results in exception #2651

Closed
thesurlydev opened this issue May 27, 2019 · 9 comments · Fixed by #2662, MechanicalRock/tech-radar#14 or #5701 · May be fixed by MechanicalRock/cdk-constructs#5 or MechanicalRock/cdk-constructs#6
Assignees
Labels
@aws-cdk/aws-codebuild Related to AWS CodeBuild @aws-cdk/aws-iam Related to AWS Identity and Access Management bug This issue is a bug. p2

Comments

@thesurlydev
Copy link
Contributor

thesurlydev commented May 27, 2019

Describe the bug
Creating a new CodeBuild project and associating an existing IAM role results in: Policy must be attached to at least one principal: user, group or role during synthesis. My best guess is that the default policy generated by CDK is getting orphaned instead of disregarded in the case where an existing IAM role is specified?

To Reproduce
Using the following code to make the association:

val codeBuildProjectRole = Role.fromRoleArn(
            this,
            "code-build-project-role",
            "arn:aws:iam::1234567890:role/service-role/codebuild-bruiser-service-role"
        )

        val projectProps = ProjectProps.builder()
            .withEnvironment(buildEnvironment)
            .withProjectName(appName)
            .withSource(gitHubEnterpriseSource)
            .withBuildSpec("buildspec.yml")
            .withVpc(props.vpc)
            .withRole(codeBuildProjectRole)
            .withArtifacts(NoBuildArtifacts())
            .withSecondaryArtifacts(
                listOf(
                    s3BucketBuildArtifacts
                )
            )
            .build()

        val project = Project(this, "code-build-project", projectProps)

Expected behavior
Associating a valid existing role to a CodeBuild project should not result in exception.

Version:

  • Ubuntu 18.04
  • Kotlin using Java CDK artifacts
  • 0.32.0
@thesurlydev thesurlydev added the bug This issue is a bug. label May 27, 2019
@thesurlydev
Copy link
Contributor Author

This was an attempt at a workaround for #2652

@skinny85 skinny85 added the @aws-cdk/aws-codebuild Related to AWS CodeBuild label May 28, 2019
@skinny85
Copy link
Contributor

Thanks for the report @digitalsanctum. Confirming this is indeed a bug - I was able to reproduce it locally. I'll be working on a fix.

skinny85 added a commit to skinny85/aws-cdk that referenced this issue May 28, 2019
A CodeBuild Project needs to have appropriate EC2 permissions on creation
when it uses a VPC. However, the default Policy that a Project Role has
depends on the Project itself (for CloudWatch Logs permissions).
Because of that, add a dependency between the Policy containing the EC2
permissions and the Project.

Also correctly handle the case when the Project's Role is imported.

Fixes aws#2651
Fixes aws#2652
rix0rrr added a commit that referenced this issue Jun 10, 2019
Now create a Policy and attach it to imported roles as well.

This will only work for imported roles in the same account. If you
need to reference roles in other accounts without trying to add
these policy statements, use an `AwsPrincipal`.

Relates to #2381, #2651, #2652, #2662.
rix0rrr added a commit that referenced this issue Jun 17, 2019
Now create a Policy and attach it to imported roles as well.

This will only work for imported roles in the same account. If you
need to reference roles in other accounts without trying to add
these policy statements, use an `AwsPrincipal`.

Relates to #2381, #2651, #2652, #2662.
skinny85 added a commit to skinny85/aws-cdk that referenced this issue Jun 17, 2019
A CodeBuild Project needs to have appropriate EC2 permissions on creation
when it uses a VPC. However, the default Policy that a Project Role has
depends on the Project itself (for CloudWatch Logs permissions).
Because of that, add a dependency between the Policy containing the EC2
permissions and the Project.

Also correctly handle the case when the Project's Role is imported.

BREAKING CHANGE: the method addToRoleInlinePolicy in CodeBuild's Project class has been removed.

Fixes aws#2651
Fixes aws#2652

comment out the imported check to see if it works now
skinny85 added a commit to skinny85/aws-cdk that referenced this issue Jun 18, 2019
A CodeBuild Project needs to have appropriate EC2 permissions on creation
when it uses a VPC. However, the default Policy that a Project Role has
depends on the Project itself (for CloudWatch Logs permissions).
Because of that, add a dependency between the Policy containing the EC2
permissions and the Project.

BREAKING CHANGE: the method addToRoleInlinePolicy in CodeBuild's Project class has been removed.

Fixes aws#2651
Fixes aws#2652
skinny85 added a commit that referenced this issue Jun 18, 2019
…#2662)

A CodeBuild Project needs to have appropriate EC2 permissions on creation
when it uses a VPC. However, the default Policy that a Project Role has
depends on the Project itself (for CloudWatch Logs permissions).
Because of that, add a dependency between the Policy containing the EC2
permissions and the Project.

BREAKING CHANGE: the method addToRoleInlinePolicy in CodeBuild's Project class has been removed.

Fixes #2651
Fixes #2652
@pcolazurdo
Copy link

pcolazurdo commented Jan 3, 2020

I'm on 1.19.0 and this is still occurring.

My code looks like:

role=iam.Role.from_role_arn(
            self,
            "codebuild-EmbeddedMetrics",
            "arn:aws:iam::xx:role/service-role/codebuild-EmbeddedMetrics-service-role"
        )

cdk_build = codebuild.PipelineProject(self, "CdkBuild",
                        build_spec  = codebuild.BuildSpec.from_source_filename("buildspec.yml"),
                        description = "EmbeddedMetrics Build",
                        role        = role,
                        environment = dict(build_image=codebuild.LinuxBuildImage.STANDARD_1_0)
                    )

And the error is:

CREATE_FAILED        | AWS::IAM::Policy        | codebuild-EmbeddedMetrics/Policy (codebuildEmbeddedMetricsPolicy11DBAAB4) The specified value for roleName is invalid. It must contain only alphanumeric characters and/or the following: +=,.@_- (Service: AmazonIdentityManagement; Status Code: 400; Error Code: ValidationError; Request ID: d202f525-b8fd-47c8-a02e-5e80dc506120)
        new Policy (/tmp/jsii-kernel-B8Mzpj/node_modules/@aws-cdk/aws-iam/lib/policy.js:29:26)
        \_ MutableImport.addToPolicy (/tmp/jsii-kernel-B8Mzpj/node_modules/@aws-cdk/aws-iam/lib/role.js:115:42)
        \_ PipelineProject.addToRolePolicy (/tmp/jsii-kernel-B8Mzpj/node_modules/@aws-cdk/aws-codebuild/lib/project.js:46:23)
        \_ new Project (/tmp/jsii-kernel-B8Mzpj/node_modules/@aws-cdk/aws-codebuild/lib/project.js:282:14)
        \_ new PipelineProject (/tmp/jsii-kernel-B8Mzpj/node_modules/@aws-cdk/aws-codebuild/lib/pipeline-project.js:11:9)
...

If I change this code to use any IAM Role not in /service-role/ path, it works

The problem seems to be in aws-iam/lib/policy as it is not cleaning the role path as needed for cloudformation to use only the last part of the path as role name

CC @skinny85 to reopen the Issue if needed

@skinny85
Copy link
Contributor

skinny85 commented Jan 3, 2020

@pcolazurdo I just tried it with 1.19.0, and it works for me:

        role=iam.Role.from_role_arn(
            self,
            "codebuild-EmbeddedMetrics",
            "arn:aws:iam::xx:role/service-role/codebuild-EmbeddedMetrics-service-role"
        )

        cdk_build = codebuild.PipelineProject(self, "CdkBuild",
            build_spec  = codebuild.BuildSpec.from_source_filename("buildspec.yml"),
            description = "EmbeddedMetrics Build",
            role        = role,
            environment = codebuild.BuildEnvironment(build_image=codebuild.LinuxBuildImage.STANDARD_3_0),
        )

And it works:

$ npx cdk synth
Resources:
  ServiceCatalogPipelineCdkBuildB88770B6:
    Type: AWS::CodeBuild::Project
    Properties:
      Artifacts:
        Type: CODEPIPELINE
      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        Image: aws/codebuild/standard:3.0
        PrivilegedMode: false
        Type: LINUX_CONTAINER
      ServiceRole: arn:aws:iam::xx:role/service-role/codebuild-EmbeddedMetrics-service-role
      Source:
        BuildSpec: buildspec.yml
        Type: CODEPIPELINE
      Description: EmbeddedMetrics Build
    Metadata:
      aws:cdk:path: hello-cdk-1/ServiceCatalogPipeline/CdkBuild/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Modules: aws-cdk=1.19.0,@aws-cdk/assets=1.19.0,@aws-cdk/aws-apigateway=1.19.0,@aws-cdk/aws-applicationautoscaling=1.19.0,@aws-cdk/aws-autoscaling=1.19.0,@aws-cdk/aws-autoscaling-common=1.19.0,@aws-cdk/aws-autoscaling-hooktargets=1.19.0,@aws-cdk/aws-certificatemanager=1.19.0,@aws-cdk/aws-cloudformation=1.19.0,@aws-cdk/aws-cloudfront=1.19.0,@aws-cdk/aws-cloudwatch=1.19.0,@aws-cdk/aws-codebuild=1.19.0,@aws-cdk/aws-codecommit=1.19.0,@aws-cdk/aws-codedeploy=1.19.0,@aws-cdk/aws-codepipeline=1.19.0,@aws-cdk/aws-codepipeline-actions=1.19.0,@aws-cdk/aws-cognito=1.19.0,@aws-cdk/aws-dms=1.19.0,@aws-cdk/aws-ec2=1.19.0,@aws-cdk/aws-ecr=1.19.0,@aws-cdk/aws-ecr-assets=1.19.0,@aws-cdk/aws-ecs=1.19.0,@aws-cdk/aws-elasticloadbalancing=1.19.0,@aws-cdk/aws-elasticloadbalancingv2=1.19.0,@aws-cdk/aws-events=1.19.0,@aws-cdk/aws-events-targets=1.19.0,@aws-cdk/aws-glue=1.19.0,@aws-cdk/aws-iam=1.19.0,@aws-cdk/aws-kinesis=1.19.0,@aws-cdk/aws-kms=1.19.0,@aws-cdk/aws-lambda=1.19.0,@aws-cdk/aws-logs=1.19.0,@aws-cdk/aws-logs-destinations=1.19.0,@aws-cdk/aws-rds=1.19.0,@aws-cdk/aws-route53=1.19.0,@aws-cdk/aws-route53-targets=1.19.0,@aws-cdk/aws-s3=1.19.0,@aws-cdk/aws-s3-assets=1.19.0,@aws-cdk/aws-sam=1.19.0,@aws-cdk/aws-secretsmanager=1.19.0,@aws-cdk/aws-servicediscovery=1.19.0,@aws-cdk/aws-sns=1.19.0,@aws-cdk/aws-sns-subscriptions=1.19.0,@aws-cdk/aws-sqs=1.19.0,@aws-cdk/aws-ssm=1.19.0,@aws-cdk/aws-stepfunctions=1.19.0,@aws-cdk/core=1.19.0,@aws-cdk/cx-api=1.19.0,@aws-cdk/region-info=1.19.0,jsii-runtime=Python/3.6.5

(BTW, you're using the environment property wrong - see my example above)

@pcolazurdo
Copy link

Thanks for the reply @skinny85 but when I try to do cdk deploy it fails with the error:

The specified value for roleName is invalid. It must contain only alphanumeric characters and/or the following: +=,.@_- (Service: AmazonIdentityManagement; Status Code: 400; Error Code: ValidationError; Request ID: b58a1d4a-04e9-4878-be9b-f66fb552cf6e)

(exactly as before)

Btw, thanks for the tip about BuildEnvironment - I was struggling to find the right syntax here and was reading through the docs

@skinny85
Copy link
Contributor

skinny85 commented Jan 6, 2020

I think that means you can't use service roles for CodeBuild projects, no? I mean, that error is the from the CodeBuild API I assume.

@jialechan
Copy link
Contributor

i have same issues,
cdk 1.19.0 (build 5597bbe)
Typescript SDK

const buildProjectRole = iam.Role.fromRoleArn(this, 'CodeBuildRole', 'arn:aws:iam::xxx:role/service-role/codebuild-role')
    
const project = new codebuild.Project(this, 'MyProject', {
      role: buildProjectRole,
      ...
}

error msg

  9/11 | 4:18:47 AM | CREATE_FAILED        | AWS::IAM::Policy             | CodeBuildRole/Policy (CodeBuildRolePolicy0442214A) The specified value for roleName is invalid. It must contain only alphanumeric characters and/or the following: +=,.@_- (Service: AmazonIdentityManagement; Status Code: 400; Error Code: ValidationError; Request ID: c0688767-1078-415a-a062-6bb9061b928d)

@pcolazurdo
Copy link

The problem seems to be in the code for IAM:
Service Role are supported in CodeBuild, but IAM Policy is expecting a Role Name and not a /path/RoleName:

"codebuildEmbeddedMetricsPolicy11DBAAB4": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyDocument": {
          "Statement": [
            ...
        "PolicyName": "codebuildEmbeddedMetricsPolicy11DBAAB4",
        "Roles": [
          "service-role/codebuild-EmbeddedMetrics-service-role"
        ]
      },
...

If I manually change this with:

"Roles": [
          "codebuild-EmbeddedMetrics-service-role"
        ]

it works totally fine

@skinny85
Copy link
Contributor

skinny85 commented Jan 7, 2020

Aaah, I get it now :). Thanks @pcolazurdo , I'll try to get this fixed!

@skinny85 skinny85 reopened this Jan 7, 2020
@SomayaB SomayaB added the @aws-cdk/aws-iam Related to AWS Identity and Access Management label Jan 7, 2020
skinny85 added a commit to skinny85/aws-cdk that referenced this issue Jan 7, 2020
Service roles have a different ARN structure
(they have a 'service-role/' segment after the 'role/' part).
Explicitly check for that case when importing a role with such an ARN
(you cannot pass 'service-role/RoleName' as a legal role name).

Fixes aws#2651
@skinny85 skinny85 added the p2 label Jan 8, 2020
@mergify mergify bot closed this as completed in #5701 Jan 8, 2020
mergify bot added a commit that referenced this issue Jan 8, 2020
Service roles have a different ARN structure
(they have a 'service-role/' segment after the 'role/' part).
Explicitly check for that case when importing a role with such an ARN
(you cannot pass 'service-role/RoleName' as a legal role name).

Fixes #2651

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment