Unverified Commit a273a55e authored by John DiSanti's avatar John DiSanti Committed by GitHub
Browse files

Split CI OIDC provider into its own stack (#948)

parent 34f43d96
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -7,7 +7,12 @@
import "source-map-support/register";
import * as cdk from "@aws-cdk/core";
import { PullRequestCdnStack } from "../lib/smithy-rs/pull-request-cdn-stack";
import { OidcProviderStack } from "../lib/oidc-provider-stack";

const app = new cdk.App();

new PullRequestCdnStack(app, "smithy-rs-pull-request-cdn-stack", {});
const oidcProviderStack = new OidcProviderStack(app, "oidc-provider-stack", {});

new PullRequestCdnStack(app, "smithy-rs-pull-request-cdn-stack", {
    githubActionsOidcProvider: oidcProviderStack.githubActionsOidcProvider,
});
+2 −17
Original line number Diff line number Diff line
@@ -6,23 +6,14 @@
import { FederatedPrincipal, OpenIdConnectProvider, Role } from "@aws-cdk/aws-iam";
import { Construct, Tags } from "@aws-cdk/core";

/// This thumbprint is used to validate GitHub's identity to AWS.
///
/// It was obtained by following instructions at:
/// https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
///
/// This was done with the initial Idp URL of:
/// https://token.actions.githubusercontent.com/.well-known/openid-configuration
const GITHUB_CERTIFICATE_THUMBPRINT = "A031C46782E6E6C662C2C87C76DA9AA62CCABD8E";

export interface Properties {
    name: string;
    githubOrg: string;
    githubRepo: string;
    oidcProvider: OpenIdConnectProvider;
}

export class GitHubOidcRole extends Construct {
    public readonly oidcProvider: OpenIdConnectProvider;
    public readonly oidcRole: Role;

    constructor(scope: Construct, id: string, properties: Properties) {
@@ -32,16 +23,10 @@ export class GitHubOidcRole extends Construct {
        Tags.of(this).add("construct-name", properties.name);
        Tags.of(this).add("construct-type", "GitHubOidcRole");

        this.oidcProvider = new OpenIdConnectProvider(this, "oidc-provider", {
            url: "https://token.actions.githubusercontent.com",
            thumbprints: [GITHUB_CERTIFICATE_THUMBPRINT],
            clientIds: ["sts.amazonaws.com"],
        });

        this.oidcRole = new Role(this, "oidc-role", {
            roleName: `${properties.name}-github-oidc-role`,
            assumedBy: new FederatedPrincipal(
                this.oidcProvider.openIdConnectProviderArn,
                properties.oidcProvider.openIdConnectProviderArn,
                {
                    StringLike: {
                        "token.actions.githubusercontent.com:sub": `repo:${properties.githubOrg}/${properties.githubRepo}:*`,
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

import { OpenIdConnectProvider } from "@aws-cdk/aws-iam";
import { Construct, StackProps, Stack, Tags } from "@aws-cdk/core";

/// This thumbprint is used to validate GitHub's identity to AWS.
///
/// It was obtained by following instructions at:
/// https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
///
/// This was done with the initial Idp URL of:
/// https://token.actions.githubusercontent.com/.well-known/openid-configuration
const GITHUB_CERTIFICATE_THUMBPRINT = "A031C46782E6E6C662C2C87C76DA9AA62CCABD8E";

// There can only be one OIDC provider for a given URL per AWS account,
// so put these in their own stack to be shared with other stacks.
export class OidcProviderStack extends Stack {
    public readonly githubActionsOidcProvider: OpenIdConnectProvider;

    constructor(scope: Construct, id: string, props?: StackProps) {
        super(scope, id, props);

        // Tag the resources created by this stack to make identifying resources easier
        Tags.of(this).add("stack", id);

        this.githubActionsOidcProvider = new OpenIdConnectProvider(this, "oidc-provider", {
            url: "https://token.actions.githubusercontent.com",
            thumbprints: [GITHUB_CERTIFICATE_THUMBPRINT],
            clientIds: ["sts.amazonaws.com"],
        });
    }
}
+8 −2
Original line number Diff line number Diff line
@@ -3,16 +3,21 @@
 * SPDX-License-Identifier: Apache-2.0.
 */

import { OpenIdConnectProvider } from "@aws-cdk/aws-iam";
import * as cdk from "@aws-cdk/core";
import { Duration, RemovalPolicy, Tags } from "@aws-cdk/core";
import { Duration, RemovalPolicy, StackProps, Tags } from "@aws-cdk/core";
import { CloudFrontS3Cdn } from "../constructs/cloudfront-s3-cdn";
import { GitHubOidcRole } from "../constructs/github-oidc-role";

export interface Properties extends StackProps {
    githubActionsOidcProvider: OpenIdConnectProvider;
}

export class PullRequestCdnStack extends cdk.Stack {
    public readonly smithyRsOidcRole: GitHubOidcRole;
    public readonly pullRequestCdn: CloudFrontS3Cdn;

    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    constructor(scope: cdk.Construct, id: string, props: Properties) {
        super(scope, id, props);

        // Tag the resources created by this stack to make identifying resources easier
@@ -22,6 +27,7 @@ export class PullRequestCdnStack extends cdk.Stack {
            name: "smithy-rs-pull-request",
            githubOrg: "awslabs",
            githubRepo: "smithy-rs",
            oidcProvider: props.githubActionsOidcProvider,
        });

        this.pullRequestCdn = new CloudFrontS3Cdn(this, "pull-request-cdn", {
+5 −9
Original line number Diff line number Diff line
@@ -7,25 +7,21 @@ import { Match, Template } from "@aws-cdk/assertions";
import * as cdk from "@aws-cdk/core";
import { Stack } from "@aws-cdk/core";
import { GitHubOidcRole } from "../../lib/constructs/github-oidc-role";
import { OidcProviderStack } from "../../lib/oidc-provider-stack";

test("it should have an OIDC provider and access role", () => {
test("it should have an OIDC access role", () => {
    const app = new cdk.App();
    const oidcStack = new OidcProviderStack(app, "oidc-provider-stack", {});
    const stack = new Stack(app, "test-stack");

    new GitHubOidcRole(stack, "test", {
        name: "some-name",
        githubOrg: "some-org",
        githubRepo: "some-repo",
        oidcProvider: oidcStack.githubActionsOidcProvider,
    });
    const template = Template.fromStack(stack);

    // Verify the OIDC provider
    template.hasResourceProperties("Custom::AWSCDKOpenIdConnectProvider", {
        ClientIDList: ["sts.amazonaws.com"],
        ThumbprintList: ["A031C46782E6E6C662C2C87C76DA9AA62CCABD8E"],
        Url: "https://token.actions.githubusercontent.com",
    });

    // Verify the OIDC role to be assumed
    template.hasResourceProperties(
        "AWS::IAM::Role",
@@ -42,7 +38,7 @@ test("it should have an OIDC provider and access role", () => {
                        },
                        Principal: {
                            Federated: {
                                Ref: Match.anyValue(),
                                "Fn::ImportValue": Match.anyValue(),
                            },
                        },
                        Effect: "Allow",
Loading