diff --git a/.changeset/friendly-trainers-cry.md b/.changeset/friendly-trainers-cry.md new file mode 100644 index 0000000000..0d8b7fbed4 --- /dev/null +++ b/.changeset/friendly-trainers-cry.md @@ -0,0 +1,16 @@ +--- +"@guardian/cdk": major +--- + +Support multiple usages of `GuGithubActionsRole` in a single AWS account + +This significantly changes the resources constructed by `GuGithubActionsRole`, +specifically, **the construct will no longer instantiate a `GitHubOidcProvider`**. +This is because you can only ever have one `GitHubOidcProvider` per provider +domain (ie `token.actions.githubusercontent.com`) - while we may want multiple +instances of `GuGithubActionsRole` in an AWS account, we can't have the +`GuGithubActionsRole` construct trying to make a new `GitHubOidcProvider` with +each instance. + +Consequently, you will need to instantiate the `GitHubOidcProvider` elsewhere +as a singleton. At the Guardian, we do this with https://github.com/guardian/aws-account-setup. diff --git a/src/constructs/iam/roles/__snapshots__/github-actions.test.ts.snap b/src/constructs/iam/roles/__snapshots__/github-actions.test.ts.snap index 309a2ae494..b8fa7c068b 100644 --- a/src/constructs/iam/roles/__snapshots__/github-actions.test.ts.snap +++ b/src/constructs/iam/roles/__snapshots__/github-actions.test.ts.snap @@ -42,19 +42,6 @@ exports[`The GitHubActionsRole construct should create the correct resources wit }, "Type": "AWS::IAM::Policy", }, - "GithubActionsOidc": { - "Properties": { - "ClientIdList": [ - "sts.amazonaws.com", - ], - "ThumbprintList": [ - "6938fd4d98bab03faadb97b34396831e3780aea1", - "1c58a3a8518e8759bf075b76b750d4f2df264fcd", - ], - "Url": "https://token.actions.githubusercontent.com", - }, - "Type": "AWS::IAM::OIDCProvider", - }, "GithubActionsRoleF5CC769F": { "Properties": { "AssumeRolePolicyDocument": { @@ -69,7 +56,16 @@ exports[`The GitHubActionsRole construct should create the correct resources wit "Effect": "Allow", "Principal": { "Federated": { - "Ref": "GithubActionsOidc", + "Fn::Join": [ + "", + [ + "arn:aws:iam::", + { + "Ref": "AWS::AccountId", + }, + ":oidc-provider/token.actions.githubusercontent.com", + ], + ], }, }, }, diff --git a/src/constructs/iam/roles/github-actions.ts b/src/constructs/iam/roles/github-actions.ts index 64fb8ff723..8204185dd9 100644 --- a/src/constructs/iam/roles/github-actions.ts +++ b/src/constructs/iam/roles/github-actions.ts @@ -54,6 +54,10 @@ export interface GuGithubActionsRoleProps { } /* +Note you can only have one of these per AWS account - `OIDCProvider`s are keyed by the +provider domain, ie `token.actions.githubusercontent.com`, so this must be instantiated +as a singleton. At the Guardian we do this in https://github.com/guardian/aws-account-setup . + AWS CDK implements an OIDCProvider as a custom resource. This requires a lambda to be deployed into the account. As far as I can tell, the lambda is automating the setting of `ThumbprintList`, which is quite generic. @@ -63,7 +67,7 @@ See: - https://github.com/aws/aws-cdk/blob/851c8ca9989856fa61496ff113f9cb8c66d02f3b/packages/%40aws-cdk/aws-iam/lib/oidc-provider.ts - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html */ -class GitHubOidcProvider extends CfnResource { +export class GitHubOidcProvider extends CfnResource { constructor(scope: GuStack) { super(scope, "GithubActionsOidc", { type: "AWS::IAM::OIDCProvider", @@ -89,7 +93,7 @@ export class GuGithubActionsRole extends GuRole { constructor(scope: GuStack, props: GuGithubActionsRoleProps) { super(scope, "GithubActionsRole", { assumedBy: new FederatedPrincipal( - new GitHubOidcProvider(scope).ref, + `arn:aws:iam::${scope.account}:oidc-provider/${GITHUB_ACTIONS_ID_TOKEN_REQUEST_DOMAIN}`, { StringLike: { [`${GITHUB_ACTIONS_ID_TOKEN_REQUEST_DOMAIN}:sub`]: GuGithubActionsRepositoryCondition.toString(