Skip to content

Conversation

@vverman
Copy link

@vverman vverman commented Nov 14, 2025

Adding documentation for Custom Credential Suppliers.

Custom Credential Suppliers enable developers to securely integrate third-party authentication directly into the Google Cloud SDKs. Custom Credential Suppliers are primarily used to handle authentication in non-standard cloud environments.

The design and scopes for this are documented under this design doc

Checklist

These tests will safely skip if the env variables aren't provided.

  1. For the aws custom credential supplier, we need: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, GCP_WORKLOAD_AUDIENCE, GCS_BUCKET_NAME. Please refer to the readme under auth/custom-credentials/aws/README.md
  2. For the okta custom credential supplier, we need: OKTA_DOMAIN, OKTA_CLIENT_ID, OKTA_CLIENT_SECRET, GCP_WORKLOAD_AUDIENCE, GCS_BUCKET_NAME. Please refer to the readme under auth/custom-credentials/okta/README.md

@vverman vverman requested review from a team as code owners November 14, 2025 02:11
@product-auto-label product-auto-label bot added samples Issues that are directly related to samples. api: auth Issues related to the Google Authentication API labels Nov 14, 2025
@snippet-bot
Copy link

snippet-bot bot commented Nov 14, 2025

Here is the summary of changes.

You are about to add 2 region tags.

This comment is generated by snippet-bot.
If you find problems with this result, please file an issue at:
https://github.com/googleapis/repo-automation-bots/issues.
To update this comment, add snippet-bot:force-run label or use the checkbox below:

  • Refresh this comment

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @vverman, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the authentication samples by adding support for Custom Credential Suppliers in Python. It provides practical examples and comprehensive documentation for integrating external identity providers like AWS and Okta with Google Cloud, facilitating secure access in hybrid or multi-cloud environments. The changes aim to make it easier for developers to leverage Workload Identity Federation with non-standard authentication sources.

Highlights

  • New Custom Credential Supplier Samples: Introduced new Python samples demonstrating how to use custom credential suppliers for both AWS and Okta authentication with Google Cloud SDKs.
  • AWS Integration: Added a sample that uses Boto3 as a custom supplier to bridge AWS credentials (e.g., from EKS IRSA) to Google Cloud Workload Identity, complete with local and containerized (EKS) running instructions.
  • Okta Integration: Included a sample demonstrating how to use Okta's Client Credentials grant flow as a custom subject token supplier for Workload Identity Federation with GCP.
  • Comprehensive Documentation: Each new sample comes with detailed READMEs covering setup, environment variables, and configuration steps for both the third-party identity provider (AWS/Okta) and Google Cloud.
  • Testing Infrastructure: Accompanying unit and system tests, along with Nox configurations, have been added for both AWS and Okta custom credential supplier samples to ensure functionality and reliability.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces new samples for using custom credential suppliers with the Google Cloud Python SDK, specifically for AWS and Okta. The code is well-structured and includes good documentation and tests. My review includes suggestions to improve error handling by using more specific exceptions and directing error messages to stderr, which is a standard practice. I've also pointed out a few minor issues like missing newlines at the end of files and an opportunity to make the Okta supplier more flexible by not hardcoding the OAuth scope. These changes will enhance the robustness and reusability of the samples.


```bash
eksctl delete cluster --name your-cluster-name
``` No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It's a good practice for text files, including Markdown files, to end with a newline character. This can prevent issues with some tools and file concatenations.

Comment on lines +15 to +21
import json
import os

import boto3
from google.auth import aws
from google.auth import exceptions
from google.auth.transport import requests as auth_requests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To support writing to standard error, the sys module should be imported. It's also a good practice to group standard library imports together, followed by third-party imports, as per PEP 8.

Suggested change
import json
import os
import boto3
from google.auth import aws
from google.auth import exceptions
from google.auth.transport import requests as auth_requests
import json
import os
import sys
import boto3
from google.auth import aws
from google.auth import exceptions
from google.auth.transport import requests as auth_requests

Comment on lines +107 to +121
if not all([gcp_audience, gcs_bucket_name]):
print(
"Required environment variables missing: GCP_WORKLOAD_AUDIENCE, GCS_BUCKET_NAME"
)
return

try:
print(f"Retrieving metadata for bucket: {gcs_bucket_name}...")
metadata = authenticate_with_aws_credentials(
gcs_bucket_name, gcp_audience, sa_impersonation_url
)
print("--- SUCCESS! ---")
print(json.dumps(metadata, indent=2))
except Exception as e:
print(f"Authentication or Request failed: {e}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There are a couple of improvements we can make here:

  1. Error messages should be printed to standard error (sys.stderr) instead of standard output. This is a standard practice for separating normal output from error diagnostics.
  2. Catching a generic Exception is too broad and can hide bugs by catching unexpected errors (like KeyboardInterrupt). It's better to catch more specific exceptions that are expected from the authentication and request process, such as google.auth.exceptions.GoogleAuthError and requests.exceptions.HTTPError.
Suggested change
if not all([gcp_audience, gcs_bucket_name]):
print(
"Required environment variables missing: GCP_WORKLOAD_AUDIENCE, GCS_BUCKET_NAME"
)
return
try:
print(f"Retrieving metadata for bucket: {gcs_bucket_name}...")
metadata = authenticate_with_aws_credentials(
gcs_bucket_name, gcp_audience, sa_impersonation_url
)
print("--- SUCCESS! ---")
print(json.dumps(metadata, indent=2))
except Exception as e:
print(f"Authentication or Request failed: {e}")
if not all([gcp_audience, gcs_bucket_name]):
print(
"Required environment variables missing: GCP_WORKLOAD_AUDIENCE, GCS_BUCKET_NAME",
file=sys.stderr,
)
return
try:
print(f"Retrieving metadata for bucket: {gcs_bucket_name}...")
metadata = authenticate_with_aws_credentials(
gcs_bucket_name, gcp_audience, sa_impersonation_url
)
print("--- SUCCESS! ---")
print(json.dumps(metadata, indent=2))
except (exceptions.GoogleAuthError, auth_requests.requests.exceptions.HTTPError) as e:
print(f"Authentication or Request failed: {e}", file=sys.stderr)

@@ -0,0 +1,84 @@
Here is the adapted `README.md` for the Python version of the Okta Custom Credential Supplier sample.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This line appears to be a leftover comment from document generation and should be removed to improve the clarity of the README.

python3 snippets.py
```

The script will then authenticate with Okta to get an OIDC token, exchange that token for a GCP federated token (and optionally a Service Account token), and use it to list metadata for the specified GCS bucket. No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It's a good practice for text files, including Markdown files, to end with a newline character. This can prevent issues with some tools and file concatenations.

Suggested change
The script will then authenticate with Okta to get an OIDC token, exchange that token for a GCP federated token (and optionally a Service Account token), and use it to list metadata for the specified GCS bucket.
The script will then authenticate with Okta to get an OIDC token, exchange that token for a GCP federated token (and optionally a Service Account token), and use it to list metadata for the specified GCS bucket.

@@ -0,0 +1,3 @@
requests==2.32.3
google-auth==2.43.0
python-dotenv==1.1.1 No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It's a good practice for text files, including requirements.txt, to end with a newline character. This can prevent issues with some tools and file concatenations.

python-dotenv==1.1.1

Comment on lines +15 to +22
import json
import os
import time
import urllib.parse

from google.auth import identity_pool
from google.auth.transport import requests as auth_requests
import requests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To support writing to standard error and for more specific exception handling, the sys and google.auth.exceptions modules should be imported. It's also a good practice to group standard library imports together, followed by third-party imports, as per PEP 8.

Suggested change
import json
import os
import time
import urllib.parse
from google.auth import identity_pool
from google.auth.transport import requests as auth_requests
import requests
import json
import os
import sys
import time
import urllib.parse
from google.auth import exceptions, identity_pool
from google.auth.transport import requests as auth_requests
import requests

}
data = {
"grant_type": "client_credentials",
"scope": "gcp.test.read", # Set scope as per Okta app config.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Okta scope is hardcoded here. For better reusability, consider passing the scope(s) as an argument to the OktaClientCredentialsSupplier constructor. This would allow users of the class to specify the required scopes for their particular Okta application configuration without modifying the class source code.

Comment on lines +117 to +136
if not all(
[gcp_audience, gcs_bucket_name, okta_domain, okta_client_id, okta_client_secret]
):
print("Missing required environment variables.")
return

try:
print(f"Retrieving metadata for bucket: {gcs_bucket_name}...")
metadata = authenticate_with_okta_credentials(
bucket_name=gcs_bucket_name,
audience=gcp_audience,
domain=okta_domain,
client_id=okta_client_id,
client_secret=okta_client_secret,
impersonation_url=sa_impersonation_url,
)
print("--- SUCCESS! ---")
print(json.dumps(metadata, indent=2))
except Exception as e:
print(f"Authentication or Request failed: {e}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There are a couple of improvements we can make here:

  1. Error messages should be printed to standard error (sys.stderr) instead of standard output. This is a standard practice for separating normal output from error diagnostics.
  2. Catching a generic Exception is too broad and can hide bugs by catching unexpected errors (like KeyboardInterrupt). It's better to catch more specific exceptions that are expected from the authentication and request process, such as google.auth.exceptions.GoogleAuthError and requests.exceptions.HTTPError.
Suggested change
if not all(
[gcp_audience, gcs_bucket_name, okta_domain, okta_client_id, okta_client_secret]
):
print("Missing required environment variables.")
return
try:
print(f"Retrieving metadata for bucket: {gcs_bucket_name}...")
metadata = authenticate_with_okta_credentials(
bucket_name=gcs_bucket_name,
audience=gcp_audience,
domain=okta_domain,
client_id=okta_client_id,
client_secret=okta_client_secret,
impersonation_url=sa_impersonation_url,
)
print("--- SUCCESS! ---")
print(json.dumps(metadata, indent=2))
except Exception as e:
print(f"Authentication or Request failed: {e}")
if not all(
[gcp_audience, gcs_bucket_name, okta_domain, okta_client_id, okta_client_secret]
):
print("Missing required environment variables.", file=sys.stderr)
return
try:
print(f"Retrieving metadata for bucket: {gcs_bucket_name}...")
metadata = authenticate_with_okta_credentials(
bucket_name=gcs_bucket_name,
audience=gcp_audience,
domain=okta_domain,
client_id=okta_client_id,
client_secret=okta_client_secret,
impersonation_url=sa_impersonation_url,
)
print("--- SUCCESS! ---")
print(json.dumps(metadata, indent=2))
except (exceptions.GoogleAuthError, requests.exceptions.HTTPError) as e:
print(f"Authentication or Request failed: {e}", file=sys.stderr)

@vverman vverman changed the title Included changes for python script for custom credential suppliers. feat: Custom Credential Supplier Documentation Nov 15, 2025
@glasnt glasnt added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Nov 16, 2025
@kokoro-team kokoro-team removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Nov 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: auth Issues related to the Google Authentication API samples Issues that are directly related to samples.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants