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.68k stars 3.92k forks source link

codebuild: project creation fails when GitHub source webhook is enabled #31726

Open tmokmss opened 1 month ago

tmokmss commented 1 month ago

Describe the bug

CloudFormation throws an error when we try to create a CodeBuild project with GitHub webhook is configured.

16:13:04 | CREATE_FAILED | AWS::CodeBuild::Project | MyProject2B52B17CC Failed to call CreateWebhook, reason: Access denied to connection arn:aws:codeconnections:us-west-2:REDACTED:connection/REDACTED (Service: AWSCodeBuild; Status Cod e: 400; Error Code: InvalidInputException; Request ID: REDACTED; Proxy: null)

Regression Issue

Last Known Working CDK Version

No response

Expected Behavior

CodeBuild project is successfully created.

Current Behavior

CloudFormation throws an error when creating a project.

Reproduction Steps

  1. First, create a GitHub app connection from the management console. https://docs.aws.amazon.com/codebuild/latest/userguide/connections-github-app.html
  2. Deploy the below stack, and you'll get an error. (replace YOUR_GITHUB_NAME and YOUR_REPOSITORY_NAME to an existing repo.)
import * as codebuild from 'aws-cdk-lib/aws-codebuild';

export class CodebuildGhaCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    const project = new codebuild.Project(this, 'MyProject', {
      source: codebuild.Source.gitHub({
        owner: 'YOUR_GITHUB_NAME',
        repo: 'YOUR_REPOSITORY_NAME',
        webhookFilters: [codebuild.FilterGroup.inEventOf(codebuild.EventAction.WORKFLOW_JOB_QUEUED)],
      }),
    });
    // uncommenting this makes it work
    // project.role!.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'));
  }
}

Possible Solution

https://github.com/aws/aws-cdk/issues/31726#issuecomment-2413937735

This was a problem of both permission and dependency.

Additional Information/Context

When I added Administrator permission to the project, CFn successfully deployed the project. But not sure exactly which permission is missing.

// WORKS
project.role!.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'));

Allowing codeconnections did not work:

    // NOT WORK
    project.addToRolePolicy(
      new PolicyStatement({
        actions: [
          'codeconnections:*',
          'codestar-connections:*',
        ],
        resources: ['*'],
      })
    );

CDK CLI Version

2.162.0

Framework Version

No response

Node.js Version

20

OS

macos

Language

TypeScript

Language Version

No response

Other information

We need to enable webhook to use a CodeBuild-hosted GitHub Actions runner.

ashishdhingra commented 1 month ago

@tmokmss Good afternoon. Somehow, I'm unable to reproduce issue at my end using CDK version 2.162.0 (build c8d7dd3):

import * as cdk from 'aws-cdk-lib';
import * as codebuild from 'aws-cdk-lib/aws-codebuild';

export class CdktestStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // This should be one time task.
    new codebuild.GitHubSourceCredentials(this, 'CodeBuildGitHubCreds', {
      accessToken: cdk.SecretValue.unsafePlainText('<<REDACTED>>')
    });

    const project = new codebuild.Project(this, 'MyProject', {
      source: codebuild.Source.gitHub({
        owner: 'mygithubname',
        repo: 'testrepo',
        webhookFilters: [codebuild.FilterGroup.inEventOf(codebuild.EventAction.WORKFLOW_JOB_QUEUED)],
      }),
    });
  }
}

gives below error during deployment:

✨  Synthesis time: 4.25s

CdktestStack: start: Building 551fa8c3d398f2112a97f5c3b96f2d1da537f7c06ff3f1345a1a3e63aa0377ad:139480602983-us-east-2
CdktestStack: success: Built 551fa8c3d398f2112a97f5c3b96f2d1da537f7c06ff3f1345a1a3e63aa0377ad:139480602983-us-east-2
CdktestStack: start: Publishing 551fa8c3d398f2112a97f5c3b96f2d1da537f7c06ff3f1345a1a3e63aa0377ad:139480602983-us-east-2
CdktestStack: success: Published 551fa8c3d398f2112a97f5c3b96f2d1da537f7c06ff3f1345a1a3e63aa0377ad:139480602983-us-east-2
Stack undefined
CdktestStack: deploying... [1/1]
CdktestStack: creating CloudFormation changeset...

 ✅  CdktestStack

✨  Deployment time: 55.54s

Stack ARN:
arn:aws:cloudformation:us-east-2:<<ACCOUNT-ID>>:stack/CdktestStack/1079e520-8a77-11ef-89fa-020707ed96ab

✨  Total time: 59.79s

I'm unsure if you added necessary permissions mentioned at https://docs.aws.amazon.com/codebuild/latest/userguide/connections-github-app.html#connections-github-role-access to the IAM role used to deploy CDK stack.

Thanks, Ashish

tmokmss commented 1 month ago

@ashishdhingra Thank you for the investigation!

Can you try GitHub App connections instead of a PAT credential? You also need to set the connection as an account level credential. With this configuraiton, the issue should reproduce.

And thank you for pointing out the necessary permission. It seems we need to create the policy before creating a project. So I confirmed something like this worked:

    const project = new codebuild.Project(this, 'MyProject', {
      source: codebuild.Source.gitHub({
        owner: 'redacted',
        repo: 'redacted',
        webhookFilters: [codebuild.FilterGroup.inEventOf(codebuild.EventAction.WORKFLOW_JOB_QUEUED)],
      }),
    });
    const codeConnectionPolicy = new Policy(this, 'CodeConnectionPolicy', {
      statements: [
        new PolicyStatement({
          actions: ['codeconnections:GetConnectionToken', 'codeconnections:GetConnection'],
          resources: ['*'],
        }),
      ],
    });
    project.role!.attachInlinePolicy(codeConnectionPolicy);
    // create the policy before the project
    (project.node.defaultChild as cdk.CfnResource).addDependency(codeConnectionPolicy.node.defaultChild as cdk.CfnResource);

I think this should be automatically configured in L2 code, or at least be clearly described in the doc.

patrickdorival commented 3 weeks ago

I was having a similar issue, however I also needed to update the CfnProject to include the missing Auth

(project.node.defaultChild as CfnProject).addPropertyOverride('Source.Auth', {
            Type: 'CODECONNECTIONS',
            Resource:
                'arn:aws:codeconnections:<region>:<account-id>:connection/<connection-id>',
        })

Agree with @tmokmss that the L2 construct should be updated because this use case, which would be very common, is missing from any of the existing constructs

tmokmss commented 3 weeks ago

@patrickdorival I configured account level credential to avoid from setting connection per project, but yeah it's disappointing that current L2 doesn't support Source.Auth property. I'll create a seprarate issue for this.

edit) We already have this one: #31236

patrickdorival commented 3 weeks ago

Yes, I saw that issue as well. Seems to be a few things missing from the L2 construct when you want to use Code Connections for your auth