-
Notifications
You must be signed in to change notification settings - Fork 31
148 lines (139 loc) · 5.66 KB
/
image-publisher.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
name: Publish policy evaluator
permissions:
contents: read
defaults:
run:
shell: bash
on:
workflow_call:
secrets:
registry-username:
description: "Username to log into the container registry."
registry-password:
description: "Password to log in the container registry."
inputs:
image:
description: "The OCI image name. This must not include a tag or digest."
required: true
type: string
digest:
description: "The OCI image digest. The image digest of the form '<algorithm>:<digest>' (e.g. 'sha256:abcdef...')"
required: true
type: string
registry-username:
description: "Username to log into the container registry."
type: string
environment:
description: "The environment the image is for. Must match one of the fields defined in the publish policy. Example: prod, dev, etc."
type: string
continue-on-error:
description: "Prevents a workflow run from failing when a job fails. Set to 'true' to allow a workflow run to pass when a job fails."
required: false
type: boolean
default: false
outputs:
outcome:
description: "The outcome status of the run ('success' or 'failure')."
value: ${{ jobs.final.outputs.outcome }}
jobs:
# detect-env detects the reusable workflow's repository and ref for use later
# in the workflow.
detect-env:
outputs:
outcome: ${{ steps.final.outputs.outcome }}
repository: ${{ steps.detect.outputs.repository }}
ref: ${{ steps.detect.outputs.ref }}
runs-on: ubuntu-latest
permissions:
id-token: write # Needed to detect the current reusable repository and ref.
steps:
- name: Detect the generator ref
id: detect
continue-on-error: true
uses: slsa-framework/slsa-github-generator/.github/actions/detect-workflow-js@v1.9.0
- name: Final outcome
id: final
env:
SUCCESS: ${{ steps.detect.outcome != 'failure' }}
run: |
set -euo pipefail
echo "outcome=$([ "$SUCCESS" == "true" ] && echo "success" || echo "failure")" >> "$GITHUB_OUTPUT"
# evaluate evaluates the publish policy.
evaluate:
needs: [detect-env]
outputs:
outcome: ${{ steps.final.outputs.outcome }}
runs-on: ubuntu-latest
permissions:
id-token: write # for creating OIDC tokens for signing.
packages: write # for uploading attestations.
contents: read # To read the repo.
steps:
- name: Checkout this repository
id: checkout
continue-on-error: true
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
repository: "${{ needs.detect-env.outputs.repository }}"
ref: "${{ needs.detect-env.outputs.ref }}"
token: "${{ github.token }}"
persist-credentials: false
fetch-depth: 1
- name: Log-in the registry
id: login
continue-on-error: true
uses: docker/login-action@49ed152c8eca782a232dede0303416e8f356c37b # v2.0.0
with:
# Use docker to simpliy local testing.
registry: docker.io
username: ${{ inputs.registry-username || secrets.registry-username }}
password: ${{ secrets.registry-password }}
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
repository: "${{ needs.detect-env.outputs.repository }}"
ref: "${{ needs.detect-env.outputs.ref }}"
token: "${{ github.token }}"
persist-credentials: false
fetch-depth: 1
- name: Install policy evaluator
id: install
continue-on-error: true
uses: slsa-framework/slsa-policy/actions/installer@v0.0.1
- id: evaluate
continue-on-error: true
env:
ENVIRONMENT: ${{ inputs.environment }}
PUBLISHER_ID: "https://github.com/${{ needs.detect-env.outputs.repository }}/.github/workflows/image-publisher.yml@${{ needs.detect-env.outputs.ref }}"
IMAGE: "${{ inputs.image }}@${{ inputs.digest }}"
working-directory: policies/publish
run: |
set -euo pipefail
slsa-policy publish evaluate org.json . "${IMAGE}" "${ENVIRONMENT}"
# NOTE: We can verify with:
# cosign verify-attestation "${IMAGE}" --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-identity "${PUBLISHER_ID}" --type https://slsa.dev/publish/v0.1 | jq -r '.payload' | base64 -d | jq
- name: Final outcome
id: final
env:
SUCCESS: ${{ steps.checkout.outcome != 'failure' && steps.install.outcome != 'failure' && steps.login.outcome != 'failure' && steps.evaluate.outcome != 'failure' }}
run: |
set -euo pipefail
echo "outcome=$([ "$SUCCESS" == "true" ] && echo "success" || echo "failure")" >> "$GITHUB_OUTPUT"
# final fails or succeeds based on the value of `inputs.continue-on-error`
# and the outcome of previous jobs.
final:
outputs:
outcome: ${{ steps.final.outputs.outcome }}
runs-on: ubuntu-latest
needs: [detect-env, evaluate]
# Note: always run even if needed jobs are skipped.
if: always()
steps:
- name: Final outcome
id: final
env:
SUCCESS: ${{ needs.detect-env.outputs.outcome != 'failure' && needs.evaluate.outputs.outcome != 'failure' }}
CONTINUE: ${{ inputs.continue-on-error }}
run: |
set -euo pipefail
echo "outcome=$([ "$SUCCESS" == "true" ] && echo "success" || echo "failure")" >> "$GITHUB_OUTPUT"
[ "$CONTINUE" == "true" ] || [ "$SUCCESS" == "true" ] || exit 27