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

[error] * invalid-publisher: valid token, but no corresponding publisher #138

Closed
yozachar opened this issue Mar 29, 2023 · 19 comments · Fixed by #142
Closed

[error] * invalid-publisher: valid token, but no corresponding publisher #138

yozachar opened this issue Mar 29, 2023 · 19 comments · Fixed by #142

Comments

@yozachar
Copy link

From validators/actions/runs/4550595346/jobs/8023753623

Run pypa/gh-action-pypi-publish@release/v1
/usr/bin/docker run --name c0442075403f75bc9417ab8fbffed20a2928e_3f477f --label 6c0442 --workdir /github/workspace --rm -e "pythonLocation" -e "PKG_CONFIG_PATH" -e "Python_ROOT_DIR" -e "Python2_ROOT_DIR" -e "Python3_ROOT_DIR" -e "LD_LIBRARY_PATH" -e "VENV" -e "INPUT_PASSWORD" -e "INPUT_USER" -e "INPUT_REPOSITORY-URL" -e "INPUT_REPOSITORY_URL" -e "INPUT_PACKAGES-DIR" -e "INPUT_PACKAGES_DIR" -e "INPUT_VERIFY-METADATA" -e "INPUT_VERIFY_METADATA" -e "INPUT_SKIP-EXISTING" -e "INPUT_SKIP_EXISTING" -e "INPUT_VERBOSE" -e "INPUT_PRINT-HASH" -e "INPUT_PRINT_HASH" -e "HOME" -e "GITHUB_JOB" -e "GITHUB_REF" -e "GITHUB_SHA" -e "GITHUB_REPOSITORY" -e "GITHUB_REPOSITORY_OWNER" -e "GITHUB_REPOSITORY_OWNER_ID" -e "GITHUB_RUN_ID" -e "GITHUB_RUN_NUMBER" -e "GITHUB_RETENTION_DAYS" -e "GITHUB_RUN_ATTEMPT" -e "GITHUB_REPOSITORY_ID" -e "GITHUB_ACTOR_ID" -e "GITHUB_ACTOR" -e "GITHUB_TRIGGERING_ACTOR" -e "GITHUB_WORKFLOW" -e "GITHUB_HEAD_REF" -e "GITHUB_BASE_REF" -e "GITHUB_EVENT_NAME" -e "GITHUB_SERVER_URL" -e "GITHUB_API_URL" -e "GITHUB_GRAPHQL_URL" -e "GITHUB_REF_NAME" -e "GITHUB_REF_PROTECTED" -e "GITHUB_REF_TYPE" -e "GITHUB_WORKFLOW_REF" -e "GITHUB_WORKFLOW_SHA" -e "GITHUB_WORKSPACE" -e "GITHUB_ACTION" -e "GITHUB_EVENT_PATH" -e "GITHUB_ACTION_REPOSITORY" -e "GITHUB_ACTION_REF" -e "GITHUB_PATH" -e "GITHUB_ENV" -e "GITHUB_STEP_SUMMARY" -e "GITHUB_STATE" -e "GITHUB_OUTPUT" -e "RUNNER_OS" -e "RUNNER_ARCH" -e "RUNNER_NAME" -e "RUNNER_TOOL_CACHE" -e "RUNNER_TEMP" -e "RUNNER_WORKSPACE" -e "ACTIONS_RUNTIME_URL" -e "ACTIONS_RUNTIME_TOKEN" -e "ACTIONS_CACHE_URL" -e "ACTIONS_ID_TOKEN_REQUEST_URL" -e "ACTIONS_ID_TOKEN_REQUEST_TOKEN" -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/validators/validators":"/github/workspace" 6c0442:075403f75bc9417ab8fbffed20a2928e  "__token__" "" "" "" "" "" "false" ""
Notice: Attempting to perform OIDC credential exchange  to retrieve a temporary short-lived API token for authentication  against https://upload.pypi.org/legacy/
Error: OIDC exchange failure: 
Token request failed: the server refused the request for the following reasons:

* `invalid-publisher`: valid token, but no corresponding publisher

What's wrong with validators/.github/workflows/build.yml?

# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

name: Build for PyPI

on:
  workflow_dispatch:
  release:
    types: [published]

permissions:
  contents: read

jobs:
  build_and_publish:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    steps:
      # checkout repository
      - uses: actions/checkout@v3
      # setup lowest supported python version
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: "3.8"
      # install & configure poetry
      - name: Install Poetry
        uses: snok/install-poetry@v1
        with:
          version: 1.4.1
          virtualenvs-create: true
          virtualenvs-in-project: true
      # install dependencies
      - name: Install dependencies
        run: poetry install --no-interaction --no-ansi --only docs
      # build package
      - name: Build package
        run: |
          source .venv/bin/activate
          python build.py
      # publish package
      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          password: ${{ secrets.PYPI_API_TOKEN }}
@webknjaz
Copy link
Member

@joe733 you forgot to declare the secret containing a PyPI API token, in you repository settings (global, or environment-scoped). So the action got an empty password input which triggered the new OIDC flow for secretless uploads. This feature is in private beta now so you need to set the secret to disable it.

https://github.com/python-validators/validators/actions/runs/4550595346#summary-12355045595

@woodruffw do you think we should add some title/pointer to the job summary to mention it's OIDC? Also explaining that to turn off the flow, one should pass in a token/password?

@webknjaz
Copy link
Member

@joe733 also, what's that build.py you're calling?

@webknjaz
Copy link
Member

@joe733 also, I see that you added a id-token: write in a separate commit. Was it in response to a workflow error you saw? What can @woodruffw and I do to make it clear that this feature needs trust to be set up on the PyPI side but is only available to select users in private beta?

Also, @woodruffw — do we need to start pointing to the new public docs?

@webknjaz
Copy link
Member

@joe733 if you want to enroll in private beta, here's some pointers: https://docs.pypi.org/trusted-publishers/. Otherwise, follow the instructions for making a project-scoped token.

@yozachar
Copy link
Author

@joe733 also, I see that you added a id-token: write in a separate commit. Was it in response to a workflow error you saw?

Hi yes @webknjaz, I didn't know OIDC would be auto triggered if secrets.PYPI_API_TOKEN was empty. Nothing in the readme seems to indicate such a behavior.

Notice: Attempting to perform OIDC credential exchange  to retrieve a temporary short-lived API token for authentication  against https://upload.pypi.org/legacy/
Error: OIDC exchange failure: 
OIDC token retrieval failed: GitHub: missing or insufficient OIDC token permissions, the ACTIONS_ID_TOKEN_REQUEST_TOKEN environment variable was unset

This generally indicates a workflow configuration error, such as insufficient
permissions. Make sure that your workflow has `id-token: write` configured
at the job level, e.g.:

    ```yaml
    permissions:
      id-token: write
    ```

Learn more at https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#adding-permissions-settings.

Before the above notice another message could be given like:

Warning: secrets.PYPI_API_TOKEN is empty or rejected.
...

Or provide another option like:

with:
    oidc: false
    password: ${{ secrets.PYPI_API_TOKEN }} # gets ignored if oidc is true

I think the author @kvesteri currently uses conventional authentication.

rel: python-validators/validators#256 (comment)

@woodruffw
Copy link
Member

do you think we should add some title/pointer to the job summary to mention it's OIDC? Also explaining that to turn off the flow, one should pass in a token/password?

Yeah, that makes sense to me. I can do that in a bit.

do we need to start pointing to the new public docs?

Also makes sense to me!

webknjaz added a commit that referenced this issue Apr 1, 2023
This change improves the error output produced within the OIDC token exchange script by adding a title and a link to the Warehouse documentation for trusted publishers.

Ref #138.
@webknjaz
Copy link
Member

webknjaz commented Apr 1, 2023

@woodruffw thanks for the PR! I was thinking that we could also have a clearer indication of why the OIDC flow got triggered in the first place. Like "Not using token- or password-based authentication because the user-provided password is empty". Other branches show things like "Using a user-provided API token for authentication" but this specific one doesn't, which is the primary cause for confusion, I suppose.

@joe733 suggested the following earlier:

Before the above notice another message could be given like:

Warning: secrets.PYPI_API_TOKEN is empty or rejected.

Or course, we cannot say secrets.PYPI_API_TOKEN in the error message because we have no way of knowing how the user named their secret or if they even provided token via a secret and not a plain text input 🤷‍♂️ but the idea in general is nice.

Or provide another option like:

with:
    oidc: false
    password: ${{ secrets.PYPI_API_TOKEN }} # gets ignored if oidc is true

Nope, the extra input idea was rejected to simplify the process for the end-users. Besides, we already have a clear indication for the OIDC opt-in which is an empty password + the __token__ user. Making the users manage a combination of inputs would increase cognitive load which would be unhelpful.

I think the author @kvesteri currently uses conventional authentication.

rel: python-validators/validators#256 (comment)

Likely, not many folks enrolled and have the feature flag for the private beta enabled.

@woodruffw
Copy link
Member

@woodruffw thanks for the PR! I was thinking that we could also have a clearer indication of why the OIDC flow got triggered in the first place. Like "Not using token- or password-based authentication because the user-provided password is empty". Other branches show things like "Using a user-provided API token for authentication" but this specific one doesn't, which is the primary cause for confusion, I suppose.

Makes sense to me, I can do that in a bit!

@woodruffw
Copy link
Member

Opened #142 with more exposition.

@tom-andersson
Copy link

tom-andersson commented Jun 13, 2023

Hey, unfortunately I'm getting the same error mentioned in the title of this issue when trying to use the trusted publisher feature. I've seen the discussion above from a couple month ago on this being a private feature for beta testers. However, it's now at the top of the README on release/v1 so I assumed that's no longer the case. Here's my YML and the associated logs - would appreciate it if someone could take a look: https://github.com/tom-andersson/deepsensor/actions/runs/5256689812/workflow

@woodruffw
Copy link
Member

That error indicates that you either haven't registered the publisher on PyPI's side, or that there may be a small typo in how you've registered it.

Can you confirm that you performed the trusted publisher registration, and also take a screencap of the publisher as it appears on the "publishing" page on PyPI? That'll help us debug further 🙂

@tom-andersson
Copy link

Thanks for the rapid response @woodruffw! I've actually solved it since my post 30 mins ago. I think the solution was to remove the optional 'environment' entry on the trusted publisher form on PyPI. I had previously named an environment in my GH repo containing PyPI secrets, which was a legacy from trying to set up publishing with API tokens. I had a theory that these secrets or the environment were somehow disrupting the authentication process, so I re-entered the trusted publisher form with the environment entry omitted and that solved it. Might be worth seeing if you can reproduce?

@woodruffw
Copy link
Member

Ah yep, that would do it -- if you specify an environment on the PyPI side, then the trusted publisher will only be authorized if the workflow actually runs in that environment.

The behavior is as follows:

  • No environment configured on PyPI: any explicit environment on GHA is okay (or none at all)
  • Environment configured on PyPI: the GHA workflow's environment must match exactly

@tom-andersson
Copy link

That makes sense, thanks for confirming @woodruffw :-)

@kemingy
Copy link

kemingy commented Jun 14, 2023

Ah yep, that would do it -- if you specify an environment on the PyPI side, then the trusted publisher will only be authorized if the workflow actually runs in that environment.

The behavior is as follows:

* No environment configured on PyPI: any explicit environment on GHA is okay (or none at all)

* Environment configured on PyPI: the GHA workflow's environment must match exactly

I also met this issue. Since using the environment is strong encouraged by PyPI, I think it's necessary to add this information to the doc and the invalid-publisher error message.

@glide-the
Copy link

glide-the commented Apr 26, 2024

I'm encountering a similar issue as @yozachar; nevertheless, I would suggest adding hints in such cases. I've noticed that the GitHub secret isn't empty in my situation

@ElieTaillard
Copy link

@glide-the check #232, maybe that can help you

@woodruffw
Copy link
Member

@glide-the Yes, #232 should provide some context.

In the future, it would be helpful if you could file a new issue with full details for this kind of problem -- it's difficult to triage "similar issues" without any additional context, especially since trusted publishing can fail in a few different but similar-looking ways. Thanks!

@jsbueno
Copy link

jsbueno commented Aug 10, 2024

or that there may be a small typo in how you've registered it.
Well... I guess Pypi won't forgive me for naming the file pipy.xml instead of pypi.xml on its side, will it? :-)

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

Successfully merging a pull request may close this issue.

8 participants