From f38d54f0d75ec3e1b27429833f635cb308c71cd4 Mon Sep 17 00:00:00 2001 From: Bharath KKB Date: Thu, 2 Dec 2021 11:38:22 -0600 Subject: [PATCH] feat: Support WIF creds (#413) * update sdk pkg * add auth * docs * address comments --- .github/workflows/setup-gcloud-it.yml | 78 +++++++++++++++++++++++++++ README.md | 64 +++++++++++++++++++--- package-lock.json | 17 +++--- package.json | 2 +- src/setup-gcloud.ts | 18 +++++-- 5 files changed, 156 insertions(+), 23 deletions(-) diff --git a/.github/workflows/setup-gcloud-it.yml b/.github/workflows/setup-gcloud-it.yml index 8679c6100..029e3c49c 100644 --- a/.github/workflows/setup-gcloud-it.yml +++ b/.github/workflows/setup-gcloud-it.yml @@ -177,3 +177,81 @@ jobs: with: entrypoint: '/bin/sh' args: '-euc "test -n "${GOOGLE_APPLICATION_CREDENTIALS}" && test -r "${GOOGLE_APPLICATION_CREDENTIALS}"' + + wif: + if: ${{ github.event_name == 'push' || github.repository == github.event.pull_request.head.repo.full_name && github.actor != 'dependabot[bot]' }} + name: 'with wif' + runs-on: '${{ matrix.os }}' + strategy: + fail-fast: false + matrix: + os: + - 'ubuntu-latest' + - 'windows-latest' + - 'macos-latest' + + permissions: + id-token: 'write' + + steps: + - uses: actions/checkout@v2 + + - uses: 'actions/setup-node@v2' + with: + node-version: '12.x' + + - id: build + name: Build dist + run: |- + npm ci + npm run build + + - uses: google-github-actions/auth@main + with: + workload_identity_provider: ${{ secrets.WIF_PROVIDER_NAME }} + service_account: ${{ secrets.OIDC_AUTH_SA_EMAIL }} + + - name: 'setup-gcloud' + uses: './' + + - id: 'gcloud' + shell: 'bash' + run: |- + gcloud secrets versions access "latest" --secret "${{ secrets.OIDC_AUTH_TEST_SECRET_NAME }}" + + credentials_json: + if: ${{ github.event_name == 'push' || github.repository == github.event.pull_request.head.repo.full_name && github.actor != 'dependabot[bot]' }} + name: 'with key and auth action' + runs-on: '${{ matrix.os }}' + strategy: + fail-fast: false + matrix: + os: + - 'ubuntu-latest' + - 'windows-latest' + - 'macos-latest' + + steps: + - uses: actions/checkout@v2 + + - uses: 'actions/setup-node@v2' + with: + node-version: '12.x' + + - id: build + name: Build dist + run: |- + npm ci + npm run build + + - uses: google-github-actions/auth@main + with: + credentials_json: ${{ secrets.SETUP_GCLOUD_IT_KEY }} + + - name: 'setup-gcloud' + uses: './' + + - id: 'gcloud' + shell: 'bash' + run: |- + gcloud secrets versions access "latest" --secret "${{ secrets.OIDC_AUTH_TEST_SECRET_NAME }}" diff --git a/README.md b/README.md index 79a231890..b2a490b77 100644 --- a/README.md +++ b/README.md @@ -57,12 +57,14 @@ steps: ## Usage ```yaml -- name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@master +- id: auth + uses: google-github-actions/auth@v0.4.1 with: - project_id: ${{ secrets.GCP_PROJECT_ID }} - service_account_key: ${{ secrets.GCP_SA_KEY }} - export_default_credentials: true + workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider' + service_account: 'my-service-account@my-project.iam.gserviceaccount.com' + +- name: Set up Cloud SDK + uses: google-github-actions/setup-gcloud@v0.2.1 - name: Use gcloud CLI run: gcloud info @@ -74,11 +76,11 @@ steps: | ------------- | ----------- | ------- | ----------- | | `version` | _optional_ | `latest`| The version of the `gcloud` to be installed. Example: `290.0.1`| | `project_id` | _optional_ | | ID of the Google Cloud Platform project. If provided, this will configure `gcloud` to use this project ID by default for commands. Individual commands can still override the project using the `--project` flag which takes precedence. | -| `service_account_key` | _optional_ | | The service account key which will be used for authentication credentials. This key should be [created](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) and stored as a [secret](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets). It can be encoded as a [Base64](https://en.wikipedia.org/wiki/Base64) string or as JSON. | | `service_account_email` | _optional_ | | Service account email address to use for authentication. This is required for legacy .p12 keys but can be omitted for JSON keys. This is usually of the format `@.iam.gserviceaccount.com`. | | `export_default_credentials`| _optional_ |`false`| Exports the path to [Default Application Credentials][dac] as the environment variable `GOOGLE_APPLICATION_CREDENTIALS` to be available in later steps. Google Cloud services automatically use this environment variable to find credentials. | | `credentials_file_path` | _optional_ | (temporary file) | Only valid when `export_default_credentials` is `true`. Sets the path at which the credentials should be written. | | `cleanup_credentials` | _optional_ | `true` | If true, the action will remove any generated credentials from the filesystem upon completion. | +| `service_account_key` | _optional_ | | (**Deprecated**) This input is deprecated. See [auth section](https://github.com/google-github-actions/setup-gcloud#authorization) for more details. The service account key which will be used for authentication credentials. This key should be [created](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) and stored as a [secret](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets). It can be encoded as a [Base64](https://en.wikipedia.org/wiki/Base64) string or as JSON. | ## Example Workflows @@ -95,9 +97,53 @@ code to [App Engine](https://cloud.google.com/appengine), a fully managed server * [Cloud Build](./example-workflows/cloud-build/README.md): An example workflow that uses GitHub Actions to build a container image with [Cloud Build](https://cloud.google.com/cloud-build). -## Sharing Credentials +## Authorization + +This action installs the Cloud SDK (`gcloud`). To configure its authentication to Google Cloud, use the [google-github-actions/auth](https://github.com/google-github-actions/auth) action. You can authenticate via: + +### Workload Identity Federation (preferred) + +```yaml +- id: auth + uses: google-github-actions/auth@v0.4.0 + with: + workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider' + service_account: 'my-service-account@my-project.iam.gserviceaccount.com' + +- name: Set up Cloud SDK + uses: google-github-actions/setup-gcloud@v0.2.1 + +- name: Use gcloud CLI + run: gcloud info +``` + +### Service Account Key JSON + +```yaml +- id: auth + uses: google-github-actions/auth@v0.4.0 + with: + credentials_json: ${{ secrets.gcp_credentials }} + +- name: Set up Cloud SDK + uses: google-github-actions/setup-gcloud@v0.2.1 + +- name: Use gcloud CLI + run: gcloud info +``` -If `export_default_credentials` is true, this GitHub Action will automatically export the credentials to be available in future steps in the job. By default, the credentials are exported into `$GITHUB_WORKSPACE` which is available to all steps in the job. The file is automatically deleted when jobs finish, regardless of their status. +### Application Default Credentials + +If and only if you are using self-hosted runners that are hosted on Google Cloud Platform, +the Cloud SDK will automatically authenticate using the machine credentials: + +```yaml +- name: Set up Cloud SDK + uses: google-github-actions/setup-gcloud@v0.2.1 + +- name: Use gcloud CLI + run: gcloud info +``` ## Contributing @@ -115,3 +161,5 @@ See [LICENSE](LICENSE). [gcloud]: https://cloud.google.com/sdk/gcloud/ [gsutil]: https://cloud.google.com/storage/docs/gsutil [sa-iam-docs]: https://cloud.google.com/iam/docs/service-accounts +[sa]: https://cloud.google.com/iam/docs/creating-managing-service-accounts +[wif]: https://cloud.google.com/iam/docs/workload-identity-federation diff --git a/package-lock.json b/package-lock.json index 426a00aa8..6e81791d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,13 +5,12 @@ "requires": true, "packages": { "": { - "name": "setup-gcloud", "version": "0.2.1", "license": "Apache-2.0", "dependencies": { "@actions/core": "^1.6.0", "@actions/tool-cache": "^1.7.1", - "@google-github-actions/setup-cloud-sdk": "^0.2.0" + "@google-github-actions/setup-cloud-sdk": "^0.3.0" }, "devDependencies": { "@types/chai": "^4.2.21", @@ -26,7 +25,7 @@ "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", "mocha": "^9.1.3", - "prettier": "^2.4.1", + "prettier": "^2.5.0", "sinon": "^12.0.1", "ts-node": "^10.4.0", "typescript": "^4.5.2" @@ -125,9 +124,9 @@ } }, "node_modules/@google-github-actions/setup-cloud-sdk": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@google-github-actions/setup-cloud-sdk/-/setup-cloud-sdk-0.2.0.tgz", - "integrity": "sha512-GkwU8D+3S42M6MNtEMaQUIphdn32rRjmjbkrqbUqtMw2Up9N0XjZ8l1QtFt5OHk/kuftC94rnDhnsyA/YLT2ow==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@google-github-actions/setup-cloud-sdk/-/setup-cloud-sdk-0.3.0.tgz", + "integrity": "sha512-yTsoPt17ogJL5FGzsYXePOg2o2k0ST+FKr8e8zFJsas5IkAbaAxQ/zp9RaXeCN0XshLAEGzRkS9747iQFK+/jQ==", "dependencies": { "@actions/core": "^1.6.0", "@actions/exec": "^1.1.0", @@ -2788,9 +2787,9 @@ } }, "@google-github-actions/setup-cloud-sdk": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@google-github-actions/setup-cloud-sdk/-/setup-cloud-sdk-0.2.0.tgz", - "integrity": "sha512-GkwU8D+3S42M6MNtEMaQUIphdn32rRjmjbkrqbUqtMw2Up9N0XjZ8l1QtFt5OHk/kuftC94rnDhnsyA/YLT2ow==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@google-github-actions/setup-cloud-sdk/-/setup-cloud-sdk-0.3.0.tgz", + "integrity": "sha512-yTsoPt17ogJL5FGzsYXePOg2o2k0ST+FKr8e8zFJsas5IkAbaAxQ/zp9RaXeCN0XshLAEGzRkS9747iQFK+/jQ==", "requires": { "@actions/core": "^1.6.0", "@actions/exec": "^1.1.0", diff --git a/package.json b/package.json index 77ee3abe9..9635c0a73 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "dependencies": { "@actions/core": "^1.6.0", "@actions/tool-cache": "^1.7.1", - "@google-github-actions/setup-cloud-sdk": "^0.2.0" + "@google-github-actions/setup-cloud-sdk": "^0.3.0" }, "devDependencies": { "@types/chai": "^4.2.21", diff --git a/src/setup-gcloud.ts b/src/setup-gcloud.ts index 3b648bce4..09cb38b91 100644 --- a/src/setup-gcloud.ts +++ b/src/setup-gcloud.ts @@ -55,12 +55,20 @@ export async function run(): Promise { } const serviceAccountKey = core.getInput('service_account_key'); - // If a service account key isn't provided, log an un-authenticated notice - if (!serviceAccountKey) { - core.info('No credentials provided, skipping authentication'); - return; - } else { + // If a service account key is provided, add warning to use google-github-actions/auth + if (serviceAccountKey) { + core.warning( + '"service_account_key" has been deprecated. ' + + 'Please switch to using google-github-actions/auth which supports both Workload Identity Federation and Service Account Key JSON authentication. ' + + 'For more details, see https://github.com/google-github-actions/setup-gcloud#authorization', + ); + } + + // Either serviceAccountKey or GOOGLE_GHA_CREDS_PATH env var required + if (serviceAccountKey || process.env.GOOGLE_GHA_CREDS_PATH) { await authenticateGcloudSDK(serviceAccountKey); + } else { + core.info('No credentials detected, skipping authentication'); } // Export credentials if requested - these credentials are exported in the