Skip to content

Commit

Permalink
Merge pull request pulumi#1513 from pulumi/torian/gcp-py-oidc-provide…
Browse files Browse the repository at this point in the history
…r-pulumi-cloud

Create Pulumi to GCP to OIDC Configuration Example
  • Loading branch information
toriancrane committed Oct 19, 2023
2 parents 68ec39b + a2d1d33 commit 49a01b5
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 0 deletions.
2 changes: 2 additions & 0 deletions gcp-py-oidc-provider-pulumi-cloud/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
venv/
6 changes: 6 additions & 0 deletions gcp-py-oidc-provider-pulumi-cloud/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: gcp-oidc
runtime:
name: python
options:
virtualenv: venv
description: A minimal Google Cloud Python Pulumi program
74 changes: 74 additions & 0 deletions gcp-py-oidc-provider-pulumi-cloud/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Provisioning an OIDC Provider in Google Cloud for Pulumi Cloud

This example will create OIDC configuration between Pulumi Cloud and Google Cloud, specifically demonstrating connectivity with [Pulumi ESC](https://www.pulumi.com/docs/pulumi-cloud/esc/). The program automates the process detailed in the Google Cloud documentation for the following activities:

- [Create Workload Identity Provider and Pool](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#create_the_workload_identity_pool_and_provider)
- [Authenticate the Workload](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#authenticate)

## Prerequisites

* [Install Pulumi](https://www.pulumi.com/docs/get-started/install/)
* [Configure Pulumi to Use GCP](https://www.pulumi.com/docs/clouds/gcp/get-started/begin/#configure-pulumi-to-access-your-google-cloud-account)
* [Create a Google Cloud Project with the required APIs enabled](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#configure)

## Running the Example

Clone [the examples repo](https://github.com/pulumi/examples/tree/master/gcp-py-oidc-provider) and navigate to the folder for this example.

```bash
git clone https://github.com/pulumi/examples.git
cd examples/gcp-py-oidc-provider-pulumi-cloud
```

Next, to deploy the application and its infrastructure, follow these steps:

1. Create a new stack, which is an isolated deployment target for this example:

```bash
pulumi stack init dev
```

1. Set your Pulumi ESC environment name and the name of your GCP Project:

```bash
pulumi config set environmentName <your-environment-name> # replace with your environment name
pulumi config set gcp:project <your-project-id> # replace with your GCP project ID
```

1. Install requirements.

```bash
python3 -m venv venv
venv/bin/pip install -r requirements.txt
```

1. Run `pulumi up -y`. Once the program completes, it will output a YAML template for you to use in the next step.

## Validating the OIDC Configuration

This next section will walk you through validating your OIDC configuration using [Pulumi ESC](https://www.pulumi.com/docs/pulumi-cloud/esc/).

Start by [creating a new Pulumi ESC environment](https://www.pulumi.com/docs/pulumi-cloud/esc/get-started/#create-an-environment). Then, copy the template definition from the output in the CLI and paste it into your environment. Save your environment file and run the `pulumi env open <your-pulumi-org>/<your-environment>` command in the CLI. You should see output similar to the following:

```bash
$ pulumi env open myOrg/myEnvironment
{
"gcp": {
"login": {
"accessToken": "N777Agel_gBF...",
"expiry": "2023-10-12T14:38:00Z",
"project": 842111111111,
"tokenType": "Bearer"
}
}
}
```

## Clean-Up Resources

Once you are done, you can destroy all of the resources as well as the stack:

```bash
$ pulumi destroy
$ pulumi stack rm
```
87 changes: 87 additions & 0 deletions gcp-py-oidc-provider-pulumi-cloud/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import pulumi
from pulumi_gcp import organizations, iam, serviceaccount
import yaml
import random

number = random.randint(1000,9999)

issuer = "https://api.pulumi.com/oidc"

# Retrieve local Pulumi configuration
pulumi_config = pulumi.Config()
audience = pulumi.get_organization()
env_name = pulumi_config.require("environmentName")
sub_id = f"pulumi:environments:org:{audience}:env:{env_name}"

# Retrieve project details
project_config = organizations.get_project()
project_id = project_config.number

# Create a Workload Identity Pool
identity_pool = iam.WorkloadIdentityPool("pulumiOidcWorkloadIdentityPool",
workload_identity_pool_id=f"pulumi-oidc-identity-pool-{number}",
description="Pulumi OIDC Workload Identity Pool",
display_name="Pulumi OIDC Identity Pool"
)

# Create a Workload Identity Provider
identity_provider = iam.WorkloadIdentityPoolProvider("pulumiOidcIdentityProvider",
workload_identity_pool_id=identity_pool.workload_identity_pool_id,
workload_identity_pool_provider_id=f"pulumi-oidc-provider-{number}",
attribute_mapping={
"google.subject": "assertion.sub",
},
oidc=iam.WorkloadIdentityPoolProviderOidcArgs(
issuer_uri=issuer,
allowed_audiences=[
audience
]
)
)

# Create a service account
service_account = serviceaccount.Account("serviceAccount",
account_id=f"pulumi-oidc-service-acct-{number}",
display_name="Pulumi OIDC Service Account"
)

# Create an IAM policy binding to grant the identity pool access to the service account
iam_policy_binding = serviceaccount.IAMBinding("iamPolicyBinding",
service_account_id=service_account.name,
role="roles/iam.workloadIdentityUser",
members=identity_pool.name.apply(
lambda name: [f"principalSet:https://iam.googleapis.com/{name}/*"]
)
)

# Generate Pulumi ESC YAML template
def create_yaml_structure(args):
gcp_project, workload_pool_id, provider_id, service_account_email = args
return {
'values': {
'gcp': {
'login': {
'fn::open::gcp-login': {
'project': int(gcp_project),
'oidc': {
'workloadPoolId': workload_pool_id,
'providerId': provider_id,
'serviceAccount': service_account_email
}
}
}
}
}
}

def print_yaml(args):
yaml_structure = create_yaml_structure(args)
yaml_string = yaml.dump(yaml_structure, sort_keys=False)
print(yaml_string)

pulumi.Output.all(
project_id,
identity_provider.workload_identity_pool_id,
identity_provider.workload_identity_pool_provider_id,
service_account.email
).apply(print_yaml)
3 changes: 3 additions & 0 deletions gcp-py-oidc-provider-pulumi-cloud/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pulumi>=3.0.0,<4.0.0
pulumi-gcp>=6.0.0,<7.0.0
PyYAML

0 comments on commit 49a01b5

Please sign in to comment.