name: Constellation measure
description: |
  Create measurements of a Constellation cluster and print to stdout.
  Optionally sign and/or upload to S3, if corresponding inputs are provided.
inputs:
  cloudProvider:
    description: "Either 'gcp' or 'azure'."
    required: true
  cosignPublicKey:
    description: 'Cosign public key'
    required: false
    default: ''
  cosignPrivateKey:
    description: 'Cosign private key'
    required: false
    default: ''
  cosignPassword:
    description: 'Password for Cosign private key'
    required: false
    default: ''
  awsAccessKeyID:
    description: 'AWS access key ID to upload measurements'
    required: false
    default: ''
  awsSecretAccessKey:
    description: 'AWS secret access key to upload measurements'
    required: false
    default: ''
  awsDefaultRegion:
    description: 'AWS region of S3 bucket to upload measurements'
    required: false
    default: ''
  awsBucketName:
    description: 'S3 bucket name to upload measurements to'
    required: false
    default: ''
runs:
  using: 'composite'
  steps:
    - name: Build hack/pcr-reader
      run: |
        go build .
        echo "$(pwd)" >> $GITHUB_PATH
      working-directory: hack/pcr-reader
      shell: bash

    # Check /docs/secure_software_distribution.md#sign-measurements
    # for why we ignore certain measurement values.
    - name: Fetch PCRs
      run: |
        KUBECONFIG="$PWD/constellation-admin.conf" kubectl rollout status ds/verification-service -n kube-system --timeout=3m
        CONSTELL_IP=$(jq -r ".bootstrapperhost" constellation-state.json)
        pcr-reader --constell-ip ${CONSTELL_IP} -format yaml > measurements.yaml
        case $CSP in
          azure)
            yq e 'del(.[0,6,10,11,12,13,14,15,16,17,18,19,20,21,22,23])' -i measurements.yaml
            ;;
          gcp)
            yq e 'del(.[11,12,13,14,15,16,17,18,19,20,21,22,23])' -i measurements.yaml
            ;;
        esac
        cat measurements.yaml
      shell: bash
      env:
        CSP: ${{ inputs.cloudProvider }}

    # TODO: Replace with https://github.com/sigstore/sigstore-installer/tree/initial
    # once it has the functionality
    - name: Install Cosign
      uses: sigstore/cosign-installer@48866aa521d8bf870604709cd43ec2f602d03ff2
      if: ${{ inputs.cosignPublicKey != '' && inputs.cosignPrivateKey != '' && inputs.cosignPassword != '' }}
    - name: Install Rekor
      run: |
        curl -LO https://github.com/sigstore/rekor/releases/download/v0.9.0/rekor-cli-linux-amd64
        sudo install rekor-cli-linux-amd64 /usr/local/bin/rekor-cli
      shell: bash
      if: ${{ inputs.cosignPublicKey != '' && inputs.cosignPrivateKey != '' && inputs.cosignPassword != '' }}
    - name: Sign measurements
      run: |
        set -e
        set -o pipefail
        echo "$COSIGN_PUBLIC_KEY" > cosign.pub
        # Enabling experimental mode also publishes signature to Rekor
        COSIGN_EXPERIMENTAL=1 cosign sign-blob --key env://COSIGN_PRIVATE_KEY measurements.yaml > measurements.yaml.sig
        # Verify - As documentation & check
        # Local Signature (input: artifact, key, signature)
        cosign verify-blob --key cosign.pub --signature measurements.yaml.sig measurements.yaml
        # Transparency Log Signature (input: artifact, key)
        uuid=$(rekor-cli search --artifact measurements.yaml | tail -n 1)
        sig=$(rekor-cli get --uuid=$uuid --format=json | jq -r .Body.HashedRekordObj.signature.content)
        cosign verify-blob --key cosign.pub --signature <(echo $sig) measurements.yaml
      shell: bash
      env:
        COSIGN_PUBLIC_KEY: ${{ inputs.cosignPublicKey }}
        COSIGN_PRIVATE_KEY: ${{ inputs.cosignPrivateKey }}
        COSIGN_PASSWORD: ${{ inputs.cosignPassword }}
      if: ${{ inputs.cosignPublicKey != '' && inputs.cosignPrivateKey != '' && inputs.cosignPassword != '' }}

    - name: Install AWS CLI
      run: sudo apt-get update && sudo apt-get -y install awscli
      shell: bash
      if: ${{ inputs.awsAccessKeyID != '' && inputs.awsSecretAccessKey != '' && inputs.awsDefaultRegion != '' && inputs.awsBucketName != '' }}
    - name: Upload to S3
      run: |
        IMAGE=$(yq e ".provider.${CSP}.image" constellation-conf.yaml)
        S3_PATH=s3://${PUBLIC_BUCKET_NAME}/${IMAGE}
        aws s3 cp measurements.yaml ${S3_PATH}/measurements.yaml
        if test -f measurements.yaml.sig; then
          aws s3 cp measurements.yaml.sig ${S3_PATH}/measurements.yaml.sig
        fi
      shell: bash
      env:
        AWS_ACCESS_KEY_ID: ${{ inputs.awsAccessKeyID }}
        AWS_SECRET_ACCESS_KEY: ${{ inputs.awsSecretAccessKey }}
        AWS_DEFAULT_REGION: ${{ inputs.awsDefaultRegion }}
        PUBLIC_BUCKET_NAME: ${{ inputs.awsBucketName }}
        CSP: ${{ inputs.cloudProvider }}
      if: ${{ inputs.awsAccessKeyID != '' && inputs.awsSecretAccessKey != '' && inputs.awsDefaultRegion != '' && inputs.awsBucketName != '' }}
