Merge pull request #143 from trail-of-forks/tob-rewrite-oidc-refs

This patch updates the user-facing OIDC mentions with the new "Trusted Publishing" term
to make it cohesive with how the PyPI docs names things now.
This commit is contained in:
Sviatoslav Sydorenko 2023-04-03 17:56:36 +02:00 committed by GitHub
commit 0bf742be3e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 18 deletions

View file

@ -62,20 +62,25 @@ The secret used in `${{ secrets.PYPI_API_TOKEN }}` needs to be created on the
settings page of your project on GitHub. See [Creating & using secrets]. settings page of your project on GitHub. See [Creating & using secrets].
### Publishing with OpenID Connect ### Trusted publishing
> **IMPORTANT**: This functionality is in beta, and will not work for you > **IMPORTANT**: This functionality is in beta, and will not work for you
> unless you're a member of the PyPI OIDC beta testers' group. For more > unless you're a member of the PyPI trusted publishing beta testers' group.
> information, see [warehouse#12965]. > For more information, see [warehouse#12965].
This action supports PyPI's [OpenID Connect publishing] > **NOTE**: Trusted publishing is sometimes referred to by its
> underlying technology -- OpenID Connect, or OIDC for short.
> If you see references to "OIDC publishing" in the context of PyPI,
> this is what they're referring to.
This action supports PyPI's [trusted publishing]
implementation, which allows authentication to PyPI without a manually implementation, which allows authentication to PyPI without a manually
configured API token or username/password combination. To perform configured API token or username/password combination. To perform
[OIDC publishing][OpenID Connect Publishing] with this action, your project's [trusted publishing] with this action, your project's
OIDC publisher must already be configured on PyPI. publisher must already be configured on PyPI.
To enter the OIDC flow, configure this action's job with the `id-token: write` To enter the trusted publishing flow, configure this action's job with the
permission and **without** an explicit username or password: `id-token: write` permission and **without** an explicit username or password:
```yaml ```yaml
jobs: jobs:
@ -83,7 +88,7 @@ jobs:
name: Upload release to PyPI name: Upload release to PyPI
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
id-token: write # IMPORTANT: this permission is mandatory for OIDC publishing id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
steps: steps:
# retrieve your distributions here # retrieve your distributions here
@ -91,7 +96,7 @@ jobs:
uses: pypa/gh-action-pypi-publish@release/v1 uses: pypa/gh-action-pypi-publish@release/v1
``` ```
Other indices that support OIDC publishing can also be used, like TestPyPI: Other indices that support trusted publishing can also be used, like TestPyPI:
```yaml ```yaml
- name: Publish package distributions to TestPyPI - name: Publish package distributions to TestPyPI
@ -268,4 +273,4 @@ https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direc
https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md
[warehouse#12965]: https://github.com/pypi/warehouse/issues/12965 [warehouse#12965]: https://github.com/pypi/warehouse/issues/12965
[OpenID Connect Publishing]: https://pypi.org/help/#openid-connect [trusted publishing]: https://docs.pypi.org/trusted-publishers/

View file

@ -13,7 +13,7 @@ _GITHUB_STEP_SUMMARY = Path(os.getenv("GITHUB_STEP_SUMMARY"))
# The top-level error message that gets rendered. # The top-level error message that gets rendered.
# This message wraps one of the other templates/messages defined below. # This message wraps one of the other templates/messages defined below.
_ERROR_SUMMARY_MESSAGE = """ _ERROR_SUMMARY_MESSAGE = """
Trusted publisher (OIDC) exchange failure: Trusted publishing exchange failure:
{message} {message}
@ -24,11 +24,14 @@ publishing, then you should double-check your secret configuration and variable
names. names.
Read more about trusted publishers at https://docs.pypi.org/trusted-publishers/ Read more about trusted publishers at https://docs.pypi.org/trusted-publishers/
Read more about how this action uses trusted publishers at
https://github.com/marketplace/actions/pypi-publish#trusted-publishing
""" """
# Rendered if OIDC identity token retrieval fails for any reason. # Rendered if OIDC identity token retrieval fails for any reason.
_TOKEN_RETRIEVAL_FAILED_MESSAGE = """ _TOKEN_RETRIEVAL_FAILED_MESSAGE = """
OIDC token retrieval failed: {identity_error} OpenID Connect token retrieval failed: {identity_error}
This generally indicates a workflow configuration error, such as insufficient This generally indicates a workflow configuration error, such as insufficient
permissions. Make sure that your workflow has `id-token: write` configured permissions. Make sure that your workflow has `id-token: write` configured
@ -71,7 +74,7 @@ def die(msg: str) -> NoReturn:
with _GITHUB_STEP_SUMMARY.open("a", encoding="utf-8") as io: with _GITHUB_STEP_SUMMARY.open("a", encoding="utf-8") as io:
print(_ERROR_SUMMARY_MESSAGE.format(message=msg), file=io) print(_ERROR_SUMMARY_MESSAGE.format(message=msg), file=io)
print(f"::error::OIDC exchange failure: {msg}", file=sys.stderr) print(f"::error::Trusted publishing exchange failure: {msg}", file=sys.stderr)
sys.exit(1) sys.exit(1)
@ -94,12 +97,14 @@ def assert_successful_audience_call(resp: requests.Response, domain: str):
case HTTPStatus.FORBIDDEN: case HTTPStatus.FORBIDDEN:
# This index supports OIDC, but forbids the client from using # This index supports OIDC, but forbids the client from using
# it (either because it's disabled, limited to a beta group, etc.) # it (either because it's disabled, limited to a beta group, etc.)
die(f"audience retrieval failed: repository at {domain} has OIDC disabled") die(
f"audience retrieval failed: repository at {domain} has trusted publishing disabled",
)
case HTTPStatus.NOT_FOUND: case HTTPStatus.NOT_FOUND:
# This index does not support OIDC. # This index does not support OIDC.
die( die(
"audience retrieval failed: repository at " "audience retrieval failed: repository at "
f"{domain} does not indicate OIDC support", f"{domain} does not indicate trusted publishing support",
) )
case other: case other:
status = HTTPStatus(other) status = HTTPStatus(other)
@ -124,7 +129,7 @@ assert_successful_audience_call(audience_resp, repository_domain)
oidc_audience = audience_resp.json()["audience"] oidc_audience = audience_resp.json()["audience"]
debug(f"selected OIDC token exchange endpoint: {token_exchange_url}") debug(f"selected trusted publishing exchange endpoint: {token_exchange_url}")
try: try:
oidc_token = id.detect_credential(audience=oidc_audience) oidc_token = id.detect_credential(audience=oidc_audience)

View file

@ -44,7 +44,7 @@ if [[ "${INPUT_USER}" == "__token__" && -z "${INPUT_PASSWORD}" ]] ; then
# No password supplied by the user implies that we're in the OIDC flow; # No password supplied by the user implies that we're in the OIDC flow;
# retrieve the OIDC credential and exchange it for a PyPI API token. # retrieve the OIDC credential and exchange it for a PyPI API token.
echo \ echo \
'::notice::Attempting to perform OIDC credential exchange' \ '::notice::Attempting to perform trusted publishing exchange' \
'to retrieve a temporary short-lived API token for authentication' \ 'to retrieve a temporary short-lived API token for authentication' \
"against ${INPUT_REPOSITORY_URL} due to __token__ username with no" \ "against ${INPUT_REPOSITORY_URL} due to __token__ username with no" \
'supplied password field' 'supplied password field'