From e7bef5e511c94940c46bba9a4193dacc7c9e97c5 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Fri, 4 Feb 2022 16:49:42 -0500 Subject: [PATCH] split signing setup into pre-release hook (#794) Signed-off-by: Alex Goodman --- .github/scripts/apple-signing/.gitignore | 3 +- .github/scripts/apple-signing/cleanup.sh | 4 +- .github/scripts/apple-signing/run.sh | 65 --------------- .../{prep-signing-dev.sh => setup-dev.sh} | 3 +- .../{prep-signing-prod.sh => setup-prod.sh} | 0 .github/scripts/apple-signing/setup.sh | 49 ++++++++++++ .github/scripts/apple-signing/sign.sh | 80 ++++++++++++++++--- .github/scripts/apple-signing/utils.sh | 2 + .goreleaser.yaml | 6 +- Makefile | 12 +-- 10 files changed, 138 insertions(+), 86 deletions(-) delete mode 100755 .github/scripts/apple-signing/run.sh rename .github/scripts/apple-signing/{prep-signing-dev.sh => setup-dev.sh} (99%) rename .github/scripts/apple-signing/{prep-signing-prod.sh => setup-prod.sh} (100%) create mode 100755 .github/scripts/apple-signing/setup.sh diff --git a/.github/scripts/apple-signing/.gitignore b/.github/scripts/apple-signing/.gitignore index baf39c0c2..301ab6fe6 100644 --- a/.github/scripts/apple-signing/.gitignore +++ b/.github/scripts/apple-signing/.gitignore @@ -1,2 +1,3 @@ dev-pki -log \ No newline at end of file +log +signing-identity.txt diff --git a/.github/scripts/apple-signing/cleanup.sh b/.github/scripts/apple-signing/cleanup.sh index 72e50eb16..318029af7 100755 --- a/.github/scripts/apple-signing/cleanup.sh +++ b/.github/scripts/apple-signing/cleanup.sh @@ -6,5 +6,5 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) . "$SCRIPT_DIR"/utils.sh # cleanup any dev certs left behind -. "$SCRIPT_DIR"/prep-signing-dev.sh -cleanup_signing \ No newline at end of file +. "$SCRIPT_DIR"/setup-dev.sh +cleanup_signing diff --git a/.github/scripts/apple-signing/run.sh b/.github/scripts/apple-signing/run.sh deleted file mode 100755 index 7411abc97..000000000 --- a/.github/scripts/apple-signing/run.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash -set -eu - -ARCHIVE_PATH="$1" -IS_SNAPSHOT="$2" - -## grab utilities -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -. "$SCRIPT_DIR"/utils.sh - -main() { - perform_notarization=false - archive_abs_path=$(realpath "$ARCHIVE_PATH") - - if [ ! -f "$archive_abs_path" ]; then - echo "archive does not exist: $archive_abs_path" - fi - - case "$IS_SNAPSHOT" in - - "1" | "true" | "yes") - commentary "assuming development setup..." - . "$SCRIPT_DIR"/prep-signing-dev.sh - ;; - - "0" | "false" | "no") - commentary "assuming production setup..." - . "$SCRIPT_DIR"/prep-signing-prod.sh - . "$SCRIPT_DIR"/notarize.sh - perform_notarization=true - ;; - - *) - exit_with_error "could not determine if this was a production build (isSnapshot='$IS_SNAPSHOT')" - ;; - esac - - . "$SCRIPT_DIR"/sign.sh - - # load up all signing material into a keychain (note: this should set the MAC_SIGNING_IDENTITY env var) - setup_signing - - # sign all of the binaries in the archive and recreate the input archive with the signed binaries - sign_binaries_in_archive "$archive_abs_path" "$MAC_SIGNING_IDENTITY" - - # send all of the binaries off to apple to bless - if $perform_notarization ; then - notarize "$archive_abs_path" - else - commentary "skipping notarization..." - fi -} - -set +u -if [ -z "$SCRIPT" ] -then - set -u - # log all output - mkdir -p "$SCRIPT_DIR/log" - /usr/bin/script "$SCRIPT_DIR/log/signing-$(basename $ARCHIVE_PATH).txt" /bin/bash -c "$0 $*" - exit $? -else - set -u - main -fi diff --git a/.github/scripts/apple-signing/prep-signing-dev.sh b/.github/scripts/apple-signing/setup-dev.sh similarity index 99% rename from .github/scripts/apple-signing/prep-signing-dev.sh rename to .github/scripts/apple-signing/setup-dev.sh index e31565ff0..4d6437367 100755 --- a/.github/scripts/apple-signing/prep-signing-dev.sh +++ b/.github/scripts/apple-signing/setup-dev.sh @@ -162,11 +162,10 @@ EOF } - function cleanup_signing() { title "delete the dev keychain and all certificate material" set -xue security delete-keychain "$KEYCHAIN_NAME" rm -f "$KEYCHAIN_PATH" rm -rf "${DIR}" -} \ No newline at end of file +} diff --git a/.github/scripts/apple-signing/prep-signing-prod.sh b/.github/scripts/apple-signing/setup-prod.sh similarity index 100% rename from .github/scripts/apple-signing/prep-signing-prod.sh rename to .github/scripts/apple-signing/setup-prod.sh diff --git a/.github/scripts/apple-signing/setup.sh b/.github/scripts/apple-signing/setup.sh new file mode 100755 index 000000000..1c482cbf6 --- /dev/null +++ b/.github/scripts/apple-signing/setup.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +set -eu + +IS_SNAPSHOT="$1" + +## grab utilities +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +. "$SCRIPT_DIR"/utils.sh + +main() { + + case "$IS_SNAPSHOT" in + + "1" | "true" | "yes") + commentary "assuming development setup..." + . "$SCRIPT_DIR"/setup-dev.sh + ;; + + "0" | "false" | "no") + commentary "assuming production setup..." + . "$SCRIPT_DIR"/setup-prod.sh + ;; + + *) + exit_with_error "could not determine if this was a production build (isSnapshot='$IS_SNAPSHOT')" + ;; + esac + + # load up all signing material into a keychain (note: this should set the MAC_SIGNING_IDENTITY env var) + setup_signing + + # write out identity to a file + echo -n "$MAC_SIGNING_IDENTITY" > "$SCRIPT_DIR/$SIGNING_IDENTITY_FILENAME" +} + +set +u +if [ -z "$SCRIPT" ] +then + set -u + # log all output + mkdir -p "$SCRIPT_DIR/log" + /usr/bin/script "$SCRIPT_DIR/log/setup.txt" /bin/bash -c "$0 $*" + exit $? +elif [ -n "$SKIP_SIGNING" ]; then + commentary "skipping signing setup..." +else + set -u + main +fi diff --git a/.github/scripts/apple-signing/sign.sh b/.github/scripts/apple-signing/sign.sh index f441fc356..0519029a0 100755 --- a/.github/scripts/apple-signing/sign.sh +++ b/.github/scripts/apple-signing/sign.sh @@ -1,6 +1,14 @@ #!/usr/bin/env bash set -eu +ARCHIVE_PATH="$1" +IS_SNAPSHOT="$2" + +## grab utilities +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +. "$SCRIPT_DIR"/utils.sh + + # sign_binary [binary-path] [signing-identity] # # signs a single binary with cosign @@ -43,36 +51,90 @@ sign_binary() { sign_binaries_in_archive() { archive_abs_path=$1 identity=$2 - + scratch_path=$(mktemp -d) trap "rm -rf -- $scratch_path" EXIT title "getting contents from the release archive: $archive_abs_path" tar -C "$scratch_path" -xvf "$archive_abs_path" - + # invalidate the current archive, we only want an asset with signed binaries from this point forward rm "$archive_abs_path" - + title "signing binaries found in the release archive" - + discovered_binaries=0 tmp_pipe=$(mktemp -ut pipe.XXX) mkfifo "$tmp_pipe" - + find "$scratch_path" -perm +111 -type f > "$tmp_pipe" & - + while IFS= read -r binary; do sign_binary "$binary" "$identity" ((discovered_binaries++)) done < "$tmp_pipe" - + rm "$tmp_pipe" - + if [ "$discovered_binaries" = "0" ]; then exit_with_error "found no binaries to sign" fi - + title "recreating the release archive: $archive_abs_path" (cd "$scratch_path" && tar -czvf "$archive_abs_path" .) } + +main() { + archive_abs_path=$(realpath "$ARCHIVE_PATH") + + if [ ! -f "$archive_abs_path" ]; then + echo "archive does not exist: $archive_abs_path" + fi + + case "$IS_SNAPSHOT" in + + "1" | "true" | "yes") + commentary "disabling notarization..." + perform_notarization=false + ;; + + "0" | "false" | "no") + commentary "enabling notarization..." + . "$SCRIPT_DIR"/notarize.sh + perform_notarization=true + ;; + + *) + exit_with_error "could not determine if this was a production build (isSnapshot='$IS_SNAPSHOT')" + ;; + esac + + # grab the signing identity from the local temp file (setup by setup.sh) + MAC_SIGNING_IDENTITY=$(cat "$SCRIPT_DIR/$SIGNING_IDENTITY_FILENAME") + + # sign all of the binaries in the archive and recreate the input archive with the signed binaries + sign_binaries_in_archive "$archive_abs_path" "$MAC_SIGNING_IDENTITY" + + # send all of the binaries off to apple to bless + if $perform_notarization ; then + notarize "$archive_abs_path" + else + commentary "skipping notarization..." + fi +} + +set +u +if [ -z "$SCRIPT" ] +then + set -u + # log all output + mkdir -p "$SCRIPT_DIR/log" + /usr/bin/script "$SCRIPT_DIR/log/signing-$(basename $ARCHIVE_PATH).txt" /bin/bash -c "$0 $*" + exit $? +elif [ -n "$SKIP_SIGNING" ]; then + commentary "skipping signing..." +else + set -u + main +fi diff --git a/.github/scripts/apple-signing/utils.sh b/.github/scripts/apple-signing/utils.sh index 2d056eb40..8e798df0d 100644 --- a/.github/scripts/apple-signing/utils.sh +++ b/.github/scripts/apple-signing/utils.sh @@ -1,3 +1,5 @@ +SIGNING_IDENTITY_FILENAME=signing-identity.txt + ## terminal goodies PURPLE='\033[0;35m' GREEN='\033[0;32m' diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 20e8e6515..54f8ae8ff 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -6,6 +6,10 @@ env: # required to support multi architecture docker builds - DOCKER_CLI_EXPERIMENTAL=enabled +before: + hooks: + - ./.github/scripts/apple-signing/setup.sh {{ .IsSnapshot }} + builds: - id: linux-build binary: syft @@ -68,7 +72,7 @@ signs: ids: - darwin-archives signature: "${artifact}" - cmd: ./.github/scripts/apple-signing/run.sh + cmd: ./.github/scripts/apple-signing/sign.sh args: - "${artifact}" - "{{ .IsSnapshot }}" diff --git a/Makefile b/Makefile index 4ecfec4b6..cfcb71f8a 100644 --- a/Makefile +++ b/Makefile @@ -233,7 +233,7 @@ $(SNAPSHOTDIR): ## Build snapshot release binaries and packages cat .goreleaser.yaml >> $(TEMPDIR)/goreleaser.yaml # build release snapshots - $(SNAPSHOT_CMD) --skip-sign --config $(TEMPDIR)/goreleaser.yaml + bash -c "SKIP_SIGNING=true $(SNAPSHOT_CMD) --skip-sign --config $(TEMPDIR)/goreleaser.yaml" .PHONY: snapshot-with-signing snapshot-with-signing: ## Build snapshot release binaries and packages (with dummy signing) @@ -243,10 +243,10 @@ snapshot-with-signing: ## Build snapshot release binaries and packages (with dum echo "dist: $(SNAPSHOTDIR)" > $(TEMPDIR)/goreleaser.yaml cat .goreleaser.yaml >> $(TEMPDIR)/goreleaser.yaml - rm -f .github/scripts/apple-signing/log/signing-* + rm -f .github/scripts/apple-signing/log/*.txt # build release snapshots - bash -c "$(SNAPSHOT_CMD) --config $(TEMPDIR)/goreleaser.yaml || (cat .github/scripts/apple-signing/log/signing-* && false)" + bash -c "$(SNAPSHOT_CMD) --config $(TEMPDIR)/goreleaser.yaml || (cat .github/scripts/apple-signing/log/*.txt && false)" # remove the keychain with the trusted self-signed cert automatically .github/scripts/apple-signing/cleanup.sh @@ -317,15 +317,15 @@ release: clean-dist CHANGELOG.md ## Build and publish final binaries and packag echo "dist: $(DISTDIR)" > $(TEMPDIR)/goreleaser.yaml cat .goreleaser.yaml >> $(TEMPDIR)/goreleaser.yaml - rm -f .github/scripts/apple-signing/log/signing-* + rm -f .github/scripts/apple-signing/log/*.txt bash -c "\ $(RELEASE_CMD) \ --config $(TEMPDIR)/goreleaser.yaml \ --release-notes <(cat CHANGELOG.md)\ - || cat .github/scripts/apple-signing/log/signing-* && false" + || cat .github/scripts/apple-signing/log/*.txt && false" - cat .github/scripts/apple-signing/log/signing-* + cat .github/scripts/apple-signing/log/*.txt # upload the version file that supports the application version update check (excluding pre-releases) .github/scripts/update-version-file.sh "$(DISTDIR)" "$(VERSION)"