Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: pypa/gh-action-pypi-publish
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.8.4
Choose a base ref
...
head repository: pypa/gh-action-pypi-publish
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.8.5
Choose a head ref
  • 10 commits
  • 3 files changed
  • 4 contributors

Commits on Apr 1, 2023

  1. oidc-exchange: more explanation

    Signed-off-by: William Woodruff <william@trailofbits.com>
    woodruffw committed Apr 1, 2023

    Verified

    This commit was signed with the committer’s verified signature.
    woodruffw William Woodruff
    Copy the full SHA
    67b747a View commit details
  2. twine-upload: expound

    Signed-off-by: William Woodruff <william@trailofbits.com>
    woodruffw committed Apr 1, 2023

    Verified

    This commit was signed with the committer’s verified signature.
    woodruffw William Woodruff
    Copy the full SHA
    3d567f4 View commit details

Commits on Apr 2, 2023

  1. Apply suggestions from code review

    Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
    woodruffw and webknjaz authored Apr 2, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    dfde872 View commit details

Commits on Apr 3, 2023

  1. Merge pull request #142 from trail-of-forks/tob-indicate-oidc

    Add explanation of why the OIDC publishing was chosen to the log output.
    webknjaz authored Apr 3, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    69efb8c View commit details
  2. README: replace OIDC with "trusted publishing"

    Also updates the link to reference the public documentation
    for trusted publishing, rather than the PyPI short help
    section (which also needs to be updated).
    
    Signed-off-by: William Woodruff <william@trailofbits.com>
    woodruffw committed Apr 3, 2023

    Verified

    This commit was signed with the committer’s verified signature.
    woodruffw William Woodruff
    Copy the full SHA
    4372cb5 View commit details
  3. oidc-exchange, twine-upload: remove more OIDC refs

    ...but not all, since some make sense in a debugging
    context.
    
    Signed-off-by: William Woodruff <william@trailofbits.com>
    woodruffw committed Apr 3, 2023

    Verified

    This commit was signed with the committer’s verified signature.
    woodruffw William Woodruff
    Copy the full SHA
    0b567d5 View commit details
  4. Apply suggestions from code review

    Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
    woodruffw and webknjaz authored Apr 3, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a0f29a5 View commit details
  5. README: retitle, add note

    Signed-off-by: William Woodruff <william@trailofbits.com>
    woodruffw committed Apr 3, 2023

    Verified

    This commit was signed with the committer’s verified signature.
    woodruffw William Woodruff
    Copy the full SHA
    89ddbea View commit details
  6. oidc-exchange: another link

    Signed-off-by: William Woodruff <william@trailofbits.com>
    woodruffw committed Apr 3, 2023

    Verified

    This commit was signed with the committer’s verified signature.
    woodruffw William Woodruff
    Copy the full SHA
    30c3822 View commit details
  7. 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.
    webknjaz authored Apr 3, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0bf742b View commit details
Showing with 36 additions and 19 deletions.
  1. +16 −11 README.md
  2. +17 −6 oidc-exchange.py
  3. +3 −2 twine-upload.sh
27 changes: 16 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -62,36 +62,41 @@ 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].


### Publishing with OpenID Connect
### Trusted publishing

> **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
> information, see [warehouse#12965].
> unless you're a member of the PyPI trusted publishing beta testers' group.
> 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
configured API token or username/password combination. To perform
[OIDC publishing][OpenID Connect Publishing] with this action, your project's
OIDC publisher must already be configured on PyPI.
[trusted publishing] with this action, your project's
publisher must already be configured on PyPI.

To enter the OIDC flow, configure this action's job with the `id-token: write`
permission and **without** an explicit username or password:
To enter the trusted publishing flow, configure this action's job with the
`id-token: write` permission and **without** an explicit username or password:

```yaml
jobs:
pypi-publish:
name: Upload release to PyPI
runs-on: ubuntu-latest
permissions:
id-token: write # IMPORTANT: this permission is mandatory for OIDC publishing
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
steps:
# retrieve your distributions here
- name: Publish package distributions to PyPI
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
- 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

[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/
23 changes: 17 additions & 6 deletions oidc-exchange.py
Original file line number Diff line number Diff line change
@@ -13,16 +13,25 @@
# The top-level error message that gets rendered.
# This message wraps one of the other templates/messages defined below.
_ERROR_SUMMARY_MESSAGE = """
Trusted publisher (OIDC) exchange failure:
Trusted publishing exchange failure:
{message}
You're seeing this because the action wasn't given the inputs needed to
perform password-based or token-based authentication. If you intended to
perform one of those authentication methods instead of trusted
publishing, then you should double-check your secret configuration and variable
names.
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.
_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
permissions. Make sure that your workflow has `id-token: write` configured
@@ -65,7 +74,7 @@ def die(msg: str) -> NoReturn:
with _GITHUB_STEP_SUMMARY.open("a", encoding="utf-8") as 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)


@@ -88,12 +97,14 @@ def assert_successful_audience_call(resp: requests.Response, domain: str):
case HTTPStatus.FORBIDDEN:
# This index supports OIDC, but forbids the client from using
# 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:
# This index does not support OIDC.
die(
"audience retrieval failed: repository at "
f"{domain} does not indicate OIDC support",
f"{domain} does not indicate trusted publishing support",
)
case other:
status = HTTPStatus(other)
@@ -118,7 +129,7 @@ def assert_successful_audience_call(resp: requests.Response, domain: str):

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:
oidc_token = id.detect_credential(audience=oidc_audience)
5 changes: 3 additions & 2 deletions twine-upload.sh
Original file line number Diff line number Diff line change
@@ -44,9 +44,10 @@ if [[ "${INPUT_USER}" == "__token__" && -z "${INPUT_PASSWORD}" ]] ; then
# 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.
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' \
"against ${INPUT_REPOSITORY_URL}"
"against ${INPUT_REPOSITORY_URL} due to __token__ username with no" \
'supplied password field'
INPUT_PASSWORD="$(python /app/oidc-exchange.py)"
elif [[ "${INPUT_USER}" == '__token__' ]]; then
echo \