Skip to content

Commit f036799

Browse files
Streamline settings (#22)
* Remove `no-default-files` setting Signed-off-by: Alex Cameron <[email protected]> * Remove `overwrite` setting * Add setting for identity token for the case where we don't want to use the GitHub Actions credential * Remove overwrite mapping * Add identity token mapping * Rename `oidc-issuer` to `verify-oidc-issuer` and only apply it to the `verify` invocation * Update action.py Co-authored-by: William Woodruff <[email protected]> * Fix CLI option * Get the name right this time... * Add more self tests to CI (#23) * Add a few more selftests * Add selftest to verify OIDC issuer * Fill in the expected OIDC issuer * Fill in expected SAN * Correct SAN * Comment out verify SAN test * Add selftest to exercise `identity-token` setting * Update .github/workflows/selftest.yml Co-authored-by: William Woodruff <[email protected]> Co-authored-by: William Woodruff <[email protected]>
1 parent 8af9a48 commit f036799

File tree

4 files changed

+126
-99
lines changed

4 files changed

+126
-99
lines changed

.github/workflows/selftest.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ jobs:
4141
id: sigstore-python
4242
with:
4343
inputs: ./test/*.txt
44+
staging: true
4445

4546
selftest-upload-artifacts:
4647
runs-on: ubuntu-latest
@@ -53,3 +54,64 @@ jobs:
5354
inputs: ./test/artifact.txt
5455
staging: true
5556
upload-signing-artifacts: true
57+
58+
selftest-custom-paths:
59+
runs-on: ubuntu-latest
60+
steps:
61+
- uses: actions/checkout@v3
62+
- name: Sign artifact and publish signature
63+
uses: ./
64+
id: sigstore-python
65+
with:
66+
inputs: ./test/artifact.txt
67+
signature: ./test/custom_signature.sig
68+
certificate: ./test/custom_certificate.crt
69+
staging: true
70+
71+
# NOTE(alex): `sigstore-python` doesn't support verifying URI SANs yet.
72+
# selftest-verify-san:
73+
# runs-on: ubuntu-latest
74+
# steps:
75+
# - uses: actions/checkout@v3
76+
# - name: Sign artifact and publish signature
77+
# uses: ./
78+
# id: sigstore-python
79+
# with:
80+
# inputs: ./test/artifact.txt
81+
# verify-cert-email: https://github.com/trailofbits/gh-action-sigstore-python/.github/workflows/selftest.yml@${{ github.ref }}
82+
# staging: true
83+
84+
selftest-verify-issuer:
85+
runs-on: ubuntu-latest
86+
steps:
87+
- uses: actions/checkout@v3
88+
- name: Sign artifact and publish signature
89+
uses: ./
90+
id: sigstore-python
91+
with:
92+
inputs: ./test/artifact.txt
93+
verify-oidc-issuer: https://token.actions.githubusercontent.com
94+
staging: true
95+
96+
selftest-identity-token:
97+
runs-on: ubuntu-latest
98+
steps:
99+
- uses: actions/checkout@v3
100+
- name: Get OIDC token
101+
id: get-oidc-token
102+
run: |
103+
identity_token=$( \
104+
curl -H \
105+
"Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
106+
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sigstore" \
107+
| jq -r .value \
108+
)
109+
echo "::set-output name=identity-token::$identity_token"
110+
shell: bash
111+
- name: Sign artifact and publish signature
112+
uses: ./
113+
id: sigstore-python
114+
with:
115+
inputs: ./test/artifact.txt
116+
identity-token: ${{ steps.get-oidc-token.outputs.identity-token }}
117+
staging: true

README.md

Lines changed: 33 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,20 @@ The `inputs` argument also supports file globbing:
6868
inputs: ./path/to/inputs/*.txt
6969
```
7070

71+
### `identity-token`
72+
73+
**Default**: Empty (the GitHub Actions credential will be used)
74+
75+
The `identity-token` setting controls the OpenID Connect token provided to Fulcio. By default, the
76+
workflow will use the credentials found in the GitHub Actions environment.
77+
78+
```yaml
79+
- uses: trailofbits/[email protected]
80+
with:
81+
inputs: file.txt
82+
identity-token: ${{ IDENTITY_TOKEN }} # assigned elsewhere
83+
```
84+
7185
### `oidc-client-id`
7286

7387
**Default**: `sigstore`
@@ -100,25 +114,6 @@ Example:
100114
oidc-client-secret: alternative-sigstore-secret
101115
```
102116

103-
### `no-default-files`
104-
105-
**Default**: `false`
106-
107-
The `no-default-files` setting controls whether the default output files (`{input}.sig` and
108-
`{input.crt}`) are emitted.
109-
110-
These output files are necessary for verification so turning this setting on will automatically set
111-
`verify` to `false`.
112-
113-
Example:
114-
115-
```yaml
116-
- uses: trailofbits/[email protected]
117-
with:
118-
inputs: file.txt
119-
no-default-files: true
120-
```
121-
122117
### `signature`
123118

124119
**Default**: Empty (signature files will get named as `{input}.sig`)
@@ -169,22 +164,6 @@ However, this example is invalid:
169164
certificate: custom-certificate-filename.crt
170165
```
171166

172-
### `overwrite`
173-
174-
**Default**: `false`
175-
176-
The `overwrite` setting controls whether preexisting signature and certificate outputs get
177-
overwritten.
178-
179-
Example:
180-
181-
```yaml
182-
- uses: trailofbits/[email protected]
183-
with:
184-
inputs: file.txt
185-
overwrite: true
186-
```
187-
188167
### `fulcio-url`
189168

190169
**Default**: `https://fulcio.sigstore.dev`
@@ -249,23 +228,6 @@ Example:
249228
ctfe: ./path/to/rekor.pub
250229
```
251230

252-
### `oidc-issuer`
253-
254-
**Default**: `https://oauth2.sigstore.dev/auth`
255-
256-
The `oidc-issuer` setting controls the OpenID Connect issuer to retrieve the OpenID Connect token
257-
from. If `verify` is on, the issuer extension of the signing certificate will also get
258-
checked to ensure that it matches.
259-
260-
Example:
261-
262-
```yaml
263-
- uses: trailofbits/[email protected]
264-
with:
265-
inputs: file.txt
266-
oidc-issuer: https://oauth2.sigstage.dev/auth
267-
```
268-
269231
### `staging`
270232

271233
**Default**: `false`
@@ -319,6 +281,25 @@ This setting only applies if `verify` is set to `true`.
319281
verify-cert-email: [email protected]
320282
```
321283

284+
### `verify-oidc-issuer`
285+
286+
**Default**: `https://oauth2.sigstore.dev/auth`
287+
288+
The `verify-oidc-issuer` setting controls whether to verify the issuer extension of the signing
289+
certificate after signing has taken place. If it is set, `sigstore-python` will compare the
290+
certificate's issuer extension against the provided value.
291+
292+
This setting only applies if `verify` is set to `true`.
293+
294+
Example:
295+
296+
```yaml
297+
- uses: trailofbits/[email protected]
298+
with:
299+
inputs: file.txt
300+
verify-oidc-issuer: https://oauth2.sigstage.dev/auth
301+
```
302+
322303
### `upload-signing-artifacts`
323304

324305
**Default**: `false`

action.py

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ def _fatal_help(msg):
7272
if _DEBUG:
7373
sigstore_python_env["SIGSTORE_LOGLEVEL"] = "DEBUG"
7474

75+
identity_token = os.getenv("GHA_SIGSTORE_PYTHON_IDENTITY_TOKEN")
76+
if identity_token != "":
77+
sigstore_sign_args.extend(["--identity-token", identity_token])
78+
7579
client_id = os.getenv("GHA_SIGSTORE_PYTHON_OIDC_CLIENT_ID")
7680
if client_id != "":
7781
sigstore_sign_args.extend(["--oidc-client-id", client_id])
@@ -80,16 +84,6 @@ def _fatal_help(msg):
8084
if client_secret != "":
8185
sigstore_sign_args.extend(["--oidc-client-secret", client_secret])
8286

83-
if os.getenv("GHA_SIGSTORE_PYTHON_NO_DEFAULT_FILES", "false") != "false":
84-
sigstore_sign_args.append("--no-default-files")
85-
86-
# If we don't write the certificate and signature to the disk, we're unable
87-
# to verify afterwards.
88-
_debug(
89-
"disabling verification due to the `no-default-files` setting being provided"
90-
)
91-
enable_verify = False
92-
9387
signature = os.getenv("GHA_SIGSTORE_PYTHON_SIGNATURE")
9488
if signature != "":
9589
sigstore_sign_args.extend(["--signature", signature])
@@ -110,9 +104,6 @@ def _fatal_help(msg):
110104
sigstore_sign_args.extend(["--certificate", output_certificate])
111105
signing_artifact_paths.append(output_certificate)
112106

113-
if os.getenv("GHA_SIGSTORE_PYTHON_OVERWRITE", "false") != "false":
114-
sigstore_sign_args.append("--overwrite")
115-
116107
fulcio_url = os.getenv("GHA_SIGSTORE_PYTHON_FULCIO_URL")
117108
if fulcio_url != "":
118109
sigstore_sign_args.extend(["--fulcio-url", fulcio_url])
@@ -130,11 +121,6 @@ def _fatal_help(msg):
130121
if rekor_root_pubkey != "":
131122
sigstore_sign_args.extend(["--rekor-root-pubkey", rekor_root_pubkey])
132123

133-
oidc_issuer = os.getenv("GHA_SIGSTORE_PYTHON_OIDC_ISSUER")
134-
if oidc_issuer != "":
135-
sigstore_sign_args.extend(["--oidc-issuer", oidc_issuer])
136-
sigstore_verify_args.extend(["--oidc-issuer", oidc_issuer])
137-
138124
if os.getenv("GHA_SIGSTORE_PYTHON_STAGING", "false") != "false":
139125
sigstore_sign_args.append("--staging")
140126
sigstore_verify_args.append("--staging")
@@ -146,6 +132,10 @@ def _fatal_help(msg):
146132
if verify_cert_email != "":
147133
sigstore_verify_args.extend(["--cert-email", verify_cert_email])
148134

135+
verify_oidc_issuer = os.getenv("GHA_SIGSTORE_PYTHON_VERIFY_OIDC_ISSUER")
136+
if verify_oidc_issuer != "":
137+
sigstore_verify_args.extend(["--cert-oidc-issuer", verify_oidc_issuer])
138+
149139
for input_ in inputs:
150140
# Forbid things that look like flags. This isn't a security boundary; just
151141
# a way to prevent (less motivated) users from breaking the action on themselves.
@@ -224,20 +214,19 @@ def _fatal_help(msg):
224214
#
225215
# In GitHub Actions, environment variables can be made to persist across
226216
# workflow steps by appending to the file at `GITHUB_ENV`.
227-
if "--no-default-files" not in sigstore_sign_args:
228-
with Path(os.getenv("GITHUB_ENV")).open("a") as gh_env:
229-
# Multiline values must match the following syntax:
230-
#
231-
# {name}<<{delimiter}
232-
# {value}
233-
# {delimiter}
234-
gh_env.write(
235-
"GHA_SIGSTORE_PYTHON_SIGNING_ARTIFACTS<<EOF"
236-
+ os.linesep
237-
+ os.linesep.join(signing_artifact_paths)
238-
+ os.linesep
239-
+ "EOF"
240-
)
217+
with Path(os.getenv("GITHUB_ENV")).open("a") as gh_env:
218+
# Multiline values must match the following syntax:
219+
#
220+
# {name}<<{delimiter}
221+
# {value}
222+
# {delimiter}
223+
gh_env.write(
224+
"GHA_SIGSTORE_PYTHON_SIGNING_ARTIFACTS<<EOF"
225+
+ os.linesep
226+
+ os.linesep.join(signing_artifact_paths)
227+
+ os.linesep
228+
+ "EOF"
229+
)
241230

242231

243232
# If signing didn't fail, then we check the verification status, if present.

action.yml

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ inputs:
66
description: "the files to sign, whitespace separated"
77
required: true
88
default: ""
9+
identity-token:
10+
description: "the OIDC identity token to use"
11+
required: false
12+
default: ""
913
oidc-client-id:
1014
description: "the custom OpenID Connect client ID to use during OAuth2"
1115
required: false
@@ -14,10 +18,6 @@ inputs:
1418
description: "the custom OpenID Connect client secret to use during OAuth2"
1519
required: false
1620
default: ""
17-
no-default-files:
18-
description: "don't emit the default output files ({input}.sig and {input}.crt)"
19-
required: false
20-
default: false
2121
signature:
2222
description: "write a single signature to the given file; does not work with multiple input files"
2323
required: false
@@ -26,10 +26,6 @@ inputs:
2626
description: "write a single certificate to the given file; does not work with multiple input files"
2727
required: false
2828
default: ""
29-
overwrite:
30-
description: "overwrite preexisting signature and certificate outputs, if present"
31-
required: false
32-
default: false
3329
fulcio-url:
3430
description: "the Fulcio instance to use (conflicts with `staging`)"
3531
required: false
@@ -46,10 +42,6 @@ inputs:
4642
description: "a PEM-encoded root public key for Rekor itself (conflicts with `staging`)"
4743
required: false
4844
default: ""
49-
oidc-issuer:
50-
description: "the OpenID Connect issuer to use; if `verify` is on, the issuer extension of the signing certificate will also get checked to ensure that it matches"
51-
required: false
52-
default: ""
5345
staging:
5446
description: "use sigstore's staging instances, instead of the default production instances"
5547
required: false
@@ -62,6 +54,10 @@ inputs:
6254
description: "verify the email address to in the signing certificate's Subject Alternative Name (only applies when `verify` is on)"
6355
required: false
6456
default: ""
57+
verify-oidc-issuer:
58+
description: "verify the issuer extension of the signing certificate"
59+
required: false
60+
default: ""
6561
upload-signing-artifacts:
6662
description: "upload all signing artifacts as workflow artifacts"
6763
required: false
@@ -89,20 +85,19 @@ runs:
8985
run: |
9086
${{ github.action_path }}/action.py "${{ inputs.inputs }}"
9187
env:
92-
GHA_SIGSTORE_PYTHON_NO_DEFAULT_FILES: "${{ inputs.no-default-files }}"
88+
GHA_SIGSTORE_PYTHON_IDENTITY_TOKEN: "${{ inputs.identity-token }}"
9389
GHA_SIGSTORE_PYTHON_SIGNATURE: "${{ inputs.signature }}"
9490
GHA_SIGSTORE_PYTHON_CERTIFICATE: "${{ inputs.certificate }}"
95-
GHA_SIGSTORE_PYTHON_OVERWRITE: "${{ inputs.overwrite }}"
9691
GHA_SIGSTORE_PYTHON_OIDC_CLIENT_ID: "${{ inputs.oidc-client-id }}"
9792
GHA_SIGSTORE_PYTHON_OIDC_CLIENT_SECRET: "${{ inputs.oidc-client-secret }}"
9893
GHA_SIGSTORE_PYTHON_FULCIO_URL: "${{ inputs.fulcio-url }}"
9994
GHA_SIGSTORE_PYTHON_REKOR_URL: "${{ inputs.rekor-url }}"
10095
GHA_SIGSTORE_PYTHON_CTFE: "${{ inputs.ctfe }}"
10196
GHA_SIGSTORE_PYTHON_REKOR_ROOT_PUBKEY: "${{ inputs.rekor-root-pubkey }}"
102-
GHA_SIGSTORE_PYTHON_OIDC_ISSUER: "${{ inputs.oidc-issuer }}"
10397
GHA_SIGSTORE_PYTHON_STAGING: "${{ inputs.staging }}"
10498
GHA_SIGSTORE_PYTHON_VERIFY: "${{ inputs.verify }}"
10599
GHA_SIGSTORE_PYTHON_VERIFY_CERT_EMAIL: "${{ inputs.verify-cert-email }}"
100+
GHA_SIGSTORE_PYTHON_VERIFY_OIDC_ISSUER: "${{ inputs.verify-oidc-issuer }}"
106101
GHA_SIGSTORE_PYTHON_INTERNAL_BE_CAREFUL_DEBUG: "${{ inputs.internal-be-careful-debug }}"
107102
shell: bash
108103

0 commit comments

Comments
 (0)