Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Pulumi to GCP to OIDC Configuration Example #1513

Merged
merged 6 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
toriancrane marked this conversation as resolved.
Show resolved Hide resolved

## 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://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
Loading