name: Container SBOM
description: Create, vuln-check, sign and upload SBOMs for container images.
inputs:
  containerReference:
    description: "Full reference to container image, e.g., ghcr.io/org/repo/img:tag"
    required: true
  cosignPublicKey:
    description: "Cosign public key"
    required: true
  cosignPrivateKey:
    description: "Cosign private key"
    required: true
  cosignPassword:
    description: "Password for Cosign private key"
    required: true

runs:
  using: "composite"
  steps:
    - name: Install Cosign
      uses: sigstore/cosign-installer@9becc617647dfa20ae7b1151972e9b3a2c338a2b # tag=v2.8.1
      if: ${{ inputs.cosignPublicKey != '' && inputs.cosignPrivateKey != '' && inputs.cosignPassword != '' }}
    - name: Download syft & grype
      run: |
        SYFT_VERSION=0.59.0
        GRYPE_VERSION=0.51.0
        curl -LO https://github.com/anchore/syft/releases/download/v${SYFT_VERSION}/syft_${SYFT_VERSION}_linux_amd64.tar.gz
        tar -xzf syft_${SYFT_VERSION}_linux_amd64.tar.gz
        ./syft version
        curl -LO https://github.com/anchore/grype/releases/download/v${GRYPE_VERSION}/grype_${GRYPE_VERSION}_linux_amd64.tar.gz
        tar -xzf grype_${GRYPE_VERSION}_linux_amd64.tar.gz
        ./grype version
        echo $(pwd) >> $GITHUB_PATH
      shell: bash

    - name: Generate SBOM
      run: |
        set -ex
        echo "$COSIGN_PRIVATE_KEY" > cosign.key
        syft attest --key cosign.key ${{ inputs.containerReference }} -o cyclonedx-json > container-image.att.json
        cosign attach attestation ${{ inputs.containerReference }} --attestation container-image.att.json
        # TODO: type should be auto-discovered after issue is resolved:
        # https://github.com/sigstore/cosign/issues/2264
        cosign verify-attestation ${{ inputs.containerReference }} --type 'https://cyclonedx.org/bom' --key env://COSIGN_PUBLIC_KEY
        grype ${{ inputs.containerReference }} --fail-on high --only-fixed
      shell: bash
      env:
        # COSIGN_EXPERIMENTAL: 1 # This breaks verification with HTTP 404
        COSIGN_PUBLIC_KEY: ${{ inputs.cosignPublicKey }}
        COSIGN_PRIVATE_KEY: ${{ inputs.cosignPrivateKey }}
        COSIGN_PASSWORD: ${{ inputs.cosignPassword }}