Skip to content

Commit 3af1768

Browse files
aeitzmanclundin25lsirac
authored
feat: Adds support for custom suppliers in AWS and Identity Pool credentials (#1496)
* feat: refactor AWS and identity pool credentials to use suppliers (#1484) * feat: refactor aws and identity pool credentials to use supplier framework * Linting * changing class types * linting * remove unused import * Fix typing * add docstring and fix casing * feat: Adds support for custom suppliers in AWS and Identity Pool credential instantiation (#1494) * feat: refactor aws and identity pool credentials to use supplier framework * Linting * changing class types * linting * remove unused import * Fix typing * add docstring and fix casing * feat: adds support for passing suppliers to credentials. * fixes merge issues and adds _has_custom_supplier method * adds _has_custom_supplier function to identity_pool * Update google/auth/external_account.py Co-authored-by: Carl Lundin <[email protected]> * Apply suggestions from code review Co-authored-by: Carl Lundin <[email protected]> * Respond to comments and fix docs --------- Co-authored-by: Carl Lundin <[email protected]> * docs: add documentation for suppliers (#1495) * docs: update docs for programmatic * add space * update user guide * update docs * Apply suggestions from code review Co-authored-by: Leo <[email protected]> * Update docs * Add docs about context and request --------- Co-authored-by: Carl Lundin <[email protected]> Co-authored-by: Leo <[email protected]>
1 parent 3993307 commit 3af1768

File tree

7 files changed

+1338
-469
lines changed

7 files changed

+1338
-469
lines changed

docs/user-guide.rst

Lines changed: 172 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ There is a separate library, `google-auth-oauthlib`_, that has some helpers
212212
for integrating with `requests-oauthlib`_ to provide support for obtaining
213213
user credentials. You can use
214214
:func:`google_auth_oauthlib.helpers.credentials_from_session` to obtain
215-
:class:`google.oauth2.credentials.Credentials` from a
215+
:class:`google.oauth2.credentials.Credentials` from a
216216
:class:`requests_oauthlib.OAuth2Session` as above::
217217

218218
from google_auth_oauthlib.helpers import credentials_from_session
@@ -459,9 +459,9 @@ Error responses must include both the ``code`` and ``message`` fields.
459459

460460
The library will populate the following environment variables when the
461461
executable is run: ``GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE``: The audience
462-
field from the credential configuration. Always present.
462+
field from the credential configuration. Always present.
463463
``GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL``: The service account
464-
email. Only present when service account impersonation is used.
464+
email. Only present when service account impersonation is used.
465465
``GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE``: The output file location from
466466
the credential configuration. Only present when specified in the
467467
credential configuration.
@@ -486,6 +486,117 @@ they do not meet your specific requirements.
486486
You can now `use the Auth library <#using-external-identities>`__ to
487487
call Google Cloud resources from an OIDC or SAML provider.
488488

489+
490+
Accessing resources using a custom supplier with OIDC or SAML
491+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
492+
493+
This library also allows for a custom implementation of :class:`google.auth.identity_pool.SubjectTokenSupplier`
494+
to be specificed when creating a :class:`google.auth.identity_pool.Credential`. The supplier must
495+
return a valid OIDC or SAML2.0 subject token, which will then be exchanged for a
496+
Google Cloud access token. If an error occurs during token retrieval, the supplier
497+
should return a :class:`google.auth.exceptions.RefreshError` and indicate via the error
498+
whether the subject token retrieval is retryable.
499+
Any call to the supplier from the Identity Pool credential will send a :class:`google.auth.external_account.SupplierContext`
500+
object, which contains the requested audience and subject type. Additionally, the credential will
501+
send the :class:`google.auth.transport.requests.Request` passed in the credential refresh call which
502+
can be used to make HTTP requests.::
503+
504+
from google.auth import exceptions
505+
from google.auth import identity_pool
506+
507+
class CustomSubjectTokenSupplier(identity_pool.SubjectTokenSupplier):
508+
509+
def get_subject_token(self, context, request):
510+
audience = context.audience
511+
subject_token_type = context.subject_token_type
512+
try:
513+
# Attempt to return the valid subject token of the requested type for the requested audience.
514+
except Exception as e:
515+
# If token retrieval fails, raise a refresh error, setting retryable to true if the client should
516+
# attempt to retrieve the subject token again.
517+
raise exceptions.RefreshError(e, retryable=True)
518+
519+
supplier = CustomSubjectTokenSupplier()
520+
521+
credentials = identity_pool.Credentials(
522+
AUDIENCE, # Set GCP Audience.
523+
"urn:ietf:params:aws:token-type:jwt", # Set subject token type.
524+
subject_token_supplier=supplier, # Set supplier.
525+
scopes=SCOPES # Set desired scopes.
526+
)
527+
528+
Where the `audience`_ is: ``///iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID``
529+
Where the following variables need to be substituted:
530+
531+
* ``$PROJECT_NUMBER``: The project number.
532+
* ``$POOL_ID``: The workload pool ID.
533+
* ``$PROVIDER_ID``: The provider ID.
534+
535+
The values for audience, service account impersonation URL, and any other builder field can also be found
536+
by generating a `credential configuration file with the gcloud CLI`_.
537+
538+
.. _audience:
539+
https://cloud.google.com/iam/docs/best-practices-for-using-workload-identity-federation#provider-audience
540+
.. _credential configuration file with the gcloud CLI:
541+
https://cloud.google.com/sdk/gcloud/reference/iam/workload-identity-pools/create-cred-config
542+
543+
Accessing resources using a custom supplier with AWS
544+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
545+
546+
This library also allows for a custom implementation of :class:`google.auth.aws.AwsSecurityCredentialsSupplier`
547+
to be specificed when creating a :class:`google.auth.aws.Credential`. The supplier must
548+
return valid AWS security credentials, which will then be exchanged for a
549+
Google Cloud access token. If an error occurs during credential retrieval, the supplier
550+
should return a :class:`google.auth.exceptions.RefreshError` and indicate via the error
551+
whether the credential retrieval is retryable.
552+
Any call to the supplier from the Identity Pool credential will send a :class:`google.auth.external_account.SupplierContext`
553+
object, which contains the requested audience and subject type. Additionally, the credential will
554+
send the :class:`google.auth.transport.requests.Request` passed in the credential refresh call which
555+
can be used to make HTTP requests.::
556+
557+
from google.auth import aws
558+
from google.auth import exceptions
559+
560+
class CustomAwsSecurityCredentialsSupplier(aws.AwsSecurityCredentialsSupplier):
561+
562+
def get_aws_security_credentials(self, context, request):
563+
audience = context.audience
564+
try:
565+
# Return valid AWS security credentials. These credentials are not cached by
566+
# the google credential, so caching should be implemented in the supplier.
567+
return aws.AwsSecurityCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY, SESSION_TOKEN)
568+
except Exception as e:
569+
# If credentials retrieval fails, raise a refresh error, setting retryable to true if the client should
570+
# attempt to retrieve the subject token again.
571+
raise exceptions.RefreshError(e, retryable=True)
572+
573+
def get_aws_region(self, context, request):
574+
# Return active AWS region.
575+
576+
supplier = CustomAwsSecurityCredentialsSupplier()
577+
578+
credentials = aws.Credentials(
579+
AUDIENCE, # Set GCP Audience.
580+
"urn:ietf:params:aws:token-type:aws4_request", # Set AWS subject token type.
581+
aws_security_token_supplier=supplier, # Set supplier.
582+
scopes=SCOPES # Set desired scopes.
583+
)
584+
585+
Where the `audience`_ is: ``///iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID``
586+
Where the following variables need to be substituted:
587+
588+
* ``$PROJECT_NUMBER``: The project number.
589+
* ``$POOL_ID``: The workload pool ID.
590+
* ``$PROVIDER_ID``: The provider ID.
591+
592+
The values for audience, service account impersonation URL, and any other builder field can also be found
593+
by generating a `credential configuration file with the gcloud CLI`_.
594+
595+
.. _audience:
596+
https://cloud.google.com/iam/docs/best-practices-for-using-workload-identity-federation#provider-audience
597+
.. _credential configuration file with the gcloud CLI:
598+
https://cloud.google.com/sdk/gcloud/reference/iam/workload-identity-pools/create-cred-config
599+
489600
Using External Identities
490601
~~~~~~~~~~~~~~~~~~~~~~~~~
491602

@@ -774,6 +885,62 @@ Refer to the `using executable-sourced credentials with Workload Identity
774885
Federation <Using-Executable-sourced-credentials-with-OIDC-and-SAML>`__ above
775886
for the executable response specification.
776887

888+
Accessing resources using a custom supplier with OIDC or SAML
889+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
890+
891+
This library also allows for a custom implementation of :class:`google.auth.identity_pool.SubjectTokenSupplier`
892+
to be specificed when creating a :class:`google.auth.identity_pool.Credential`. The supplier must
893+
return a valid OIDC or SAML2.0 subject token, which will then be exchanged for a
894+
Google Cloud access token. If an error occurs during token retrieval, the supplier
895+
should return a :class:`google.auth.exceptions.RefreshError` and indicate via the error
896+
whether the subject token retrieval is retryable.
897+
Any call to the supplier from the Identity Pool credential will send a :class:`google.auth.external_account.SupplierContext`
898+
object, which contains the requested audience and subject type. Additionally, the credential will
899+
send the :class:`google.auth.transport.requests.Request` passed in the credential refresh call which
900+
can be used to make HTTP requests.::
901+
902+
from google.auth import exceptions
903+
from google.auth import identity_pool
904+
905+
class CustomSubjectTokenSupplier(identity_pool.SubjectTokenSupplier):
906+
907+
def get_subject_token(self, context, request):
908+
audience = context.audience
909+
subject_token_type = context.subject_token_type
910+
try:
911+
# Attempt to return the valid subject token of the requested type for the requested audience.
912+
except Exception as e:
913+
# If token retrieval fails, raise a refresh error, setting retryable to true if the client should
914+
# attempt to retrieve the subject token again.
915+
raise exceptions.RefreshError(e, retryable=True)
916+
917+
918+
supplier = CustomSubjectTokenSupplier()
919+
920+
credentials = identity_pool.Credentials(
921+
AUDIENCE, # Set GCP Audience.
922+
"urn:ietf:params:aws:token-type:jwt", # Set subject token type.
923+
subject_token_supplier=supplier, # Set supplier.
924+
scopes=SCOPES, # Set desired scopes.
925+
workforce_pool_user_project=USER_PROJECT # Set workforce pool user project.
926+
)
927+
928+
Where the audience is: ``//iam.googleapis.com/locations/global/workforcePools/$WORKFORCE_POOL_ID/providers/$PROVIDER_ID``
929+
Where the following variables need to be substituted:
930+
931+
* ``$WORKFORCE_POOL_ID``: The workforce pool ID.
932+
* ``$PROVIDER_ID``: The provider ID.
933+
934+
and the workforce pool user project is the project number associated with the `workforce pools user project`_.
935+
936+
The values for audience, service account impersonation URL, and any other builder field can also be found
937+
by generating a `credential configuration file`_ with the gcloud CLI.
938+
939+
.. _workforce pools user project:
940+
https://cloud.google.com/iam/docs/workforce-identity-federation#workforce-pools-user-project
941+
.. _credential configuration file:
942+
https://cloud.google.com/iam/docs/workforce-obtaining-short-lived-credentials#use_configuration_files_for_sign-in
943+
777944
Security considerations
778945
~~~~~~~~~~~~~~~~~~~~~~~
779946

@@ -814,7 +981,7 @@ Impersonated credentials
814981
++++++++++++++++++++++++
815982

816983
Impersonated Credentials allows one set of credentials issued to a user or service account
817-
to impersonate another. The source credentials must be granted
984+
to impersonate another. The source credentials must be granted
818985
the "Service Account Token Creator" IAM role. ::
819986

820987
from google.auth import impersonated_credentials
@@ -884,7 +1051,7 @@ Token broker ::
8841051
credential_access_boundary = downscoped.CredentialAccessBoundary(
8851052
rules=[rule])
8861053

887-
# Retrieve the source credentials via ADC.
1054+
# Retrieve the source credentials via ADC.
8881055
source_credentials, _ = google.auth.default()
8891056

8901057
# Create the downscoped credentials.

0 commit comments

Comments
 (0)