auth/README.md
2021-09-16 12:54:29 -04:00

202 lines
7.4 KiB
Markdown

# oidc-auth-google-cloud
This GitHub Action exchanges a GitHub Actions OIDC token into a Google Cloud
access token using [Workload Identity Federation][wif]. This obviates the need
to export a long-lived Google Cloud service account key and establishes a trust
delegation relationship between a particular GitHub Actions workflow invocation
and permissions on Google Cloud.
#### Previously
1. Create a Google Cloud service account and grant IAM permissions
1. Export the long-lived JSON service account key
1. Upload the JSON service account key to a GitHub secret
#### With Workload Identity Federation
1. Create a Google Cloud service account and grant IAM permissions
1. Create and configure a Workload Identity Provider for GitHub
1. Exchange the GitHub Actions OIDC token for a short-lived Google Cloud access
token
## Prerequisites
- This action requires you to create and configure a Google Cloud Workload
Identity Provider. See [#setup] for instructions.
## Usage
```yaml
jobs:
run:
# ...
# Add "id-token" with the intended permissions.
permissions:
id-token: write
contents: read
steps:
- id: 'google-cloud-auth'
name: 'Authenticate to Google Cloud'
uses: 'github.com/sethvargo/oidc-auth-google-cloud'
with:
workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider'
service_account: 'my-service-account@my-project.iam.gserviceaccount.com'
# Example of using the output:
- id: 'access-secret'
run: |-
curl https://secretmanager.googleapis.com/v1/projects/my-project/secrets/my-secret/versions/1:access \
--header "Authorization: Bearer ${{ steps.integration.outputs.access_token }}"
```
## Inputs
- `workload_identity_provider`: (Required) The full identifier of the Workload
Identity Provider, including the project number, pool name, and provider
name. This must be the full identifier which includes all parts, for
example:
```text
projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider
```
- `service_account`: (Required) Email address or unique identifier of the
Google Cloud service account for which to generate credentials. For example:
```text
my-service-account@my-project.iam.gserviceaccount.com
```
- `audience`: (Optional) The value for the audience (`aud`) parameter in the
generated GitHub Actions OIDC token. At present, the only valid value is
`"sigstore"`, but this variable exists in case custom values are permitted
in the future. The default value is `"sigstore"`.
- `delegates`: (Optional) List of additional service account emails or unique
identities to use for impersonation in the chain. By default there are no
delegates.
- `lifetime`: (Optional) Desired lifetime duration of the access token, in
seconds. This must be specified as the number of seconds with a trailing "s"
(e.g. 30s). The default value is 1 hour (3600s).
## Outputs
- `access_token`: The authenticated Google Cloud access token for calling
other Google Cloud APIs.
- `expiration`: The RFC3339 UTC "Zulu" format timestamp when the token
expires.
## Setup
To exchange a GitHub Actions OIDC token for a Google Cloud access token, you
must create and configure a Workload Identity Provider. These instructions use
the [gcloud][gcloud] command-line tool.
1. Create or use an existing Google Cloud project. You must have privileges to
create Workload Identity Pools, Workload Identity Providers, and to manage
Service Accounts and IAM permissions. Save your project ID as an environment
variable. The rest of these steps assume this environment variable is set:
```sh
export PROJECT_ID="my-project" # update with your value
```
1. (Optional) Create a Google Cloud Service Account. If you already have a
Service Account, take note of the email address and skip this step.
```sh
gcloud iam service-accounts create "my-service-account" \
--project "${PROJECT_ID}"
```
1. (Optional) Grant the Google Cloud Service Account permissions to access
Google Cloud resources. This step varies by use case. For demonstration
purposes, you could grant access to a Google Secret Manager secret or Google
Cloud Storage object.
1. Create a Workload Identity Pool:
```sh
gcloud iam workload-identity-pools create "my-pool" \
--project="${PROJECT_ID}" \
--location="global" \
--display-name="Demo pool"
```
1. Create a Workload Identity Provider in that pool:
```sh
gcloud iam workload-identity-pools providers create-oidc "my-provider" \
--project="${PROJECT_ID}" \
--location="global" \
--workload-identity-pool="my-pool" \
--display-name="Demo provider" \
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.aud=assertion.aud" \
--issuer-uri="https://vstoken.actions.githubusercontent.com" \
--allowed-audiences="sigstore"
```
- The audience of "sigstore" is currently the only value GitHub allows.
- The attribute mappings map claims in the GitHub Actions JWT to
assertions you can make about the request (like the repository or GitHub
username of the principal invoking the GitHub Action). These can be used
to further restrict the authentication using `--attribute-condition`
flags.
1. Get the full ID for the Workload Identity Provider:
```sh
gcloud iam workload-identity-pools providers describe "my-provider" \
--project="${PROJECT_ID}" \
--location="global" \
--workload-identity-pool="my-pool"
```
Take note of the `name` attribute. It will be of the format:
```text
projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider
```
Save this value as an environment variable:
```sh
export WORKLOAD_IDENTITY_PROVIDER_ID="..." # value from above
```
1. Allow authentications from the Workload Identity Provider to impersonate the
Service Account created above:
**Warning**: This grants access to any resource in the pool (all GitHub
repos). It's **strongly recommended** that you map to a specific attribute
such as the actor or repository name instead. See [mapping external
identities][map-external] for more information.
```sh
gcloud iam service-accounts add-iam-policy-binding "my-service-account@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_PROVIDER_ID}/*"
```
To map to a specific repository:
```sh
gcloud iam service-accounts add-iam-policy-binding "my-service-account@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_PROVIDER_ID}/attribute.repo/my-repo"
```
1. Use this GitHub Action with the Workload Identity Provider ID and Service
Account email. The GitHub Action will mint a GitHub OIDC token and exchange
the GitHub token for a Google Cloud access token (assuming the authorization
is correct). This all happens without exporting a Google Cloud service
account key JSON!
[wif]: https://cloud.google.com/iam/docs/workload-identity-federation
[gcloud]: https://cloud.google.com/sdk
[map-external]: https://cloud.google.com/iam/docs/access-resources-oidc#impersonate