From 4afa7fc72e73e38395246b82e003cb777d9bdbd4 Mon Sep 17 00:00:00 2001 From: diana esteves Date: Fri, 20 Sep 2024 19:34:13 +0000 Subject: [PATCH 1/5] init --- aws-ts-oidc-provider-pulumi-cloud/Pulumi.yaml | 15 ++++----------- aws-ts-oidc-provider-pulumi-cloud/README.md | 14 +++----------- aws-ts-oidc-provider-pulumi-cloud/package.json | 13 +++++++------ 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/aws-ts-oidc-provider-pulumi-cloud/Pulumi.yaml b/aws-ts-oidc-provider-pulumi-cloud/Pulumi.yaml index 4632bdb67..f4a993b1f 100644 --- a/aws-ts-oidc-provider-pulumi-cloud/Pulumi.yaml +++ b/aws-ts-oidc-provider-pulumi-cloud/Pulumi.yaml @@ -3,19 +3,12 @@ description: ${DESCRIPTION} runtime: nodejs template: - description: A minimal TypeScript Pulumi program to set up AWS OIDC+Pulumi ESC + description: A minimal TypeScript Pulumi program to set up AWS OIDC config: aws:region: - description: The AWS region to deploy into + description: AWS Region default: us-west-2 - oidcIdpUrl: - description: The URL of the OIDC IdP to use - default: https://api.pulumi.com/oidc - thumbprint: - description: The thumbprint of the OIDC IdP SSL certificate. - # This is a valid AWS OIDC thumbprint as of June 2024. - default: 9e99a48a9960b14926bb7f3b02e22da2b0ab7280 escEnv: - description: The Pulumi ESC Environment to create ('.' to skip) - default: aws-oidc-env + description: Pulumi ESC Environment to create ('.' to skip) + default: auth/aws \ No newline at end of file diff --git a/aws-ts-oidc-provider-pulumi-cloud/README.md b/aws-ts-oidc-provider-pulumi-cloud/README.md index ab95e5de1..f2aac865e 100644 --- a/aws-ts-oidc-provider-pulumi-cloud/README.md +++ b/aws-ts-oidc-provider-pulumi-cloud/README.md @@ -5,7 +5,7 @@ A Pulumi template to: - Create AWS resources for AWS OIDC (IdP + Role) - Create a new Pulumi Cloud ESC Environment (optional) -Last update: July 2024 +Last update: September 2024 ## 📋 Pre-requisites @@ -32,15 +32,7 @@ Once copied to your machine, feel free to edit as needed. ## 🎬 How to run -This template will pick up the thumbprint from the URL that you set in the stack configuration. By default it will use the OIDC IDP URL for Pulumi Cloud, unless you set a different one. - -To set a different URL you can run the following command: - -```bash -pulumi config set oidcIdpUrl {url} -``` - -(where `{url}` is the URL for the OIDC IDP) +This template will pick up the thumbprint from the URL that you set in the stack configuration. By default it will use the OIDC IDP URL for Pulumi Cloud. You must also set the name of the environment that you would like to use: @@ -48,7 +40,7 @@ You must also set the name of the environment that you would like to use: pulumi config set escEnv {environment-name} ``` -(Note that `{environment-name}` must be in the format `{orgname}/environmentname}` where `orgname` can be your individual account name or the the organization that you are adding the environment to) +(Note that `{environment-name}` must be in the format `{orgname}/{project}/{environmentname}` where `orgname` can be your individual account name or the the organization that you are adding the environment to) To deploy your infrastructure, run: diff --git a/aws-ts-oidc-provider-pulumi-cloud/package.json b/aws-ts-oidc-provider-pulumi-cloud/package.json index 5f85e19aa..ca565c25c 100644 --- a/aws-ts-oidc-provider-pulumi-cloud/package.json +++ b/aws-ts-oidc-provider-pulumi-cloud/package.json @@ -2,13 +2,14 @@ "name": "aws-ts-oidc-provider-pulumi-cloud", "main": "index.ts", "devDependencies": { - "@types/node": "^20", - "typescript": "^5.4.5" + "@types/node": "^22", + "typescript": "^5.6.2" }, "dependencies": { - "@pulumi/aws": "^6.40.0", - "@pulumi/pulumi": "^3.120.0", - "@pulumi/pulumiservice": "^0.21.2", - "@pulumi/tls": "^5.0.3" + "@pulumi/aws": "^6.52.0", + "@pulumi/command": "^1.0.1", + "@pulumi/pulumi": "^3.133.0", + "@pulumi/pulumiservice": "^0.26.0", + "@pulumi/tls": "^5.0.6" } } From 8a96b8230365672c51cc2dcdb1e6e0e9aa027528 Mon Sep 17 00:00:00 2001 From: diana esteves Date: Fri, 20 Sep 2024 20:42:53 +0000 Subject: [PATCH 2/5] wip --- aws-ts-oidc-provider-pulumi-cloud/.gitignore | 3 +- aws-ts-oidc-provider-pulumi-cloud/Pulumi.yaml | 3 - aws-ts-oidc-provider-pulumi-cloud/index.ts | 133 ++++++++++-------- .../package.json | 2 +- 4 files changed, 77 insertions(+), 64 deletions(-) diff --git a/aws-ts-oidc-provider-pulumi-cloud/.gitignore b/aws-ts-oidc-provider-pulumi-cloud/.gitignore index e37caccd6..63951cb6a 100644 --- a/aws-ts-oidc-provider-pulumi-cloud/.gitignore +++ b/aws-ts-oidc-provider-pulumi-cloud/.gitignore @@ -1,3 +1,4 @@ /bin/ /node_modules/ -test/ \ No newline at end of file +test/ +Pulumi.test.yaml \ No newline at end of file diff --git a/aws-ts-oidc-provider-pulumi-cloud/Pulumi.yaml b/aws-ts-oidc-provider-pulumi-cloud/Pulumi.yaml index f4a993b1f..eabe384c0 100644 --- a/aws-ts-oidc-provider-pulumi-cloud/Pulumi.yaml +++ b/aws-ts-oidc-provider-pulumi-cloud/Pulumi.yaml @@ -8,7 +8,4 @@ template: aws:region: description: AWS Region default: us-west-2 - escEnv: - description: Pulumi ESC Environment to create ('.' to skip) - default: auth/aws \ No newline at end of file diff --git a/aws-ts-oidc-provider-pulumi-cloud/index.ts b/aws-ts-oidc-provider-pulumi-cloud/index.ts index 8a0af2432..1c38fee58 100644 --- a/aws-ts-oidc-provider-pulumi-cloud/index.ts +++ b/aws-ts-oidc-provider-pulumi-cloud/index.ts @@ -1,89 +1,104 @@ // Copyright 2024, Pulumi Corporation. All rights reserved. import * as aws from "@pulumi/aws"; +import * as command from "@pulumi/command"; import * as pulumi from "@pulumi/pulumi"; import * as pulumiservice from "@pulumi/pulumiservice"; import * as tls from "@pulumi/tls"; // Configurations const audience = pulumi.getOrganization(); -const config = new pulumi.Config(); -const oidcIdpUrl: string = config.get("oidcIdpUrl") || "https://api.pulumi.com/oidc"; -const escEnv: string = config.require("escEnv"); +const oidcIdpUrl: string = "https://api.pulumi.com/oidc"; // Get TLS thumbprint for OIDC Provider const certs = tls.getCertificateOutput({ url: oidcIdpUrl, }); - const thumbprint = certs.certificates[0].sha1Fingerprint; -// Create a new OIDC Provider -const oidcProvider = new aws.iam.OpenIdConnectProvider("oidcProvider", { - clientIdLists: [audience], - url: oidcIdpUrl, - thumbprintLists: [thumbprint], -}, { - protect: true, -}); +function getProviderArn() { + const existingProvider = aws.iam.getOpenIdConnectProviderOutput({ + url: oidcIdpUrl + }) + if (existingProvider) { + console.log("OIDC Provider already exists ..."); + // upsert audience + new command.local.Command("oidc-client-id", { + create: pulumi.interpolate`aws iam add-client-id-to-open-id-connect-provider --open-id-connect-provider-arn ${existingProvider.arn} --client-id aws:${audience}`, + delete: pulumi.interpolate`aws iam remove-client-id-from-open-id-connect-provider --open-id-connect-provider-arn ${existingProvider.arn} --client-id aws:${audience}`, + }); + return existingProvider.arn; + } else { + console.log("Creating OIDC Provider ..."); + const provider = new aws.iam.OpenIdConnectProvider("oidcProvider", { + clientIdLists: [audience], + url: oidcIdpUrl, + thumbprintLists: [thumbprint], + }, { + protect: true, + }) + return provider.arn; + } +} -// Create a new role that can be assumed by the OIDC provider -const role = new aws.iam.Role("oidcProviderRole", { - assumeRolePolicy: pulumi.all([oidcProvider.url, oidcProvider.arn, audience]).apply(([url, arn, audience]) => JSON.stringify({ - Version: "2012-10-17", - Statement: [{ - Effect: "Allow", - Principal: { Federated: arn }, - Action: "sts:AssumeRoleWithWebIdentity", - Condition: { StringEquals: { [`${url}:aud`]: [audience] } }, +export const arn: pulumi.Output = getProviderArn(); + +const policyDocument = arn.apply(arn => aws.iam.getPolicyDocument({ + version: "2012-10-17", + statements: [{ + effect: "Allow", + actions: ["sts:AssumeRoleWithWebIdentity"], + principals: [{ + type: "Federated", + identifiers: [arn], }], - })), -}); + conditions: [{ + test: "StringEquals", + variable: `api.pulumi.com/oidc:aud`, + values: [`aws:${audience}`], // new format + }] + }] +})); -// Get the existing AdministratorAccess policy -const existingPolicy = aws.iam.getPolicy({ - arn: "arn:aws:iam::aws:policy/AdministratorAccess", +// // Create a new role that can be assumed by the OIDC provider +const role = new aws.iam.Role("role", { + assumeRolePolicy: policyDocument.json, }); - -// Attach other policies to the role as needed -const attach = new aws.iam.RolePolicyAttachment("oidcProviderRolePolicyAttachment", { - role: role, - policyArn: existingPolicy.then(policy => policy.arn), +// Attach the AWS managed policy "AdministratorAccess" to the role. +new aws.iam.RolePolicyAttachment("policy", { + policyArn: "arn:aws:iam::aws:policy/AdministratorAccess", + role: role.name, }); -if (escEnv === ".") { - console.log("Skipping ESC Environment creation ..."); -} -else { - const envJson = pulumi.jsonStringify({ - "values": { - "aws": { - "login": { - "fn::open::aws-login": { - "oidc": { - "duration": "1h", - "roleArn": role.arn, - "sessionName": "pulumi-environments-session", - }, +const envJson = pulumi.jsonStringify({ + "values": { + "aws": { + "login": { + "fn::open::aws-login": { + "oidc": { + "duration": "1h", + "roleArn": role.arn, + "sessionName": "pulumi-environments-session", }, }, }, - "environmentVariables": { - "AWS_ACCESS_KEY_ID": "${aws.login.accessKeyId}", - "AWS_SECRET_ACCESS_KEY": "${aws.login.secretAccessKey}", - "AWS_SESSION_TOKEN": "${aws.login.sessionToken}", - }, }, - }); - - const envAsset = envJson.apply(json => new pulumi.asset.StringAsset(json)); + "environmentVariables": { + "AWS_ACCESS_KEY_ID": "${aws.login.accessKeyId}", + "AWS_SECRET_ACCESS_KEY": "${aws.login.secretAccessKey}", + "AWS_SESSION_TOKEN": "${aws.login.sessionToken}", + }, + }, +}); - const env = new pulumiservice.Environment("oidcEnvironment", { - name: escEnv, - organization: audience, - yaml: envAsset, - }); +export const envAsset = envJson.apply(json => new pulumi.asset.StringAsset(json)); -} // end of else +// Create a new environment +new pulumiservice.Environment("aws-oidc-admin", { + name: "test", + // project: "auth", // new field + organization: audience, + yaml: envAsset, +}); diff --git a/aws-ts-oidc-provider-pulumi-cloud/package.json b/aws-ts-oidc-provider-pulumi-cloud/package.json index ca565c25c..f53e2bea4 100644 --- a/aws-ts-oidc-provider-pulumi-cloud/package.json +++ b/aws-ts-oidc-provider-pulumi-cloud/package.json @@ -9,7 +9,7 @@ "@pulumi/aws": "^6.52.0", "@pulumi/command": "^1.0.1", "@pulumi/pulumi": "^3.133.0", - "@pulumi/pulumiservice": "^0.26.0", + "@pulumi/pulumiservice": "0.23.2", "@pulumi/tls": "^5.0.6" } } From 05ecf79c1e9479a0000de8e001e725cf8a9ca1a1 Mon Sep 17 00:00:00 2001 From: diana esteves Date: Fri, 20 Sep 2024 20:45:29 +0000 Subject: [PATCH 3/5] remove option for escEnv --- aws-ts-oidc-provider-pulumi-cloud/README.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/aws-ts-oidc-provider-pulumi-cloud/README.md b/aws-ts-oidc-provider-pulumi-cloud/README.md index f2aac865e..2532f4253 100644 --- a/aws-ts-oidc-provider-pulumi-cloud/README.md +++ b/aws-ts-oidc-provider-pulumi-cloud/README.md @@ -3,7 +3,7 @@ A Pulumi template to: - Create AWS resources for AWS OIDC (IdP + Role) -- Create a new Pulumi Cloud ESC Environment (optional) +- Create a new Pulumi Cloud ESC Environment Last update: September 2024 @@ -34,14 +34,6 @@ Once copied to your machine, feel free to edit as needed. This template will pick up the thumbprint from the URL that you set in the stack configuration. By default it will use the OIDC IDP URL for Pulumi Cloud. -You must also set the name of the environment that you would like to use: - -```bash -pulumi config set escEnv {environment-name} -``` - -(Note that `{environment-name}` must be in the format `{orgname}/{project}/{environmentname}` where `orgname` can be your individual account name or the the organization that you are adding the environment to) - To deploy your infrastructure, run: ```bash From e37e5c7407a3c5820e4ef0dd532fedb0dad4e6e9 Mon Sep 17 00:00:00 2001 From: diana esteves Date: Fri, 20 Sep 2024 16:12:07 -0500 Subject: [PATCH 4/5] rm export --- aws-ts-oidc-provider-pulumi-cloud/index.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/aws-ts-oidc-provider-pulumi-cloud/index.ts b/aws-ts-oidc-provider-pulumi-cloud/index.ts index 1c38fee58..867a3291a 100644 --- a/aws-ts-oidc-provider-pulumi-cloud/index.ts +++ b/aws-ts-oidc-provider-pulumi-cloud/index.ts @@ -71,7 +71,6 @@ new aws.iam.RolePolicyAttachment("policy", { role: role.name, }); - const envJson = pulumi.jsonStringify({ "values": { "aws": { @@ -93,12 +92,12 @@ const envJson = pulumi.jsonStringify({ }, }); -export const envAsset = envJson.apply(json => new pulumi.asset.StringAsset(json)); +const envAsset = envJson.apply(json => new pulumi.asset.StringAsset(json)); // Create a new environment new pulumiservice.Environment("aws-oidc-admin", { name: "test", - // project: "auth", // new field + // project: "auth", // post esc-GA organization: audience, yaml: envAsset, }); From d0f106489ae478f89503493a343fc9a3be6d199b Mon Sep 17 00:00:00 2001 From: diana esteves Date: Mon, 23 Sep 2024 15:08:23 -0500 Subject: [PATCH 5/5] lint --- aws-ts-oidc-provider-pulumi-cloud/index.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/aws-ts-oidc-provider-pulumi-cloud/index.ts b/aws-ts-oidc-provider-pulumi-cloud/index.ts index 867a3291a..4cfc82a37 100644 --- a/aws-ts-oidc-provider-pulumi-cloud/index.ts +++ b/aws-ts-oidc-provider-pulumi-cloud/index.ts @@ -18,12 +18,12 @@ const thumbprint = certs.certificates[0].sha1Fingerprint; function getProviderArn() { const existingProvider = aws.iam.getOpenIdConnectProviderOutput({ - url: oidcIdpUrl - }) + url: oidcIdpUrl, + }); if (existingProvider) { console.log("OIDC Provider already exists ..."); // upsert audience - new command.local.Command("oidc-client-id", { + const cmd = new command.local.Command("oidc-client-id", { create: pulumi.interpolate`aws iam add-client-id-to-open-id-connect-provider --open-id-connect-provider-arn ${existingProvider.arn} --client-id aws:${audience}`, delete: pulumi.interpolate`aws iam remove-client-id-from-open-id-connect-provider --open-id-connect-provider-arn ${existingProvider.arn} --client-id aws:${audience}`, }); @@ -36,7 +36,7 @@ function getProviderArn() { thumbprintLists: [thumbprint], }, { protect: true, - }) + }); return provider.arn; } } @@ -56,8 +56,8 @@ const policyDocument = arn.apply(arn => aws.iam.getPolicyDocument({ test: "StringEquals", variable: `api.pulumi.com/oidc:aud`, values: [`aws:${audience}`], // new format - }] - }] + }], + }], })); // // Create a new role that can be assumed by the OIDC provider @@ -66,7 +66,7 @@ const role = new aws.iam.Role("role", { }); // Attach the AWS managed policy "AdministratorAccess" to the role. -new aws.iam.RolePolicyAttachment("policy", { +const rpa = new aws.iam.RolePolicyAttachment("policy", { policyArn: "arn:aws:iam::aws:policy/AdministratorAccess", role: role.name, }); @@ -95,7 +95,7 @@ const envJson = pulumi.jsonStringify({ const envAsset = envJson.apply(json => new pulumi.asset.StringAsset(json)); // Create a new environment -new pulumiservice.Environment("aws-oidc-admin", { +const env = new pulumiservice.Environment("aws-oidc-admin", { name: "test", // project: "auth", // post esc-GA organization: audience,