Skip to content

Commit e8754a0

Browse files
authored
[#patch] fix: image sign identity (#295)
1 parent 53a09d4 commit e8754a0

2 files changed

Lines changed: 159 additions & 5 deletions

File tree

.github/workflows/docker-build-and-push.yml

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ on:
3737
scan-image:
3838
type: boolean
3939
default: true
40+
sign-image:
41+
type: boolean
42+
default: true
4043
tags:
4144
type: string
4245
default: |
@@ -56,6 +59,19 @@ on:
5659
working-directory:
5760
type: string
5861
default: '.'
62+
outputs:
63+
image_name:
64+
description: "Full image name (<registry>/<image>)."
65+
value: ${{ jobs.build-and-push-image.outputs.image_name }}
66+
image_digest:
67+
description: "Pushed image digest (sha256:...), empty when push=false."
68+
value: ${{ jobs.build-and-push-image.outputs.image_digest }}
69+
image_ref:
70+
description: "Immutable image reference (<registry>/<image>@<digest>), empty when push=false."
71+
value: ${{ jobs.build-and-push-image.outputs.image_ref }}
72+
local_image_ref:
73+
description: "Local image reference used when push=false."
74+
value: ${{ jobs.build-and-push-image.outputs.local_image_ref }}
5975
secrets:
6076
registry-username:
6177
required: false
@@ -64,6 +80,11 @@ on:
6480

6581
jobs:
6682
build-and-push-image:
83+
outputs:
84+
image_name: ${{ steps.workflow-outputs.outputs.image_name }}
85+
image_digest: ${{ steps.workflow-outputs.outputs.image_digest }}
86+
image_ref: ${{ steps.workflow-outputs.outputs.image_ref }}
87+
local_image_ref: ${{ steps.workflow-outputs.outputs.local_image_ref }}
6788
permissions:
6889
artifact-metadata: write
6990
attestations: write
@@ -144,6 +165,18 @@ jobs:
144165
load: true
145166
push: false
146167
tags: localimage:${{ github.sha }}
168+
- name: Set workflow outputs
169+
id: workflow-outputs
170+
env:
171+
IMAGE_NAME: ${{ format('{0}/{1}', inputs.registry, inputs.image) }}
172+
IMAGE_DIGEST: ${{ inputs.push && steps.build.outputs.digest || '' }}
173+
IMAGE_REF: ${{ inputs.push && format('{0}/{1}@{2}', inputs.registry, inputs.image, steps.build.outputs.digest) || '' }}
174+
LOCAL_IMAGE_REF: ${{ !inputs.push && format('localimage:{0}', github.sha) || '' }}
175+
run: |
176+
echo "image_name=${IMAGE_NAME}" >> "${GITHUB_OUTPUT}"
177+
echo "image_digest=${IMAGE_DIGEST}" >> "${GITHUB_OUTPUT}"
178+
echo "image_ref=${IMAGE_REF}" >> "${GITHUB_OUTPUT}"
179+
echo "local_image_ref=${LOCAL_IMAGE_REF}" >> "${GITHUB_OUTPUT}"
147180
- name: Generate artifact attestation
148181
if: inputs.push
149182
uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0
@@ -180,17 +213,18 @@ jobs:
180213
sbom-path: ${{ inputs.working-directory }}/sbom.spdx.json
181214
- name: Install cosign
182215
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
183-
if: inputs.push
216+
if: inputs.push && inputs.sign-image
184217
- name: Sign image
185-
if: inputs.push
218+
if: inputs.push && inputs.sign-image
186219
env:
187220
COSIGN_YES: 'true'
188221
IMAGE_REF: ${{ format('{0}/{1}@{2}', inputs.registry, inputs.image, steps.build.outputs.digest) }}
189-
CERT_IDENTITY: ${{ format('https://github.com/{0}', github.workflow_ref) }}
190222
CERT_OIDC_ISSUER: https://token.actions.githubusercontent.com
191223
run: |
192224
cosign sign "${IMAGE_REF}"
193-
cosign verify --certificate-identity "${CERT_IDENTITY}" --certificate-oidc-issuer "${CERT_OIDC_ISSUER}" "${IMAGE_REF}"
225+
cosign verify \
226+
--certificate-identity-regexp '^https://github.com/notdodo/github-actions/.github/workflows/docker-build-and-push.yml@refs/tags/docker-build-and-push-v[0-9]+$' \
227+
--certificate-oidc-issuer "${CERT_OIDC_ISSUER}" "${IMAGE_REF}"
194228
- uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1.5.0
195229
if: inputs.scan-image
196230
- name: Run reviewdog

README.md

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ Collection of reusable workflows and custom actions designed to streamline autom
77
## Available Workflows
88

99
- `notdodo/github-actions/.github/workflows/clean-branch-cache.yml`: Use to cleanup the cache for a merge branch
10-
- `notdodo/github-actions/.github/workflows/docker-build-and-push.yml`: Builds a Dockerfile and upload the image to a registry and also performs a scan using [Trivy](https://trivy.dev/latest/)
10+
- `notdodo/github-actions/.github/workflows/docker-build-and-push.yml`: Builds a Dockerfile, optionally signs it with cosign, uploads the image to a registry, and performs a scan using [Trivy](https://trivy.dev/latest/)
1111
- `notdodo/github-actions/.github/workflows/gitleaks.yml`: Uses [Gitleaks](https://gitleaks.io/index.html) to scan the code for secrets
1212
- `notdodo/github-actions/.github/workflows/go-ci.yml`: Used for Golang CI linting and testing
1313
- `notdodo/github-actions/.github/workflows/go-security-scan.yml`: Used for Golang CI security scanning with Sarif support
1414
- `notdodo/github-actions/.github/workflows/infra-security-scan.yml`: Used for docker, Makefiles, Kubernetes security scanning with Sarif support
15+
- `notdodo/github-actions/.github/workflows/pulumi-preview.yml`: Used to run Pulumi preview with PR comments and OIDC authentication
16+
- `notdodo/github-actions/.github/workflows/pulumi-up.yml`: Used to run Pulumi up for stack deployments with OIDC authentication
1517
- `notdodo/github-actions/.github/workflows/python-ci.yml`: Used for Python CI linting and checking for [Poetry](https://python-poetry.org/) projects
1618
- `notdodo/github-actions/.github/workflows/rust-ci.yml`: Used for Rust CI linting, building and testing
1719
- `notdodo/github-actions/.github/workflows/sast.yml`: Used to run Semgrep on the repository with Sarif support
@@ -80,6 +82,51 @@ jobs:
8082
# infra-scan-v0.0.0
8183
```
8284

85+
### Pulumi Preview
86+
87+
```yaml
88+
name: Pulumi Preview
89+
on:
90+
pull_request:
91+
branches:
92+
- main
93+
94+
jobs:
95+
pulumi-preview:
96+
permissions:
97+
contents: read
98+
pull-requests: write
99+
id-token: write
100+
uses: notdodo/github-actions/.github/workflows/pulumi-preview.yml@pulumi-preview-v0
101+
with:
102+
stack-name: notdodo/my-project/dev
103+
working-directory: infra
104+
aws-role: arn:aws:iam::123456789012:role/github-actions-pulumi-preview
105+
aws-region: eu-west-1
106+
```
107+
108+
### Pulumi Up
109+
110+
```yaml
111+
name: Pulumi Up
112+
on:
113+
push:
114+
branches:
115+
- main
116+
117+
jobs:
118+
pulumi-up:
119+
permissions:
120+
contents: read
121+
id-token: write
122+
uses: notdodo/github-actions/.github/workflows/pulumi-up.yml@pulumi-up-v0
123+
with:
124+
stack-name: notdodo/my-project/prod
125+
working-directory: infra
126+
aws-role: arn:aws:iam::123456789012:role/github-actions-pulumi-up
127+
aws-region: eu-west-1
128+
```
129+
83130
### Python CI
84131
85132
```yaml
@@ -136,6 +183,79 @@ jobs:
136183
registry-password: ${{ secrets.GITHUB_TOKEN }}
137184
```
138185
186+
By default, this workflow signs pushed images with cosign (`sign-image: true`) using the reusable workflow identity (the certificate identity belongs to the reusable workflow reference).
187+
188+
To skip signing in the reusable workflow:
189+
190+
```yaml
191+
jobs:
192+
build-push-docker-image:
193+
uses: notdodo/github-actions/.github/workflows/docker-build-and-push.yml@docker-build-and-push-v1
194+
with:
195+
image: notdodo/my-app
196+
push: true
197+
registry: ghcr.io
198+
sign-image: false
199+
secrets:
200+
registry-username: notdodo
201+
registry-password: ${{ secrets.GITHUB_TOKEN }}
202+
```
203+
204+
Example: sign in the caller workflow instead of the reusable workflow.
205+
206+
When used as a reusable workflow, these job outputs are available to the caller:
207+
208+
- `image_name`: `<registry>/<image>`
209+
- `image_digest`: pushed digest (`sha256:...`), empty when `push: false`
210+
- `image_ref`: immutable image reference (`<registry>/<image>@<digest>`), empty when `push: false`
211+
- `local_image_ref`: local image reference (`localimage:<sha>`), only set when `push: false`
212+
213+
```yaml
214+
name: Docker Build, Then Sign in Caller
215+
on:
216+
push:
217+
branches: [main]
218+
219+
jobs:
220+
build-image:
221+
permissions:
222+
attestations: write
223+
contents: read
224+
id-token: write
225+
packages: write
226+
security-events: write
227+
uses: notdodo/github-actions/.github/workflows/docker-build-and-push.yml@docker-build-and-push-v1
228+
with:
229+
image: notdodo/my-app
230+
push: true
231+
registry: ghcr.io
232+
sign-image: false
233+
secrets:
234+
registry-username: notdodo
235+
registry-password: ${{ secrets.GITHUB_TOKEN }}
236+
237+
sign-image:
238+
needs: [build-image]
239+
runs-on: ubuntu-latest
240+
permissions:
241+
id-token: write
242+
contents: read
243+
steps:
244+
- uses: sigstore/cosign-installer@v4.0.0
245+
- name: Sign and verify
246+
env:
247+
COSIGN_YES: "true"
248+
IMAGE_REF: ${{ needs.build-image.outputs.image_ref }}
249+
CERT_OIDC_ISSUER: https://token.actions.githubusercontent.com
250+
CERT_IDENTITY: ${{ format('https://github.com/{0}', github.workflow_ref) }}
251+
run: |
252+
cosign sign "${IMAGE_REF}"
253+
cosign verify \
254+
--certificate-identity "${CERT_IDENTITY}" \
255+
--certificate-oidc-issuer "${CERT_OIDC_ISSUER}" \
256+
"${IMAGE_REF}"
257+
```
258+
139259
### Auto tagger
140260

141261
```yaml

0 commit comments

Comments
 (0)