#!/usr/bin/env bash # The release's secrets checked without a build (#7), by the release-check # job in seconds and by scripts/release.sh before its own: the keystore's # SHA-256 and the entry its password opens (compare with the keystore you # hold: `sha256sum FILE`, `keytool -list`), and that Firebase's settings # are whole JSON. Never prints a key, a password or the settings. # KEYSTORE_B64=path PASSWORD_FILE=path [FIREBASE_CONFIG=path] scripts/release-check.sh set -euo pipefail b64=${KEYSTORE_B64:-/run/secrets/android-keystore} password=${PASSWORD_FILE:-/run/secrets/android-keystore-password} firebase=${FIREBASE_CONFIG:-/run/secrets/firebase-config} for f in "$b64" "$password"; do [ -s "$f" ] || { echo "release-check: no $f: the job needs the android-keystore secrets" >&2; exit 1; } done keys=$(mktemp -d) trap 'rm -rf "$keys"' EXIT chmod 700 "$keys" base64 -d "$b64" > "$keys/release.p12" || { echo "release-check: the android-keystore secret is not base64 (base64 -w0 FILE.p12)" >&2; exit 1; } echo "release-check: keystore sha256 $(sha256sum < "$keys/release.p12" | cut -d' ' -f1)" keytool=$(command -v keytool || (ls /opt/gradle-home/jdks/*/bin/keytool 2>/dev/null || true) | head -1) if [ -z "$keytool" ]; then echo "release-check: no keytool here, so the password is not checked" >&2 else # As the build reads it: the whole file, trimmed. tr -d '\r' < "$password" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | head -c 4096 > "$keys/pass" if ! "$keytool" -list -keystore "$keys/release.p12" -storetype PKCS12 -storepass:file "$keys/pass" > "$keys/list" 2>&1; then # keytool's own reason (it never prints the password). echo "release-check: keytool cannot open the keystore: $(grep -m1 -i 'error\|exception' "$keys/list" | head -c 300)" >&2 exit 1 fi grep -E 'PrivateKeyEntry|SHA-256\)' "$keys/list" || { echo "release-check: the keystore holds no private key" >&2; exit 1; } "$keytool" -list -keystore "$keys/release.p12" -storetype PKCS12 -storepass:file "$keys/pass" 2>/dev/null | grep -q '^oxygenhub,' \ || { echo "release-check: the keystore has no entry named oxygenhub, which the build signs with" >&2; exit 1; } # Signing reads the private key with the same password: a request for a # certificate uses the key, so it fails just as signing would. "$keytool" -certreq -alias oxygenhub -keystore "$keys/release.p12" -storetype PKCS12 \ -storepass:file "$keys/pass" -keypass:file "$keys/pass" > /dev/null 2> "$keys/certreq.err" \ || { echo "release-check: the key oxygenhub cannot be read with the keystore's password, as signing needs: $(head -c 300 "$keys/certreq.err")" >&2; exit 1; } echo "release-check: the key oxygenhub opens with the password" if [ "$(wc -l < "$password")" -gt 1 ]; then echo "release-check: the password secret has more than one line; the build reads all of it" >&2 fi fi if [ -s "$firebase" ]; then if command -v python3 > /dev/null; then python3 -I -c 'import json,sys; json.load(open(sys.argv[1]))' "$firebase" 2>/dev/null \ || { echo "release-check: the firebase-config secret is not whole JSON (is its last } missing?)" >&2; exit 1; } elif [ "$(tr -d '[:space:]' < "$firebase" | tail -c 1)" != "}" ]; then echo "release-check: the firebase-config secret does not end with } (is its last line missing?)" >&2 exit 1 fi echo "release-check: firebase-config reads as JSON" else echo "release-check: no $firebase: a release takes no alerts" >&2 fi echo "release-check: ok"