Skip to content

Commit

Permalink
feat: pluggable auth support (#1045)
Browse files Browse the repository at this point in the history
* feat: Add Pluggable auth support

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

feat: Add Pluggable auth support (#988)

* Port identity pool credentials

* access_token retrieved

* -> pluggable

* Update pluggable.py

* Create test_pluggable.py

* Unit tests

* Address pr issues

feat: Add file caching (#990)

* Add file cache

* feat: add output file cache support

🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Update pluggable.py

🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Update pluggable.py

Update setup.py

🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Update setup.py

Update setup.py

pytest_subprocess

timeout

Update pluggable.py

env

🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Update _default.py

🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Update requirements.txt

Update _default.py

Update pluggable.py

Update pluggable.py

Update pluggable.py

Update test_pluggable.py

format validations

Update _default.py

Update requirements.txt

🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Revert "Update requirements.txt"

This reverts commit 1c9b6db.

Revert "Update _default.py"

This reverts commit ac6c360.

Revert "Revert "Update _default.py""

This reverts commit 1c08483.

Raise output format error but retry parsing token if `success` is 0

🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Update requirements.txt

Delete test_pluggable.py

Revert "Delete test_pluggable.py"

This reverts commit 74beba9.

Update pluggable.py

Update pluggable.py

pytest-subprocess

🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

lint

Update pluggable.py

nox cover

nox cover

🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

lint

Update test_pluggable.py

Update test_pluggable.py

* Disable Pluggable Auth for Python 2.*

Update noxfile.py

* Update pluggable.py

* Update pluggable.py

* Update pluggable.py

* Update pluggable.py

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* Address PR issues

* Update pluggable.py

* Update pluggable.py

* Update user-guide.rst

* Update user-guide.rst

* Update user-guide.rst

* Update user-guide.rst

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
Co-authored-by: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com>
Co-authored-by: Leo <39062083+lsirac@users.noreply.github.com>
  • Loading branch information
4 people authored Jun 28, 2022
1 parent 72e7bc3 commit de14f4e
Show file tree
Hide file tree
Showing 6 changed files with 1,256 additions and 3 deletions.
153 changes: 151 additions & 2 deletions docs/user-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,155 @@ Follow the detailed instructions on how to
.. _Configure Workload Identity Federation from an OIDC identity provider:
https://cloud.google.com/iam/docs/access-resources-oidc

Using Executable-sourced credentials with OIDC and SAML
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**Executable-sourced credentials** For executable-sourced credentials, a
local executable is used to retrieve the 3rd party token. The executable
must handle providing a valid, unexpired OIDC ID token or SAML assertion
in JSON format to stdout.

To use executable-sourced credentials, the
``GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES`` environment variable must
be set to ``1``.

To generate an executable-sourced workload identity configuration, run
the following command:

.. code:: bash
# Generate a configuration file for executable-sourced credentials.
gcloud iam workload-identity-pools create-cred-config \
projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID \
--service-account=$SERVICE_ACCOUNT_EMAIL \
--subject-token-type=$SUBJECT_TOKEN_TYPE \
# The absolute path for the program, including arguments.
# e.g. --executable-command="/path/to/command --foo=bar"
--executable-command=$EXECUTABLE_COMMAND \
# Optional argument for the executable timeout. Defaults to 30s.
# --executable-timeout-millis=$EXECUTABLE_TIMEOUT \
# Optional argument for the absolute path to the executable output file.
# See below on how this argument impacts the library behaviour.
# --executable-output-file=$EXECUTABLE_OUTPUT_FILE \
--output-file /path/to/generated/config.json
Where the following variables need to be substituted: -
``$PROJECT_NUMBER``: The Google Cloud project number. - ``$POOL_ID``:
The workload identity pool ID. - ``$PROVIDER_ID``: The OIDC or SAML
provider ID. - ``$SERVICE_ACCOUNT_EMAIL``: The email of the service
account to impersonate. - ``$SUBJECT_TOKEN_TYPE``: The subject token
type. - ``$EXECUTABLE_COMMAND``: The full command to run, including
arguments. Must be an absolute path to the program.

The ``--executable-timeout-millis`` flag is optional. This is the
duration for which the auth library will wait for the executable to
finish, in milliseconds. Defaults to 30 seconds when not provided. The
maximum allowed value is 2 minutes. The minimum is 5 seconds.

The ``--executable-output-file`` flag is optional. If provided, the file
path must point to the 3PI credential response generated by the
executable. This is useful for caching the credentials. By specifying
this path, the Auth libraries will first check for its existence before
running the executable. By caching the executable JSON response to this
file, it improves performance as it avoids the need to run the
executable until the cached credentials in the output file are expired.
The executable must handle writing to this file - the auth libraries
will only attempt to read from this location. The format of contents in
the file should match the JSON format expected by the executable shown
below.

To retrieve the 3rd party token, the library will call the executable
using the command specified. The executable’s output must adhere to the
response format specified below. It must output the response to stdout.

A sample successful executable OIDC response:

.. code:: json
{
"version": 1,
"success": true,
"token_type": "urn:ietf:params:oauth:token-type:id_token",
"id_token": "HEADER.PAYLOAD.SIGNATURE",
"expiration_time": 1620499962
}
A sample successful executable SAML response:

.. code:: json
{
"version": 1,
"success": true,
"token_type": "urn:ietf:params:oauth:token-type:saml2",
"saml_response": "...",
"expiration_time": 1620499962
}
A sample executable error response:

.. code:: json
{
"version": 1,
"success": false,
"code": "401",
"message": "Caller not authorized."
}
These are all required fields for an error response. The code and
message fields will be used by the library as part of the thrown
exception.

Response format fields summary: ``version``: The version of the JSON
output. Currently only version 1 is supported. ``success``: The
status of the response. When true, the response must contain the 3rd
party token, token type, and expiration. The executable must also exit
with exit code 0. When false, the response must contain the error code
and message fields and exit with a non-zero value. ``token_type``:
The 3rd party subject token type. Must be
*urn:ietf:params:oauth:token-type:jwt*,
*urn:ietf:params:oauth:token-type:id_token*, or
*urn:ietf:params:oauth:token-type:saml2*. ``id_token``: The 3rd party
OIDC token. ``saml_response``: The 3rd party SAML response.
``expiration_time``: The 3rd party subject token expiration time in
seconds (unix epoch time). ``code``: The error code string.
``message``: The error message.

All response types must include both the ``version`` and ``success``
fields. Successful responses must include the ``token_type``,
``expiration_time``, and one of ``id_token`` or ``saml_response``.
Error responses must include both the ``code`` and ``message`` fields.

The library will populate the following environment variables when the
executable is run: ``GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE``: The audience
field from the credential configuration. Always present.
``GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL``: The service account
email. Only present when service account impersonation is used.
``GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE``: The output file location from
the credential configuration. Only present when specified in the
credential configuration.

These environment variables can be used by the executable to avoid
hard-coding these values.

Security considerations

The following security practices are highly recommended:
Access to the script should be restricted as it will be displaying
credentials to stdout. This ensures that rogue processes do not gain
access to the script. The configuration file should not be
modifiable. Write access should be restricted to avoid processes
modifying the executable command portion.

Given the complexity of using executable-sourced credentials, it is
recommended to use the existing supported mechanisms
(file-sourced/URL-sourced) for providing 3rd party credentials unless
they do not meet your specific requirements.

You can now `use the Auth library <#using-external-identities>`__ to
call Google Cloud resources from an OIDC or SAML provider.

Using External Identities
~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -395,7 +544,7 @@ Impersonated credentials
++++++++++++++++++++++++

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

from google.auth import impersonated_credentials
Expand All @@ -417,7 +566,7 @@ the "Service Account Token Creator" IAM role. ::


In the example above `source_credentials` does not have direct access to list buckets
in the target project. Using `ImpersonatedCredentials` will allow the source_credentials
in the target project. Using `ImpersonatedCredentials` will allow the source_credentials
to assume the identity of a target_principal that does have access.


Expand Down
11 changes: 10 additions & 1 deletion google/auth/_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,14 +324,23 @@ def _get_external_account_credentials(
google.auth.exceptions.DefaultCredentialsError: if the info dictionary
is in the wrong format or is missing required information.
"""
# There are currently 2 types of external_account credentials.
# There are currently 3 types of external_account credentials.
if info.get("subject_token_type") == _AWS_SUBJECT_TOKEN_TYPE:
# Check if configuration corresponds to an AWS credentials.
from google.auth import aws

credentials = aws.Credentials.from_info(
info, scopes=scopes, default_scopes=default_scopes
)
elif (
info.get("credential_source") is not None
and info.get("credential_source").get("executable") is not None
):
from google.auth import pluggable

credentials = pluggable.Credentials.from_info(
info, scopes=scopes, default_scopes=default_scopes
)
else:
try:
# Check if configuration corresponds to an Identity Pool credentials.
Expand Down
Loading

0 comments on commit de14f4e

Please # to comment.