Add image digest to image signing step #6
Workflow file for this run
This file contains hidden or 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
| name: Build and publish Docker image | ||
|
Check failure on line 1 in .github/workflows/ci-spring-boot-build-publish-image.yml
|
||
| 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" | ||