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

In Using a Publisher docs, call out that GitHub Actions permissions also need contents: read to checkout private repositories #17148

Open
contrast-jproberts opened this issue Nov 21, 2024 · 7 comments
Labels
blocked Issues we can't or shouldn't get to yet documentation trusted-publishing

Comments

@contrast-jproberts
Copy link

contrast-jproberts commented Nov 21, 2024

What's the problem this feature will solve?
https://docs.pypi.org/trusted-publishers/using-a-publisher/ gives examples of how to change a GitHub Actions workflow to use Trusted Publishing. There's an IMPORTANT comment that we add permissions to the job for writing OIDC tokens. I thought these permissions were merged with the default permissions. That's not true though, the permissions must be complete because they will override any defaults.

Users who publish source distributions from a checkout of the GitHub repository, will also need the contents: read permission. Without it, the checkout fails with remote: Repository not found. For more complete error output, see the bottom code block of https://github.com/orgs/community/discussions/57621 .

Describe the solution you'd like
I'd like to see the documentation call out that contents: read is also required in the permissions to use actions/checkout. I think the practice is common enough that it's worth clarifying. I expect most packages would publish using either a source distribution from actions/checkout, or wheels that are either built in the same job from actions/checkout or downloaded from a previous job with actions/download-artifact. Downloading artifacts doesn't need any extra permissions, but the other two use cases will.

@contrast-jproberts contrast-jproberts added feature request requires triaging maintainers need to do initial inspection of issue labels Nov 21, 2024
@di
Copy link
Member

di commented Nov 21, 2024

Thanks for filing an issue.

Users who publish source distributions from a checkout of the GitHub repository, will also need the content: read permission.

I don't think this is exactly true. For example, here's a workflow for sampleproject that only has a job-level id-token: write permission, but it's able to successfully run actions/checkout (example run) without additional permissions.

At https://docs.pypi.org/trusted-publishers/using-a-publisher/ , we recommend adding a job-level permission, not a workflow-level permission:

jobs:
  pypi-publish:
    name: upload release to PyPI
    runs-on: ubuntu-latest
    # Specifying a GitHub environment is optional, but strongly encouraged
    environment: pypi
    permissions:
      # IMPORTANT: this permission is mandatory for trusted publishing
      id-token: write
    steps:
      # retrieve your distributions here

      - name: Publish package distributions to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1

The docs at https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token says:

When you add the permissions key within a specific job, all actions and run commands within that job that use the GITHUB_TOKEN gain the access rights you specify.

My read of this is that job-level permissions are additive to default or specified workflow permissions, which seems to be the case based on that example.

Here's another example that explicitly sets contents: read as a workflow-level permission and then later sets only id-token: write as a job-level permission, which also runs actions/download-artifact without any problem (example run).

If you have an example workflow & run that is failing when only setting id-token: wrote as a job-level permission, can you share it here so we can take a closer look?

(PS, note that you have a typo, it's contents: read, not content: read)

@contrast-jproberts
Copy link
Author

contrast-jproberts commented Nov 21, 2024

Thanks for the quick response!

You're right about the typo, that was a mistake in the issue but not my code. Sorry about that. I've made edits to avoid confusion.

I have been using a job-level permission. I think the issue could be that I'm attempting to checkout a private repository, whereas the examples you've seen are public.

Here's the job contents if it helps. There's a custom action as the second step, but I saw failures in the first.

jobs:
  deploy:
    environment: release  # requires approvals for this job to run
    permissions:
      # contents: read # required for cloning the repository # TODO: add this back so actions/checkout doesn't fail.
      id-token: write # required for trusted publishing
    runs-on: ubuntu-latest
    timeout-minutes: 6
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
      - uses: ./.github/actions/setup
        with:
          python-version: '3.12'
          build: 'true'
      - name: Deploy to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1

I can confirm that after I added the contents: read permission, everything worked perfectly. I didn't need to make any other changes.

If this is only an issue for private repositories, I understand if that's less prevalent and doesn't meet the bar for a documentation update.

@contrast-jproberts contrast-jproberts changed the title In Using a Publisher docs, call out that GitHub Actions permissions also need content: read to checkout repositories In Using a Publisher docs, call out that GitHub Actions permissions also need content: read to checkout private repositories Nov 21, 2024
@contrast-jproberts contrast-jproberts changed the title In Using a Publisher docs, call out that GitHub Actions permissions also need content: read to checkout private repositories In Using a Publisher docs, call out that GitHub Actions permissions also need contents: read to checkout private repositories Nov 21, 2024
@di
Copy link
Member

di commented Nov 21, 2024

Indeed, seems like this is an undocumented behavior of private repositories: actions/checkout#445 (comment)

And it's been identified here: pypa/gh-action-pypi-publish#237

Based on that, my understanding is that you would need to specify contents: read regardless of whether you've set additional permissions on the job, is that the case?

@contrast-jproberts
Copy link
Author

Oh, good find! If I'd seen that pypa/gh-action-pypi-publish#237 I wouldn't have opened this issue 😅

I didn't need the contents: read permission before, when I hadn't specified any permissions at the workflow or job level. Without permissions specified, I see this in the output of the "Set up job" section

GITHUB_TOKEN Permissions
  Contents: read
  Metadata: read
  Packages: read

So I think those are the defaults. Once I set the id-token: write permission, the output becomes

GITHUB_TOKEN Permissions
  Metadata: read

I was surprised to see the Metadata permission is still present.

I'll keep investigating on my end. It's clear I jumped to conclusions before opening this issue. Thank you for your patience and help refining the problem.

@contrast-jproberts
Copy link
Author

I'm also happy to close this and follow pypa/gh-action-pypi-publish#237 if they're better owners.

@di
Copy link
Member

di commented Nov 21, 2024

Huh, quite odd behavior. I think whatever the outcome in pypa/gh-action-pypi-publish#237 we'll want to do something similar in our docs, so OK to leave this open in addition.

@di di added blocked Issues we can't or shouldn't get to yet and removed requires triaging maintainers need to do initial inspection of issue labels Nov 21, 2024
@contrast-jproberts
Copy link
Author

This docs page matches what I've been seeing: https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#permissions-for-the-github_token

Notably, the default "restricted" permissions set give read access to contents, metadata and packages like I saw without any permissions fields defined in my workflow at the top level or job level.

Then we modified permissions, which is explained in https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token (emphasis mine)

You can use the permissions key in your workflow file to modify permissions for the GITHUB_TOKEN for an entire workflow or for individual jobs. This allows you to configure the minimum required permissions for a workflow or job. When the permissions key is used, all unspecified permissions are set to no access, with the exception of the metadata scope, which always gets read access.

So while I was surprised that read permission for metadata was still present, it seems to be a documented special case. No other permissions are available though unless they're explicitly set, which explains why I needed to add contents: read.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked Issues we can't or shouldn't get to yet documentation trusted-publishing
Projects
None yet
Development

No branches or pull requests

2 participants