verify.sh
bash
sha256:bd1eb24434d281fe65142038c1bf217493421f5a86880c22dff7e6037d2d4700
feat(companion): add production macOS distribution path
Human
minor
⚠ breaking
25 days ago
| 1 | #!/bin/bash |
| 2 | set -euo pipefail |
| 3 | |
| 4 | app="" |
| 5 | package_file="" |
| 6 | manifest="" |
| 7 | signature="" |
| 8 | checksums="" |
| 9 | public_key_file="${KNOWTATION_UPDATE_PUBLIC_KEY_FILE:-}" |
| 10 | while [[ $# -gt 0 ]]; do |
| 11 | case "$1" in |
| 12 | --app) app="$2"; shift 2 ;; |
| 13 | --package) package_file="$2"; shift 2 ;; |
| 14 | --manifest) manifest="$2"; shift 2 ;; |
| 15 | --signature) signature="$2"; shift 2 ;; |
| 16 | --checksums) checksums="$2"; shift 2 ;; |
| 17 | --public-key-file) public_key_file="$2"; shift 2 ;; |
| 18 | *) echo "unknown argument: $1" >&2; exit 2 ;; |
| 19 | esac |
| 20 | done |
| 21 | |
| 22 | repo_root="$(cd "$(dirname "$0")/../../.." && pwd)" |
| 23 | for required in "$app" "$package_file" "$manifest" "$signature" "$checksums" "$public_key_file"; do |
| 24 | [[ -e "$required" ]] || { echo "missing verification input: $required" >&2; exit 2; } |
| 25 | done |
| 26 | [[ "${KNOWTATION_APPLE_TEAM_ID:-}" =~ ^[A-Z0-9]{10}$ ]] || { |
| 27 | echo "KNOWTATION_APPLE_TEAM_ID is required" >&2; exit 1; |
| 28 | } |
| 29 | verification_tmp="$(mktemp -d "${TMPDIR:-/tmp}/knowtation-release-verify.XXXXXX")" |
| 30 | trap 'rm -rf "$verification_tmp"' EXIT |
| 31 | |
| 32 | verify_identity() { |
| 33 | local target="$1" |
| 34 | local expected_identifier="$2" |
| 35 | local information |
| 36 | information="$(codesign -d --verbose=4 "$target" 2>&1)" |
| 37 | grep -Fqx "Identifier=$expected_identifier" <<< "$information" |
| 38 | grep -Fqx "TeamIdentifier=$KNOWTATION_APPLE_TEAM_ID" <<< "$information" |
| 39 | } |
| 40 | |
| 41 | codesign --verify --deep --strict --verbose=4 "$app" |
| 42 | node "$repo_root/scripts/release/macos/verify-runtime-manifest.mjs" \ |
| 43 | --app "$app" --require-committed-source |
| 44 | spctl --assess --type execute --verbose=4 "$app" |
| 45 | verify_identity "$app" "store.knowtation.companion" |
| 46 | verify_identity "$app/Contents/Library/LaunchServices/KnowtationCustodyAgent.app" \ |
| 47 | "store.knowtation.companion.custody" |
| 48 | verify_identity "$app/Contents/Helpers/knowtation" "store.knowtation.cli" |
| 49 | verify_identity "$app/Contents/Helpers/knowtation-mcp" "store.knowtation.mcp" |
| 50 | verify_identity "$app/Contents/Resources/runtime/node/bin/node" "store.knowtation.runtime.node" |
| 51 | custody_app="$app/Contents/Library/LaunchServices/KnowtationCustodyAgent.app" |
| 52 | test -f "$custody_app/Contents/embedded.provisionprofile" |
| 53 | codesign -d --entitlements :- "$custody_app" > "$verification_tmp/custody-entitlements.plist" 2>/dev/null |
| 54 | test "$(plutil -extract com.apple.application-identifier raw \ |
| 55 | "$verification_tmp/custody-entitlements.plist")" = \ |
| 56 | "$KNOWTATION_APPLE_TEAM_ID.store.knowtation.companion.custody" |
| 57 | test "$(plutil -extract keychain-access-groups.0 raw \ |
| 58 | "$verification_tmp/custody-entitlements.plist")" = \ |
| 59 | "$KNOWTATION_APPLE_TEAM_ID.store.knowtation.companion.custody" |
| 60 | pkgutil --check-signature "$package_file" |
| 61 | spctl --assess --type install --verbose=4 "$package_file" |
| 62 | xcrun stapler validate "$app" |
| 63 | xcrun stapler validate "$package_file" |
| 64 | |
| 65 | (cd "$(dirname "$checksums")" && shasum -a 256 -c "$(basename "$checksums")") |
| 66 | unzip -t "$(dirname "$manifest")/Knowtation-0.1.0-100-macos-arm64.zip" |
| 67 | |
| 68 | node "$repo_root/scripts/release/macos/verify-update-manifest.mjs" \ |
| 69 | --manifest "$manifest" \ |
| 70 | --signature "$signature" \ |
| 71 | --public-key-file "$public_key_file" \ |
| 72 | --trust "$app/Contents/Resources/update-trust.json" \ |
| 73 | --package "$package_file" |
| 74 | |
| 75 | test "$(plutil -extract CFBundleIdentifier raw "$app/Contents/Info.plist")" = "store.knowtation.companion" |
| 76 | test "$(plutil -extract CFBundleShortVersionString raw "$app/Contents/Info.plist")" = "0.1.0" |
| 77 | test "$(plutil -extract CFBundleVersion raw "$app/Contents/Info.plist")" = "100" |
| 78 | lipo -verify_arch arm64 "$app/Contents/MacOS/Knowtation" |
| 79 | lipo -verify_arch arm64 "$app/Contents/Helpers/knowtation" |
| 80 | lipo -verify_arch arm64 "$app/Contents/Helpers/knowtation-mcp" |
| 81 | lipo -verify_arch arm64 "$app/Contents/Resources/runtime/node/bin/node" |
| 82 | while IFS= read -r -d '' native; do |
| 83 | test "$(lipo -archs "$native")" = "arm64" |
| 84 | done < <(find "$app/Contents/Resources/runtime" -type f \( -name '*.node' -o -name '*.dylib' \) -print0) |
| 85 | |
| 86 | if find "$app" -type f \( -name '.env' -o -name '*.pem' -o -name '*.p12' -o -name 'local.yaml' \) -print -quit | grep -q .; then |
| 87 | echo "secret-bearing or local configuration file found in app" >&2 |
| 88 | exit 1 |
| 89 | fi |
| 90 | |
| 91 | if find "$app/Contents/Resources/runtime/node_modules" -type d \( -name sharp -o -name 'sharp-*' -o -name 'libvips-*' \) -print -quit | grep -q .; then |
| 92 | echo "excluded sharp/libvips dependency found" >&2 |
| 93 | exit 1 |
| 94 | fi |
| 95 | |
| 96 | if grep -q "No license text was present" "$app/Contents/Resources/THIRD-PARTY-NOTICES.txt"; then |
| 97 | echo "runtime dependency is missing distributable license text" >&2 |
| 98 | exit 1 |
| 99 | fi |
| 100 | |
| 101 | echo "release verification passed" |
File History
1 commit
sha256:bd1eb24434d281fe65142038c1bf217493421f5a86880c22dff7e6037d2d4700
feat(companion): add production macOS distribution path
Human
minor
⚠
25 days ago