appsok/scripts/setup-appsok-ci-secrets.sh

135 lines
3.6 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
TEAM_ID="${APPSOK_TEAM_ID:-AWA82DP9WD}"
DEFAULT_PROFILE="${APPSOK_NOTARY_PROFILE:-appsok-notary}"
AGE_KEY="${APPSOK_SOPS_AGE_KEY_FILE:-$HOME/.config/sops/age/appsok-ci-key.txt}"
SECRET_FILE="${APPSOK_CI_SECRET_FILE:-secrets/appsok.ci.sops.json}"
cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
need() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "missing command: $1" >&2
exit 1
fi
}
need age-keygen
need python3
need security
need sops
need xcrun
if [ ! -t 0 ]; then
echo "run this script from an interactive terminal" >&2
exit 1
fi
prompt_plain() {
local label="$1"
local var="$2"
local value
printf "%s: " "$label" > /dev/tty
IFS= read -r value < /dev/tty
printf -v "$var" '%s' "$value"
}
prompt_secret() {
local label="$1"
local var="$2"
local value
local tty_state
tty_state="$(stty -g < /dev/tty)"
printf "%s: " "$label" > /dev/tty
stty -echo < /dev/tty
if ! IFS= read -r value < /dev/tty; then
stty "$tty_state" < /dev/tty
printf "\n" > /dev/tty
return 1
fi
stty "$tty_state" < /dev/tty
printf "\n" > /dev/tty
printf -v "$var" '%s' "$value"
}
mkdir -p "$(dirname "$AGE_KEY")" "$(dirname "$SECRET_FILE")"
if [ ! -f "$AGE_KEY" ]; then
age-keygen -o "$AGE_KEY" >/dev/null
chmod 600 "$AGE_KEY"
fi
AGE_RECIPIENT="$(awk '/^# public key: / {print $4}' "$AGE_KEY")"
if [ -z "$AGE_RECIPIENT" ]; then
echo "failed to read age public key from $AGE_KEY" >&2
exit 1
fi
SOPS_PATH_REGEX="$(SECRET_FILE="$SECRET_FILE" python3 - <<'PY'
import os
import re
print(re.escape(os.environ["SECRET_FILE"]) + "$")
PY
)"
cat > .sops.yaml <<YAML
creation_rules:
- path_regex: $SOPS_PATH_REGEX
age: "$AGE_RECIPIENT"
YAML
prompt_secret "Mac login/keychain password" KEYCHAIN_PASSWORD
prompt_plain "Apple ID email" APPLE_ID
prompt_secret "App-specific password" APP_SPECIFIC_PASSWORD
prompt_plain "Notary profile [$DEFAULT_PROFILE]" NOTARY_PROFILE
NOTARY_PROFILE="${NOTARY_PROFILE:-$DEFAULT_PROFILE}"
prompt_plain "Jenkins URL" JENKINS_URL
prompt_plain "Jenkins username" JENKINS_USERNAME
prompt_secret "Jenkins API token" JENKINS_API_TOKEN
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT
chmod 600 "$tmp"
export KEYCHAIN_PASSWORD APPLE_ID APP_SPECIFIC_PASSWORD NOTARY_PROFILE TEAM_ID JENKINS_URL JENKINS_USERNAME JENKINS_API_TOKEN
python3 - <<'PY' > "$tmp"
import json
import os
payload = {
"keychain_password": os.environ["KEYCHAIN_PASSWORD"],
"apple_id": os.environ["APPLE_ID"],
"app_specific_password": os.environ["APP_SPECIFIC_PASSWORD"],
"notary_profile": os.environ["NOTARY_PROFILE"],
"team_id": os.environ["TEAM_ID"],
"jenkins_url": os.environ["JENKINS_URL"],
"jenkins_username": os.environ["JENKINS_USERNAME"],
"jenkins_api_token": os.environ["JENKINS_API_TOKEN"],
}
print(json.dumps(payload, indent=2))
PY
SOPS_AGE_KEY_FILE="$AGE_KEY" \
sops --filename-override "$SECRET_FILE" -e "$tmp" > "$SECRET_FILE"
SOPS_AGE_KEY_FILE="$AGE_KEY" sops -d "$SECRET_FILE" >/dev/null
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$HOME/Library/Keychains/login.keychain-db"
security set-keychain-settings -lut 21600 "$HOME/Library/Keychains/login.keychain-db"
security set-key-partition-list \
-S apple-tool:,apple:,codesign: \
-s \
-k "$KEYCHAIN_PASSWORD" \
"$HOME/Library/Keychains/login.keychain-db"
xcrun notarytool store-credentials "$NOTARY_PROFILE" \
--apple-id "$APPLE_ID" \
--team-id "$TEAM_ID" \
--password "$APP_SPECIFIC_PASSWORD"
xcrun notarytool history --keychain-profile "$NOTARY_PROFILE" >/dev/null
echo "saved encrypted secret: $SECRET_FILE"
echo "saved age key: $AGE_KEY"
echo "saved notary profile: $NOTARY_PROFILE"