Skip to content

Commit a98c10d

Browse files
committed
Add instructions on trusted publishers
1 parent 471d8cf commit a98c10d

2 files changed

Lines changed: 85 additions & 31 deletions

File tree

.github/workflows/publish.yml

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454

5555
Provenance:
5656
needs: ["Build"]
57-
uses: "slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.4.0"
57+
uses: "slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.5.0"
5858
permissions:
5959
actions: read
6060
id-token: write
@@ -70,16 +70,21 @@ jobs:
7070
if: startsWith(github.ref, 'refs/tags/')
7171
needs: ["Build", "Provenance"]
7272
runs-on: "ubuntu-latest"
73-
# This environment gives access to 'secrets.PYPI_TOKEN'
74-
# and must be approved by environment reviewers before running.
75-
environment:
76-
name: "publish"
7773

7874
permissions:
7975
# contents: write is only needed to upload the
8076
# dists to the GitHub release.
8177
contents: write
8278

79+
# This permission allows for the gh-action-pypi-publish
80+
# step to access GitHub OpenID Connect tokens.
81+
id-token: write
82+
83+
# This job requires the 'publish' GitHub Environment to run.
84+
# This value is also set in the Trusted Publisher.
85+
environment:
86+
name: "publish"
87+
8388
# Now that we've built and attested to the distributables
8489
# provenance we can upload them to PyPI and add to the GitHub release.
8590
steps:
@@ -96,7 +101,4 @@ jobs:
96101
gh release upload ${{ github.ref_name }} dist/* --repo ${{ github.repository }}
97102
98103
- name: "Publish dists to PyPI"
99-
uses: "pypa/gh-action-pypi-publish@c7f29f7adef1a245bd91520e94867e5c6eedddcc"
100-
with:
101-
user: __token__
102-
password: "${{ secrets.PYPI_TOKEN }}"
104+
uses: "pypa/gh-action-pypi-publish@0bf742be3ebe032c25dd15117957dc15d0cfc38d"

README.md

Lines changed: 74 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ The goals of this project are to:
1717
- Obtain a perfect rating from [OpenSSF Scorecard](https://github.com/ossf/scorecard)
1818
- [SLSA Level 3](https://slsa.dev) using GitHub OIDC
1919

20-
## Configuring git
20+
## Configuring git for commit and tag signing
21+
22+
> **Info**
23+
> Commit and tag signing is a practice that's recommended to avoid commit author spoofing
24+
> but isn't strictly required for a secure project configuration.
25+
> If you'd like to skip this step, you can jump ahead to [creating a GitHub repository](https://github.com/sethmlarson/secure-python-package-template/#creating-the-github-repository).
2126
2227
Git needs to be configured to be able to sign commits and tags. Git uses GPG for signing, so you need to
2328
[create a GPG key](https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key)
@@ -150,26 +155,6 @@ To ssh://github.com/sethmlarson/package-name
150155

151156
Success! You should now see the commit and all files on your GitHub repository.
152157

153-
## Configuring PyPI
154-
155-
PyPI is increasing the minimum requirements for account security and credential management to make consuming packages on PyPI more secure. This includes [eventually requiring 2FA for all users and requiring API tokens to publish packages](https://pyfound.blogspot.com/2020/01/start-using-2fa-and-api-tokens-on-pypi.html). Instead of waiting for these best practices to become required we can opt-in to them now.
156-
157-
### Obtain an API token
158-
159-
API tokens will eventually be required for all packages to publish to PyPI.
160-
161-
- Upload a dummy v0.0 package under the desired package name using your PyPI username and password.
162-
- Create an API token that is scoped to only the package
163-
- Copy the value into your clipboard, it will be used later (see `PYPI_TOKEN` in the GitHub Environments section below)
164-
165-
### Opt-in to required 2FA
166-
167-
If you don't have 2FA enabled on PyPI already there's a section in the [PyPI Help page](https://pypi.org/help) about how to enable 2FA for your account. To make 2FA required for the new project:
168-
169-
- Open "Your projects" on PyPI
170-
- Select "Manage" for the project
171-
- Settings > Enable 2FA requirement for project
172-
173158
## Configuring the GitHub repository
174159

175160
### Dependabot
@@ -275,6 +260,73 @@ pip-compile \
275260
users to privately submit vulnerability reports directly to the repository.
276261
- Update the URL in the `SECURITY.md` file to the URL of your own repository.
277262

263+
## Configuring PyPI
264+
265+
PyPI is increasing the minimum requirements for account security and credential management to make consuming packages on PyPI more secure. This includes [eventually requiring 2FA for all users and requiring API tokens to publish packages](https://pyfound.blogspot.com/2020/01/start-using-2fa-and-api-tokens-on-pypi.html). Instead of waiting for these best practices to become required we can opt-in to them now.
266+
267+
### Opt-in to required 2FA
268+
269+
If you don't have 2FA enabled on PyPI already there's a section in the [PyPI Help page](https://pypi.org/help) about how to enable 2FA for your account. To make 2FA required for the new project:
270+
271+
- Open "Your projects" on PyPI
272+
- Select "Manage" for the project
273+
- Settings > Enable 2FA requirement for project
274+
275+
### Configuring a Trusted Publisher
276+
277+
If your project is hosted on GitHub you can take advantage of a new PyPI feature called "[Trusted Publishers](https://docs.pypi.org/trusted-publishers/)".
278+
It's recommended to use a Trusted Publisher over an API key or password because it provides an additional layer of security
279+
by requiring the package to originate from a pre-configured GitHub repository, workflow, and environment.
280+
281+
There's a [short guide on how to add a Trusted Publisher to the project](https://docs.pypi.org/trusted-publishers/adding-a-publisher/).
282+
Below is an example of how to map the publishing GitHub Workflow definition to the PyPI Trusted Publisher.
283+
284+
> **Warning**
285+
> Care should be taken that the publishing workflow can only be triggered
286+
> by the GitHub accounts that you intend. Remember that git tags (without Protected Tags enabled)
287+
> only require write access to the repository. This is why GitHub Environments with
288+
> a set of required reviewers is highly recommended to have an explicit list of
289+
> people who are allowed to completely execute the publish job.
290+
291+
Configuring the Trusted Publisher requires 4 values:
292+
293+
- GitHub repository owner
294+
- GitHub repository name
295+
- GitHub workflow filename
296+
- GitHub environment name (optional, but highly recommended!)
297+
298+
Using this repository ([https://github.com/sethmlarson/secure-python-package-template](https://github.com/sethmlarson/secure-python-package-template)) as an example, the values to set up a Trusted Publisher would be:
299+
300+
- GitHub repository owner: `sethmlarson`
301+
- GitHub repository name: `secure-python-package-template`
302+
- GitHub workflow filename: `publish.yml`
303+
- GitHub environment name: `publish`
304+
305+
Below is the minimum configurations required from the GitHub Workflow:
306+
307+
```yaml
308+
# Filename: '.github/workflows/publish.yml'
309+
# Note that the 'publish.yml' filename doesn't need the '.github/workflows' prefix.
310+
jobs:
311+
publish:
312+
# ...
313+
permissions:
314+
# This permission allows for the gh-action-pypi-publish
315+
# step to access GitHub OpenID Connect tokens.
316+
id-token: write
317+
318+
# This job requires the 'publish' GitHub Environment to run.
319+
# This value is also set in the Trusted Publisher.
320+
environment:
321+
name: "publish"
322+
323+
steps:
324+
# - ...
325+
# The 'pypa/gh-action-pypi-publish' action reads OpenID Connect
326+
# Note that there's zero config below, it's all magically handled!
327+
- uses: "pypa/gh-action-pypi-publish@0bf742be3ebe032c25dd15117957dc15d0cfc38d"
328+
```
329+
278330
## Verifying configurations
279331

280332
### Verifying reproducible builds
@@ -298,7 +350,7 @@ Check out the corresponding git tag.
298350
git checkout v0.1.0
299351
```
300352
301-
Run below command and export the stored value into `SOURCE_DATE_EPOCH`..
353+
Run below command and export the stored value into `SOURCE_DATE_EPOCH`:
302354
303355
```sh
304356
$ git log -1 --pretty=%ct

0 commit comments

Comments
 (0)