From 9ce6d67df89f86205b3a615a81c3ea0a5647b408 Mon Sep 17 00:00:00 2001 From: Diana Borbe Date: Wed, 19 Aug 2026 17:38:13 +0200 Subject: [PATCH 1/4] Add docker workflow --- .github/workflows/docker.yaml | 152 ++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 .github/workflows/docker.yaml diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100644 index 0000000..a7e9dd8 --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,152 @@ +name: Build and Publish Docker Image + +on: + push: + branches: + - '**' + workflow_dispatch: + inputs: + tag: + description: 'Git ref (branch or tag) to build' + required: true + type: string + pkcs11: + description: 'Bundle PKCS#11 provider libs (SoftHSM2 + OpenSC) in the runtime image' + required: false + default: false + type: boolean + +env: + REGISTRY: ghcr.io + ORG: ${{ github.repository_owner }} + IMAGE_NAME: kms + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build: + permissions: + packages: write + contents: read + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-24.04 + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + name: build (${{ matrix.platform }}) + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + # On workflow_dispatch, build the caller-specified ref. On push events + # inputs.tag is empty, which checkout treats as the triggering commit. + ref: ${{ inputs.tag }} + # Full history + tags so the Makefile's git-describe version stamp works. + fetch-depth: 0 + + - name: Prepare platform pair + run: | + platform="${{ matrix.platform }}" + echo "PLATFORM_PAIR=${platform//\//-}" >> "$GITHUB_ENV" + + - name: Resolve KMS_VERSION + run: | + # Same default as the Makefile's KMS_VERSION. + echo "KMS_VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo '0.1.0-dev')" >> "$GITHUB_ENV" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + platforms: ${{ matrix.platform }} + # Mirrors `make docker-build`. + build-args: | + KMS_VERSION=${{ env.KMS_VERSION }} + PKCS11=${{ inputs.pkcs11 || false }} + outputs: type=image,name=${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=kms-${{ env.PLATFORM_PAIR }} + cache-to: type=gha,mode=max,scope=kms-${{ env.PLATFORM_PAIR }} + + - name: Export digest + run: | + mkdir -p "${{ runner.temp }}/digests" + digest="${{ steps.build.outputs.digest }}" + touch "${{ runner.temp }}/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digests-${{ env.PLATFORM_PAIR }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + needs: build + permissions: + packages: write + contents: read + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: ${{ runner.temp }}/digests + pattern: digests-* + merge-multiple: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Prepare Docker tag + id: tags + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + DOCKER_TAG="${{ inputs.tag }}" + elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then + DOCKER_TAG="latest" + else + # Non-main branch push → use the branch name + DOCKER_TAG="${{ github.ref_name }}" + fi + DOCKER_TAG=$(echo "$DOCKER_TAG" | sed 's/[^a-zA-Z0-9\.-]/-/g') + echo "DOCKER_TAG=${DOCKER_TAG}" >> "$GITHUB_OUTPUT" + + - name: Create manifest list and push + working-directory: ${{ runner.temp }}/digests + run: | + docker buildx imagetools create \ + -t "${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.DOCKER_TAG }}" \ + $(printf '${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) + + - name: Inspect manifest + run: | + docker buildx imagetools inspect \ + "${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.DOCKER_TAG }}" \ No newline at end of file From ab564043b64994c2e59aec36f530b1935a18800a Mon Sep 17 00:00:00 2001 From: Diana Borbe Date: Wed, 19 Aug 2026 17:49:28 +0200 Subject: [PATCH 2/4] After code review --- .github/workflows/docker.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index a7e9dd8..94ca0ed 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -3,7 +3,10 @@ name: Build and Publish Docker Image on: push: branches: - - '**' + - 'main' + pull_request: + branches: + - 'main' workflow_dispatch: inputs: tag: From c60ae9a14256214044f99df1483d96f48af3271d Mon Sep 17 00:00:00 2001 From: Diana Borbe Date: Wed, 19 Aug 2026 17:54:09 +0200 Subject: [PATCH 3/4] Update --- .github/workflows/docker.yaml | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 94ca0ed..087bdd4 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -110,6 +110,8 @@ jobs: contents: read runs-on: ubuntu-latest timeout-minutes: 5 + env: + TAG: ${{ github.event.inputs.tag || (github.event_name == 'push' && github.ref == 'refs/heads/main' && 'latest') || github.ref_name }} steps: - name: Download digests uses: actions/download-artifact@v4 @@ -130,17 +132,25 @@ jobs: - name: Prepare Docker tag id: tags + env: + EVENT_NAME: ${{ github.event_name }} + GIT_REF: ${{ github.ref }} run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - DOCKER_TAG="${{ inputs.tag }}" - elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then - DOCKER_TAG="latest" - else - # Non-main branch push → use the branch name - DOCKER_TAG="${{ github.ref_name }}" + set -euo pipefail + DOCKER_TAG="${TAG//[^a-zA-Z0-9._-]/-}" + # Sanitizing can also yield `latest` from a ref named `latest`, so + # re-check ownership after rewriting rather than before. + if [[ "$DOCKER_TAG" == "latest" && ! ( "$EVENT_NAME" == "push" && "$GIT_REF" == "refs/heads/main" ) ]]; then + echo "::error::refusing to publish 'latest' from $EVENT_NAME on $GIT_REF" + exit 1 fi - DOCKER_TAG=$(echo "$DOCKER_TAG" | sed 's/[^a-zA-Z0-9\.-]/-/g') - echo "DOCKER_TAG=${DOCKER_TAG}" >> "$GITHUB_OUTPUT" + # Reject what Docker would not accept as a tag, rather than letting + # imagetools fail later with an opaque reference-parse error. + if [[ ! "$DOCKER_TAG" =~ ^[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}$ ]]; then + echo "::error::ref did not yield a usable image tag: $DOCKER_TAG" + exit 1 + fi + echo "DOCKER_TAG=$DOCKER_TAG" >> "$GITHUB_OUTPUT" - name: Create manifest list and push working-directory: ${{ runner.temp }}/digests From 71917bed35896eced90b8cce64c764ac5341d4a4 Mon Sep 17 00:00:00 2001 From: Diana Borbe Date: Wed, 19 Aug 2026 18:00:24 +0200 Subject: [PATCH 4/4] After code review --- .github/workflows/docker.yaml | 16 ++++++++-------- Dockerfile | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 087bdd4..497ada8 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -46,7 +46,7 @@ jobs: name: build (${{ matrix.platform }}) steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: # On workflow_dispatch, build the caller-specified ref. On push events # inputs.tag is empty, which checkout treats as the triggering commit. @@ -65,10 +65,10 @@ jobs: echo "KMS_VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo '0.1.0-dev')" >> "$GITHUB_ENV" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0 - name: Log in to Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -76,7 +76,7 @@ jobs: - name: Build and push by digest id: build - uses: docker/build-push-action@v6 + uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 with: context: . file: Dockerfile @@ -96,7 +96,7 @@ jobs: touch "${{ runner.temp }}/digests/${digest#sha256:}" - name: Upload digest - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: digests-${{ env.PLATFORM_PAIR }} path: ${{ runner.temp }}/digests/* @@ -114,17 +114,17 @@ jobs: TAG: ${{ github.event.inputs.tag || (github.event_name == 'push' && github.ref == 'refs/heads/main' && 'latest') || github.ref_name }} steps: - name: Download digests - uses: actions/download-artifact@v4 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: ${{ runner.temp }}/digests pattern: digests-* merge-multiple: true - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0 - name: Log in to Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} diff --git a/Dockerfile b/Dockerfile index f9d3b1a..38ebe5f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,4 +37,5 @@ USER kms WORKDIR /home/kms EXPOSE 9090 -ENTRYPOINT ["kms", "--home", "/home/kms", "start"] +ENTRYPOINT ["kms"] +CMD ["--home", "/home/kms", "start"]