From 850d94c2890f37d4b1c57e9de84d481cc742abc0 Mon Sep 17 00:00:00 2001 From: Scott Schreckengaust <345885+scottschreckengaust@users.noreply.github.com> Date: Wed, 25 Feb 2026 20:04:46 +0000 Subject: [PATCH 1/6] fix(lint): pretty up JSON Signed-off-by: Scott Schreckengaust <345885+scottschreckengaust@users.noreply.github.com> --- .claude/settings.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.claude/settings.json b/.claude/settings.json index eaa3835..a818e4b 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,14 +1,14 @@ { - "permissions": { - "allow": [] - }, "attribution": { - "pr": "🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n---\n\nBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the [project license](https://github.com/awslabs/agent-plugins/blob/main/LICENSE)." + "pr": "\ud83e\udd16 Generated with [Claude Code](https://claude.com/claude-code)\n\n---\n\nBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the [project license](https://github.com/awslabs/agent-plugins/blob/main/LICENSE)." }, "enabledPlugins": { - "code-review@claude-plugins-official": true, - "pr-review-toolkit@claude-plugins-official": true, "claude-md-management@claude-plugins-official": true, - "plugin-dev@claude-plugins-official": true + "code-review@claude-plugins-official": true, + "plugin-dev@claude-plugins-official": true, + "pr-review-toolkit@claude-plugins-official": true + }, + "permissions": { + "allow": [] } } From b3d2a29c0f131a675a819e344cf932c303a41e8a Mon Sep 17 00:00:00 2001 From: Scott Schreckengaust <345885+scottschreckengaust@users.noreply.github.com> Date: Wed, 25 Feb 2026 22:27:50 +0000 Subject: [PATCH 2/6] ci: add CodeBuild workflow and administrators guide Adds a workflow_dispatch-triggered GitHub Actions workflow that runs the full build on AWS CodeBuild via aws-actions/aws-codebuild-run-build (no webhooks). Authenticates via OIDC using aws-actions/configure-aws-credentials, gated by a protected "codebuild" GitHub environment requiring non-self-approval from the @awslabs/agent-plugins-admins team. Adds docs/ADMINISTRATORS_GUIDE.md with: - Copy-pasteable CloudFormation templates for the IAM OIDC role (step 2) and CodeBuild project with S3 artifact bucket (step 3) - GitHub CLI commands for environment setup with team-based reviewers - KMS decrypt permissions for SSE-encrypted SARIF artifacts - Troubleshooting table for common deployment issues Cross-references added to README.md, CONTRIBUTING.md, and MAINTAINERS_GUIDE.md. Co-Authored-By: Claude Opus 4.6 --- .claude/settings.json | 14 +- .github/workflows/build-codebuild.yml | 91 +++++ CONTRIBUTING.md | 1 + README.md | 4 + docs/ADMINISTRATORS_GUIDE.md | 489 ++++++++++++++++++++++++++ docs/MAINTAINERS_GUIDE.md | 21 +- 6 files changed, 603 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/build-codebuild.yml create mode 100644 docs/ADMINISTRATORS_GUIDE.md diff --git a/.claude/settings.json b/.claude/settings.json index a818e4b..eaa3835 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,14 +1,14 @@ { + "permissions": { + "allow": [] + }, "attribution": { - "pr": "\ud83e\udd16 Generated with [Claude Code](https://claude.com/claude-code)\n\n---\n\nBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the [project license](https://github.com/awslabs/agent-plugins/blob/main/LICENSE)." + "pr": "🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n---\n\nBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the [project license](https://github.com/awslabs/agent-plugins/blob/main/LICENSE)." }, "enabledPlugins": { - "claude-md-management@claude-plugins-official": true, "code-review@claude-plugins-official": true, - "plugin-dev@claude-plugins-official": true, - "pr-review-toolkit@claude-plugins-official": true - }, - "permissions": { - "allow": [] + "pr-review-toolkit@claude-plugins-official": true, + "claude-md-management@claude-plugins-official": true, + "plugin-dev@claude-plugins-official": true } } diff --git a/.github/workflows/build-codebuild.yml b/.github/workflows/build-codebuild.yml new file mode 100644 index 0000000..0c0b29a --- /dev/null +++ b/.github/workflows/build-codebuild.yml @@ -0,0 +1,91 @@ +# This workflow runs on a GitHub-hosted runner, authenticates to AWS via OIDC, +# and invokes CodeBuild's StartBuild API. CloudWatch logs are streamed back +# to the GitHub Actions console. +# +# Prerequisites: see docs/ADMINISTRATORS_GUIDE.md#codebuild-integration + +name: Build (CodeBuild) + +on: + workflow_dispatch: {} + +permissions: + actions: none + attestations: none + checks: none + contents: none + deployments: none + discussions: none + id-token: none + issues: none + models: none + packages: none + pages: none + pull-requests: none + repository-projects: none + security-events: none + statuses: none + +jobs: + build: + # Protected environment — requires non-self-approval before the job runs. + # Configure in Settings > Environments > codebuild: + # - Required reviewers: at least 1 + # - Prevent self-review: enabled + environment: codebuild + + permissions: + actions: read + contents: read + id-token: write # Required for OIDC token request to AWS STS + + runs-on: ubuntu-latest + + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@e3ef6f550da368605b4c77eccc1b4b21662498dd # v4.1.0 + with: + role-to-assume: ${{ secrets.AWS_CODEBUILD_ROLE_ARN }} + aws-region: ${{ vars.AWS_REGION || 'us-east-1' }} + + - name: Verify AWS identity + run: aws sts get-caller-identity + + - name: Run CodeBuild + id: codebuild + uses: aws-actions/aws-codebuild-run-build@d8279f349f3b1b84e834c30e47c20dcb8888b7e5 # v1.0.18 + with: + project-name: ${{ vars.CODEBUILD_PROJECT_NAME }} + source-version-override: ${{ github.sha }} + # BUILD_GENERAL1_SMALL | BUILD_GENERAL1_MEDIUM | BUILD_GENERAL1_LARGE + compute-type-override: BUILD_GENERAL1_LARGE + buildspec-override: | + version: 0.2 + env: + variables: + MISE_YES: "1" + phases: + install: + commands: + - curl https://mise.run | sh + - mise install + pre_build: + commands: + - eval "$(~/.local/bin/mise activate bash)" + - mise --version + - mise ls + build: + commands: + - eval "$(~/.local/bin/mise activate bash)" + - mise run build + post_build: + commands: + - echo "Build completed with status $CODEBUILD_BUILD_SUCCEEDING" + artifacts: + files: + - '**/*_sarif.json' + discard-paths: yes + + - name: Build ID + if: always() + run: echo "CodeBuild Build ID ${{ steps.codebuild.outputs.aws-build-id }}" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b1ff167..df84e64 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,7 @@ Depending on your role, please review the appropriate guide for repository-speci - [Development Guide](./docs/DEVELOPMENT_GUIDE.md) - For contributors and developers - [Maintainers Guide](./docs/MAINTAINERS_GUIDE.md) - For reviewers, maintainers, and admins +- [Administrators Guide](./docs/ADMINISTRATORS_GUIDE.md) - For AWS account and GitHub environment setup **Using Claude Code?** See the [Claude Code Setup](./docs/DEVELOPMENT_GUIDE.md#claude-code-setup) section in the Development Guide for project-specific configuration. diff --git a/README.md b/README.md index 0523024..8f9f36b 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,10 @@ If you want to add a new plugin to the library, check out our [design guidelines Repository reviewers, maintainers, and admins can find PR review workflows, merge rules, and CI/CD documentation in the [maintainers guide](./docs/MAINTAINERS_GUIDE.md). +## Administrators + +AWS account setup, IAM OIDC federation, CodeBuild integration, and GitHub environment configuration are documented in the [administrators guide](./docs/ADMINISTRATORS_GUIDE.md). + ## Additional Resources - [Introducing Agent Plugins for AWS Blog](https://aws.amazon.com/blogs/developer/introducing-agent-plugins-for-aws/) diff --git a/docs/ADMINISTRATORS_GUIDE.md b/docs/ADMINISTRATORS_GUIDE.md new file mode 100644 index 0000000..9a82398 --- /dev/null +++ b/docs/ADMINISTRATORS_GUIDE.md @@ -0,0 +1,489 @@ +# Administrators Guide + +This guide covers AWS account setup, IAM configuration, and GitHub environment configuration for repository administrators. For day-to-day CI/CD and merge workflows, see the [Maintainers Guide](./MAINTAINERS_GUIDE.md). + +## CodeBuild Integration + +The [Build (CodeBuild)](./../.github/workflows/build-codebuild.yml) workflow runs the full project build (`mise run build`) on AWS CodeBuild. It is triggered manually via `workflow_dispatch` and gated by a protected GitHub environment that requires non-self-approval. + +The workflow runs on a GitHub-hosted runner, authenticates to AWS via OIDC, and invokes CodeBuild's `StartBuild` API using the [aws-codebuild-run-build](https://github.com/aws-actions/aws-codebuild-run-build) action. CloudWatch logs are streamed back to the GitHub Actions console. No webhooks are involved. + +### Architecture + +```text +workflow_dispatch + │ + ▼ +GitHub Environment gate ("codebuild") + - requires non-self-approval + │ + ▼ +GitHub-hosted runner (ubuntu-latest) + │ + ├─► configure-aws-credentials (OIDC) + │ role-to-assume: AWS_CODEBUILD_ROLE_ARN + │ + └─► aws-codebuild-run-build (StartBuild API) + project: CODEBUILD_PROJECT_NAME + buildspec: inline (mise install → mise run build) + logs: streamed via CloudWatch +``` + +### Prerequisites + +Complete these steps in order. Steps 1-3 are AWS-side, steps 4-5 are GitHub-side. + +#### 1. Create the IAM OIDC identity provider + +If your account already has the GitHub Actions OIDC provider (`token.actions.githubusercontent.com`), skip to step 2. + +```bash +aws iam create-open-id-connect-provider \ + --url https://token.actions.githubusercontent.com \ + --client-id-list sts.amazonaws.com \ + --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 +``` + +> The thumbprint is a formality — AWS validates via the OIDC discovery document. GitHub rotates certificates independently. + +#### 2. Create the CodeBuild project + +> **Prerequisite:** GitHub credentials must already be connected to CodeBuild in this account. If not, import them first: +> +> ```bash +> aws codebuild import-source-credentials \ +> --server-type GITHUB \ +> --auth-type PERSONAL_ACCESS_TOKEN \ +> --token +> ``` + +Deploy the CloudFormation stack below. It creates: + +- A CodeBuild project with GitHub source and no buildspec (the workflow passes an inline override) +- A service role with least-privilege permissions for CloudWatch Logs and S3 artifacts +- An S3 bucket for build artifacts (SARIF reports from security scanners) +- A CloudWatch log group with 90-day retention (matches GitHub Actions log retention) + +**CloudFormation template:** + +```yaml +AWSTemplateFormatVersion: '2010-09-09' +Description: >- + CodeBuild project for the Build (CodeBuild) GitHub Actions workflow. + The workflow passes an inline buildspec override, so no buildspec file + is configured on the project. + +Parameters: + ProjectName: + Type: String + Default: agent-plugins-build + Description: >- + CodeBuild project name. Must match the CODEBUILD_PROJECT_NAME + GitHub Actions variable. + + GitHubRepoUrl: + Type: String + Default: https://github.com/awslabs/agent-plugins + Description: HTTPS URL of the GitHub repository. + + ComputeType: + Type: String + Default: BUILD_GENERAL1_LARGE + AllowedValues: + - BUILD_GENERAL1_SMALL + - BUILD_GENERAL1_MEDIUM + - BUILD_GENERAL1_LARGE + Description: Compute resources for the build environment. + + Image: + Type: String + Default: aws/codebuild/amazonlinux-x86_64-standard:5.0 + Description: Docker image for the build environment. + + LogRetentionDays: + Type: Number + Default: 90 + AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365] + Description: Number of days to retain CloudWatch build logs. + +Resources: + ArtifactBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub '${ProjectName}-artifacts-${AWS::AccountId}' + LifecycleConfiguration: + Rules: + - Id: ExpireArtifacts + Status: Enabled + ExpirationInDays: !Ref LogRetentionDays + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: aws:kms + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + + LogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub '/aws/codebuild/${ProjectName}' + RetentionInDays: !Ref LogRetentionDays + + ServiceRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub '${ProjectName}-service-role' + Description: !Sub 'Service role for CodeBuild project ${ProjectName}.' + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: CloudWatchLogs + PolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: AllowLogs + Effect: Allow + Action: + - logs:CreateLogStream + - logs:PutLogEvents + Resource: !Sub >- + arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}:* + - PolicyName: S3Artifacts + PolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: AllowArtifactUpload + Effect: Allow + Action: + - s3:PutObject + - s3:GetBucketAcl + - s3:GetBucketLocation + Resource: + - !GetAtt ArtifactBucket.Arn + - !Sub '${ArtifactBucket.Arn}/*' + - Sid: AllowKMSForArtifacts + Effect: Allow + Action: + - kms:Decrypt + - kms:GenerateDataKey + Resource: '*' + Condition: + StringEquals: + kms:ViaService: !Sub 's3.${AWS::Region}.amazonaws.com' + + Project: + Type: AWS::CodeBuild::Project + Properties: + Name: !Ref ProjectName + Description: >- + Runs the agent-plugins build. Invoked by the Build (CodeBuild) + GitHub Actions workflow via aws-codebuild-run-build. + ServiceRole: !GetAtt ServiceRole.Arn + Source: + Type: GITHUB + Location: !Ref GitHubRepoUrl + BuildSpec: '{}' + Artifacts: + Type: S3 + Location: !Ref ArtifactBucket + NamespaceType: BUILD_ID + Packaging: ZIP + EncryptionDisabled: false + Environment: + Type: LINUX_CONTAINER + ComputeType: !Ref ComputeType + Image: !Ref Image + LogsConfig: + CloudWatchLogs: + Status: ENABLED + GroupName: !Ref LogGroup + TimeoutInMinutes: 60 + QueuedTimeoutInMinutes: 30 + +Outputs: + ProjectName: + Description: >- + Store this as the CODEBUILD_PROJECT_NAME variable in GitHub Actions. + Value: !Ref Project + + ProjectArn: + Description: ARN of the CodeBuild project. + Value: !GetAtt Project.Arn + + ArtifactBucketName: + Description: >- + S3 bucket for build artifacts (SARIF reports). Pass this as the + ArtifactBucketName parameter when deploying the IAM role stack in step 3. + Value: !Ref ArtifactBucket + + ServiceRoleArn: + Description: ARN of the CodeBuild service role. + Value: !GetAtt ServiceRole.Arn +``` + +**Deploy with defaults:** + +```bash +aws cloudformation deploy \ + --template-file administrators-guide-codebuild-project.yaml \ + --stack-name agent-plugins-codebuild \ + --capabilities CAPABILITY_NAMED_IAM +``` + +After deployment, note the `ProjectName` and `ArtifactBucketName` outputs — you will need them in steps 3 and 5. + +#### 3. Create the IAM role and policy + +Deploy the CloudFormation stack below. It creates a single IAM role with: + +- An OIDC trust policy scoped to `repo:awslabs/agent-plugins:environment:codebuild` +- Least-privilege permissions: `codebuild:StartBuild`, `codebuild:BatchGetBuilds`, `logs:GetLogEvents`, and `s3:GetObject` on the artifact bucket from step 2 + +**CloudFormation template:** + +```yaml +AWSTemplateFormatVersion: '2010-09-09' +Description: >- + IAM role for the Build (CodeBuild) GitHub Actions workflow. + Assumes OIDC federation from the "codebuild" GitHub environment. + +Parameters: + GitHubOrg: + Type: String + Default: awslabs + Description: GitHub organization that owns the repository. + + GitHubRepo: + Type: String + Default: agent-plugins + Description: GitHub repository name. + + GitHubEnvironment: + Type: String + Default: codebuild + Description: >- + GitHub environment name. The OIDC subject claim is scoped to this + environment so only approved jobs can assume the role. + + CodeBuildProjectName: + Type: String + Default: agent-plugins-build + Description: Name of the CodeBuild project (from step 2 ProjectName output). + + ArtifactBucketName: + Type: String + Default: '' + Description: >- + Name of the S3 bucket for build artifacts (from step 2 + ArtifactBucketName output). If provided, the role gets s3:GetObject + to download SARIF reports. + + CreateOIDCProvider: + Type: String + Default: 'true' + AllowedValues: ['true', 'false'] + Description: >- + Set to false if the GitHub Actions OIDC provider already exists in + this account. When false, provide OIDCProviderArn. + + OIDCProviderArn: + Type: String + Default: '' + Description: >- + ARN of an existing GitHub Actions OIDC provider. Required when + CreateOIDCProvider is false. + +Conditions: + ShouldCreateOIDCProvider: !Equals [!Ref CreateOIDCProvider, 'true'] + HasExistingOIDCProvider: !Not [!Equals [!Ref OIDCProviderArn, '']] + HasArtifactBucket: !Not [!Equals [!Ref ArtifactBucketName, '']] + +Resources: + GitHubOIDCProvider: + Type: AWS::IAM::OIDCProvider + Condition: ShouldCreateOIDCProvider + Properties: + Url: https://token.actions.githubusercontent.com + ClientIdList: + - sts.amazonaws.com + ThumbprintList: + - 6938fd4d98bab03faadb97b34396831e3780aea1 + + GitHubActionsCodeBuildRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub '${GitHubRepo}-codebuild-gha' + Description: !Sub >- + Assumed by GitHub Actions (OIDC) to run CodeBuild builds for + ${GitHubOrg}/${GitHubRepo} from the ${GitHubEnvironment} environment. + MaxSessionDuration: 3600 + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Federated: !If + - ShouldCreateOIDCProvider + - !Ref GitHubOIDCProvider + - !If + - HasExistingOIDCProvider + - !Ref OIDCProviderArn + - !Sub >- + arn:${AWS::Partition}:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com + Action: sts:AssumeRoleWithWebIdentity + Condition: + StringEquals: + token.actions.githubusercontent.com:aud: sts.amazonaws.com + token.actions.githubusercontent.com:sub: !Sub >- + repo:${GitHubOrg}/${GitHubRepo}:environment:${GitHubEnvironment} + Policies: + - PolicyName: CodeBuildAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: AllowStartAndMonitorBuild + Effect: Allow + Action: + - codebuild:StartBuild + - codebuild:BatchGetBuilds + Resource: !Sub >- + arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/${CodeBuildProjectName} + - Sid: AllowReadBuildLogs + Effect: Allow + Action: + - logs:GetLogEvents + Resource: !Sub >- + arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${CodeBuildProjectName}:* + - !If + - HasArtifactBucket + - Sid: AllowDownloadArtifacts + Effect: Allow + Action: + - s3:GetObject + - s3:ListBucket + Resource: + - !Sub 'arn:${AWS::Partition}:s3:::${ArtifactBucketName}' + - !Sub 'arn:${AWS::Partition}:s3:::${ArtifactBucketName}/*' + - !Ref AWS::NoValue + - !If + - HasArtifactBucket + - Sid: AllowDecryptArtifacts + Effect: Allow + Action: + - kms:Decrypt + - kms:GenerateDataKey + Resource: '*' + Condition: + StringEquals: + kms:ViaService: !Sub 's3.${AWS::Region}.amazonaws.com' + - !Ref AWS::NoValue + +Outputs: + RoleArn: + Description: >- + Store this as the AWS_CODEBUILD_ROLE_ARN secret in the GitHub + "codebuild" environment. + Value: !GetAtt GitHubActionsCodeBuildRole.Arn + + OIDCProviderArn: + Condition: ShouldCreateOIDCProvider + Description: ARN of the created OIDC provider. + Value: !Ref GitHubOIDCProvider +``` + +**Deploy with the artifact bucket from step 2:** + +```bash +aws cloudformation deploy \ + --template-file administrators-guide-codebuild-role.yaml \ + --stack-name agent-plugins-gha-codebuild \ + --capabilities CAPABILITY_NAMED_IAM \ + --parameter-overrides \ + ArtifactBucketName=agent-plugins-build-artifacts-123456789012 +``` + +**Deploy with an existing OIDC provider:** + +```bash +aws cloudformation deploy \ + --template-file administrators-guide-codebuild-role.yaml \ + --stack-name agent-plugins-gha-codebuild \ + --capabilities CAPABILITY_NAMED_IAM \ + --parameter-overrides \ + CreateOIDCProvider=false \ + OIDCProviderArn=arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com \ + ArtifactBucketName=agent-plugins-build-artifacts-123456789012 +``` + +After deployment, note the `RoleArn` output — you will need it in step 5. + +#### 4. Create the GitHub environment + +**Using the GitHub CLI:** + +```bash +# Look up the agent-plugins-admins team ID +TEAM_ID=$(gh api orgs/awslabs/teams/agent-plugins-admins --jq '.id') + +# Create the environment with the admins team as required reviewers +gh api -X PUT repos/awslabs/agent-plugins/environments/codebuild \ + --input - < Environments > New environment** +2. Name: `codebuild` +3. Configure protection rules: + - **Required reviewers**: add the `@awslabs/agent-plugins-admins` team + - **Prevent self-review**: enable this checkbox + +The non-self-approval requirement ensures that the person who triggers the workflow cannot approve their own run. + +#### 5. Configure GitHub secrets and variables + +In **Settings > Environments > codebuild**: + +| Type | Name | Value | +| ------ | ------------------------ | ----------------------------------------------------------- | +| Secret | `AWS_CODEBUILD_ROLE_ARN` | The `RoleArn` output from the CloudFormation stack (step 3) | + +In **Settings > Secrets and variables > Actions > Variables**: + +| Type | Name | Value | +| -------- | ------------------------ | ---------------------------------------------------------------- | +| Variable | `AWS_REGION` | AWS region where the CodeBuild project lives (e.g., `us-east-1`) | +| Variable | `CODEBUILD_PROJECT_NAME` | The `ProjectName` output from the CloudFormation stack (step 2) | + +`AWS_CODEBUILD_ROLE_ARN` is scoped to the `codebuild` environment so it is only available to jobs that have passed the approval gate. `AWS_REGION` and `CODEBUILD_PROJECT_NAME` are not sensitive and are stored as repo-level variables. + +### Running the Workflow + +1. Go to **Actions > Build (CodeBuild) > Run workflow** +2. Select the branch to build +3. A reviewer (not yourself) must approve the environment deployment +4. The build runs on CodeBuild and streams logs back to the Actions console + +### Troubleshooting + +| Symptom | Cause | Fix | +| --------------------------------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------- | +| "Not authorized to perform sts:AssumeRoleWithWebIdentity" | OIDC subject claim mismatch | Verify the IAM trust policy `sub` condition matches `repo:awslabs/agent-plugins:environment:codebuild` exactly | +| "Could not find project" | Wrong project name or region | Check `CODEBUILD_PROJECT_NAME` and `AWS_REGION` variables | +| Build hangs waiting for approval | No reviewer configured | Add a required reviewer in the `codebuild` environment settings | +| "Access denied" on StartBuild | IAM policy too restrictive | Ensure the role has `codebuild:StartBuild` and `codebuild:BatchGetBuilds` on the correct project ARN | diff --git a/docs/MAINTAINERS_GUIDE.md b/docs/MAINTAINERS_GUIDE.md index abb83d3..4e06289 100644 --- a/docs/MAINTAINERS_GUIDE.md +++ b/docs/MAINTAINERS_GUIDE.md @@ -111,16 +111,17 @@ Triage incoming issues by applying appropriate labels and assigning to the relev All workflows are in [`.github/workflows/`](../.github/workflows/): -| Workflow | Trigger | Purpose | -| ------------------------ | -------------------------- | ----------------------------------------------------------------- | -| `build.yml` | PR, push to main | Full build (`mise run build`: lint + format check + security) | -| `pull-request-lint.yml` | PR | Conventional commit title validation, contributor statement check | -| `merge-prevention.yml` | PR, merge queue | `do-not-merge` label and `HALT_MERGES` enforcement | -| `security-scanners.yml` | PR, push to main | Bandit, SemGrep, Gitleaks, Checkov, Grype | -| `codeql.yml` | PR, push to main, schedule | GitHub CodeQL analysis | -| `dependency-review.yml` | PR | Dependency vulnerability review | -| `scorecard-analysis.yml` | Push to main, schedule | OpenSSF Scorecard | -| `stale.yml` | Daily cron | Stale PR/issue management | +| Workflow | Trigger | Purpose | +| ------------------------ | -------------------------- | --------------------------------------------------------------------------------------------------------- | +| `build.yml` | PR, push to main | Full build (`mise run build`: lint + format check + security) | +| `build-codebuild.yml` | `workflow_dispatch` | Full build on AWS CodeBuild (see [Administrators Guide](./ADMINISTRATORS_GUIDE.md#codebuild-integration)) | +| `pull-request-lint.yml` | PR | Conventional commit title validation, contributor statement check | +| `merge-prevention.yml` | PR, merge queue | `do-not-merge` label and `HALT_MERGES` enforcement | +| `security-scanners.yml` | PR, push to main | Bandit, SemGrep, Gitleaks, Checkov, Grype | +| `codeql.yml` | PR, push to main, schedule | GitHub CodeQL analysis | +| `dependency-review.yml` | PR | Dependency vulnerability review | +| `scorecard-analysis.yml` | Push to main, schedule | OpenSSF Scorecard | +| `stale.yml` | Daily cron | Stale PR/issue management | ## Release Process From 4ca8ced8b765e59f1a8c3e6da6be6a62d3daeba8 Mon Sep 17 00:00:00 2001 From: Scott Schreckengaust <345885+scottschreckengaust@users.noreply.github.com> Date: Thu, 26 Feb 2026 00:44:00 +0000 Subject: [PATCH 3/6] update documentation Signed-off-by: Scott Schreckengaust <345885+scottschreckengaust@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index df84e64..f606781 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Depending on your role, please review the appropriate guide for repository-speci - [Development Guide](./docs/DEVELOPMENT_GUIDE.md) - For contributors and developers - [Maintainers Guide](./docs/MAINTAINERS_GUIDE.md) - For reviewers, maintainers, and admins -- [Administrators Guide](./docs/ADMINISTRATORS_GUIDE.md) - For AWS account and GitHub environment setup +- [Administrators Guide](./docs/ADMINISTRATORS_GUIDE.md) - For GitHub repository and AWS account setup **Using Claude Code?** See the [Claude Code Setup](./docs/DEVELOPMENT_GUIDE.md#claude-code-setup) section in the Development Guide for project-specific configuration. diff --git a/README.md b/README.md index 8f9f36b..0c498e8 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ Repository reviewers, maintainers, and admins can find PR review workflows, merg ## Administrators -AWS account setup, IAM OIDC federation, CodeBuild integration, and GitHub environment configuration are documented in the [administrators guide](./docs/ADMINISTRATORS_GUIDE.md). +GitHub environment and AWS account configuration are documented in the [administrators guide](./docs/ADMINISTRATORS_GUIDE.md). ## Additional Resources From 6405153a2106eb3d9d7a3638da26d236fccd9f2b Mon Sep 17 00:00:00 2001 From: Scott Schreckengaust Date: Thu, 26 Feb 2026 09:32:48 -0800 Subject: [PATCH 4/6] docs: add GitHub fine-grained PAT setup to administrators guide Add step 2 documenting how to create a fine-grained GitHub PAT with least-privilege permissions (Contents: Read-only) and import it into CodeBuild. Renumber subsequent steps (3-6) and update all cross-references. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/ADMINISTRATORS_GUIDE.md | 76 +++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/docs/ADMINISTRATORS_GUIDE.md b/docs/ADMINISTRATORS_GUIDE.md index 9a82398..62a2531 100644 --- a/docs/ADMINISTRATORS_GUIDE.md +++ b/docs/ADMINISTRATORS_GUIDE.md @@ -31,7 +31,7 @@ GitHub-hosted runner (ubuntu-latest) ### Prerequisites -Complete these steps in order. Steps 1-3 are AWS-side, steps 4-5 are GitHub-side. +Complete these steps in order. #### 1. Create the IAM OIDC identity provider @@ -46,16 +46,48 @@ aws iam create-open-id-connect-provider \ > The thumbprint is a formality — AWS validates via the OIDC discovery document. GitHub rotates certificates independently. -#### 2. Create the CodeBuild project +#### 2. Create a GitHub Personal Access Token and import source credentials -> **Prerequisite:** GitHub credentials must already be connected to CodeBuild in this account. If not, import them first: -> -> ```bash -> aws codebuild import-source-credentials \ -> --server-type GITHUB \ -> --auth-type PERSONAL_ACCESS_TOKEN \ -> --token -> ``` +CodeBuild needs a GitHub Personal Access Token (PAT) to clone the repository source. A **fine-grained token** is recommended over a classic token because it supports least-privilege permissions and can be scoped to a single repository. + +> **PAT creation is not scriptable.** GitHub does not expose a REST API or CLI endpoint to create tokens. You must use the GitHub web UI. + +**Create the fine-grained token:** + +1. Go to **github.com > Settings > Developer settings > Personal access tokens > Fine-grained tokens** +2. Click **Generate new token** +3. Configure the token: + - **Token name**: `codebuild-agent-plugins` (or similar) + - **Expiration**: choose an appropriate lifetime (default 30 days, max 1 year) + - **Resource owner**: select the organization that owns the repository (e.g., `awslabs`) + - **Repository access**: select **Only select repositories** and choose `awslabs/agent-plugins` + - **Permissions > Repository permissions**: + - **Contents**: Read-only + - All other permissions can remain at **No access** +4. Click **Generate token** and copy the value immediately — it will not be shown again + +> A classic token would require the `repo` scope, which grants full read/write access to all private repositories — far broader than what CodeBuild needs for this workflow. + +**Import the token into CodeBuild:** + +```bash +aws codebuild import-source-credentials \ + --server-type GITHUB \ + --auth-type PERSONAL_ACCESS_TOKEN \ + --token +``` + +**Verify the import:** + +```bash +aws codebuild list-source-credentials +``` + +You should see an entry with `serverType: GITHUB` and `authType: PERSONAL_ACCESS_TOKEN`. + +#### 3. Create the CodeBuild project + +> **Prerequisite:** complete step 2 to import GitHub credentials before creating the project. Deploy the CloudFormation stack below. It creates: @@ -221,7 +253,7 @@ Outputs: ArtifactBucketName: Description: >- S3 bucket for build artifacts (SARIF reports). Pass this as the - ArtifactBucketName parameter when deploying the IAM role stack in step 3. + ArtifactBucketName parameter when deploying the IAM role stack in step 4. Value: !Ref ArtifactBucket ServiceRoleArn: @@ -238,14 +270,14 @@ aws cloudformation deploy \ --capabilities CAPABILITY_NAMED_IAM ``` -After deployment, note the `ProjectName` and `ArtifactBucketName` outputs — you will need them in steps 3 and 5. +After deployment, note the `ProjectName` and `ArtifactBucketName` outputs — you will need them in steps 4 and 6. -#### 3. Create the IAM role and policy +#### 4. Create the IAM role and policy Deploy the CloudFormation stack below. It creates a single IAM role with: - An OIDC trust policy scoped to `repo:awslabs/agent-plugins:environment:codebuild` -- Least-privilege permissions: `codebuild:StartBuild`, `codebuild:BatchGetBuilds`, `logs:GetLogEvents`, and `s3:GetObject` on the artifact bucket from step 2 +- Least-privilege permissions: `codebuild:StartBuild`, `codebuild:BatchGetBuilds`, `logs:GetLogEvents`, and `s3:GetObject` on the artifact bucket from step 3 **CloudFormation template:** @@ -276,13 +308,13 @@ Parameters: CodeBuildProjectName: Type: String Default: agent-plugins-build - Description: Name of the CodeBuild project (from step 2 ProjectName output). + Description: Name of the CodeBuild project (from step 3 ProjectName output). ArtifactBucketName: Type: String Default: '' Description: >- - Name of the S3 bucket for build artifacts (from step 2 + Name of the S3 bucket for build artifacts (from step 3 ArtifactBucketName output). If provided, the role gets s3:GetObject to download SARIF reports. @@ -399,7 +431,7 @@ Outputs: Value: !Ref GitHubOIDCProvider ``` -**Deploy with the artifact bucket from step 2:** +**Deploy with the artifact bucket from step 3:** ```bash aws cloudformation deploy \ @@ -423,9 +455,9 @@ aws cloudformation deploy \ ArtifactBucketName=agent-plugins-build-artifacts-123456789012 ``` -After deployment, note the `RoleArn` output — you will need it in step 5. +After deployment, note the `RoleArn` output — you will need it in step 6. -#### 4. Create the GitHub environment +#### 5. Create the GitHub environment **Using the GitHub CLI:** @@ -455,20 +487,20 @@ EOF The non-self-approval requirement ensures that the person who triggers the workflow cannot approve their own run. -#### 5. Configure GitHub secrets and variables +#### 6. Configure GitHub secrets and variables In **Settings > Environments > codebuild**: | Type | Name | Value | | ------ | ------------------------ | ----------------------------------------------------------- | -| Secret | `AWS_CODEBUILD_ROLE_ARN` | The `RoleArn` output from the CloudFormation stack (step 3) | +| Secret | `AWS_CODEBUILD_ROLE_ARN` | The `RoleArn` output from the CloudFormation stack (step 4) | In **Settings > Secrets and variables > Actions > Variables**: | Type | Name | Value | | -------- | ------------------------ | ---------------------------------------------------------------- | | Variable | `AWS_REGION` | AWS region where the CodeBuild project lives (e.g., `us-east-1`) | -| Variable | `CODEBUILD_PROJECT_NAME` | The `ProjectName` output from the CloudFormation stack (step 2) | +| Variable | `CODEBUILD_PROJECT_NAME` | The `ProjectName` output from the CloudFormation stack (step 3) | `AWS_CODEBUILD_ROLE_ARN` is scoped to the `codebuild` environment so it is only available to jobs that have passed the approval gate. `AWS_REGION` and `CODEBUILD_PROJECT_NAME` are not sensitive and are stored as repo-level variables. From 8ad78f7a1cd30d40cb882d6c5c171e1c1589e6bb Mon Sep 17 00:00:00 2001 From: Scott Schreckengaust Date: Thu, 26 Feb 2026 11:16:24 -0800 Subject: [PATCH 5/6] docs: add CLI examples for CloudFormation overrides and GitHub secrets Add custom parameter-overrides example and describe-stacks output command to step 3. Add gh secret set / gh variable set commands to step 6. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/ADMINISTRATORS_GUIDE.md | 38 +++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/ADMINISTRATORS_GUIDE.md b/docs/ADMINISTRATORS_GUIDE.md index 62a2531..8422cad 100644 --- a/docs/ADMINISTRATORS_GUIDE.md +++ b/docs/ADMINISTRATORS_GUIDE.md @@ -270,7 +270,29 @@ aws cloudformation deploy \ --capabilities CAPABILITY_NAMED_IAM ``` -After deployment, note the `ProjectName` and `ArtifactBucketName` outputs — you will need them in steps 4 and 6. +**Deploy with custom parameters:** + +```bash +aws cloudformation deploy \ + --template-file administrators-guide-codebuild-project.yaml \ + --stack-name agent-plugins-codebuild \ + --capabilities CAPABILITY_NAMED_IAM \ + --parameter-overrides \ + ProjectName=my-codebuild-project \ + GitHubRepoUrl=https://github.com/my-org/my-repo \ + ComputeType=BUILD_GENERAL1_MEDIUM \ + Image=aws/codebuild/amazonlinux-x86_64-standard:5.0 \ + LogRetentionDays=30 +``` + +After deployment, retrieve the `ProjectName` and `ArtifactBucketName` outputs — you will need them in steps 4 and 6: + +```bash +aws cloudformation describe-stacks \ + --stack-name agent-plugins-codebuild \ + --query "Stacks[0].Outputs[?OutputKey=='ProjectName' || OutputKey=='ArtifactBucketName'].[OutputKey,OutputValue]" \ + --output table +``` #### 4. Create the IAM role and policy @@ -489,6 +511,20 @@ The non-self-approval requirement ensures that the person who triggers the workf #### 6. Configure GitHub secrets and variables +**Using the GitHub CLI:** + +```bash +# Environment secret (scoped to the codebuild environment) +gh secret set AWS_CODEBUILD_ROLE_ARN --env codebuild \ + --body "" + +# Repo-level variables (not sensitive) +gh variable set AWS_REGION --body "us-east-1" +gh variable set CODEBUILD_PROJECT_NAME --body "" +``` + +**Using the GitHub UI:** + In **Settings > Environments > codebuild**: | Type | Name | Value | From 123720e458e127688fcbac7d1cf9815c38355c1c Mon Sep 17 00:00:00 2001 From: Scott Schreckengaust Date: Thu, 26 Feb 2026 12:36:53 -0800 Subject: [PATCH 6/6] docs: harden CodeBuild CloudFormation template - Add S3 bucket policy enforcing SSL-only access (W51 remediation) - Add cfn_nag suppression metadata with rationale (W11, W28, W32, W35, W84) - Add checkov skip comments with rationale (CKV_AWS_18, CKV_AWS_21, CKV_AWS_158) - Enable build badge on CodeBuild project - Set PrivilegedMode: false explicitly on build environment Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/ADMINISTRATORS_GUIDE.md | 60 ++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/docs/ADMINISTRATORS_GUIDE.md b/docs/ADMINISTRATORS_GUIDE.md index 8422cad..3044144 100644 --- a/docs/ADMINISTRATORS_GUIDE.md +++ b/docs/ADMINISTRATORS_GUIDE.md @@ -140,7 +140,17 @@ Parameters: Resources: ArtifactBucket: + # checkov:skip=CKV_AWS_18:Access logging disproportionate for temporary CI artifacts with lifecycle expiration + # checkov:skip=CKV_AWS_21:Versioning unnecessary for ephemeral build artifacts with lifecycle expiration Type: AWS::S3::Bucket + Metadata: + cfn_nag: + rules_to_suppress: + - id: W35 + reason: >- + Access logging is unnecessary for a CI artifact bucket with + lifecycle expiration. It would require a separate logging + bucket, disproportionate for temporary SARIF reports. Properties: BucketName: !Sub '${ProjectName}-artifacts-${AWS::AccountId}' LifecycleConfiguration: @@ -158,14 +168,54 @@ Resources: IgnorePublicAcls: true RestrictPublicBuckets: true + ArtifactBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref ArtifactBucket + PolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: DenyNonSSLAccess + Effect: Deny + Principal: '*' + Action: 's3:*' + Resource: + - !GetAtt ArtifactBucket.Arn + - !Sub '${ArtifactBucket.Arn}/*' + Condition: + Bool: + aws:SecureTransport: 'false' + LogGroup: + # checkov:skip=CKV_AWS_158:CloudWatch Logs encrypted by AWS-managed keys by default; CMK adds unnecessary cost for CI logs Type: AWS::Logs::LogGroup + Metadata: + cfn_nag: + rules_to_suppress: + - id: W84 + reason: >- + CloudWatch Logs are encrypted at rest with AWS-managed keys + by default. A customer-managed KMS key adds cost and + operational overhead with no benefit for CI build logs. Properties: LogGroupName: !Sub '/aws/codebuild/${ProjectName}' RetentionInDays: !Ref LogRetentionDays ServiceRole: Type: AWS::IAM::Role + Metadata: + cfn_nag: + rules_to_suppress: + - id: W11 + reason: >- + The KMS Resource: '*' is scoped by kms:ViaService condition + to S3 only. The AWS-managed KMS key ARN cannot be predicted + at deploy time, so a wildcard is the standard pattern. + - id: W28 + reason: >- + Explicit naming (${ProjectName}-service-role) is intentional + for discoverability and cross-stack references. The role is + not expected to require replacement. Properties: RoleName: !Sub '${ProjectName}-service-role' Description: !Sub 'Service role for CodeBuild project ${ProjectName}.' @@ -213,11 +263,20 @@ Resources: Project: Type: AWS::CodeBuild::Project + Metadata: + cfn_nag: + rules_to_suppress: + - id: W32 + reason: >- + Artifacts use EncryptionDisabled: false, which encrypts with + the AWS-managed key. A customer-managed KMS key adds cost + and complexity with no benefit for CI build artifacts. Properties: Name: !Ref ProjectName Description: >- Runs the agent-plugins build. Invoked by the Build (CodeBuild) GitHub Actions workflow via aws-codebuild-run-build. + BadgeEnabled: true ServiceRole: !GetAtt ServiceRole.Arn Source: Type: GITHUB @@ -233,6 +292,7 @@ Resources: Type: LINUX_CONTAINER ComputeType: !Ref ComputeType Image: !Ref Image + PrivilegedMode: false # Enable only if the build needs to run Docker commands LogsConfig: CloudWatchLogs: Status: ENABLED