From adef75a5a62cc4473182a78754a310e4a73d3511 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 02:15:59 +0000 Subject: [PATCH 1/7] Bump cryptography from 41.0.2 to 41.0.3 in /requirements Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.2 to 41.0.3. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/41.0.2...41.0.3) --- updated-dependencies: - dependency-name: cryptography dependency-type: indirect ... Signed-off-by: dependabot[bot] --- requirements/runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/runtime.txt b/requirements/runtime.txt index b3f1337..c795e84 100644 --- a/requirements/runtime.txt +++ b/requirements/runtime.txt @@ -14,7 +14,7 @@ cffi==1.15.1 # via cryptography charset-normalizer==3.2.0 # via requests -cryptography==41.0.2 +cryptography==41.0.3 # via secretstorage docutils==0.20.1 # via readme-renderer From 71a0032909f17bb44704d5fc46876cdaee124ca0 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 9 Aug 2023 15:08:47 -0400 Subject: [PATCH 2/7] oidc-exchange: render claims if exchange fails Signed-off-by: William Woodruff --- oidc-exchange.py | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/oidc-exchange.py b/oidc-exchange.py index cc625d3..c6b40a7 100644 --- a/oidc-exchange.py +++ b/oidc-exchange.py @@ -1,3 +1,5 @@ +import base64 +import json import os import sys from http import HTTPStatus @@ -50,6 +52,25 @@ _SERVER_REFUSED_TOKEN_EXCHANGE_MESSAGE = """ Token request failed: the server refused the request for the following reasons: {reasons} + +This generally indicates a trusted publisher configuration error, but could +also indicate an internal error on GitHub or PyPI's part. + +{rendered_claims} +""" + +_RENDERED_CLAIMS = """ +The claims rendered below are **for debugging purposes only**. You should **not** +use them to configure a trusted publisher unless they already match your expectations. + +If a claim is not present in the claim set, then it is rendered as `MISSING`. + +* `sub`: `{sub}` +* `repository`: `{repository}` +* `repository_owner`: `{repository_owner}` +* `repository_owner_id`: `{repository_owner_id}` +* `job_workflow_ref`: `{job_workflow_ref}` +* `ref`: `{ref}` """ # Rendered if the package index's token response isn't valid JSON. @@ -121,6 +142,23 @@ def assert_successful_audience_call(resp: requests.Response, domain: str): ) +def render_claims(oidc_token: str) -> str: + _, payload, _ = oidc_token.split(".", 2) + claims = json.loads(base64.urlsafe_b64decode(payload)) + + def _get(name: str) -> str: + return claims.get(name, "MISSING") + + return _RENDERED_CLAIMS.format( + sub=_get("sub"), + repository=_get("repository"), + repository_owner=_get("repository_owner"), + repository_owner_id=_get("repository_owner_id"), + job_workflow_ref=_get("job_workflow_ref"), + ref=_get("ref"), + ) + + repository_url = get_normalized_input("repository-url") repository_domain = urlparse(repository_url).netloc token_exchange_url = f"https://{repository_domain}/_/oidc/github/mint-token" @@ -165,7 +203,13 @@ if not mint_token_resp.ok: for error in mint_token_payload["errors"] ) - die(_SERVER_REFUSED_TOKEN_EXCHANGE_MESSAGE.format(reasons=reasons)) + rendered_claims = render_claims(oidc_token) + + die( + _SERVER_REFUSED_TOKEN_EXCHANGE_MESSAGE.format( + reasons=reasons, rendered_claims=rendered_claims + ) + ) pypi_token = mint_token_payload.get("token") if pypi_token is None: From 8bdd0cc2a0ec4a8773b96ddd5bdc4a2dd849cf81 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 9 Aug 2023 15:10:56 -0400 Subject: [PATCH 3/7] oidc-exchange: lintage Signed-off-by: William Woodruff --- oidc-exchange.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oidc-exchange.py b/oidc-exchange.py index c6b40a7..886edcd 100644 --- a/oidc-exchange.py +++ b/oidc-exchange.py @@ -142,8 +142,8 @@ def assert_successful_audience_call(resp: requests.Response, domain: str): ) -def render_claims(oidc_token: str) -> str: - _, payload, _ = oidc_token.split(".", 2) +def render_claims(token: str) -> str: + _, payload, _ = token.split(".", 2) claims = json.loads(base64.urlsafe_b64decode(payload)) def _get(name: str) -> str: From e5f0690e9195178c6f53954b1f9059b3d9b11116 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 9 Aug 2023 15:12:44 -0400 Subject: [PATCH 4/7] oidc-exchange: ignore a nested function Signed-off-by: William Woodruff --- oidc-exchange.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oidc-exchange.py b/oidc-exchange.py index 886edcd..200c12b 100644 --- a/oidc-exchange.py +++ b/oidc-exchange.py @@ -146,7 +146,7 @@ def render_claims(token: str) -> str: _, payload, _ = token.split(".", 2) claims = json.loads(base64.urlsafe_b64decode(payload)) - def _get(name: str) -> str: + def _get(name: str) -> str: # noqa: WPS430 return claims.get(name, "MISSING") return _RENDERED_CLAIMS.format( From 326f9ad1e131f526357a666f008015a0ee96fbcf Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 9 Aug 2023 15:17:18 -0400 Subject: [PATCH 5/7] oidc-exchange: add-trailing-comma Signed-off-by: William Woodruff --- oidc-exchange.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oidc-exchange.py b/oidc-exchange.py index 200c12b..671c034 100644 --- a/oidc-exchange.py +++ b/oidc-exchange.py @@ -207,8 +207,8 @@ if not mint_token_resp.ok: die( _SERVER_REFUSED_TOKEN_EXCHANGE_MESSAGE.format( - reasons=reasons, rendered_claims=rendered_claims - ) + reasons=reasons, rendered_claims=rendered_claims, + ), ) pypi_token = mint_token_payload.get("token") From 4864f13c38a29318fc09dca6b0258644d80b8e07 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 9 Aug 2023 17:58:56 -0400 Subject: [PATCH 6/7] README: use semantic callouts See: https://github.com/orgs/community/discussions/16925 Signed-off-by: William Woodruff --- README.md | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 59a5921..fc33564 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ tag, or opt-in to [use a full Git commit SHA] and Dependabot. ### Trusted publishing -> **NOTE**: Trusted publishing is sometimes referred to by its +> [!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. @@ -61,10 +62,11 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 ``` -> **Pro tip**: instead of using branch pointers, like `unstable/v1`, pin -versions of Actions that you use to tagged versions or sha1 commit identifiers. -This will make your workflows more secure and better reproducible, saving you -from sudden and unpleasant surprises. +> [!NOTE] +> Instead of using branch pointers, like `unstable/v1`, pin versions of Actions +> that you use to tagged versions or sha1 commit identifiers. +> This will make your workflows more secure and better reproducible, saving you +> from sudden and unpleasant surprises. Other indices that support trusted publishing can also be used, like TestPyPI: @@ -76,7 +78,8 @@ Other indices that support trusted publishing can also be used, like TestPyPI: ``` _(don't forget to update the environment name to `testpypi` or similar!)_ -> **Pro tip**: only set the `id-token: write` permission in the job that does +> [!NOTE] +> Only set the `id-token: write` permission in the job that does > publishing, not globally. Also, try to separate building from publishing > — this makes sure that any scripts maliciously injected into the build > or test environment won't be able to elevate privileges while flying under @@ -96,7 +99,8 @@ This GitHub Action [has nothing to do with _building package distributions_]. Users are responsible for preparing dists for upload by putting them into the `dist/` folder prior to running this Action. -> **IMPORTANT**: Since this GitHub Action is docker-based, it can only +> [!IMPORTANT] +> Since this GitHub Action is docker-based, it can only > be used from within GNU/Linux based jobs in GitHub Actions CI/CD > workflows. This is by design and is unlikely to change due to a number > of considerations we rely on. @@ -187,9 +191,10 @@ default) setting as follows: skip-existing: true ``` -> **Pro tip**: try to avoid enabling this setting where possible. If you -have steps for publishing to both PyPI and TestPyPI, consider only using -it for the latter, having the former fail loudly on duplicates. +> [!NOTE] +> Try to avoid enabling this setting where possible. If you +> have steps for publishing to both PyPI and TestPyPI, consider only using +> it for the latter, having the former fail loudly on duplicates. ### For Debugging From 637917e5f201407b3d6e3be9df6af349083d0a79 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 9 Aug 2023 18:01:51 -0400 Subject: [PATCH 7/7] README: re-add "pro tip" language Signed-off-by: William Woodruff --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fc33564..986a218 100644 --- a/README.md +++ b/README.md @@ -63,8 +63,8 @@ jobs: ``` > [!NOTE] -> Instead of using branch pointers, like `unstable/v1`, pin versions of Actions -> that you use to tagged versions or sha1 commit identifiers. +> Pro tip: instead of using branch pointers, like `unstable/v1`, pin versions of +> Actions that you use to tagged versions or sha1 commit identifiers. > This will make your workflows more secure and better reproducible, saving you > from sudden and unpleasant surprises. @@ -79,7 +79,7 @@ Other indices that support trusted publishing can also be used, like TestPyPI: _(don't forget to update the environment name to `testpypi` or similar!)_ > [!NOTE] -> Only set the `id-token: write` permission in the job that does +> Pro tip: only set the `id-token: write` permission in the job that does > publishing, not globally. Also, try to separate building from publishing > — this makes sure that any scripts maliciously injected into the build > or test environment won't be able to elevate privileges while flying under @@ -192,7 +192,7 @@ default) setting as follows: ``` > [!NOTE] -> Try to avoid enabling this setting where possible. If you +> Pro tip: try to avoid enabling this setting where possible. If you > have steps for publishing to both PyPI and TestPyPI, consider only using > it for the latter, having the former fail loudly on duplicates.