Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Improve AWS supplier samples #1586

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions docs/user-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -552,36 +552,45 @@ whether the credential retrieval is retryable.
Any call to the supplier from the Identity Pool credential will send a :class:`google.auth.external_account.SupplierContext`
object, which contains the requested audience and subject type. Additionally, the credential will
send the :class:`google.auth.transport.requests.Request` passed in the credential refresh call which
can be used to make HTTP requests.::
can be used to make HTTP requests. Using a custom supplier allows workload or workforce identity federation to be used
aeitzman marked this conversation as resolved.
Show resolved Hide resolved
with other AWS credential sources such as EKS or ECS in addition to the EC2 metadata endpoint which is already natively supported by ADC.::

import boto3
from google.auth import aws
from google.auth import exceptions
from google.cloud import storage

class CustomAwsSecurityCredentialsSupplier(aws.AwsSecurityCredentialsSupplier):

def __init__(self, region):
self._region = region

def get_aws_security_credentials(self, context, request):
audience = context.audience
aws_credentials = boto3.Session(region_name=self._region).get_credentials().get_frozen_credentials()

try:
# Return valid AWS security credentials. These credentials are not cached by
# the google credential, so caching should be implemented in the supplier.
return aws.AwsSecurityCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY, SESSION_TOKEN)
return aws.AwsSecurityCredentials(aws_credentials.access_key, aws_credentials.secret_key, aws_credentials.token)
except Exception as e:
# If credentials retrieval fails, raise a refresh error, setting retryable to true if the client should
# attempt to retrieve the subject token again.
raise exceptions.RefreshError(e, retryable=True)

def get_aws_region(self, context, request):
# Return active AWS region.
return self._region

supplier = CustomAwsSecurityCredentialsSupplier()
aws_region = "AWS_REGION" # Set the current AWS region (i.e. us-east-2)
supplier = CustomAwsSecurityCredentialsSupplier(aws_region)

# Create credentials using the custom supplier.
credentials = aws.Credentials(
AUDIENCE, # Set GCP Audience.
"urn:ietf:params:aws:token-type:aws4_request", # Set AWS subject token type.
aws_security_credentials_supplier=supplier, # Set supplier.
scopes=SCOPES # Set desired scopes.
scopes=['https://www.googleapis.com/auth/cloud-platform'] # Set scopes.
)

# Create service client and use the credentials you just created.
# The GCP project id must also be set.
storage_client = storage.Client(credentials=credentials, project=GCP_PROJECT_ID)

Where the `audience`_ is: ``///iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID``
Where the following variables need to be substituted:

Expand Down
65 changes: 65 additions & 0 deletions samples/cloud-client/snippets/authenticate_with_aws_supplier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Copyright 2024 Google Inc.
#
# 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.

# [START auth_cloud_aws_supplier]

from google.cloud import storage

from google.auth import aws
from google.auth import exceptions
import boto3


class CustomAwsSecurityCredentialsSupplier(aws.AwsSecurityCredentialsSupplier):

def __init__(self, region):
self._region = region

def get_aws_security_credentials(self, context, request):
aws_credentials = boto3.Session(region_name=self._region).get_credentials().get_frozen_credentials()

try:
return aws.AwsSecurityCredentials(aws_credentials.access_key, aws_credentials.secret_key, aws_credentials.token)
except Exception as e:
raise exceptions.RefreshError(e, retryable=True)

def get_aws_region(self, context, request):
return self._region


def authenticate_with_aws_supplier(project_id="your-google-cloud-project-id", aws_region="your_aws_region", audience="your_federation_audience"):
"""
List storage buckets by authenticating with a custom AWS supplier.

// TODO(Developer) Before running this sample,:
// 1. Replace the project, region, and audience variables.
// 2. Make sure you have the necessary permission to list storage buckets: "storage.buckets.list"
"""

credentials = aws.Credentials(
audience,
"urn:ietf:params:aws:token-type:aws4_request",
aws_security_credentials_supplier=CustomAwsSecurityCredentialsSupplier(aws_region),
scopes=['https://www.googleapis.com/auth/cloud-platform']
)

# Construct the Storage client.
storage_client = storage.Client(credentials=credentials, project=project_id)
buckets = storage_client.list_buckets()
print("Buckets:")
for bucket in buckets:
print(bucket.name)
print("Listed all storage buckets.")

# [END auth_cloud_aws_supplier]