Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trusted Publishers doesn't accept JWTs from github.com when iss customisation is enabled #17700

Open
unlobito opened this issue Mar 3, 2025 · 2 comments

Comments

@unlobito
Copy link

unlobito commented Mar 3, 2025

Describe the bug

Using GitHub Actions on github.com on an organisation that's customised the enterprise's issuer value causes PyPI to refuse release uploads with the reason:

  • invalid-payload: unknown trusted publishing issuer

Expected behavior

PyPI should accept JWTs from github.com where iss customisation is enabled, or should allow specifying an enterprise slug when Adding a Trusted Publisher to an Existing PyPI project.

To Reproduce

  1. Follow https://docs.pypi.org/trusted-publishers/adding-a-publisher/ to use a Trusted Publisher for uploads to PyPI with GitHub Actions
  2. [Customise] the issuer value for an enterprise
  3. Observe a Trusted publishing exchange failure: https://github.com/Skyscanner/pycfmodel/actions/runs/13563626065

My Platform

pypa/gh-action-pypi-publish@release/v1 for GitHub Actions, on github.com Enterprise Cloud

Additional context

Customizing the issuer value for an enterprise changes the OIDC JWT iss value for all repos/orgs in the enterprise to include the enterprise slug, which is often different from the organisation slug (and afaik can't be publicly determined).

For example, our iss value on https://github.com/Skyscanner changed from https://token.actions.githubusercontent.com to https://token.actions.githubusercontent.com/skyscanner.

Note these happen to have the same jwks_uri as uncustomised/regular JWTs from github.com.

@unlobito unlobito added bug 🐛 requires triaging maintainers need to do initial inspection of issue labels Mar 3, 2025
@di
Copy link
Member

di commented Mar 3, 2025

Thanks for the issue, this is indeed similar to #15838 in that we don't support arbitrary issuers and probably won't in the future (there is a good explanation of why here).

I think this is different, however, since the issuer is still the token.actions.githubusercontent.com domain. Additionally, per "Customizing the issuer value for an enterprise", the slug is predictable in this case, so we can cross-check it with the enterprise claim when it is set.

Given that, I think we could let users optionally provide a value for enterprise when configuring the publisher. We could either assume the presence of this field means we should expect the issuer to be customized, or we could add an additional option to change the expected issuer, although I'm not sure I see value in just verifying the enterprise claim when the default issuer is being used.

(cc @woodruffw for thoughts as well)

@di di added feature request trusted-publishing and removed requires triaging maintainers need to do initial inspection of issue bug 🐛 labels Mar 3, 2025
@di di pinned this issue Mar 3, 2025
@di di unpinned this issue Mar 3, 2025
@woodruffw
Copy link
Member

Thanks for the ping @di!

Yeah, I agree we can probably handle this case, since it's not "really" a custom OIDC issuer, just a namespacing customization of one we already understand 🙂

One hiccup in terms of handling this is the JWKS updating/synchronization logic: right now we have a hardcoded suite of supported OIDC issuers, with fixed issuer URLs:

config.register_service_factory(
OIDCPublisherServiceFactory(
publisher="github",
issuer_url=GITHUB_OIDC_ISSUER_URL,
service_class=oidc_publisher_service_class,
),
IOIDCPublisherService,
name="github",
)
config.register_service_factory(
OIDCPublisherServiceFactory(
publisher="gitlab",
issuer_url=GITLAB_OIDC_ISSUER_URL,
service_class=oidc_publisher_service_class,
),
IOIDCPublisherService,
name="gitlab",
)
config.register_service_factory(
OIDCPublisherServiceFactory(
publisher="google",
issuer_url=GOOGLE_OIDC_ISSUER_URL,
service_class=oidc_publisher_service_class,
),
IOIDCPublisherService,
name="google",
)
config.register_service_factory(
OIDCPublisherServiceFactory(
publisher="activestate",
issuer_url=ACTIVESTATE_OIDC_ISSUER_URL,
service_class=oidc_publisher_service_class,
),
IOIDCPublisherService,
name="activestate",
)

Those URLs are used to key into the appropriate service when verifying JWTs, so we'd probably need a bit of customization/dynamization to handle these kinds of enterprise-suffixed issuers.

# Associate the given issuer claim with Warehouse's OIDCPublisherService.
service_name = OIDC_ISSUER_SERVICE_NAMES.get(unverified_issuer)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants