Skip to main content

AWS CDK construct to create OIDC roles for CircleCI jobs

Project description

CircleCI OIDC

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

Security Benefits

By using the OpenID Connect provider, you can communicate with AWS from CircleCI without saving static credentials (e.g., AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY) in your CircleCI project settings or a context. Removing static credentials, especially in light of the early 2023 breach, is a best practice for security.

Quick Start

Install the package:

npm install @blimmer/cdk-circleci-oidc

or

yarn add @blimmer/cdk-circleci-oidc

Then, create the provider and role(s).

import { Stack, StackProps } from "aws-cdk-lib";
import { CircleCiOidcProvider, CircleCiOidcRole } from "@blimmer/cdk-circleci-oidc";
import { Construct } from "constructs";
import { ManagedPolicy, PolicyStatement } from "aws-cdk-lib/aws-iam";
import { Bucket } from "aws-cdk-lib/aws-s3";

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

    // The provider is only created _once per AWS account_. It might make sense to define this in a separate stack
    // that defines more global resources. See below for how to use import the provider in stacks that don't define it.
    const provider = new CircleCiOidcProvider(this, "OidcProvider", {
      // Find your organization ID in the CircleCI dashboard under "Organization Settings"
      organizationId: "11111111-2222-3333-4444-555555555555",
    });

    const myCircleCiRole = new CircleCiOidcRole(this, "MyCircleCiRole", {
      provider,
      roleName: "MyCircleCiRole",

      // Pass some managed policies to the role
      managedPolicies: [ManagedPolicy.fromAwsManagedPolicyName("AmazonS3ReadOnlyAccess")],
    });

    // You can work with the CircleCI role like any other role
    myCircleCiRole.addToPolicy(
      new PolicyStatement({
        actions: ["s3:ListAllMyBuckets"],
        resources: ["*"],
      }),
    );

    // Including using `.grant` convenience methods
    const bucket = new Bucket(this, "MyBucket");
    bucket.grantRead(myCircleCiRole);
  }
}

Now, in your .circleci/config.yml file, you can use the AWS CLI Orb to assume your new role.

version: 2.1

orbs:
  aws-cli: circleci/aws-cli@4.1.0 # https://circleci.com/developer/orbs/orb/circleci/aws-cli

workflows:
  version: 2
  build:
    jobs:
      - oidc-job:
          context: oidc-assumption # You _must_ use a context, even if it doesn't contain any secrets (see https://circleci.com/docs/openid-connect-tokens/#openid-connect-id-token-availability)

jobs:
  oidc-job:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      # https://circleci.com/developer/orbs/orb/circleci/aws-cli#commands-setup
      - aws-cli/setup:
          role_arn: "arn:aws:iam::123456789101:role/MyCircleCiRole"
      - run:
          name: List S3 Buckets
          command: aws s3 ls

Usage in Stacks that Don't Define the Provider

The CircleCiOidcProvider is only created once per account. You can use the CircleCiOidcProvider.fromOrganizationId method to import a previously created provider into any stack.

import { Stack, StackProps } from "aws-cdk-lib";
import { CircleCiOidcRole, CircleCiOidcProvider } from "@blimmer/cdk-circleci-oidc";
import { Construct } from "constructs";

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

    const myCircleCiRole = new CircleCiOidcRole(this, "MyCircleCiRole", {
      provider: CircleCiOidcProvider.fromOrganizationId(this, "11111111-2222-3333-4444-555555555555"),
      roleName: "MyCircleCiRole",
    });
  }
}

Usage

For detailed API docs, see API.md.

Python

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

pip install cdk-circleci-oidc

Upgrading Between Major Versions

The API can be expected to change between major versions. Please consult the UPGRADING docs for for information.

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_circleci_oidc-1.0.2.tar.gz (58.0 kB view details)

Uploaded Source

Built Distribution

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

cdk_circleci_oidc-1.0.2-py3-none-any.whl (56.1 kB view details)

Uploaded Python 3

File details

Details for the file cdk_circleci_oidc-1.0.2.tar.gz.

File metadata

  • Download URL: cdk_circleci_oidc-1.0.2.tar.gz
  • Upload date:
  • Size: 58.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.12.8

File hashes

Hashes for cdk_circleci_oidc-1.0.2.tar.gz
Algorithm Hash digest
SHA256 0b63ade7703e7913cfc5ba896206d7d3eb86b507cd26463162d12315edb83b94
MD5 5d81f128a32d54c3f4a85177edf6f483
BLAKE2b-256 690ff5c6fa39018920b1dff3d4f50d4689350eefa13070bd919065b41c353db8

See more details on using hashes here.

File details

Details for the file cdk_circleci_oidc-1.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for cdk_circleci_oidc-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 36fb8038c1a8e4125c26b88de6ec5b2298dcf5a8855f59230f814ebb0cf07cd6
MD5 c82a7daddb8762185f5e4dc998c3025e
BLAKE2b-256 5e3c8d86cc728f4dc548741bebf8e4bf38383a36864e4cd844429d6b9607458b

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