#!/bin/bash set -eu function die() { echo "ERROR: $*" >&2 exit 1 } function pass() { echo "PASS: $*" >&2 } function config() { domain=$1; shift remove_keys=$1; shift cat << EOF { "monitor": [ { "bootstrap_at": "2025-01-01T00:00:00Z", "suffix": "$domain" } ], "remove_logs": [ EOF mapfile -t keys <<< "$remove_keys" for ((i = 0; i < ${#keys[@]}; i++)); do key=${keys[i]} if ((i == ${#keys[@]} - 1)); then echo " \"$key\"" else echo " \"$key\"," fi done cat << EOF ] } EOF } #------------------------------------------------------------------------------- # Options #------------------------------------------------------------------------------- TARGET_LOG=${TARGET_LOG:-"Google 'Argon2025h1' log"} # which log to test with WAIT=${WAIT:-3} # seconds to wait for entries #------------------------------------------------------------------------------- # Working directories #------------------------------------------------------------------------------- cd "$(dirname "$0")" dir=./testonly rm -rf "$dir" mkdir "$dir" #------------------------------------------------------------------------------- # Metadata to configure monitoring of a single log #------------------------------------------------------------------------------- go run gitlab.torproject.org/rgdd/ct/cmd/ct-metadata@latest get source -n google > "$dir/metadata.json" log_id=$(jq -r --arg desc "$TARGET_LOG" '.operators[].logs[] | select(.description == $desc) | .log_id' "$dir/metadata.json" | base64 -d | base16) remove_keys=$(jq -r --arg desc "$TARGET_LOG" '.operators[].logs[] | select(.description != $desc) | .key' "$dir/metadata.json") config "www.example.org" "$remove_keys" > $dir/config.json go run ../cmd/silentct-mon --bootstrap -c "$dir/config.json" -d "$dir/state" -C "dev:silentct" -v DEBUG pass "bootstrap the monitor with a single log" sleep "$WAIT" #------------------------------------------------------------------------------- # Figure out which domain name will be in the next log entry #------------------------------------------------------------------------------- next_index=$(jq '.next_index' "$dir/state/monitor_state/$log_id.json") next_domain=$(go run github.com/google/certificate-transparency-go/client/ctclient@latest \ get-entries --first "$next_index" --last "$next_index" --text --log_name "$TARGET_LOG" | \ grep DNS | cut -d',' -f1 | cut -d':' -f2) [[ -n $next_domain ]] || die "failed to extract next domain name" #------------------------------------------------------------------------------- # Run and find a match which turns into a certificate mis-issuance notice #------------------------------------------------------------------------------- config "$next_domain" "$remove_keys" >"$dir/config.json" timeout 10s go run ../cmd/silentct-mon -c "$dir/config.json" -d "$dir/state" -C "dev:silentct" -p 1s -v DEBUG 2>&1 | tee "$dir/output.txt" grep -q -E '([1-9][0-9]*|[1-9] matches)' "$dir/output.txt" || die "expected at least one match" grep -q -F '[NOTICE] certificate mis-issuance?' "$dir/output.txt" || die "expected notice about mis-issued certificate" pass "run the monitor and be warned of an unreported certificate" #------------------------------------------------------------------------------- # Success #------------------------------------------------------------------------------- echo "---" >&2 echo "All smoke tests passed" >&2