diff --git a/Dockerfile b/Dockerfile index d198c51..72faadc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM docker:20.10.23-dind +FROM docker:28.3.1-dind-alpine3.22 # Cannot use a rootless container due to permissions errors writing to the # workspace @@ -6,7 +6,7 @@ FROM docker:20.10.23-dind # This is an alpine-based image RUN true && \ - apk add --no-cache curl && \ + apk add --no-cache curl uhubctl && \ apkArch="$(arch)" && \ if [ $apkArch = "x86_64" ]; then apkArch=amd64; fi && \ curl -sLO https://github.com/sigstore/rekor/releases/download/v1.0.1/rekor-cli-linux-${apkArch} && \ diff --git a/README.md b/README.md index 27a52f9..3cfa919 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,56 @@ -Notifies using ntfy -=================== +Signs files using an HSM +======================== -Usage: +Basic Usage +----------- ```yaml - - name: Notify - uses: https://git.lerch.org/lobo/action-notify-ntfy@v1 - if: always() + - name: Sign + id: sign + uses: https://git.lerch.org/lobo/action-hsm-sign@v1 with: - # Can use ** glob syntax for all files - files: output/** - user_pin: ${{ secrets.HSM_USER_PIN }} - # if specified, public key will be used to upload artifacts to the sigstore server - public_key: https://lerch.org/server_public_key.pem + pin: ${{ secrets.HSM_USER_PIN }} + files: ??? + public_key: 'https://emil.lerch.org/serverpublic.pem' +``` + +If a public key is specified, [rekor](https://github.com/sigstore/rekor) will +be invoked, sending the signature to the [sigstore public transparency +log](https://sigstore.dev). + +The action provides the following outputs: + +* Source: Source file used for the signature +* Signature: Signature +* URL: If a public key is specified, the URL output provides the sigstore log url + +Because multiple files can be signed, these outputs have numerical suffixes. +In the above example, the output `${{ steps.sign.outputs.URL_1 }}` would be the +url for the first file signed with this action + +Usage with Smart USB Hubs +------------------------- + +Many consumer HSMs will "hang" after prolonged usage. To alleviate problems +associated with this, this action can integrate with smart USB hubs to turn +on the hub's port and wait for the OS to recognize the attached HSM before +performing the signing action. + +**NOTE: The action will turn off the port on the USB hub when it is done processing** + +To enable this feature, use inputs uhub_location **and** uhub_port. To +determine the proper values for these, it is best to consult [uhubctl +documentation](https://github.com/mvp/uhubctl?tab=readme-ov-file#usage) and +run some command line tests. Updating the previous example: + +```yaml + - name: Sign + id: sign + uses: https://git.lerch.org/lobo/action-hsm-sign@v1 + with: + pin: ${{ secrets.HSM_USER_PIN }} + files: ??? + public_key: 'https://emil.lerch.org/serverpublic.pem' + uhub_location: "1-1.3" + uhub_port: "4" ``` diff --git a/action.yml b/action.yml index d6cfc55..60c7010 100644 --- a/action.yml +++ b/action.yml @@ -15,6 +15,12 @@ inputs: public_key: description: 'URL to PEM format public key. Specify only if uploading to sigstore' required: false + uhub_location: + description: 'If HSM is attached to software controlled power hub, location of hub (-l parameter of uhubctl)' + required: false + uhub_port: + description: 'If HSM is attached to software controlled power hub, port to power on, then off (-p parameter of uhubctl)' + required: false runs: using: 'docker' image: 'Dockerfile' diff --git a/entrypoint.sh b/entrypoint.sh index fda402b..7958871 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,5 +1,28 @@ #!/bin/sh +if [ -n "${INPUT_UHUB_LOCATION}" ] && [ -n "${INPUT_UHUB_PORT}" ]; then + uhubctl -a off -p "${INPUT_UHUB_PORT}" -l "${INPUT_UHUB_LOCATION}" # Off seems to be reflected immediately + # Capture the number of hidraw devices with the port off + devs="$(find /dev -maxdepth 1 -name 'hi*' |wc -l)" + uhubctl -a on -p "${INPUT_UHUB_PORT}" -l "${INPUT_UHUB_LOCATION}" + retries=0 + while [ "$(find /dev -maxdepth 1 -name 'hi*' |wc -l)" = "$devs" ] && [ $retries -lt 10 ]; do + # Generally takes a few seconds to settle in + echo "waiting for device connection ($retries / 10)" + sleep 1 + retries=$((i+1)) + done + if [ $retries -ge 10 ]; then + echo "device is not available. Aborting" + exit 1 + fi +else + if [ -n "${INPUT_UHUB_LOCATION}" ] || [ -n "${INPUT_UHUB_PORT}" ]; then + echo "if UHUB functionality is desired, both uhub_location and uhub_port must be specified" + exit 1 + fi +fi + dir="$(dirname "${INPUT_FILES}")" glob="$(basename "${INPUT_FILES}")" # Pass these through sort so we can have deterministic output indexing @@ -50,3 +73,8 @@ while IFS= read -r f; do done <