-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
37 changed files
with
1,791 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
name: build | ||
description: 'Build connaisseur image' | ||
inputs: | ||
image_registry: | ||
description: 'Image registry to be used' | ||
required: true | ||
image_repo: | ||
description: 'Image repository to be used' | ||
required: true | ||
image_tag: | ||
description: 'Image tag to be used' | ||
required: true | ||
ref_tags: | ||
description: 'Reference tags to be used' | ||
required: true | ||
image_labels: | ||
description: 'Image labels to be used' | ||
required: true | ||
repo_owner: | ||
description: 'Name of repository owner, e.g. "github.repository_owner" for ghcr.io' | ||
required: true | ||
repo_token: | ||
description: 'Access token for repository owner, e.g. "secrets.GITHUB_TOKEN" for ghcr.io' | ||
required: true | ||
cosign_version: | ||
description: 'Cosign version to be used' | ||
required: true | ||
cosign_private_key: | ||
description: 'Cosign private key' | ||
required: true | ||
cosign_password: | ||
description: 'Cosign private key password' | ||
required: true | ||
outputs: | ||
cosign_public_key: | ||
description: 'Cosign public key' | ||
value: ${{ steps.verify.outputs.public_key }} | ||
runs: | ||
using: "composite" | ||
steps: | ||
- name: Install Cosign | ||
uses: sigstore/cosign-installer@11086d25041f77fe8fe7b9ea4e48e3b9192b8f19 # v3.1.2 (probably) | ||
- name: Set up Docker buildx | ||
uses: docker/setup-buildx-action@f03ac48505955848960e80bbb68046aa35c7b9e7 # v2.4.1 | ||
- name: Login with registry | ||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0 | ||
with: | ||
registry: ${{ inputs.image_registry }} | ||
username: ${{ inputs.repo_owner }} | ||
password: ${{ inputs.repo_token }} | ||
- name: Generate tags | ||
id: tags | ||
run: | | ||
echo "${{ inputs.ref_tags }}" | ||
export PREFIX="${{ inputs.image_registry }}/${{ inputs.image_repo }}:" | ||
TAGS="${PREFIX}${{ inputs.image_tag }},$(echo ${{ inputs.ref_tags }} | tr ' ' '\n' | awk '{print "${PREFIX}"$1}' | envsubst | tr '\n' ',')" | ||
echo tags=${TAGS} >> ${GITHUB_OUTPUT} | ||
shell: bash | ||
- name: Build and push image | ||
id: build | ||
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v4.0.0 | ||
with: | ||
push: true | ||
cache-from: type=gha | ||
cache-to: type=gha,mode=max | ||
file: build/Dockerfile | ||
labels: ${{ inputs.image_labels }} | ||
tags: ${{ steps.tags.outputs.tags }} | ||
provenance: true | ||
sbom: true | ||
- name: Create SBOM | ||
uses: anchore/sbom-action@07978da4bdb4faa726e52dfc6b1bed63d4b56479 # v0.13.3 | ||
with: | ||
image: ${{ inputs.image_registry }}/${{ inputs.image_repo }}@${{ steps.build.outputs.digest }} | ||
format: cyclonedx-json | ||
artifact-name: sbom.cdx | ||
output-file: sbom.cdx | ||
- name: Sign image | ||
id: sign | ||
run: | | ||
cosign sign --key env://COSIGN_PRIVATE_KEY -a tag=${{ inputs.image_tag }} -y ${TAGS} | ||
cosign attach sbom --sbom sbom.cdx --type cyclonedx ${TAGS} | ||
cosign sign --key env://COSIGN_PRIVATE_KEY --attachment sbom -y ${TAGS} | ||
env: | ||
TAGS: ${{ inputs.image_registry }}/${{ inputs.image_repo }}@${{ steps.build.outputs.digest }} | ||
COSIGN_PRIVATE_KEY: ${{ inputs.cosign_private_key }} | ||
COSIGN_PASSWORD: ${{ inputs.cosign_password }} | ||
shell: bash | ||
- name: Verify build data | ||
id: verify | ||
run: | | ||
mkdir ci | ||
cosign public-key --key env://COSIGN_PRIVATE_KEY > ci/cosign.pub | ||
PUBLIC_KEY="$(cat ci/cosign.pub)" | ||
cosign tree ${TAGS} | ||
PUBLIC_KEY=${PUBLIC_KEY} cosign verify --key env://PUBLIC_KEY ${TAGS} | ||
PUBLIC_KEY=${PUBLIC_KEY} cosign verify --key env://PUBLIC_KEY --attachment sbom ${TAGS} | ||
SIGNATURE=$(cosign triangulate ${TAGS}) | ||
PUBLIC_KEY="${PUBLIC_KEY//$'\n'/'<br>'}" | ||
SBOM="${SIGNATURE::-4}.sbom" | ||
echo public_key="${PUBLIC_KEY}" >> ${GITHUB_OUTPUT} | ||
echo signature=${SIGNATURE} >> ${GITHUB_OUTPUT} | ||
echo sbom=${SBOM} >> ${GITHUB_OUTPUT} | ||
env: | ||
TAGS: ${{ inputs.image_registry }}/${{ inputs.image_repo }}@${{ steps.build.outputs.digest }} | ||
COSIGN_PRIVATE_KEY: ${{ inputs.cosign_private_key }} | ||
COSIGN_PASSWORD: ${{ inputs.cosign_password }} | ||
shell: bash | ||
- name: Upload public key | ||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 | ||
with: | ||
name: cosign.pub | ||
path: ci/cosign.pub | ||
- name: Show build and signature information | ||
run: | | ||
CONFIGURE="yq '. *+ load(\"tests/integration/var-img.yaml\")' tests/integration/ghcr-values.yaml > ghcr.yaml &&\n\t IMAGE=\"${{ inputs.image_registry }}/${{ inputs.image_repo }}\" TAG=\"${{ inputs.image_tag }}\" IMAGEPULLSECRET=\"<ImagePullSecret name>\" envsubst < ghcr.yaml > update &&\n\t yq '. *+ load(\"update\")' -i charts/connaisseur/values.yaml &&\n\t rm ghcr.yaml update" | ||
CONFIGURE=$(printf -- "${CONFIGURE}") | ||
PUBLIC_KEY="${{ steps.verify.outputs.public_key }}" | ||
PUBLIC_KEY="$(printf -- "${PUBLIC_KEY//'<br>'/'\n'}")" | ||
HELM_PATCH="yq e '.kubernetes.deployment.image.repository = \"${{ inputs.image_registry }}/${{ inputs.image_repo }}\"' -i charts/connaisseur/values.yaml\nyq e '.kubernetes.deployment.image.tag = \"${{ inputs.image_tag }}\"' -i charts/connaisseur/values.yaml" | ||
HELM_PATCH=$(printf -- "${HELM_PATCH}") | ||
echo "# :building_construction: Build Information" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<table>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<tr><th>Build artifacts</th><th>Value</th></tr>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<tr><td>Registry</td><td><code>${{ inputs.image_registry }}</code></td></tr>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<tr><td>Repository</td><td><code>${{ inputs.image_repo }}</code></td></tr>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<tr><td>Tags</td><td><code>${{ inputs.image_tag }}</code>, <code>${{ inputs.ref_tags }}</code></td></tr>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<tr><td>Workflow image</td><td><code>${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }}</code></td></tr>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<tr><td>All reference tags</td><td><code>$(echo ${{ steps.tags.outputs.tags }} | tr ',' '\n')</code></td></tr>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<tr><td>Digest</td><td><code>${{ steps.build.outputs.digest }}</code></td></tr>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<tr><td>Signature</td><td><code>${{ steps.verify.outputs.signature }}</code></td></tr>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<tr><td>Public key</td><td><code>${PUBLIC_KEY}</code></td></tr>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<tr><td>SBOM (cyclonedx-json)</td><td><code>${{ steps.verify.outputs.sbom }}</code></td></tr>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "</table>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<details><summary>:bookmark_tabs: Metadata</summary>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<pre><code>${{ steps.build.outputs.metadata }}</code></pre>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "</details>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<details><summary>:hammer_and_wrench: Use Build Artifacts</summary>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "(needs <a href='https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry'>docker login via PAT</a> with package:read permission)" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<ul>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li><b>Workflow image reference</b> by tag: <pre><code>${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }}</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li><b>Main image reference</b> by tag: <pre><code>${{ inputs.image_registry }}/${{ inputs.image_repo }}:$(echo ${{ inputs.ref_tags }} | tr ' ' '\n' | head -n1)</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li><b>Image reference</b> by digest: <pre><code>${{ inputs.image_registry }}/${{ inputs.image_repo }}@${{ steps.build.outputs.digest }}</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li><b>Cosign signature</b>: <pre><code>${{ steps.verify.outputs.signature }}</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li><b>Syft SBOM (cyclonedx-json)</b>: <pre><code>${{ steps.verify.outputs.sbom }}</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Pull via <b>Docker</b>: <pre lang="bash"><code>docker pull ${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }}</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Use in <b>Helm chart</b> (needs <a href='https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/'>imagePullSecret via dockerconfigjson<a> of PAT with package:read permission): <pre lang="bash"><code>${HELM_PATCH}</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Configure <b>Helm chart</b> for successful validation build image (RUN ONLY ONCE, insert name of <code>imagePullSecret</code> in connaisseur namespace): <pre lang="bash"><code>${CONFIGURE}</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "</ul>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "</details>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<details><summary>:mag: Verify Build</summary>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "(needs <a href='https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry'>Docker login via PAT</a> with package:read permission)" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<ul>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Show <b>BuildKit image details</b>: <pre><code>docker buildx imagetools inspect ${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }}</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Extract <b>BuildKit SBOM</b> (can be consumed by e.g. <a href='https://github.com/anchore/syft'>syft</a> or <a href='https://github.com/anchore/grype'>grype</a>): <pre><code>docker buildx imagetools inspect ${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }} --format \"{{ json .SBOM.SPDX }}\"</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Extract <b>BuildKit provenance (<a href='https://slsa.dev/provenance/v0.2'>SLSA</a>)</b> data: <pre><code>docker buildx imagetools inspect ${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }} --format \"{{ json .Provenance.SLSA }}\"</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li><b>Cosign public key</b>: <pre><code>${PUBLIC_KEY}</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Store <b>Cosign public key</b>: <pre lang="bash"><code>echo \"${PUBLIC_KEY}\" > cosign.pub </code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Verify <b>Cosign signature</b> using <code>cosign.pub</code> file: <pre lang="bash"><code>cosign verify --key cosign.pub ${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }} </code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Verify <b>Cosign signature</b> : <pre lang="bash"><code>COSIGN_PUBLIC_KEY='${PUBLIC_KEY}' cosign verify --key env://COSIGN_PUBLIC_KEY ${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }} </code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Display all <b>Cosign supply chain security artifacts</b>: <pre lang="bash"><code>cosign tree ${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }} </code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "<li>Download <b>Cosign-attached SBOM</b> (syft-generated cyclonedx-json): <pre lang="bash"><code> | ||
COSIGN_PUBLIC_KEY='${PUBLIC_KEY}' cosign verify --key env://COSIGN_PUBLIC_KEY --attachment sbom ${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }} && # verify signature before download | ||
cosign download sbom ${{ inputs.image_registry }}/${{ inputs.image_repo }}:${{ inputs.image_tag }} > sbom.cdx # perform actual download | ||
</code></pre></li>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "</ul>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "</details>" >> ${GITHUB_STEP_SUMMARY} | ||
echo "" >> ${GITHUB_STEP_SUMMARY} | ||
echo "Let's start testing :rocket:" >> ${GITHUB_STEP_SUMMARY} | ||
shell: bash |
Oops, something went wrong.