Skip to main content

AWS CDK construct to create OIDC roles for CircleCI jobs

Project description

@blimmer/cdk-github-oidc

This repository contains constructs to communicate between GitHub Actions and AWS via an Open ID Connect (OIDC) provider. The process is described in this GitHub Actions documentation.

Security Benefits

By using the OpenID Connect provider, you can communicate with AWS from GitHub Actions without saving static credentials (e.g., AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY) in your GitHub Actions secret variables. Removing static credentials is a best practice for security.

Quick Start

Installation

npm install --save @blimmer/cdk-github-oidc

or

yarn add @blimmer/cdk-github-oidc

Create or Import a Provider

Each AWS account must be bootstrapped with an OIDC provider. Use the GithubActionsIdentityProvider construct to create a new provider.

import { GithubActionsIdentityProvider } from "@blimmer/cdk-github-oidc";

export class MyStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    const provider = new GithubActionsIdentityProvider(this, "Provider");
  }
}

If you want to use an existing provider, you can import it using the GithubActionsIdentityProvider.fromAccount() method.

import { GithubActionsIdentityProvider } from "@blimmer/cdk-github-oidc";

export class MyStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    const provider = GithubActionsIdentityProvider.fromAccount(this);
  }
}

Create a Role

Once you have a handle to a provider, you can create a role assumed by GitHub Actions.

import { GithubActionsRole, GithubActionsIdentityProvider, BranchFilter } from "@blimmer/cdk-github-oidc";

export class MyStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    const provider = new GithubActionsIdentityProvider(this, "Provider");

    const role = new GithubActionsRole(this, "Role", {
      provider,
      roleName: "my-github-actions-role",
      description: "Role assumed by GitHub Actions",
      subjectFilters: [new BranchFilter({ owner: "blimmer", repository: "cdk-github-oidc", branch: "*" })],
    });
  }
}

Subject Filters

As you can see in the example above, you must pass one or more SubjectFilters to the GithubActionsRole construct. These filters are used to determine which GitHub Actions workflows can assume the role.

This construct exposes first class support for the following filters:

  • AllowAllFilter

    // Allow all branches, tags, environments, pull requests, etc.
    new AllowAllFilter({ owner: "blimmer", repository: "cdk-github-oidc" });
    
  • BranchFilter

    // Allow all branches
    new BranchFilter({ owner: "blimmer", repository: "cdk-github-oidc", branch: "*" });
    
    // Specify a branch
    new BranchFilter({ owner: "blimmer", repository: "cdk-github-oidc", branch: "main" });
    
    // Specify a branch pattern
    new BranchFilter({ owner: "blimmer", repository: "cdk-github-oidc", branch: "feature/*" });
    
  • TagFilter

    // Allow all tags
    new TagFilter({ owner: "blimmer", repository: "cdk-github-oidc", tag: "*" });
    
    // Specify a tag
    new TagFilter({ owner: "blimmer", repository: "cdk-github-oidc", tag: "v1.0.0" });
    
    // Specify a tag pattern
    new TagFilter({ owner: "blimmer", repository: "cdk-github-oidc", tag: "v1.*" });
    
  • EnvironmentFilter

    // Allow all environments
    new EnvironmentFilter({ owner: "blimmer", repository: "cdk-github-oidc", environment: "*" });
    
    // Specify an environment
    new EnvironmentFilter({ owner: "blimmer", repository: "cdk-github-oidc", environment: "staging" });
    
  • PullRequestFilter

    // Allow all pull requests
    new PullRequestFilter({ owner: "blimmer", repository: "cdk-github-oidc" });
    

If none of these filters fit your use case, you can implement your via the IGithubActionOidcFilter interface, or use the CustomFilter construct.

You can learn more about subject filters in the Github docs

Granting Permissions to the Role

The GithubActionsRole construct is a Role construct, so you can use all of the same properties and methods as you would with a normal CDK IAM Role construct.

import { GithubActionsRole, GithubActionsIdentityProvider, BranchFilter } from "@blimmer/cdk-github-oidc";
import { Bucket } from "aws-cdk-lib/aws-s3";
import { PolicyStatement } from "aws-cdk-lib/aws-iam";

export class MyStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    const bucket = new Bucket(this, "Bucket");

    const provider = new GithubActionsIdentityProvider(this, "Provider");
    const role = new GithubActionsRole(this, "Role", {
      provider,
      roleName: "my-github-actions-role",
      description: "Role assumed by GitHub Actions",
      subjectFilters: [new BranchFilter({ owner: "blimmer", repository: "cdk-github-oidc", branch: "*" })],
    });

    // Grant access via CDK `grant*` methods
    // https://docs.aws.amazon.com/cdk/v2/guide/permissions.html#permissions_grants
    role.grantReadWrite(bucket);

    // Add a custom policy
    role.addToPolicy(new PolicyStatement({ actions: ["s3:PutObject"], resources: ["arn:aws:s3:::my-bucket/*"] }));
  }
}

Using a Role in a Workflow

To use a role in a GitHub Actions workflow, you can use the aws-actions/configure-aws-credentials action.

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write # Required for OIDC role assumption
    steps:
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/my-github-actions-role
          region: us-west-2

See the aws-actions/configure-aws-credentials docs for more details.

Usage

For detailed API docs, see API.md.

Python

This package is available for Python as cdk-github-oidc.

pip install cdk-github-oidc

Migrating from aws-cdk-github-oidc

This package was inspired by aws-cdk-github-oidc, but this package became somewhat unmaintained.

For a role that looked like this in aws-cdk-github-oidc:

import { GithubActionsIdentityProvider, GithubActionsRole } from "aws-cdk-github-oidc";

const provider = new GithubActionsIdentityProvider(scope, "GithubProvider");
const deployRole = new GithubActionsRole(scope, "DeployRole", {
  provider,
  owner: "octo-org",
  repo: "octo-repo",
  roleName: "MyDeployRole",
  description: "This role deploys stuff to AWS",
  maxSessionDuration: cdk.Duration.hours(2),
});

The equivalent role in this package looks like this:

import { GithubActionsIdentityProvider, GithubActionsRole, AllowAllFilter } from "@blimmer/cdk-github-oidc";

const provider = new GithubActionsIdentityProvider(scope, "GithubProvider");
const deployRole = new GithubActionsRole(scope, "DeployRole", {
  provider,
  roleName: "MyDeployRole",
  description: "This role deploys stuff to AWS",
  subjectFilters: [
    // I encourage you to scope this down to a different filter (e.g., BranchFilter, TagFilter, PullRequestFilter, etc.)
    new AllowAllFilter({ owner: "octo-org", repository: "octo-repo" }),
  ],
  maxSessionDuration: cdk.Duration.hours(2),
});

Resource Replacement

By default, CloudFormation will create resources before destroying the old ones. This is a problem when transitioning between aws-cdk-github-oidc and @blimmer/cdk-github-oidc because the GithubActionsIdentityProvider is a singleton. It might also affect your roles, if you specified a roleName.

To work around this issue, delete the old provider and role(s) before migrating to use this package. This will cause downtime while you delete/re-create the resources.

Resources

Contributing

Contributions, issues, and feedback are welcome!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cdk_github_oidc-1.0.0.tar.gz (73.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cdk_github_oidc-1.0.0-py3-none-any.whl (70.8 kB view details)

Uploaded Python 3

File details

Details for the file cdk_github_oidc-1.0.0.tar.gz.

File metadata

  • Download URL: cdk_github_oidc-1.0.0.tar.gz
  • Upload date:
  • Size: 73.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for cdk_github_oidc-1.0.0.tar.gz
Algorithm Hash digest
SHA256 72eb50a11e3abd8fb0a53b1d20a898adff4a26969b1f724b57e4e4a4e1753e11
MD5 ad6df0169005cde4954bf359b93d4bee
BLAKE2b-256 34625c662f522e7acd026163c73e43aa7124ad1e6e9c95cc8a36f1ec7da417ee

See more details on using hashes here.

File details

Details for the file cdk_github_oidc-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for cdk_github_oidc-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0eb51367c2bee2c4d7aa79a3177e7f3a2cd3f5e464a5c20412f56ae70b758e9e
MD5 b733f7f72268196edfffe1f789d49c97
BLAKE2b-256 b9573ac0e9f88392628e22ce20f7c5c36ac9f46082553c2787a26a68fc84665f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page