Compare commits

..

No commits in common. "0920706a19e9d22c3d0da43d1db5939c6ad837a8" and "28d44ba25933bc5bc7f2d69931f8001632c46611" have entirely different histories.

15 changed files with 446 additions and 536 deletions

View File

@ -1,3 +1,17 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: 'Draft release'
on:
@ -13,14 +27,12 @@ on:
- 'minor'
- 'patch'
permissions:
contents: 'read'
pull-requests: 'write'
jobs:
draft-release:
uses: 'google-github-actions/.github/.github/workflows/draft-release.yml@v3' # ratchet:exclude
name: 'Draft release'
uses: 'google-github-actions/.github/.github/workflows/draft-release.yml@v0'
with:
version_strategy: '${{ github.event.inputs.version_strategy }}'
# secrets must be explicitly passed to reusable workflows https://docs.github.com/en/enterprise-cloud@latest/actions/using-workflows/reusing-workflows#using-inputs-and-secrets-in-a-reusable-workflow
secrets:
ACTIONS_BOT_TOKEN: '${{ secrets.ACTIONS_BOT_TOKEN }}'

View File

@ -16,10 +16,10 @@ jobs:
steps:
- name: 'Checkout'
uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4
uses: 'actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871' # ratchet:actions/checkout@v4
- name: 'Publish'
id: 'publish'
uses: 'actions/publish-immutable-action@4bc8754ffc40f27910afb20287dbbbb675a4e978' # ratchet:actions/publish-immutable-action@v0.0.4
uses: 'actions/publish-immutable-action@4b1aa5c1cde5fedc80d52746c9546cb5560e5f53' # ratchet:actions/publish-immutable-action@v0.0.3
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'

View File

@ -1,3 +1,17 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: 'Release'
on:
@ -6,12 +20,12 @@ on:
- 'main'
- 'release/**/*'
permissions:
contents: 'read'
packages: 'write'
jobs:
release:
uses: 'google-github-actions/.github/.github/workflows/release.yml@v3' # ratchet:exclude
if: |-
${{ startsWith(github.event.head_commit.message, 'Release: v') }}
name: 'Release'
uses: 'google-github-actions/.github/.github/workflows/release.yml@v1' # ratchet:exclude
# secrets must be explicitly passed to reusable workflows https://docs.github.com/en/enterprise-cloud@latest/actions/using-workflows/reusing-workflows\#using-inputs-and-secrets-in-a-reusable-workflow
secrets:
ACTIONS_BOT_TOKEN: '${{ secrets.ACTIONS_BOT_TOKEN }}'

View File

@ -33,19 +33,15 @@ defaults:
run:
shell: 'bash'
permissions:
contents: 'read'
statuses: 'write'
jobs:
unit:
name: 'unit'
runs-on: 'ubuntu-latest'
steps:
- uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4
- uses: 'actions/checkout@v4'
- uses: 'actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a' # ratchet:actions/setup-node@v4
- uses: 'actions/setup-node@v4'
with:
node-version: '20.x'
@ -78,9 +74,9 @@ jobs:
id-token: 'write'
steps:
- uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4
- uses: 'actions/checkout@v4'
- uses: 'actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a' # ratchet:actions/setup-node@v4
- uses: 'actions/setup-node@v4'
with:
node-version: '20.x'
@ -103,7 +99,7 @@ jobs:
--fail \
--header "Authorization: Bearer ${{ steps.auth-default.outputs.auth_token }}"
- uses: 'google-github-actions/setup-gcloud@main' # ratchet:exclude
- uses: 'google-github-actions/setup-gcloud@v2'
with:
version: '>= 363.0.0'
@ -131,9 +127,9 @@ jobs:
id-token: 'write'
steps:
- uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4
- uses: 'actions/checkout@v4'
- uses: 'actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a' # ratchet:actions/setup-node@v4
- uses: 'actions/setup-node@v4'
with:
node-version: '20.x'
@ -147,7 +143,7 @@ jobs:
workload_identity_provider: '${{ vars.WIF_PROVIDER_NAME }}'
service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}'
- uses: 'google-github-actions/setup-gcloud@main' # ratchet:exclude
- uses: 'google-github-actions/setup-gcloud@v2'
with:
version: '>= 363.0.0'
@ -199,9 +195,9 @@ jobs:
- 'macos-latest'
steps:
- uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4
- uses: 'actions/checkout@v4'
- uses: 'actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a' # ratchet:actions/setup-node@v4
- uses: 'actions/setup-node@v4'
with:
node-version: '20.x'
@ -214,7 +210,7 @@ jobs:
with:
credentials_json: '${{ secrets.SERVICE_ACCOUNT_KEY_JSON }}'
- uses: 'google-github-actions/setup-gcloud@main' # ratchet:exclude
- uses: 'google-github-actions/setup-gcloud@v2'
with:
version: '>= 363.0.0'
@ -260,9 +256,9 @@ jobs:
strategy:
fail-fast: false
steps:
- uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4
- uses: 'actions/checkout@v4'
- uses: 'actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a' # ratchet:actions/setup-node@v4
- uses: 'actions/setup-node@v4'
with:
node-version: '20.x'
@ -275,7 +271,7 @@ jobs:
credentials_json: '${{ secrets.SERVICE_ACCOUNT_KEY_JSON }}'
- name: 'docker'
uses: 'docker://index.docker.io/library/alpine@sha256:56fa17d2a7e7f168a043a2712e63aed1f8543aeafdcee47c58dcffe38ed51099' # ratchet:docker://alpine:3
uses: 'docker://alpine:3'
with:
entrypoint: '/bin/sh'
args: '-euc "test -n "${GOOGLE_APPLICATION_CREDENTIALS}" && test -r "${GOOGLE_APPLICATION_CREDENTIALS}"'

View File

@ -27,7 +27,7 @@ jobs:
runs-on: 'ubuntu-latest'
steps:
- uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' # ratchet:actions/github-script@v7
- uses: 'actions/github-script@v7'
with:
script: |-
const msg =

View File

@ -84,12 +84,6 @@ For more usage options, see the [examples](docs/EXAMPLES.md).
> SDK](https://github.com/firebase/firebase-admin-node/issues/1377). Use Service
> Account Key JSON authentication instead.
> [!WARNING]
>
> As of the time of this writing, the GitHub OIDC token expires in 5 minutes,
> which means any derived credentials also expire in 5 minutes.
The following inputs are for _authenticating_ to Google Cloud via Workload
Identity Federation.
@ -322,6 +316,7 @@ regardless of the authentication mechanism.
"token_format" is "id_token".
<a id="setup"></a>
## Setup

View File

@ -56,7 +56,7 @@ inputs:
description: |-
If true, the action will securely generate a credentials file which can be
used for authentication via gcloud and Google Cloud SDKs.
default: 'true'
default: true
required: false
export_environment_variables:
description: |-
@ -79,7 +79,7 @@ inputs:
If false, the action will not export any environment variables, meaning
future steps are unlikely to be automatically authenticated to Google
Cloud.
default: 'true'
default: true
required: false
token_format:
description: |-
@ -113,7 +113,7 @@ inputs:
If true, the action will remove any created credentials from the
filesystem upon completion. This only applies if "create_credentials_file"
is true.
default: 'true'
default: true
required: false
# access token params
@ -175,7 +175,7 @@ inputs:
generated token. If true, the token will contain "email" and
"email_verified" claims. This is only valid when "token_format" is
"id_token".
default: 'false'
default: false
required: false
outputs:

6
dist/main/index.js vendored

File diff suppressed because one or more lines are too long

6
dist/post/index.js vendored

File diff suppressed because one or more lines are too long

View File

@ -187,69 +187,6 @@ jobs:
run: |-
curl https://myapp-uvehjacqzq.a.run.app \
--header "Authorization: Bearer ${{ steps.auth.outputs.id_token }}"
# Example of using ID token in Python code
- id: 'python-example'
run: |-
python -c "
import os
import requests
# ID token is available as environment variable
id_token = os.environ.get('GOOGLE_ID_TOKEN', '${{ steps.auth.outputs.id_token }}')
# Use the token to invoke a Cloud Run service
response = requests.get(
'https://myapp-uvehjacqzq.a.run.app',
headers={'Authorization': f'Bearer {id_token}'}
)
print(response.text)
"
```
### Using Default Credentials with Scopes in Python
When using Workload Identity Federation with Python libraries, you may need to
add scopes before refreshing credentials:
```yaml
jobs:
job_id:
permissions:
contents: 'read'
id-token: 'write'
steps:
- uses: 'actions/checkout@v4'
- id: 'auth'
uses: 'google-github-actions/auth@v2'
with:
workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider'
service_account: 'my-service-account@my-project.iam.gserviceaccount.com'
- id: 'python-auth'
run: |-
python -c "
from google.auth import default
from google.auth.transport.requests import Request
# Get default credentials
credentials, project = default()
# Add scopes before refreshing for impersonation
credentials = credentials.with_scopes(
['https://www.googleapis.com/auth/cloud-platform']
)
# Refresh to get the token
credentials.refresh(request=Request())
# Now you can use the credentials
print(f'Access token: {credentials.token}')
if hasattr(credentials, 'id_token'):
print(f'ID token: {credentials.id_token}')
"
```
[github-markdown-toc]: https://github.blog/changelog/2021-04-13-table-of-contents-support-in-markdown-files/

View File

@ -230,53 +230,6 @@ tool like `jq`:
cat credentials.json | jq -r tostring
```
<a name="cannot-refresh"></a>
## Cannot refresh credentials to retrieve an ID token
If you get an error like:
```text
google.auth.exceptions.RefreshError: ('Unable to acquire impersonated credentials', '{"error": {"code": 400, "message": "Request contains an invalid argument.", "status": "INVALID_ARGUMENT"}}')
```
when trying to refresh credentials in Python code to get an ID token, this is
usually because the credentials are missing required scopes. The Google Auth
library requires scopes to be set when refreshing credentials for impersonation.
To fix this issue, add the required scopes before refreshing:
```python
from google.auth import default
from google.auth.transport.requests import Request
credentials, project = default()
# Add scopes before refreshing
credentials = credentials.with_scopes(
["https://www.googleapis.com/auth/cloud-platform"]
)
credentials.refresh(request=Request())
# Now you can access the ID token
print(credentials.id_token)
```
Alternatively, you can use the `token_format` parameter of this action to
generate an ID token directly:
```yaml
- uses: 'google-github-actions/auth@v2'
with:
workload_identity_provider: ${{ secrets.WIF_PROVIDER }}
service_account: ${{ secrets.WIF_SERVICE_ACCOUNT }}
token_format: 'id_token'
id_token_audience: 'https://example.com'
```
This will export the ID token as an environment variable that you can use in
your Python code.
## Organizational Policy Constraints
> ** NOTE!** Your Google Cloud organization administrator controls these

715
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "@google-github-actions/auth",
"version": "2.1.10",
"version": "2.1.7",
"description": "Authenticate to Google Cloud using OIDC tokens or JSON service account keys.",
"main": "dist/main/index.js",
"scripts": {
@ -23,22 +23,22 @@
"author": "GoogleCloudPlatform",
"license": "Apache-2.0",
"dependencies": {
"@actions/core": "^1.11.1",
"@actions/http-client": "^2.2.3",
"@google-github-actions/actions-utils": "^0.8.6"
"@actions/core": "^1.10.1",
"@actions/http-client": "^2.2.2",
"@google-github-actions/actions-utils": "^0.8.3"
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.25.1",
"@types/node": "^22.14.1",
"@vercel/ncc": "^0.38.3",
"eslint-config-prettier": "^10.1.2",
"eslint-plugin-prettier": "^5.2.6",
"eslint": "^9.25.1",
"prettier": "^3.5.3",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.9.0",
"@types/node": "^22.4.1",
"@vercel/ncc": "^0.38.1",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint": "^9.9.0",
"prettier": "^3.3.3",
"ts-node": "^10.9.2",
"typescript-eslint": "^8.31.0",
"@typescript-eslint/eslint-plugin": "^8.31.0",
"typescript": "^5.8.3"
"typescript-eslint": "^8.2.0",
"@typescript-eslint/eslint-plugin": "^8.2.0",
"typescript": "^5.5.4"
}
}

View File

@ -16,6 +16,7 @@ import { join as pathjoin } from 'path';
import {
exportVariable,
getBooleanInput,
getIDToken,
getInput,
setFailed,
@ -28,7 +29,6 @@ import {
isEmptyDir,
isPinnedToHead,
parseMultilineCSV,
parseBoolean,
parseDuration,
pinnedToHeadWarning,
} from '@google-github-actions/actions-utils';
@ -79,8 +79,8 @@ export async function run(logger: Logger) {
const oidcTokenAudience =
getInput(`audience`) || `https://iam.googleapis.com/${workloadIdentityProvider}`;
const credentialsJSON = getInput(`credentials_json`);
const createCredentialsFile = parseBoolean(getInput(`create_credentials_file`));
const exportEnvironmentVariables = parseBoolean(getInput(`export_environment_variables`));
const createCredentialsFile = getBooleanInput(`create_credentials_file`);
const exportEnvironmentVariables = getBooleanInput(`export_environment_variables`);
const tokenFormat = getInput(`token_format`);
const delegates = parseMultilineCSV(getInput(`delegates`));
const universe = getInput(`universe`);
@ -301,7 +301,7 @@ export async function run(logger: Logger) {
logger.debug(`Creating id token`);
const idTokenAudience = getInput('id_token_audience', { required: true });
const idTokenIncludeEmail = parseBoolean(getInput('id_token_include_email'));
const idTokenIncludeEmail = getBooleanInput('id_token_include_email');
// Ensure a service_account was provided if using WIF.
if (!serviceAccount) {

View File

@ -12,21 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { getInput, setFailed } from '@actions/core';
import { getBooleanInput, setFailed } from '@actions/core';
import { errorMessage, forceRemove, parseBoolean } from '@google-github-actions/actions-utils';
import { errorMessage, forceRemove } from '@google-github-actions/actions-utils';
import { Logger } from './logger';
export async function run(logger: Logger) {
try {
const createCredentials = parseBoolean(getInput('create_credentials_file'));
const createCredentials = getBooleanInput('create_credentials_file');
if (!createCredentials) {
logger.info(`Skipping credential cleanup - "create_credentials_file" is false.`);
return;
}
const cleanupCredentials = parseBoolean(getInput('cleanup_credentials'));
const cleanupCredentials = getBooleanInput('cleanup_credentials');
if (!cleanupCredentials) {
logger.info(`Skipping credential cleanup - "cleanup_credentials" is false.`);
return;