Skip to content

Add image digest to image signing step #6

Add image digest to image signing step

Add image digest to image signing step #6

name: Build and publish Docker image

Check failure on line 1 in .github/workflows/ci-spring-boot-build-publish-image.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/ci-spring-boot-build-publish-image.yml

Invalid workflow file

(Line: 249, Col: 19): Unrecognized named-value: 'jobs'. Located at position 1 within expression: jobs.build-publish-image.outputs.image-digest
on:
workflow_call:
inputs:
image-name:
description: Name of Docker image
required: false
type: string
image-pack:
description: Docker image pack of builder-jammy-tiny, builder-jammy-base or builder-jammy-full
default: builder-jammy-tiny
required: false
type: string
image-signing:
description: Flag to toggle image signing on/off - default off
default: true
required: false
type: boolean
java-version:
description: Main version of java
default: "11"
required: false
type: string
container-scan-offline-mode:
description: Container-scan is default download updated CVE definitions via Trivy, enable offline on download problems
default: false
type: boolean
slack-channel-id:
description: Team channel id
default: ""
required: false
type: string
application-path:
default: "./"
required: false
type: string
cache-path:
default: "**/pom.xml"
required: false
type: string
update-versions:
default: "true"
required: false
type: string
setup-npm-auth:
description: Configure private NPM registry authentication
default: false
required: false
type: boolean
container-registry:
description: Azure Container Registry name
default: "creiddev.azurecr.io"
required: false
type: string
sp-container-registry-client-id:
required: false
default: "AZURE_CLIENT_ID"
type: string
description: Service Principal used for container registry in inputs
outputs:
image-version:
description: "Docker image version"
value: ${{ jobs.build-publish-image.outputs.image-tag }}
image-digest:
description: "Docker image SHA256 digest"
value: ${{ jobs.build-publish-image.outputs.image-digest }}
jobs:
inputs-to-summary:
runs-on: ubuntu-latest
steps:
- name: "Write inputs to summary"
uses: felleslosninger/github-actions/json-to-summary@e4ba7c675762d5e9d3eeb48d6b75042e3dd325d3 # pin@v0.7.5
with:
json: ${{ toJson(inputs) }}
title: "Inputs"
build-publish-image:
runs-on: ubuntu-latest
outputs:
image-tag: ${{ steps.set-image-tag.outputs.image-tag }}
image-digest: ${{ steps.set-image-digest.outputs.image-digest }}
permissions:
id-token: write
contents: write
packages: read
steps:
- name: Set image tag
id: set-image-tag
run: |
image_tag=$(date +'%Y-%m-%d-%H%M')-${GITHUB_SHA::8}
echo "image-tag=$image_tag" >> "$GITHUB_OUTPUT"
echo "- Image tag: $image_tag" >> "$GITHUB_STEP_SUMMARY"
- name: Set image name
id: set-image-name
run: |
image_name=${{ inputs.container-registry }}/${{ inputs.image-name || github.event.repository.name }}
echo "image-name=$image_name" >> "$GITHUB_OUTPUT"
echo "- Image name: $image_name" >> "$GITHUB_STEP_SUMMARY"
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # pin@v5.0.0
- name: Set up JDK ${{ inputs.java-version }}
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # pin@v5.0.0
with:
distribution: "liberica"
java-version: ${{ inputs.java-version }}
cache: maven
cache-dependency-path: ${{ inputs.cache-path }}
- name: Maven environment setup
uses: s4u/maven-settings-action@894661b3ddae382f1ae8edbeab60987e08cf0788 # pin@v4.0.0
with:
servers: |
[{
"id": "github-oidc-sdk",
"username": "${{ secrets.GH_PACKAGES_READ_USER }}",
"password": "${{ secrets.GH_PACKAGES_READ_PAT }}"
},
{
"id": "github",
"username": "${{ secrets.GH_PACKAGES_READ_USER }}",
"password": "${{ secrets.GH_PACKAGES_READ_PAT }}"
}]
- name: Maven update version used in application.yaml
run: |
if [ "${{ inputs.update-versions }}" == "true" ]; then
mvn versions:set -B -DnewVersion="${{ steps.set-image-tag.outputs.image-tag }}"
echo "- \`mvn versions\` was executed" >> "$GITHUB_STEP_SUMMARY"
else
echo "- \`mvn versions\` was not executed" >> "$GITHUB_STEP_SUMMARY"
fi
- name: Configure private NPM registry authentication
if: ${{ inputs.setup-npm-auth == true }}
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # pin@v5.0.0
with:
node-version: '20.x'
registry-url: 'https://npm.pkg.github.com'
scope: '@felleslosninger'
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build image with Maven/Spring Boot
run: |
mvn -B spring-boot:build-image \
--file ${{ inputs.application-path }}pom.xml \
-Dspring-boot.build-image.imageName=${{ steps.set-image-name.outputs.image-name }}:${{ steps.set-image-tag.outputs.image-tag }} \
-Dspring-boot.build-image.builder=paketobuildpacks/${{ inputs.image-pack }} \
-Dspring-boot.build-image.createdDate=now
- name: Set trivyignore env if file exists
id: set-trivyignore-path
run: |
if [ -f "${{ inputs.application-path }}.trivyignore" ]; then
trivyignore_path=${{ inputs.application-path }}.trivyignore
echo "trivyignore-path=$trivyignore_path" >> "$GITHUB_OUTPUT"
echo "- Trivy ignore path: $trivyignore_path" >> "$GITHUB_STEP_SUMMARY"
fi
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # pin@v0.33.1
id: trivy-primary
env:
TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db:2,public.ecr.aws/aquasecurity/trivy-db:2
TRIVY_JAVA_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-java-db:1,public.ecr.aws/aquasecurity/trivy-java-db:1
with:
image-ref: ${{ steps.set-image-name.outputs.image-name }}:${{ steps.set-image-tag.outputs.image-tag }}
exit-code: "1"
severity: "CRITICAL,HIGH"
trivyignores: ${{ steps.set-trivyignore-path.outputs.trivyignore-path }}
- name: Create SBOM artifact name
id: sbom-name
run: |
SBOM_NAME=$(echo ${{ steps.set-image-name.outputs.image-name }} | tr '/' '-')
echo "sbom-artifact-id=$SBOM_NAME" >> "$GITHUB_OUTPUT"
echo "- SBOM: $SBOM_NAME" >> "$GITHUB_STEP_SUMMARY"
- name: Run Trivy SBOM generation
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # pin@v0.33.1
env:
TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db:2,public.ecr.aws/aquasecurity/trivy-db:2
TRIVY_JAVA_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-java-db:1,public.ecr.aws/aquasecurity/trivy-java-db:1
with:
scan-type: image
format: github
image-ref: "${{ steps.set-image-name.outputs.image-name }}:${{ steps.set-image-tag.outputs.image-tag }}"
output: "sbom-${{ steps.sbom-name.outputs.sbom-artifact-id }}-${{ steps.set-image-tag.outputs.image-tag }}.json"
trivyignores: ${{ steps.set-trivyignore-path.outputs.trivyignore-path }}
github-pat: ${{ secrets.GITHUB_TOKEN }}
- name: Upload trivy report as a Github artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # pin@v4.6.2
with:
name: "sbom-${{ steps.sbom-name.outputs.sbom-artifact-id }}-${{ steps.set-image-tag.outputs.image-tag }}"
path: "${{ github.workspace }}/sbom-${{ steps.sbom-name.outputs.sbom-artifact-id }}-${{ steps.set-image-tag.outputs.image-tag }}.json"
- name: Login to Azure
uses: azure/login@v2
with:
client-id: ${{ secrets[inputs.sp-container-registry-client-id] }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Login to Azure Container Registry
run: az acr login --name "$ACR_NAME"
env:
ACR_NAME: ${{ inputs.container-registry }}
- name: Push image
run: docker push ${{ steps.set-image-name.outputs.image-name }}:${{ steps.set-image-tag.outputs.image-tag }}
- name: Set image digest
id: set-image-digest
run: |
image_digest=$(docker inspect \
--format='{{.RepoDigests}}' ${{ steps.set-image-name.outputs.image-name }}:${{ steps.set-image-tag.outputs.image-tag }} \
| cut -d '@' -f 2 \
| cut -d ']' -f 1)
echo "image-digest=$image_digest" >> "$GITHUB_OUTPUT"
echo "- Image digest: $image_digest" >> "$GITHUB_STEP_SUMMARY"
- name: Image signing
if: ${{ inputs.image-signing == true }}
uses: felleslosninger/github-workflows-internal/image-signing@image-signing-as-composite-action
with:
image: ${{ steps.set-image-name.outputs.image-name }}:${{ steps.set-image-tag.outputs.image-tag }}"
subject: ${{ github.event.repository.name }}
digest: ${{ jobs.build-publish-image.outputs.image-digest }}
notify-on-errors:
runs-on: ubuntu-latest
needs: [build-publish-image]
if: always() && contains(needs.*.result, 'failure')
strategy:
matrix:
slack-channel: ["${{ inputs.slack-channel-id }}", "C05G4B8R2GG"]
steps:
- name: Send Slack notification
uses: felleslosninger/github-actions/send-slack-notification@e4ba7c675762d5e9d3eeb48d6b75042e3dd325d3 # pin@v0.7.5
with:
slack-channel-id: ${{ matrix.slack-channel }}
slack-bot-token: ${{ secrets.SLACK_CICD_NOTIFICATION_TOKEN }}
failed: "true"