Skip to content

Commit 5d5dceb

Browse files
chore: Cherry-picked changes from upstream (#54)
* Update troubleshooting docs for Python (#488) Closes google-github-actions/auth#487 * Update troubleshooting docs for Python (#488) Closes google-github-actions/auth#487 * Update troubleshooting docs for Python (#488) Closes google-github-actions/auth#487 * Add linters (#499) * Update deps (#500) * auto cherry pick updated test.yml updated package json updated auto-cherry-pick updated * chore: dist updated (#56) * Update auto_cherry_pick.yml Create claude_review.yml Update auto_cherry_pick.yml Update auto_cherry_pick.yml auto-cherry-pick updated * Update auto_cherry_pick.yml --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Raj Kumar Panda <[email protected]>
2 parents d2ca783 + 4f2c6b7 commit 5d5dceb

File tree

12 files changed

+169
-25
lines changed

12 files changed

+169
-25
lines changed

.github/workflows/auto_cherry_pick.yml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@ on:
77
description: "Base branch to create the PR against"
88
required: true
99
default: "main"
10-
schedule:
11-
- cron: "0 0 * * 1"
10+
mode:
11+
description: "Run mode: cherry-pick or verify"
12+
required: false
13+
default: "cherry-pick"
14+
15+
pull_request:
16+
types: [labeled, opened, synchronize]
1217

1318
permissions:
1419
contents: write
@@ -17,9 +22,11 @@ permissions:
1722
issues: write
1823

1924
jobs:
20-
audit-fix:
21-
uses: step-security/reusable-workflows/.github/workflows/auto_cherry_pick.yaml@upstream-Changes-CherryPick
25+
cherry-pick:
26+
if: github.event_name == 'workflow_dispatch' || contains(fromJson(toJson(github.event.pull_request.labels)).*.name, 'review-required')
27+
uses: step-security/reusable-workflows/.github/workflows/auto_cherry_pick.yaml@feature/verify-cherry-pick
2228
with:
2329
original-owner: "google-github-actions"
2430
repo-name: "auth"
25-
base_branch: ${{ inputs.base_branch || 'main' }}
31+
base_branch: ${{ inputs.base_branch || 'main' }}
32+
mode: ${{ github.event_name == 'pull_request' && 'verify' || inputs.mode }}

.github/workflows/claude_review.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Claude Code Review
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, labeled]
6+
7+
jobs:
8+
code-review:
9+
uses: step-security/reusable-workflows/.github/workflows/claude_review.yml@v1
10+
secrets:
11+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
12+
13+
permissions:
14+
contents: write
15+
pull-requests: write
16+
packages: read
17+
issues: write
18+
id-token: write

.github/workflows/test.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ concurrency:
2929
group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}'
3030
cancel-in-progress: true
3131

32+
permissions:
33+
contents: read
34+
3235
defaults:
3336
run:
3437
shell: 'bash'
3538

36-
permissions:
37-
contents: read
38-
3939
jobs:
4040
unit:
4141
name: 'unit'
@@ -51,7 +51,7 @@ jobs:
5151

5252
- uses: 'actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e' # v4.3.0
5353
with:
54-
node-version: '20.x'
54+
node-version-file: 'package.json'
5555

5656
- name: 'npm build'
5757
run: 'npm ci && npm run build'
@@ -91,7 +91,7 @@ jobs:
9191

9292
- uses: 'actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e' # v4.3.0
9393
with:
94-
node-version: '20.x'
94+
node-version-file: 'package.json'
9595

9696
- name: 'npm build'
9797
run: 'npm ci && npm run build'
@@ -136,7 +136,7 @@ jobs:
136136

137137
- uses: 'actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e' # v4.3.0
138138
with:
139-
node-version: '20.x'
139+
node-version-file: 'package.json'
140140

141141
- name: 'npm build'
142142
run: 'npm ci && npm run build'

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,6 @@ regardless of the authentication mechanism.
308308
"token_format" is "id_token".
309309
310310
311-
312311
<a id="setup"></a>
313312
## Setup
314313

bin/runTests.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ set -eEuo pipefail
1616
FILES="$(node -e "process.stdout.write(require('node:fs').readdirSync('./', { recursive: true }).filter((e) => {return e.endsWith('.test.ts') && !e.startsWith('node_modules');}).sort().join(' '));")"
1717

1818
set -x
19+
20+
# shellcheck disable=SC2086
1921
exec node --require ts-node/register --test-reporter spec --test ${FILES}

dist/main/index.js

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/post/index.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/EXAMPLES.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,69 @@ jobs:
187187
run: |-
188188
curl https://myapp-uvehjacqzq.a.run.app \
189189
--header "Authorization: Bearer ${{ steps.auth.outputs.id_token }}"
190+
191+
# Example of using ID token in Python code
192+
- id: 'python-example'
193+
run: |-
194+
python -c "
195+
import os
196+
import requests
197+
198+
# ID token is available as environment variable
199+
id_token = os.environ.get('GOOGLE_ID_TOKEN', '${{ steps.auth.outputs.id_token }}')
200+
201+
# Use the token to invoke a Cloud Run service
202+
response = requests.get(
203+
'https://myapp-uvehjacqzq.a.run.app',
204+
headers={'Authorization': f'Bearer {id_token}'}
205+
)
206+
print(response.text)
207+
"
208+
```
209+
210+
### Using Default Credentials with Scopes in Python
211+
212+
When using Workload Identity Federation with Python libraries, you may need to
213+
add scopes before refreshing credentials:
214+
215+
```yaml
216+
jobs:
217+
job_id:
218+
permissions:
219+
contents: 'read'
220+
id-token: 'write'
221+
222+
steps:
223+
- uses: 'actions/checkout@v4'
224+
225+
- id: 'auth'
226+
uses: 'google-github-actions/auth@v2'
227+
with:
228+
workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider'
229+
service_account: '[email protected]'
230+
231+
- id: 'python-auth'
232+
run: |-
233+
python -c "
234+
from google.auth import default
235+
from google.auth.transport.requests import Request
236+
237+
# Get default credentials
238+
credentials, project = default()
239+
240+
# Add scopes before refreshing for impersonation
241+
credentials = credentials.with_scopes(
242+
['https://www.googleapis.com/auth/cloud-platform']
243+
)
244+
245+
# Refresh to get the token
246+
credentials.refresh(request=Request())
247+
248+
# Now you can use the credentials
249+
print(f'Access token: {credentials.token}')
250+
if hasattr(credentials, 'id_token'):
251+
print(f'ID token: {credentials.id_token}')
252+
"
190253
```
191254

192255
[github-markdown-toc]: https://github.blog/changelog/2021-04-13-table-of-contents-support-in-markdown-files/

docs/TROUBLESHOOTING.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,53 @@ tool like `jq`:
230230
cat credentials.json | jq -r tostring
231231
```
232232

233+
<a name="cannot-refresh"></a>
234+
235+
## Cannot refresh credentials to retrieve an ID token
236+
237+
If you get an error like:
238+
239+
```text
240+
google.auth.exceptions.RefreshError: ('Unable to acquire impersonated credentials', '{"error": {"code": 400, "message": "Request contains an invalid argument.", "status": "INVALID_ARGUMENT"}}')
241+
```
242+
243+
when trying to refresh credentials in Python code to get an ID token, this is
244+
usually because the credentials are missing required scopes. The Google Auth
245+
library requires scopes to be set when refreshing credentials for impersonation.
246+
247+
To fix this issue, add the required scopes before refreshing:
248+
249+
```python
250+
from google.auth import default
251+
from google.auth.transport.requests import Request
252+
253+
credentials, project = default()
254+
255+
# Add scopes before refreshing
256+
credentials = credentials.with_scopes(
257+
["https://www.googleapis.com/auth/cloud-platform"]
258+
)
259+
credentials.refresh(request=Request())
260+
261+
# Now you can access the ID token
262+
print(credentials.id_token)
263+
```
264+
265+
Alternatively, you can use the `token_format` parameter of this action to
266+
generate an ID token directly:
267+
268+
```yaml
269+
- uses: 'google-github-actions/auth@v2'
270+
with:
271+
workload_identity_provider: ${{ secrets.WIF_PROVIDER }}
272+
service_account: ${{ secrets.WIF_SERVICE_ACCOUNT }}
273+
token_format: 'id_token'
274+
id_token_audience: 'https://example.com'
275+
```
276+
277+
This will export the ID token as an environment variable that you can use in
278+
your Python code.
279+
233280
## Organizational Policy Constraints
234281

235282
> **ℹ️ NOTE!** Your Google Cloud organization administrator controls these

package-lock.json

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)