Skip to content

Commit

Permalink
Merge PRs #174 #175 and #172 into unstable/v1
Browse files Browse the repository at this point in the history
  • Loading branch information
webknjaz committed Aug 10, 2023
4 parents 413a8d5 + 326f9ad + 637917e + adef75a commit ade57f5
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 12 deletions.
25 changes: 15 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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]
> 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.

Other indices that support trusted publishing can also be used, like TestPyPI:

Expand All @@ -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]
> 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
Expand All @@ -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.
Expand Down Expand Up @@ -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]
> 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.

### For Debugging

Expand Down
46 changes: 45 additions & 1 deletion oidc-exchange.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import base64
import json
import os
import sys
from http import HTTPStatus
Expand Down Expand Up @@ -50,6 +52,25 @@
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.
Expand Down Expand Up @@ -121,6 +142,23 @@ def assert_successful_audience_call(resp: requests.Response, domain: str):
)


def render_claims(token: str) -> str:
_, payload, _ = token.split(".", 2)
claims = json.loads(base64.urlsafe_b64decode(payload))

def _get(name: str) -> str: # noqa: WPS430
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"
Expand Down Expand Up @@ -165,7 +203,13 @@ def assert_successful_audience_call(resp: requests.Response, domain: str):
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:
Expand Down
2 changes: 1 addition & 1 deletion requirements/runtime.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit ade57f5

Please sign in to comment.