ci: reproducible builds ko (no gcp) (#871)

* add ko build actions and worklflows
* add apko build actions and worklflows
* add .ko.yaml file
* add apko image definitions
* add signing container, add signing sboms, add uploading sboms
This commit is contained in:
leongross 2023-01-13 07:38:31 -08:00 committed by GitHub
parent 82462fab17
commit c36a009188
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 690 additions and 0 deletions

167
.github/actions/build_apko/action.yml vendored Normal file
View File

@ -0,0 +1,167 @@
name: Build container images using apko
description: Build one or multiple apko images based on supplied .yaml files
inputs:
apkoConfig:
description: "Path to the apko .yaml config file. If left empty, all images will be built."
required: false
apkoTag:
description: "Use this image tag"
required: false
default: latest
apkoArch:
description: "Use this image architecture"
required: false
default: amd64
registry:
description: "Container registry to use"
default: "ghcr.io"
required: true
githubToken:
description: "GitHub authorization token"
required: true
cosignPublicKey:
description: "Cosign public key"
required: false
default: ""
cosignPrivateKey:
description: "Cosign private key"
required: false
default: ""
cosignPassword:
description: "Password for Cosign private key"
required: false
default: ""
# Linux runner only (docker required)
runs:
using: "composite"
steps:
- name: Install deps
shell: bash
run: |
echo "::group::Install dependencies"
sudo apt-get update
sudo apt-get install -y zip
echo "::endgroup::"
- name: Log in to the Container registry
id: docker-login
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # tag=v2.1.0
with:
registry: ${{ inputs.registry }}
username: ${{ github.actor }}
password: ${{ inputs.githubToken }}
- name: Install Cosign
uses: sigstore/cosign-installer@9becc617647dfa20ae7b1151972e9b3a2c338a2b # v2.8.1
if: ${{ inputs.cosignPublicKey != '' && inputs.cosignPrivateKey != '' && inputs.cosignPassword != '' }}
- name: Build apko images and sign them
run: |
if [[ -z "${{ inputs.apkoConfig }}" ]]; then
echo "Building all images in image"
mkdir sboms
for imageConfig in apko/*.yaml; do
echo "Building image for $imageConfig"
imageName=$(basename $imageConfig | cut -d. -f1 )
registry="${{ inputs.registry }}/edgelesssys/apko-${imageName}"
outTar="${imageName}.tar"
mkdir -p sboms/$imageName
# build the image
docker run \
-v "$PWD":/work \
cgr.dev/chainguard/apko:${{ inputs.apkoTag }} \
build \
"${imageConfig}" \
--build-arch ${{ inputs.apkoArch }} \
--sbom \
"${registry}" \
"${outTar}"
# push container
docker load < $outTar
docker push $registry
imageDigest=$(docker inspect --format='{{index .RepoDigests 0}}' $registry)
echo "$imageDigest" >> "$GITHUB_STEP_SUMMARY"
# cosign the container and push to registry
cosign sign \
--key env://COSIGN_PRIVATE_KEY \
$imageDigest \
-y
# move sboms to folder
mv sbom-*.* sboms/$imageName/
done
else
echo "Building image for ${{ inputs.apkoConfig }}"
imageName=$(basename ${{ inputs.apkoConfig }} | cut -d. -f1 )
registry="${{ inputs.registry }}/edgelesssys/apko-${imageName}"
outTar="${imageName}.tar"
mkdir -p sboms/$imageName
# build the image
docker run \
-v "$PWD":/work \
cgr.dev/chainguard/apko:${{ inputs.apkoTag }} \
build \
"${imageConfig}" \
--build-arch ${{ inputs.apkoArch }} \
--sbom \
"${registry}" \
"${outTar}"
# push container
docker load < $outTar
docker push $registry
imageDigest=$(docker inspect --format='{{index .RepoDigests 0}}' $registry)
echo "$imageDigest" >> "$GITHUB_STEP_SUMMARY"
# cosign the container and push to registry
cosign sign \
--key env://COSIGN_PRIVATE_KEY \
$imageDigest \
-y
mv sbom-*.* sboms/$imageName/
fi
shell: bash
env:
COSIGN_EXPERIMENTAL: "true"
COSIGN_PUBLIC_KEY: ${{ inputs.cosignPublicKey }}
COSIGN_PRIVATE_KEY: ${{ inputs.cosignPrivateKey }}
COSIGN_PASSWORD: ${{ inputs.cosignPassword }}
- name: Sign sboms
run: |
for dir in sboms/*; do
for file in $dir/*; do
cosign sign-blob \
--key env://COSIGN_PRIVATE_KEY \
$file \
-y \
> $file.sig
done
done
zip -r sboms.zip sboms
shell: bash
env:
COSIGN_PUBLIC_KEY: ${{ inputs.cosignPublicKey }}
COSIGN_PRIVATE_KEY: ${{ inputs.cosignPrivateKey }}
COSIGN_PASSWORD: ${{ inputs.cosignPassword }}
if: ${{ inputs.cosignPublicKey != '' && inputs.cosignPrivateKey != '' && inputs.cosignPassword != '' }}
- name: Upload SBOMs
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
name: sboms
path: sboms.zip
if: always()
continue-on-error: true

111
.github/actions/build_ko/action.yml vendored Normal file
View File

@ -0,0 +1,111 @@
name: Build micro service using Ko
description: Build and upload a go micro service using ko
inputs:
name:
description: "Name of the micro-service"
required: true
registry:
description: "Name of the registry to use"
required: false
default: "ghcr.io"
pseudoVersion:
description: "Check if pseudo-version should be generated"
default: "false"
required: true
koConfig:
description: "Path to the .ko.yaml config file"
required: false
default: ".ko.yaml"
koTarget:
description: "Go package to build with ko"
required: true
pushTag:
description: "Use this image tag"
required: false
githubToken:
description: "GitHub authorization token"
required: true
generateKoSBOM:
description: "Generate unsigned ko SBOM"
required: false
default: "false"
outputs:
container_full:
description: "Full container reference"
value: ${{ steps.build.container_full }}
container_image:
description: "Container image"
value: ${{ steps.build.outputs.container_image }}
container_tag:
description: "Container tag"
value: ${{ steps.build.container_tag }}
# Linux runner only
runs:
using: "composite"
steps:
- name: Determine pseudo version
if: inputs.pseudoVersion == 'true'
id: pseudo-version
uses: ./.github/actions/pseudo_version
- name: Set up ko
uses: imjasonh/setup-ko@9a31684920a610d5dbe8012888714d64706f9787 # tag=v0.6
- name: Build and upload ko container image
shell: bash
id: build
env:
KO_USER: ${{ github.actor }}
KO_CONFIG_PATH: ${{ inputs.koConfig }}
KO_PASSWORD: ${{ inputs.githubToken }}
KO_DOCKER_REPO: ${{ inputs.registry }}/edgelesssys/${{ inputs.name }}-ko
run: |
tags=""
sbom=""
if [[ "${{ github.ref }}" == "${{ github.event.repository.default_branch }}" ]]; then
tags="latest"
else:
tags="${{ github.sha }}"
fi
if [ -n "${{ inputs.pushTag }}" ]; then
if [ -n "${tags}" ]; then
tags="${tags},${{ inputs.pushTag }}"
else
tags="${{ inputs.pushTag }}"
fi
fi
if [ -n "${{ steps.pseudo-version.outputs.pseudoVersion }}" ]; then
if [ -n "${tags}" ]; then
tags="${tags},${{ steps.pseudo-version.outputs.pseudoVersion }}"
else
tags="${{ steps.pseudo-version.outputs.pseudoVersion }}"
fi
fi
if [ "${{ inputs.generateKoSBOM }}" == "false" ]; then
sbom="--sbom=none"
fi
container_full=$(ko build ${{ inputs.koTarget }} --bare --tags ${tags} ${sbom})
container_image=$(echo $container_full | cut -d@ -f1)
container_sha256=$(echo $container_full | cut -d: -f2)
cat <<EOF > container_data_ko.json
{
"container_full": "${container_full}",
"container_image": "${container_image}",
"container_sha256": "${container_sha256}"
}
EOF
- name: Upload Container Data # since github censors hashes that may share data with secrets, we need to upload the data as an artifact
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
name: container_data_ko
path: container_data_ko.json

View File

@ -0,0 +1,79 @@
name: Build micro service (KO)
description: Build and upload a container image for a Constellation micro-service
inputs:
name:
description: "Name of the micro-service"
required: true
koConfig:
description: "Path to the .ko.yaml config file"
default: ".ko.yaml"
required: false
pseudoVersion:
description: "Check if pseudo-version should be generated"
default: "false"
required: true
koTarget:
description: "Go package to build with ko"
required: true
pushTag:
description: "Use this image tag"
required: false
githubToken:
description: "GitHub authorization token"
required: true
generateKoSBOM:
description: "Generate unsigned ko SBOM"
required: false
default: "false"
cosignPublicKey:
description: "Cosign public key"
required: false
cosignPrivateKey:
description: "Cosign private key"
required: false
cosignPassword:
description: "Password for Cosign private key"
required: false
# Linux runner only
runs:
using: "composite"
steps:
- name: Determine pseudo version
if: inputs.pseudoVersion == 'true'
uses: ./.github/actions/pseudo_version
with:
constellationPath: ${{ inputs.constellationPath }}
- name: Build and upload container image
id: build-and-upload
uses: ./.github/actions/build_ko
with:
name: ${{ inputs.name }}
koConfig: ${{ inputs.koConfig }}
pseudoVersion: ${{ inputs.pseudoVersion }}
koTarget: ${{ inputs.koTarget }}
githubToken: ${{ inputs.GITHUB_TOKEN }}
pushTag: ci-test
- name: Download ko Container Data
id: download_container_data
uses: actions/download-artifact@v2
with:
name: container_data_ko
path: CONTAINER_DATA_KO
- name: Set container url to Github Env
shell: bash
run: |
container_full=$(jq -r .container_full < container_data_ko.json)
echo CONTAINER_FULL=$container_full >> $GITHUB_ENV
- name: Generate SBOM
uses: ./.github/actions/container_sbom
with:
containerReference: ${{ env.CONTAINER_FULL }}
cosignPublicKey: ${{ inputs.cosignPublicKey }}
cosignPrivateKey: ${{ inputs.cosignPrivateKey }}
cosignPassword: ${{ inputs.cosignPassword }}
if: ${{ inputs.cosignPublicKey != '' && inputs.cosignPrivateKey != '' && inputs.cosignPassword != '' && inputs.generateKoSBOM == 'false' }}

33
.github/workflows/build-apko-image.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: Build and upload all apko container images
on:
workflow_dispatch:
push:
branches:
- main
- "release/**"
jobs:
build-apko-image:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Check out repository
id: checkout
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0
with:
ref: ${{ github.head_ref }}
- name: Build and upload apko image
uses: ./.github/actions/build_apko
with:
apkoConfig: ""
apkoTag: "latest"
apkoArch: "amd64"
registry: ghcr.io
githubToken: ${{ secrets.GITHUB_TOKEN }}
cosignPublicKey: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PUBLIC_KEY || secrets.COSIGN_DEV_PUBLIC_KEY }}
cosignPrivateKey: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PRIVATE_KEY || secrets.COSIGN_DEV_PRIVATE_KEY }}
cosignPassword: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PASSWORD || secrets.COSIGN_DEV_PASSWORD }}

View File

@ -0,0 +1,31 @@
name: Build and upload constellation node operator image (KO)
on:
workflow_dispatch:
push:
branches:
- main
- "release/**"
jobs:
build-constellation-node-operator:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Check out repository
id: checkout
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0
with:
ref: ${{ github.head_ref }}
- name: Build and upload constellation-node-operator container image
uses: ./.github/actions/build_micro_service_ko
with:
name: node-operator
koTarget: ./operators/constellation-node-operator
githubToken: ${{ secrets.GITHUB_TOKEN }}
cosignPublicKey: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PUBLIC_KEY || secrets.COSIGN_DEV_PUBLIC_KEY }}
cosignPrivateKey: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PRIVATE_KEY || secrets.COSIGN_DEV_PRIVATE_KEY }}
cosignPassword: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PASSWORD || secrets.COSIGN_DEV_PASSWORD }}

View File

@ -0,0 +1,39 @@
name: Build and upload join service image (KO)
env:
REGISTRY: ghcr.io
on:
workflow_dispatch:
push:
branches:
- main
- "release/**"
jobs:
build-join-service-ko:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Check out repository
id: checkout
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0
with:
ref: ${{ github.head_ref }}
- name: Setup Go environment
uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f # tag=v3.3.1
with:
go-version: "1.19.5"
- name: Build and upload join service container image
id: build-and-upload
uses: ./.github/actions/build_micro_service_ko
with:
name: joinservice
koTarget: ./joinservice/cmd
githubToken: ${{ secrets.GITHUB_TOKEN }}
cosignPublicKey: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PUBLIC_KEY || secrets.COSIGN_DEV_PUBLIC_KEY }}
cosignPrivateKey: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PRIVATE_KEY || secrets.COSIGN_DEV_PRIVATE_KEY }}
cosignPassword: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PASSWORD || secrets.COSIGN_DEV_PASSWORD }}

View File

@ -0,0 +1,43 @@
name: Build and upload KMS image (KO)
env:
REGISTRY: ghcr.io
on:
workflow_dispatch:
push:
branches:
- main
- "release/**"
jobs:
build-kms-server:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Check out repository
id: checkout
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0
with:
ref: ${{ github.head_ref }}
- name: Setup Go environment
uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f # tag=v3.3.1
with:
go-version: "1.19.5"
- name: Set up ko
uses: imjasonh/setup-ko@9a31684920a610d5dbe8012888714d64706f9787 # tag=v0.6
- name: Build and upload KMS server container image
id: build-and-upload
uses: ./.github/actions/build_micro_service_ko
with:
name: kmsserver
koConfig: .ko.yaml
koTarget: ./kms/cmd
githubToken: ${{ secrets.GITHUB_TOKEN }}
cosignPublicKey: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PUBLIC_KEY || secrets.COSIGN_DEV_PUBLIC_KEY }}
cosignPrivateKey: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PRIVATE_KEY || secrets.COSIGN_DEV_PRIVATE_KEY }}
cosignPassword: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PASSWORD || secrets.COSIGN_DEV_PASSWORD }}

View File

@ -0,0 +1,37 @@
name: Build and upload verification-service image (KO)
on:
workflow_dispatch:
push:
branches:
- main
- "release/**"
jobs:
build-verification-service:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Check out repository
id: checkout
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0
with:
ref: ${{ github.head_ref }}
- name: Setup Go environment
uses: actions/setup-go@c4a742cab115ed795e34d4513e2cf7d472deb55f # tag=v3.3.1
with:
go-version: "1.19.5"
- name: Build and upload verification-service container image (KO)
id: build-and-upload
uses: ./.github/actions/build_micro_service_ko
with:
name: verification-service
koTarget: ./verify/cmd
githubToken: ${{ secrets.GITHUB_TOKEN }}
cosignPublicKey: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PUBLIC_KEY || secrets.COSIGN_DEV_PUBLIC_KEY }}
cosignPrivateKey: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PRIVATE_KEY || secrets.COSIGN_DEV_PRIVATE_KEY }}
cosignPassword: ${{ startsWith(github.ref, 'refs/heads/release/v') && secrets.COSIGN_PASSWORD || secrets.COSIGN_DEV_PASSWORD }}

80
.ko.yaml Normal file
View File

@ -0,0 +1,80 @@
defaultBaseImage: ghcr.io/edgelesssys/apko-alpine-base:latest
baseImageOverrides:
github.com/edgelesssys/constellation/operators/constellation-node-operator/v2: ghcr.io/edgelesssys/apko-alpine-base-user-65532
github.com/edgelesssys/constellation/v2/hack/qemu-metadata-api: ghcr.io/edgelesssys/apko-alpine-qemu-metadata-api
builds:
- id: kms
dir: .
main: ./kms/cmd
env:
- CGO_ENABLED=0
- GOOS=linux
- GOARCH=amd64
flags:
- -trimpath
- -buildvcs=false
- -a
ldflags:
- -s -w -buildid=''
- -extldflags "-static"
- id: joinservice
dir: .
main: ./joinservice/cmd
env:
- CGO_ENABLED=0
- GOOS=linux
- GOARCH=amd64
flags:
- -trimpath
- -buildvcs=false
- -a
ldflags:
- -s -w -buildid=''
- -extldflags "-static"
- id: constellation-node-operator
dir: .
main: ./operators/constellation-node-operator/
env:
- CGO_ENABLED=0
- GOOS=linux
- GOARCH=amd64
flags:
- -trimpath
- -buildvcs=false
- -a
ldflags:
- -s -w -buildid=''
- -extldflags "-static"
- id: verification-service
dir: .
main: ./verify/cmd
env:
- CGO_ENABLED=0
- GOOS=linux
- GOARCH=amd64
flags:
- -trimpath
- -buildvcs=false
- -a
ldflags:
- -s -w -buildid=''
- -extldflags "-static"
- id: qemu-metadata-api
dir: .
main: ./hack/qemu-metadata-api/
env:
- CGO_ENABLED=0
- GOOS=linux
- GOARCH=amd64
flags:
- -trimpath
- -buildvcs=false
- -a
ldflags:
- -s -w -buildid=''

View File

@ -0,0 +1,25 @@
contents:
repositories:
- https://dl-cdn.alpinelinux.org/alpine/edge/main
packages:
- alpine-base
entrypoint:
command: /bin/sh -l
accounts:
groups:
- groupname: "65532"
gid: 65532
users:
- username: "65532"
gid: 65532
uid: 65532
run-as: "65532"
environment:
PATH: /usr/sbin:/sbin:/usr/bin:/bin
archs:
- amd64
- 386

15
apko/alpine-base.yaml Normal file
View File

@ -0,0 +1,15 @@
contents:
repositories:
- https://dl-cdn.alpinelinux.org/alpine/edge/main
packages:
- alpine-base
entrypoint:
command: /bin/sh -l
environment:
PATH: /usr/sbin:/sbin:/usr/bin:/bin
archs:
- amd64
- 386

View File

@ -0,0 +1,16 @@
contents:
repositories:
- https://dl-cdn.alpinelinux.org/alpine/edge/main
- https://dl-cdn.alpinelinux.org/alpine/edge/community
packages:
- alpine-base
- cryptsetup-dev
- bash
- gcompat
environment:
PATH: /usr/sbin:/sbin:/usr/bin:/bin
archs:
- amd64
- 386

View File

@ -0,0 +1,14 @@
contents:
repositories:
- https://dl-cdn.alpinelinux.org/alpine/edge/main
- https://dl-cdn.alpinelinux.org/alpine/edge/community
packages:
- alpine-base
- libvirt-dev
- bash
environment:
PATH: /usr/sbin:/sbin:/usr/bin:/bin
archs:
- amd64
- 386