-
Notifications
You must be signed in to change notification settings - Fork 1
167 lines (153 loc) · 7.06 KB
/
get-repo-config.yml
File metadata and controls
167 lines (153 loc) · 7.06 KB
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
name: Get Repo Config and Image
on:
workflow_call:
inputs:
registry:
required: false
type: string
default: ghcr.io
namespace:
required: false
type: string
default: nhsdigital/eps-devcontainers
owner:
required: false
type: string
default: NHSDigital
verify_published_from_main_image:
required: false
type: boolean
default: true
predicate_type:
required: false
type: string
default: https://slsa.dev/provenance/v1
outputs:
tag_format:
description: The tag format to be used for releases, as defined in .github/config/settings.yml
value: ${{ jobs.get_config_values.outputs.tag_format }}
devcontainer_image:
description: The devcontainer image name as defined in .devcontainer/devcontainer.json
value: ${{ jobs.get_config_values.outputs.devcontainer_image }}
devcontainer_version:
description: The devcontainer image version as defined in .devcontainer/devcontainer.json
value: ${{ jobs.get_config_values.outputs.devcontainer_version }}
pinned_image:
description: Fully-qualified digest-pinned image reference
value: ${{ jobs.verify_attestation.outputs.pinned_image }}
resolved_digest:
description: Resolved digest for the supplied image reference
value: ${{ jobs.verify_attestation.outputs.resolved_digest }}
permissions: {}
jobs:
get_config_values:
runs-on: ubuntu-22.04
permissions:
attestations: read
contents: read
packages: read
outputs:
tag_format: ${{ steps.load-config.outputs.TAG_FORMAT }}
devcontainer_version: ${{ steps.load-config.outputs.DEVCONTAINER_VERSION }}
devcontainer_image: ${{ steps.load-config.outputs.DEVCONTAINER_IMAGE }}
runtime_docker_image: ${{ steps.load-config.outputs.RUNTIME_DOCKER_IMAGE }}
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
persist-credentials: false
- name: Load config value
id: load-config
run: |
TAG_FORMAT=$(yq '.TAG_FORMAT' .github/config/settings.yml)
DEVCONTAINER_IMAGE=$(jq -r '.build.args.IMAGE_NAME' .devcontainer/devcontainer.json)
DEVCONTAINER_VERSION=$(jq -r '.build.args.IMAGE_VERSION' .devcontainer/devcontainer.json)
RUNTIME_DOCKER_IMAGE="${DEVCONTAINER_IMAGE}:githubactions-${DEVCONTAINER_VERSION}"
{
echo "TAG_FORMAT=$TAG_FORMAT"
echo "DEVCONTAINER_IMAGE=$DEVCONTAINER_IMAGE"
echo "DEVCONTAINER_VERSION=$DEVCONTAINER_VERSION"
echo "RUNTIME_DOCKER_IMAGE=$RUNTIME_DOCKER_IMAGE"
} >> "$GITHUB_OUTPUT"
verify_attestation:
runs-on: ubuntu-22.04
needs: get_config_values
permissions:
contents: read
packages: read
attestations: read
outputs:
pinned_image: ${{ steps.resolve.outputs.pinned_image }}
resolved_digest: ${{ steps.resolve.outputs.resolved_digest }}
steps:
- name: Login to github container registry
if: startsWith(inputs.registry, 'ghcr.io')
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Resolve digest
id: resolve
shell: bash
env:
RUNTIME_DOCKER_IMAGE: ${{ needs.get_config_values.outputs.runtime_docker_image }}
REGISTRY: ${{ inputs.registry }}
NAMESPACE: ${{ inputs.namespace }}
run: |
set -euo pipefail
if [[ "$RUNTIME_DOCKER_IMAGE" == *"/"* ]]; then
IMAGE_REF="$RUNTIME_DOCKER_IMAGE"
else
IMAGE_REF="${REGISTRY}/${NAMESPACE}/${RUNTIME_DOCKER_IMAGE}"
fi
if [[ "$IMAGE_REF" == *@sha256:* ]]; then
IMAGE_BASE="${IMAGE_REF%@*}"
RESOLVED_DIGEST="${IMAGE_REF#*@}"
else
RESOLVED_DIGEST=""
MAX_ATTEMPTS=5
for attempt in $(seq 1 "$MAX_ATTEMPTS"); do
if OUTPUT="$(docker buildx imagetools inspect "$IMAGE_REF" 2>&1)"; then
RESOLVED_DIGEST="$(awk '/^Digest:/ {print $2; exit}' <<< "$OUTPUT")"
if [[ -n "$RESOLVED_DIGEST" ]]; then
break
fi
echo "Digest not found in imagetools output (attempt ${attempt}/${MAX_ATTEMPTS})." >&2
else
echo "Failed to inspect image ${IMAGE_REF} (attempt ${attempt}/${MAX_ATTEMPTS})." >&2
echo "$OUTPUT" >&2
fi
if [[ "$attempt" -lt "$MAX_ATTEMPTS" ]]; then
sleep $((attempt * 2))
fi
done
IMAGE_BASE="${IMAGE_REF%:*}"
fi
if [[ -z "$RESOLVED_DIGEST" ]]; then
echo "Could not resolve digest for image: $IMAGE_REF" >&2
exit 1
fi
PINNED_IMAGE="${IMAGE_BASE}@${RESOLVED_DIGEST}"
echo "resolved_digest=${RESOLVED_DIGEST}" >> "$GITHUB_OUTPUT"
echo "pinned_image=${PINNED_IMAGE}" >> "$GITHUB_OUTPUT"
echo "Resolved image reference: ${IMAGE_REF}"
echo "Resolved digest: ${RESOLVED_DIGEST}"
echo "Resolved image reference: ${PINNED_IMAGE}"
- name: Verify attestation
shell: bash
env:
GH_TOKEN: ${{ github.token }}
OWNER: ${{ inputs.owner }}
VERIFY_PUBLISHED_FROM_MAIN_IMAGE: ${{ inputs.verify_published_from_main_image }}
PREDICATE_TYPE: ${{ inputs.predicate_type }}
PINNED_IMAGE: ${{ steps.resolve.outputs.pinned_image }}
run: |
set -euo pipefail
args=("oci://${PINNED_IMAGE}" "--owner" "$OWNER" "--predicate-type" "$PREDICATE_TYPE")
if [[ "$VERIFY_PUBLISHED_FROM_MAIN_IMAGE" == "true" ]]; then
args+=("--source-ref" "refs/heads/main")
fi
GH_FORCE_TTY=120 gh attestation verify "${args[@]}" 2>&1
echo "Verified attestation for ${PINNED_IMAGE}"