209 lines
6.6 KiB
Bash
Executable File
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 "$@"
|