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

This commit is contained in:
John DiSanti 2021-12-09 11:13:57 -08:00 committed by GitHub
parent 34f43d96cf
commit a273a55e8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 29 deletions

View File

@ -7,7 +7,12 @@
import "source-map-support/register"; import "source-map-support/register";
import * as cdk from "@aws-cdk/core"; import * as cdk from "@aws-cdk/core";
import { PullRequestCdnStack } from "../lib/smithy-rs/pull-request-cdn-stack"; import { PullRequestCdnStack } from "../lib/smithy-rs/pull-request-cdn-stack";
import { OidcProviderStack } from "../lib/oidc-provider-stack";
const app = new cdk.App(); 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,
});

View File

@ -6,23 +6,14 @@
import { FederatedPrincipal, OpenIdConnectProvider, Role } from "@aws-cdk/aws-iam"; import { FederatedPrincipal, OpenIdConnectProvider, Role } from "@aws-cdk/aws-iam";
import { Construct, Tags } from "@aws-cdk/core"; 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 { export interface Properties {
name: string; name: string;
githubOrg: string; githubOrg: string;
githubRepo: string; githubRepo: string;
oidcProvider: OpenIdConnectProvider;
} }
export class GitHubOidcRole extends Construct { export class GitHubOidcRole extends Construct {
public readonly oidcProvider: OpenIdConnectProvider;
public readonly oidcRole: Role; public readonly oidcRole: Role;
constructor(scope: Construct, id: string, properties: Properties) { 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-name", properties.name);
Tags.of(this).add("construct-type", "GitHubOidcRole"); 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", { this.oidcRole = new Role(this, "oidc-role", {
roleName: `${properties.name}-github-oidc-role`, roleName: `${properties.name}-github-oidc-role`,
assumedBy: new FederatedPrincipal( assumedBy: new FederatedPrincipal(
this.oidcProvider.openIdConnectProviderArn, properties.oidcProvider.openIdConnectProviderArn,
{ {
StringLike: { StringLike: {
"token.actions.githubusercontent.com:sub": `repo:${properties.githubOrg}/${properties.githubRepo}:*`, "token.actions.githubusercontent.com:sub": `repo:${properties.githubOrg}/${properties.githubRepo}:*`,

View File

@ -0,0 +1,35 @@
/*
* 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"],
});
}
}

View File

@ -3,16 +3,21 @@
* SPDX-License-Identifier: Apache-2.0. * SPDX-License-Identifier: Apache-2.0.
*/ */
import { OpenIdConnectProvider } from "@aws-cdk/aws-iam";
import * as cdk from "@aws-cdk/core"; 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 { CloudFrontS3Cdn } from "../constructs/cloudfront-s3-cdn";
import { GitHubOidcRole } from "../constructs/github-oidc-role"; import { GitHubOidcRole } from "../constructs/github-oidc-role";
export interface Properties extends StackProps {
githubActionsOidcProvider: OpenIdConnectProvider;
}
export class PullRequestCdnStack extends cdk.Stack { export class PullRequestCdnStack extends cdk.Stack {
public readonly smithyRsOidcRole: GitHubOidcRole; public readonly smithyRsOidcRole: GitHubOidcRole;
public readonly pullRequestCdn: CloudFrontS3Cdn; 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); super(scope, id, props);
// Tag the resources created by this stack to make identifying resources easier // 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", name: "smithy-rs-pull-request",
githubOrg: "awslabs", githubOrg: "awslabs",
githubRepo: "smithy-rs", githubRepo: "smithy-rs",
oidcProvider: props.githubActionsOidcProvider,
}); });
this.pullRequestCdn = new CloudFrontS3Cdn(this, "pull-request-cdn", { this.pullRequestCdn = new CloudFrontS3Cdn(this, "pull-request-cdn", {

View File

@ -7,25 +7,21 @@ import { Match, Template } from "@aws-cdk/assertions";
import * as cdk from "@aws-cdk/core"; import * as cdk from "@aws-cdk/core";
import { Stack } from "@aws-cdk/core"; import { Stack } from "@aws-cdk/core";
import { GitHubOidcRole } from "../../lib/constructs/github-oidc-role"; 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 app = new cdk.App();
const oidcStack = new OidcProviderStack(app, "oidc-provider-stack", {});
const stack = new Stack(app, "test-stack"); const stack = new Stack(app, "test-stack");
new GitHubOidcRole(stack, "test", { new GitHubOidcRole(stack, "test", {
name: "some-name", name: "some-name",
githubOrg: "some-org", githubOrg: "some-org",
githubRepo: "some-repo", githubRepo: "some-repo",
oidcProvider: oidcStack.githubActionsOidcProvider,
}); });
const template = Template.fromStack(stack); 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 // Verify the OIDC role to be assumed
template.hasResourceProperties( template.hasResourceProperties(
"AWS::IAM::Role", "AWS::IAM::Role",
@ -42,7 +38,7 @@ test("it should have an OIDC provider and access role", () => {
}, },
Principal: { Principal: {
Federated: { Federated: {
Ref: Match.anyValue(), "Fn::ImportValue": Match.anyValue(),
}, },
}, },
Effect: "Allow", Effect: "Allow",

View File

@ -0,0 +1,21 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
import { Template } from "@aws-cdk/assertions";
import * as cdk from "@aws-cdk/core";
import { OidcProviderStack } from "../lib/oidc-provider-stack";
test("it should have an OIDC provider", () => {
const app = new cdk.App();
const stack = new OidcProviderStack(app, "oidc-provider-stack", {});
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",
});
});