Files
c-relay-pg/tests/multi_admin_test.sh

209 lines
6.6 KiB
Bash
Executable File

#!/bin/bash
# Multi-admin integration test for c-relay-pg
# Validates:
# 1) primary admin can add a secondary admin
# 2) secondary admin can execute non-privileged admin command (system_status)
# 3) secondary admin cannot mutate admin list (remove_admin)
# 4) primary admin can remove secondary admin
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[PASS]${NC} $1"
}
log_error() {
echo -e "${RED}[FAIL]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
RELAY_URL="ws://127.0.0.1:8888"
# test key set used by ./make_and_restart_relay.sh -t
PRIMARY_ADMIN_PRIVKEY="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
PRIMARY_ADMIN_PUBKEY="6a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"
RELAY_PUBKEY="4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa"
# secondary admin keypair generated per test run
SECONDARY_ADMIN_PRIVKEY=""
SECONDARY_ADMIN_PUBKEY=""
# postgres defaults from make_and_restart_relay.sh
PGHOST="localhost"
PGPORT="5432"
PGDATABASE="crelay"
PGUSER="crelay"
PGPASSWORD="crelay"
require_bin() {
if ! command -v "$1" >/dev/null 2>&1; then
log_error "Required command not found: $1"
exit 1
fi
}
get_admin_list_from_db() {
PGPASSWORD="$PGPASSWORD" psql \
-h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$PGDATABASE" \
-tAc "SELECT value FROM config WHERE key='admin_pubkey';" 2>/dev/null | tr -d '[:space:]'
}
send_admin_command() {
local signer_privkey="$1"
local command_json="$2"
local encrypted
encrypted=$(nak encrypt "$command_json" --sec "$signer_privkey" --recipient-pubkey "$RELAY_PUBKEY" 2>/dev/null)
if [[ -z "${encrypted:-}" ]]; then
log_error "Failed to encrypt command: $command_json"
return 1
fi
local event_json
event_json=$(nak event --kind 23456 --content "$encrypted" --sec "$signer_privkey" --tag "p=$RELAY_PUBKEY" 2>/dev/null)
if [[ -z "${event_json:-}" ]]; then
log_error "Failed to build admin event for command: $command_json"
return 1
fi
local result
result=$(echo "$event_json" | nak event "$RELAY_URL" 2>&1 || true)
if echo "$result" | grep -Eiq "error|failed|denied|invalid|unauthorized"; then
log_warn "Relay returned non-success for command '$command_json': $result"
return 1
fi
return 0
}
contains_pubkey() {
local csv="$1"
local key="$2"
IFS=',' read -r -a arr <<< "$csv"
for k in "${arr[@]}"; do
[[ "$k" == "$key" ]] && return 0
done
return 1
}
main() {
log_info "Starting multi-admin integration test"
require_bin nak
require_bin psql
require_bin grep
require_bin tr
SECONDARY_ADMIN_PRIVKEY=$(nak key generate 2>/dev/null || true)
if [[ -z "$SECONDARY_ADMIN_PRIVKEY" ]]; then
log_error "Could not generate secondary admin private key"
exit 1
fi
SECONDARY_ADMIN_PUBKEY=$(nak key public "$SECONDARY_ADMIN_PRIVKEY" 2>/dev/null || true)
if [[ -z "$SECONDARY_ADMIN_PUBKEY" ]]; then
log_error "Could not derive secondary admin pubkey from generated private key"
exit 1
fi
log_info "Primary admin pubkey: ${PRIMARY_ADMIN_PUBKEY:0:16}..."
log_info "Secondary admin pubkey: ${SECONDARY_ADMIN_PUBKEY:0:16}..."
local current_admins
current_admins=$(get_admin_list_from_db)
if [[ -z "$current_admins" ]]; then
log_error "Could not read admin_pubkey from database"
exit 1
fi
if ! contains_pubkey "$current_admins" "$PRIMARY_ADMIN_PUBKEY"; then
log_error "Primary admin missing from DB admin list: $current_admins"
exit 1
fi
log_success "Primary admin exists in config table"
# Clean slate: if secondary already present from prior run, remove via primary
if contains_pubkey "$current_admins" "$SECONDARY_ADMIN_PUBKEY"; then
log_info "Secondary admin already present; removing for clean start"
send_admin_command "$PRIMARY_ADMIN_PRIVKEY" "[\"system_command\",\"remove_admin\",\"$SECONDARY_ADMIN_PUBKEY\"]" || true
sleep 2
fi
log_info "Adding secondary admin via primary admin command"
send_admin_command "$PRIMARY_ADMIN_PRIVKEY" "[\"system_command\",\"add_admin\",\"$SECONDARY_ADMIN_PUBKEY\"]"
sleep 2
current_admins=$(get_admin_list_from_db)
if ! contains_pubkey "$current_admins" "$SECONDARY_ADMIN_PUBKEY"; then
log_error "Secondary admin was not added. admin_pubkey='$current_admins'"
exit 1
fi
log_success "Secondary admin was added"
# Verify secondary can execute a standard admin command with measurable side effect
# Use whitelist insertion and verify via DB.
local test_whitelist_pubkey
test_whitelist_pubkey=$(nak key public "$(nak key generate 2>/dev/null)" 2>/dev/null || true)
if [[ -z "$test_whitelist_pubkey" ]]; then
log_error "Failed to generate test pubkey for secondary-admin whitelist command"
exit 1
fi
log_info "Sending whitelist command as secondary admin"
send_admin_command "$SECONDARY_ADMIN_PRIVKEY" "[\"whitelist\",\"pubkey\",\"$test_whitelist_pubkey\"]"
sleep 2
local whitelist_count
whitelist_count=$(PGPASSWORD="$PGPASSWORD" psql \
-h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$PGDATABASE" \
-tAc "SELECT COUNT(*) FROM auth_rules WHERE rule_type='whitelist' AND pattern_type='pubkey' AND pattern_value='$test_whitelist_pubkey' AND active=1;" 2>/dev/null | tr -d '[:space:]')
if [[ "${whitelist_count:-0}" -lt 1 ]]; then
log_error "Secondary admin did not create whitelist rule as expected"
exit 1
fi
log_success "Secondary admin executed whitelist admin command"
# Verify secondary cannot mutate admin list (remove_admin restricted to primary)
log_info "Attempting remove_admin as secondary (should be rejected)"
send_admin_command "$SECONDARY_ADMIN_PRIVKEY" "[\"system_command\",\"remove_admin\",\"$SECONDARY_ADMIN_PUBKEY\"]" || true
sleep 2
current_admins=$(get_admin_list_from_db)
if ! contains_pubkey "$current_admins" "$SECONDARY_ADMIN_PUBKEY"; then
log_error "Secondary admin was able to remove admin (unexpected). admin_pubkey='$current_admins'"
exit 1
fi
log_success "Secondary admin could not remove admin list entry"
# Cleanup: primary removes secondary
log_info "Removing secondary admin via primary admin"
send_admin_command "$PRIMARY_ADMIN_PRIVKEY" "[\"system_command\",\"remove_admin\",\"$SECONDARY_ADMIN_PUBKEY\"]"
sleep 2
current_admins=$(get_admin_list_from_db)
if contains_pubkey "$current_admins" "$SECONDARY_ADMIN_PUBKEY"; then
log_error "Secondary admin still present after primary remove_admin. admin_pubkey='$current_admins'"
exit 1
fi
log_success "Primary admin removed secondary admin"
log_success "Multi-admin integration test passed"
}
main "$@"