|
5 | 5 | # SPDX-License-Identifier: Apache-2.0 |
6 | 6 | # SPDX-ArtifactOfProjectHomePage: https://github.com/vegardit/docker-softhsm2-pkcs11-proxy |
7 | 7 |
|
8 | | -function curl() { |
9 | | - command curl -sSfL --connect-timeout 10 --max-time 30 --retry 3 --retry-all-errors "$@" |
10 | | -} |
11 | | - |
12 | 8 | shared_lib="$(dirname "${BASH_SOURCE[0]}")/.shared" |
13 | | -[[ -e $shared_lib ]] || curl "https://raw.githubusercontent.com/vegardit/docker-shared/v1/download.sh?_=$(date +%s)" | bash -s v1 "$shared_lib" || exit 1 |
| 9 | +[[ -e $shared_lib ]] || curl -sSfL "https://raw.githubusercontent.com/vegardit/docker-shared/v1/download.sh?_=$(date +%s)" | bash -s v1 "$shared_lib" || exit 1 |
14 | 10 | # shellcheck disable=SC1091 # Not following: $shared_lib/lib/build-image-init.sh was not specified as input |
15 | 11 | source "$shared_lib/lib/build-image-init.sh" |
16 | 12 |
|
17 | 13 |
|
18 | 14 | ################################################# |
19 | | -# specify target image repo/tag |
| 15 | +# declare image meta |
20 | 16 | ################################################# |
21 | 17 | image_repo=${DOCKER_IMAGE_REPO:-vegardit/softhsm2-pkcs11-proxy} |
22 | | -base_image_name=${DOCKER_BASE_IMAGE:-alpine:3} |
23 | | -case $base_image_name in |
24 | | - *alpine*) base_image_linux_flavor=alpine ;; |
25 | | - *debian*) base_image_linux_flavor=debian ;; |
26 | | - *) echo "ERROR: Unsupported base image $base_image_name"; exit 1 ;; |
| 18 | +base_image=${DOCKER_BASE_IMAGE:-alpine:3} |
| 19 | +case $base_image in |
| 20 | + *alpine*) base_image_linux_flavor=alpine ;; |
| 21 | + *debian*) base_image_linux_flavor=debian ;; |
| 22 | + *) echo "ERROR: Unsupported base image $base_image"; exit 1 ;; |
27 | 23 | esac |
28 | 24 |
|
29 | 25 | app_version=${SOFTHSM_VERSION:-latest} |
30 | 26 | case $app_version in \ |
31 | | - latest) |
32 | | - #app_version=$(curl https://github.com/softhsm/SoftHSMv2/releases/latest | sed -n "s/.*releases\/tag\/\([0-9]\.[0-9]\.[0-9]\)['\"].*/\1/p" | head -1) |
33 | | - app_version=$(curl https://github.com/softhsm/SoftHSMv2/tags | sed -n "s/.*releases\/tag\/\([0-9]\.[0-9]\.[0-9]\)['\"].*/\1/p" | head -1) |
34 | | - softhsm_source_url=https://codeload.github.com/softhsm/SoftHSMv2/tar.gz/refs/tags/$app_version |
35 | | - app_version_is_latest=1 |
36 | | - ;; |
37 | | - develop) |
38 | | - softhsm_source_url=https://codeload.github.com/softhsm/SoftHSMv2/tar.gz/refs/heads/develop |
39 | | - ;; |
40 | | - *) |
41 | | - softhsm_source_url=https://codeload.github.com/softhsm/SoftHSMv2/tar.gz/refs/tags/$app_version |
42 | | - ;; |
| 27 | + latest) |
| 28 | + #app_version=$(curl https://github.com/softhsm/SoftHSMv2/releases/latest | sed -n "s/.*releases\/tag\/\([0-9]\.[0-9]\.[0-9]\)['\"].*/\1/p" | head -1) |
| 29 | + app_version=$(curl https://github.com/softhsm/SoftHSMv2/tags | sed -n "s/.*releases\/tag\/\([0-9]\.[0-9]\.[0-9]\)['\"].*/\1/p" | head -1) |
| 30 | + softhsm_source_url=https://codeload.github.com/softhsm/SoftHSMv2/tar.gz/refs/tags/$app_version |
| 31 | + app_version_is_latest=1 |
| 32 | + ;; |
| 33 | + develop) softhsm_source_url=https://codeload.github.com/softhsm/SoftHSMv2/tar.gz/refs/heads/develop ;; |
| 34 | + *) softhsm_source_url=https://codeload.github.com/softhsm/SoftHSMv2/tar.gz/refs/tags/$app_version ;; |
43 | 35 | esac |
44 | 36 | log INFO "app_version=$app_version" |
45 | 37 | log INFO "softhsm_source_url=$softhsm_source_url" |
46 | 38 |
|
| 39 | +platforms="linux/amd64,linux/arm64/v8" # linux/arm/v7 |
47 | 40 |
|
48 | | -################################################# |
49 | | -# calculate tags |
50 | | -################################################# |
51 | | -declare -a tags=() |
| 41 | +declare -A image_meta=( |
| 42 | + [authors]="Vegard IT GmbH (vegardit.com)" |
| 43 | + [title]="$image_repo" |
| 44 | + [description]="Docker image to run a virtual HSM (Hardware Security Module) network service based on SoftHSM2 and pkcs11-proxy" |
| 45 | + [source]="$(git config --get remote.origin.url)" |
| 46 | + [revision]="$(git rev-parse --short HEAD)" |
| 47 | + [version]="$(git rev-parse --short HEAD)" |
| 48 | + [created]="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" |
| 49 | +) |
52 | 50 |
|
| 51 | +declare -a tags=() |
53 | 52 | if [[ $app_version == develop ]]; then |
54 | | - tags+=("$image_repo:develop-$base_image_linux_flavor") # :develop-alpine |
55 | | - if [[ $base_image_linux_flavor == alpine ]]; then |
56 | | - tags+=("$image_repo:develop") # :develop |
57 | | - fi |
| 53 | + tags+=("develop-$base_image_linux_flavor") # :develop-alpine |
| 54 | + if [[ $base_image_linux_flavor == alpine ]]; then |
| 55 | + tags+=("develop") # :develop |
| 56 | + fi |
58 | 57 | else |
59 | | - if [[ $app_version =~ ^[0-9]+\..*$ ]]; then |
60 | | - tags+=("$image_repo:${app_version%%.*}.x-$base_image_linux_flavor") # :2.x-alpine |
61 | | - if [[ $base_image_linux_flavor == alpine ]]; then |
62 | | - tags+=("$image_repo:${app_version%%.*}.x-$base_image_linux_flavor") # :2.x |
63 | | - fi |
64 | | - fi |
65 | | - |
66 | | - if [[ ${app_version_is_latest:-} == 1 ]]; then |
67 | | - tags+=("$image_repo:latest-$base_image_linux_flavor") # :latest-alpine |
68 | | - if [[ $base_image_linux_flavor == alpine ]]; then |
69 | | - tags+=("$image_repo:latest") # :latest |
70 | | - fi |
71 | | - fi |
| 58 | + if [[ $app_version =~ ^[0-9]+\..*$ ]]; then |
| 59 | + tags+=("${app_version%%.*}.x-$base_image_linux_flavor") # :2.x-alpine |
| 60 | + if [[ $base_image_linux_flavor == alpine ]]; then |
| 61 | + tags+=("${app_version%%.*}.x-$base_image_linux_flavor") # :2.x |
| 62 | + fi |
| 63 | + fi |
| 64 | + if [[ ${app_version_is_latest:-} == 1 ]]; then |
| 65 | + tags+=("latest-$base_image_linux_flavor") # :latest-alpine |
| 66 | + if [[ $base_image_linux_flavor == alpine ]]; then |
| 67 | + tags+=("latest") # :latest |
| 68 | + fi |
| 69 | + fi |
72 | 70 | fi |
73 | 71 |
|
74 | | -tag_args=() |
75 | | -for t in "${tags[@]}"; do |
76 | | - tag_args+=( --tag "$t" ) |
77 | | -done |
78 | | - |
79 | | -image_name=${tags[0]} |
80 | | - |
81 | 72 |
|
82 | 73 | ################################################# |
83 | | -# build the image |
| 74 | +# decide if multi-arch build |
84 | 75 | ################################################# |
85 | | -log INFO "Building docker image [$image_name]..." |
86 | | -if [[ $OSTYPE == "cygwin" || $OSTYPE == "msys" ]]; then |
87 | | - project_root=$(cygpath -w "$project_root") |
| 76 | +if [[ ${DOCKER_PUSH:-} == "true" || ${DOCKER_PUSH_GHCR:-} == "true" ]]; then |
| 77 | + build_multi_arch="true" |
88 | 78 | fi |
89 | 79 |
|
90 | | -case $base_image_name in |
91 | | - *alpine*) dockerfile="alpine.Dockerfile" ;; |
92 | | - *debian*) dockerfile="debian.Dockerfile" ;; |
93 | | - *) echo "ERROR: Unsupported base image $base_image_name"; exit 1 ;; |
94 | | -esac |
| 80 | + |
| 81 | +################################################# |
| 82 | +# prepare docker |
| 83 | +################################################# |
| 84 | +run_step -- docker version |
95 | 85 |
|
96 | 86 | # https://github.com/docker/buildx/#building-multi-platform-images |
97 | | -set -x |
| 87 | +run_step -- docker buildx version # ensures buildx is enabled |
98 | 88 |
|
99 | | -docker --version |
100 | 89 | export DOCKER_BUILDKIT=1 |
101 | | -export DOCKER_CLI_EXPERIMENTAL=1 # prevents "docker: 'buildx' is not a docker command." |
| 90 | +export DOCKER_CLI_EXPERIMENTAL=1 # prevents "docker: 'buildx' is not a docker command." in older Docker versions |
| 91 | + |
| 92 | +if [[ ${build_multi_arch:-} == "true" ]]; then |
| 93 | + # Use a temporary local registry to work around Docker/Buildx/BuildKit quirks, |
| 94 | + # enabling us to build/test multiarch images locally before pushing. |
| 95 | + run_step -- start_docker_registry LOCAL_REGISTRY |
102 | 96 |
|
103 | | -# Register QEMU emulators for all architectures so Docker can run and build multi-arch images |
104 | | -docker run --privileged --rm ghcr.io/dockerhub-mirror/tonistiigi__binfmt --install all |
| 97 | + # Register QEMU emulators so Docker can run and build multi-arch images |
| 98 | + run_step "Install QEMU emulators" -- \ |
| 99 | + docker run --privileged --rm ghcr.io/dockerhub-mirror/tonistiigi__binfmt --install all |
| 100 | +fi |
105 | 101 |
|
106 | 102 | # https://docs.docker.com/build/buildkit/configure/#resource-limiting |
107 | 103 | echo " |
108 | 104 | [worker.oci] |
109 | 105 | max-parallelism = 3 |
110 | 106 | " | sudo tee /etc/buildkitd.toml |
111 | 107 |
|
112 | | -docker buildx version # ensures buildx is enabled |
113 | | -docker buildx create --config /etc/buildkitd.toml --use # prevents: error: multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use") |
114 | | -trap 'docker buildx stop' EXIT |
115 | | -# shellcheck disable=SC2154,SC2046 # base_layer_cache_key is referenced but not assigned / Quote this to prevent word splitting |
116 | | -docker buildx build "$project_root" \ |
117 | | - --file "image/$dockerfile" \ |
118 | | - --progress=plain \ |
119 | | - --pull \ |
120 | | - --build-arg INSTALL_SUPPORT_TOOLS="${INSTALL_SUPPORT_TOOLS:-0}" \ |
121 | | - `# using the current date as value for BASE_LAYER_CACHE_KEY, i.e. the base layer cache (that holds system packages with security updates) will be invalidate once per day` \ |
122 | | - --build-arg BASE_LAYER_CACHE_KEY="$base_layer_cache_key" \ |
123 | | - --build-arg BASE_IMAGE="$base_image_name" \ |
124 | | - --build-arg BUILD_DATE="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \ |
125 | | - --build-arg GIT_BRANCH="${GIT_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}" \ |
126 | | - --build-arg GIT_COMMIT_DATE="$(date -d "@$(git log -1 --format='%at')" --utc +'%Y-%m-%d %H:%M:%S UTC')" \ |
127 | | - --build-arg GIT_COMMIT_HASH="$(git rev-parse --short HEAD)" \ |
128 | | - --build-arg GIT_REPO_URL="$(git config --get remote.origin.url)" \ |
129 | | - --build-arg SOFTHSM_SOURCE_URL="$softhsm_source_url" \ |
130 | | - --build-arg PKCS11_PROXY_SOURCE_URL="https://codeload.github.com/smallstep/pkcs11-proxy/tar.gz/refs/heads/master" \ |
131 | | - `#--build-arg PKCS11_PROXY_SOURCE_URL="https://codeload.github.com/scobiej/pkcs11-proxy/tar.gz/refs/heads/osx-openssl1-1"` \ |
132 | | - `#--build-arg PKCS11_PROXY_SOURCE_URL="https://codeload.github.com/SUNET/pkcs11-proxy/tar.gz/refs/heads/master"` \ |
133 | | - $(if [[ ${ACT:-} == "true" || ${DOCKER_PUSH:-} != "true" ]]; then \ |
134 | | - echo -n "--load --output type=docker"; \ |
135 | | - else \ |
136 | | - echo -n "--platform linux/amd64,linux/arm64" `# ,linux/arm/v7"`; \ |
137 | | - fi) \ |
138 | | - "${tag_args[@]}" \ |
139 | | - $(if [[ ${DOCKER_PUSH:-} == "true" ]]; then echo -n "--push"; fi) \ |
140 | | - "$@" |
141 | | -set +x |
| 108 | +builder_name="bx-$(date +%s)-$RANDOM" |
| 109 | +run_step "Configure buildx builder" -- docker buildx create \ |
| 110 | + --name "$builder_name" \ |
| 111 | + --bootstrap \ |
| 112 | + --config /etc/buildkitd.toml \ |
| 113 | + --driver-opt network=host `# required for buildx to access the temporary registry` \ |
| 114 | + --driver docker-container \ |
| 115 | + --driver-opt image=ghcr.io/dockerhub-mirror/moby__buildkit:latest |
| 116 | +trap 'docker buildx rm --force "$builder_name"' EXIT |
142 | 117 |
|
143 | | -if [[ ${DOCKER_PUSH:-} == "true" ]]; then |
144 | | - docker image pull "$image_name" |
| 118 | + |
| 119 | +################################################# |
| 120 | +# build the image |
| 121 | +################################################# |
| 122 | +image_name=image_repo:${tags[0]} |
| 123 | + |
| 124 | +case $base_image in |
| 125 | + *alpine*) dockerfile="alpine.Dockerfile" ;; |
| 126 | + *debian*) dockerfile="debian.Dockerfile" ;; |
| 127 | + *) echo "ERROR: Unsupported base image $base_image"; exit 1 ;; |
| 128 | +esac |
| 129 | + |
| 130 | +build_opts=( |
| 131 | + --file "image/$dockerfile" |
| 132 | + --builder "$builder_name" |
| 133 | + --progress=plain |
| 134 | + --pull |
| 135 | + # using the current date as value for BASE_LAYER_CACHE_KEY, i.e. the base layer cache (that holds system packages with security updates) will be invalidate once per day |
| 136 | + --build-arg BASE_LAYER_CACHE_KEY="$base_layer_cache_key" |
| 137 | + --build-arg BASE_IMAGE="$base_image" |
| 138 | + --build-arg GIT_BRANCH="${GIT_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}" |
| 139 | + --build-arg GIT_COMMIT_DATE="$(date -d "@$(git log -1 --format='%at')" --utc +'%Y-%m-%d %H:%M:%S UTC')" |
| 140 | + --build-arg SOFTHSM_SOURCE_URL="$softhsm_source_url" |
| 141 | + --build-arg PKCS11_PROXY_SOURCE_URL="https://codeload.github.com/smallstep/pkcs11-proxy/tar.gz/refs/heads/master" |
| 142 | + #--build-arg PKCS11_PROXY_SOURCE_URL="https://codeload.github.com/scobiej/pkcs11-proxy/tar.gz/refs/heads/osx-openssl1-1" |
| 143 | + #--build-arg PKCS11_PROXY_SOURCE_URL="https://codeload.github.com/SUNET/pkcs11-proxy/tar.gz/refs/heads/master" |
| 144 | + --build-arg INSTALL_SUPPORT_TOOLS="${INSTALL_SUPPORT_TOOLS:-0}" |
| 145 | +) |
| 146 | + |
| 147 | +for key in "${!image_meta[@]}"; do |
| 148 | + build_opts+=(--build-arg "OCI_${key}=${image_meta[$key]}") |
| 149 | + if [[ ${build_multi_arch:-} == "true" ]]; then |
| 150 | + build_opts+=(--annotation "index:org.opencontainers.image.${key}=${image_meta[$key]}") |
| 151 | + fi |
| 152 | +done |
| 153 | + |
| 154 | +if [[ ${build_multi_arch:-} == "true" ]]; then |
| 155 | + build_opts+=(--push) |
| 156 | + build_opts+=(--sbom=true) # https://docs.docker.com/build/metadata/attestations/sbom/#create-sbom-attestations |
| 157 | + build_opts+=(--platform "$platforms") |
| 158 | + build_opts+=(--tag "$LOCAL_REGISTRY/$image_name") |
| 159 | +else |
| 160 | + build_opts+=(--output "type=docker,load=true") |
| 161 | + build_opts+=(--tag "$image_name") |
145 | 162 | fi |
146 | 163 |
|
| 164 | +if [[ $OSTYPE == "cygwin" || $OSTYPE == "msys" ]]; then |
| 165 | + project_root=$(cygpath -w "$project_root") |
| 166 | +fi |
| 167 | + |
| 168 | +run_step "Building docker image [$image_name]..." -- \ |
| 169 | + docker buildx build "${build_opts[@]}" "$project_root" |
| 170 | + |
147 | 171 |
|
148 | 172 | ################################################# |
149 | | -# test image |
| 173 | +# load image into local docker daemon for testing |
150 | 174 | ################################################# |
151 | | -echo |
152 | | -log INFO "Testing docker image [$image_name]..." |
153 | | -(set -x; docker run --rm "$image_name" /usr/local/bin/softhsm2-util --version) |
154 | | -echo |
| 175 | +if [[ ${build_multi_arch:-} == "true" ]]; then |
| 176 | + run_step "Load image into local daemon for testing" @@ " |
| 177 | + docker pull '$LOCAL_REGISTRY/$image_name'; |
| 178 | + docker tag '$LOCAL_REGISTRY/$image_name' '$image_name' |
| 179 | + " |
| 180 | +fi |
155 | 181 |
|
156 | 182 |
|
157 | 183 | ################################################# |
158 | 184 | # perform security audit |
159 | 185 | ################################################# |
160 | 186 | if [[ ${DOCKER_AUDIT_IMAGE:-1} == "1" ]]; then |
| 187 | + run_step "Auditing docker image [$image_name]" -- \ |
161 | 188 | bash "$shared_lib/cmd/audit-image.sh" "$image_name" |
162 | 189 | fi |
163 | 190 |
|
164 | 191 |
|
165 | 192 | ################################################# |
166 | | -# push image to ghcr.io |
| 193 | +# test image |
| 194 | +################################################# |
| 195 | +run_step "Testing docker image [$image_name]" -- \ |
| 196 | + docker run --pull=never --rm "$image_name" /usr/local/bin/softhsm2-util --version |
| 197 | + |
| 198 | + |
| 199 | +################################################# |
| 200 | +# push image |
167 | 201 | ################################################# |
| 202 | +function regctl() { |
| 203 | + run_step "regctl ${*}" -- \ |
| 204 | + docker run --rm \ |
| 205 | + -u "$(id -u):$(id -g)" -e HOME -v "$HOME:$HOME" \ |
| 206 | + -v /etc/docker/certs.d:/etc/docker/certs.d:ro \ |
| 207 | + --network host `# required to access the temporary registry` \ |
| 208 | + ghcr.io/regclient/regctl:latest \ |
| 209 | + --host "reg=$LOCAL_REGISTRY,tls=disabled" \ |
| 210 | + "${@}" |
| 211 | +} |
| 212 | + |
| 213 | +if [[ ${DOCKER_PUSH:-} == "true" ]]; then |
| 214 | + for tag in "${tags[@]}"; do |
| 215 | + regctl image copy --referrers "$LOCAL_REGISTRY/$image_name" "docker.io/$image_repo:$tag" |
| 216 | + done |
| 217 | +fi |
168 | 218 | if [[ ${DOCKER_PUSH_GHCR:-} == "true" ]]; then |
169 | | - for tag in "${tags[@]}"; do |
170 | | - set -x |
171 | | - docker run --rm \ |
172 | | - -u "$(id -u):$(id -g)" -e HOME -v "$HOME:$HOME" \ |
173 | | - -v /etc/docker/certs.d:/etc/docker/certs.d:ro \ |
174 | | - ghcr.io/regclient/regctl:latest \ |
175 | | - image copy "$tag" "ghcr.io/$tag" |
176 | | - set +x |
177 | | - done |
| 219 | + for tag in "${tags[@]}"; do |
| 220 | + regctl image copy --referrers "$LOCAL_REGISTRY/$image_name" "ghcr.io/$image_repo:$tag" |
| 221 | + done |
178 | 222 | fi |
0 commit comments