diff --git a/.github/actions/attach-cyclonedx-sbom/action.yml b/.github/actions/attach-cyclonedx-sbom/action.yml index b66f8497..e5246d70 100644 --- a/.github/actions/attach-cyclonedx-sbom/action.yml +++ b/.github/actions/attach-cyclonedx-sbom/action.yml @@ -6,9 +6,8 @@ inputs: description: Fully qualified image reference with tag required: true digest: - description: Image digest (sha256:...) for exact pushed reference; if omitted, digest is resolved from image - required: false - default: "" + description: Image digest (sha256:...) for exact pushed reference + required: true sbom_file: description: Output file for generated CycloneDX JSON required: false @@ -25,7 +24,7 @@ inputs: runs: using: composite steps: - - name: Resolve image subject reference + - name: Build exact image subject reference id: resolve_subject shell: bash env: @@ -34,23 +33,17 @@ runs: run: | set -e -o pipefail - DIGEST="${DIGEST_INPUT}" - if [ -z "${DIGEST}" ] && [[ "${IMAGE}" == *@sha256:* ]]; then - DIGEST="${IMAGE##*@}" - fi - if [ -z "${DIGEST}" ]; then - DIGEST="$(docker buildx imagetools inspect "${IMAGE}" | awk '/Digest:/ { print $2; exit }')" - fi + DIGEST="${DIGEST_INPUT#digest:}" + DIGEST="${DIGEST#:}" - if [ -z "${DIGEST}" ]; then - echo "Failed to resolve digest for ${IMAGE}" + if ! [[ "${DIGEST}" =~ ^sha256:[a-f0-9]{64}$ ]]; then + echo "Invalid digest provided: ${DIGEST_INPUT}" exit 1 fi - SUBJECT_REF="${IMAGE%@*}@${DIGEST}" + IMAGE_BASE="${IMAGE%@*}" + SUBJECT_REF="${IMAGE_BASE}@${DIGEST}" echo "Using subject reference: ${SUBJECT_REF}" - - echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT" echo "subject_ref=${SUBJECT_REF}" >> "$GITHUB_OUTPUT" - name: Generate CycloneDX SBOM diff --git a/.github/workflows/docker-workflow.yml b/.github/workflows/docker-workflow.yml index 9e0ed2df..f65af9f1 100644 --- a/.github/workflows/docker-workflow.yml +++ b/.github/workflows/docker-workflow.yml @@ -381,9 +381,10 @@ jobs: - name: Generate and attach CycloneDX SBOM to /ci/ image if: ${{ inputs.generate_sbom }} - uses: MOV-AI/.github/.github/actions/attach-cyclonedx-sbom@v3 + uses: MOV-AI/.github/.github/actions/attach-cyclonedx-sbom@feat/docker_sbom_cycloneDX with: - image: ${{ format('{0}@{1}', steps.get_image_names.outputs.DOCKER_IMAGES, steps.build_ci_image.outputs.digest) }} + image: ${{ steps.get_image_names.outputs.DOCKER_IMAGES }} + digest: ${{ steps.build_ci_image.outputs.digest }} sbom_file: sbom-ci-${{ matrix.name }}.cyclonedx.json artifact_name: sbom-ci-${{ matrix.name }} test: @@ -502,7 +503,10 @@ jobs: OFFICIAL_PUSH_OUTPUT="$(docker push "${OFFICIAL_IMAGE}" 2>&1)" echo "${OFFICIAL_PUSH_OUTPUT}" OFFICIAL_DIGEST="$(printf '%s\n' "${OFFICIAL_PUSH_OUTPUT}" | awk '/digest: sha256:/ { print $2; exit }')" - if [ -z "${OFFICIAL_DIGEST}" ]; then + OFFICIAL_DIGEST="${OFFICIAL_DIGEST#digest:}" + OFFICIAL_DIGEST="${OFFICIAL_DIGEST#:}" + + if [ -z "${OFFICIAL_DIGEST}" ] || ! [[ "${OFFICIAL_DIGEST}" =~ ^sha256:[a-f0-9]{64}$ ]]; then echo "Failed to capture digest for pushed image ${OFFICIAL_IMAGE}" exit 1 fi @@ -511,6 +515,32 @@ jobs: # Handle latest tag if [ "${LATEST}" = "true" ]; then + + - name: Prepare official SBOM image ref + id: prepare_official_sbom_image + if: ${{ inputs.generate_sbom }} + shell: bash + env: + IMAGE_BASE: ${{ steps.push_images.outputs.image }} + DIGEST_INPUT: ${{ steps.push_images.outputs.digest }} + run: | + set -e -o pipefail + + DIGEST="${DIGEST_INPUT#digest:}" + DIGEST="${DIGEST#:}" + + if [ -n "${DIGEST}" ] && ! [[ "${DIGEST}" =~ ^sha256:[a-f0-9]{64}$ ]]; then + echo "Invalid official digest: ${DIGEST}" + exit 1 + fi + + if [ -n "${DIGEST}" ]; then + IMAGE_REF="${IMAGE_BASE}@${DIGEST}" + else + IMAGE_REF="${IMAGE_BASE}" + fi + + echo "image=${IMAGE_REF}" | tee -a "$GITHUB_OUTPUT" echo "Pushing latest tag to official registry..." docker tag "${DOCKER_REGISTRY}/ci/${OFC_IMAGE_NAME}:${VERSION}" \ "${DOCKER_REGISTRY}/${OFC_IMAGE_DIR}/${OFC_IMAGE_NAME}:latest" @@ -556,9 +586,10 @@ jobs: - name: Generate and attach CycloneDX SBOM if: ${{ inputs.generate_sbom }} - uses: MOV-AI/.github/.github/actions/attach-cyclonedx-sbom@v3 + uses: MOV-AI/.github/.github/actions/attach-cyclonedx-sbom@feat/docker_sbom_cycloneDX with: - image: ${{ format('{0}@{1}', steps.push_images.outputs.image, steps.push_images.outputs.digest) }} + image: ${{ steps.prepare_official_sbom_image.outputs.image }} + digest: ${{ steps.push_images.outputs.digest }} sbom_file: sbom-official-${{ matrix.name }}.cyclonedx.json artifact_name: sbom-official-${{ matrix.name }} @@ -571,32 +602,6 @@ jobs: run: | set -e git config --global --add safe.directory "$(pwd)" - git config --global user.name "${{ secrets.commit_user }}" - git config --global user.email "${{ secrets.commit_mail }}" - bump-my-version bump patch --commit --tag - - - name: Push version bump to protected branch - uses: MOV-AI/.github/.github/actions/push-to-protected-branch@v3 - if: ${{ inputs.version == 'auto' && matrix.name == needs.parse-matrix.outputs.first_image }} - with: - token: ${{ secrets.commit_token }} - git_user_email: ${{ secrets.commit_mail }} - git_user_name: ${{ secrets.commit_user }} - branch: ${{ needs.raise-version.outputs.branch_name }} - repository: ${{ github.repository }} - - create-release: - needs: [raise-version, publish] - if: ${{ inputs.create_release && inputs.deploy }} - runs-on: ubuntu-22.04 - steps: - - name: Checkout - uses: actions/checkout@v5 - - - name: Download release notes - uses: actions/download-artifact@v4 - with: - name: release-notes - name: Download CycloneDX SBOM artifacts if: ${{ inputs.generate_sbom }}