diff --git a/docs/user/trusted-publishers/adding-a-publisher.md b/docs/user/trusted-publishers/adding-a-publisher.md index d7711c50834a..a75d39ad8db6 100644 --- a/docs/user/trusted-publishers/adding-a-publisher.md +++ b/docs/user/trusted-publishers/adding-a-publisher.md @@ -45,7 +45,41 @@ each. === "Google Cloud" - TODO + For Google Cloud, you **must** provide the email address of the account or + service account used to publish. [You can learn more about Google Cloud + service accounts + here](https://cloud.google.com/iam/docs/service-account-overview). + + For example, if you have created a service account named + "SERVICE_ACCOUNT_NAME" in the project "PROJECT_NAME" which is in use by + the environment where you would like to publish to PyPI from, your service + account email would take the form + `SERVICE_ACCOUNT_NAME@PROJECT_NAME.iam.gserviceaccount.com`, and you would do + the following: + + ![](/assets/trusted-publishing/google/project-publishing-form.png) + + !!! warning + + Google Cloud also provides [default service + accounts](https://cloud.google.com/iam/docs/service-account-types#default) + for various products: + + * Compute Engine: `PROJECT_ID-compute@developer.gserviceaccount.com` + * App Engine: `PROJECT_NAME@appspot.gserviceaccount.com` + + However it is **not** recommended that these be used for publishing, as + they are provided by default to every service when they are created. + + !!! note + + Configuring the subject is optional. The subject is the numeric ID that + represents the principal making the request. While not required, providing the + subject further restricts the identity which is used for publishing, ensuring + that only a specific instance of a service account can publish, not any service + account with the configured email. See + + for more details === "ActiveState" diff --git a/docs/user/trusted-publishers/creating-a-project-through-oidc.md b/docs/user/trusted-publishers/creating-a-project-through-oidc.md index 6a59dd621cc9..4f453311abb8 100644 --- a/docs/user/trusted-publishers/creating-a-project-through-oidc.md +++ b/docs/user/trusted-publishers/creating-a-project-through-oidc.md @@ -41,8 +41,16 @@ provide the name of the PyPI project that will be created. === "Google Cloud" - TODO + If you have a service account named + `SERVICE_ACCOUNT_NAME@PROJECT_NAME.iam.gserviceaccount.com`, which is in use by + the environment where you would like to publish to PyPI from, then you would do + the following: + + ![](/assets/trusted-publishing/google/pending-publisher-form-filled.png) + + !!! note + Like with "normal" trusted publishers, configuring the subject is optional. === "ActiveState" diff --git a/docs/user/trusted-publishers/security-model.md b/docs/user/trusted-publishers/security-model.md index d1acc887d4ee..226d0330ae9a 100644 --- a/docs/user/trusted-publishers/security-model.md +++ b/docs/user/trusted-publishers/security-model.md @@ -133,7 +133,23 @@ own security model and considerations. === "Google Cloud" - TODO + ### Security Model + + If a trusted publisher is configured for a given PyPI project, any service + that uses the configured service account can request an OpenID Connect token + from Google's identity provider on behalf of that identity. That token can be + exchanged for a PyPI API token with the ability to publish to the PyPI project. + The identity used for publishing can be optionally constrained further by + specifying the subject, an ID that represents the principal making the request. + + ### Considerations + + When using trusted publishing with Google Cloud, you must trust the service account + and _any service which uses it as the default ephemeral identity_. + + Specifically, it is not recommened to configure the [default service + accounts](https://cloud.google.com/iam/docs/service-account-types#default), as + they are provided by default to every service when they are created. === "ActiveState" diff --git a/docs/user/trusted-publishers/using-a-publisher.md b/docs/user/trusted-publishers/using-a-publisher.md index f1ee0b004509..171d1d63c9ff 100644 --- a/docs/user/trusted-publishers/using-a-publisher.md +++ b/docs/user/trusted-publishers/using-a-publisher.md @@ -212,7 +212,59 @@ below describe the setup process for each supported trusted publisher. === "Google Cloud" - TODO + You can use the tool to automatically detect + and produce OIDC credentials on Google Cloud services. + + First, ensure that `id` and `twine` are installed in the environment you + plan to publish from: + + ``` + $ python -m pip install -U id twine + ``` + + If you're unsure what the email address is for the service account your + service is using, you can verify it with: + + ``` + $ python -m id pypi -d | jq 'select(.email) | .email' + ``` + + Generate an OIDC token from within the environment and store it. The + audience should be either `pypi` or `testpypi` depending on which index you are + publishing to: + + ``` + $ oidc_token=$(python -m id pypi) + ``` + + !!! note + `pypi` is only correct for PyPI. For TestPyPI, the correct + audience is `testpypi`. More generally, you can access any instance's expected + OIDC audience via the `{index}/_/oidc/audience` endpoint: + + ```console + $ curl https://pypi.org/_/oidc/audience + {"audience":"pypi"} + ``` + + Finally, we can submit that token to PyPI and get a short-lived API token + back: + + ```bash + resp=$(curl -X POST https://pypi.org/_/oidc/mint-token -d "{\"token\": \"${oidc_token}\"}") + api_token=$(jq -r '.token' <<< "${resp}") + ``` + + !!! note + + This is the URL for PyPI. For TestPyPI, the correct + domain should be is `test.pypi.org`. + + This API token can be fed into `twine` or any other uploading client: + + ```bash + TWINE_USERNAME=__token__ TWINE_PASSWORD=${api_token} twine upload dist/* + ``` === "ActiveState"