Update tooling and documentation: - Smoke test script with scheduler health checks - Release cleanup script - Native test scripts with Redis integration - TUI SSH test script - Performance regression detector with scheduler metrics - Profiler with distributed tracing - Native CMake with test targets - Dataset hash tests - Storage symlink resistance tests - Configuration reference documentation updates
165 lines
4.7 KiB
Bash
165 lines
4.7 KiB
Bash
#!/bin/bash
|
|
# Pre-deployment audit sink gate script
|
|
# Verifies the write-once audit sink is reachable and writable
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Default values
|
|
ENV="staging"
|
|
TIMEOUT=10
|
|
AUDIT_SINK_HOST=""
|
|
AUDIT_SINK_PORT=""
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--env)
|
|
ENV="$2"
|
|
shift 2
|
|
;;
|
|
--timeout)
|
|
TIMEOUT="$2"
|
|
shift 2
|
|
;;
|
|
--host)
|
|
AUDIT_SINK_HOST="$2"
|
|
shift 2
|
|
;;
|
|
--port)
|
|
AUDIT_SINK_PORT="$2"
|
|
shift 2
|
|
;;
|
|
--help)
|
|
echo "Usage: $0 [OPTIONS]"
|
|
echo ""
|
|
echo "Options:"
|
|
echo " --env ENV Environment (staging|prod) [default: staging]"
|
|
echo " --timeout SECONDS Timeout in seconds [default: 10]"
|
|
echo " --host HOST Audit sink host (auto-detected if not set)"
|
|
echo " --port PORT Audit sink port (auto-detected if not set)"
|
|
echo " --help Show this help message"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Auto-detect audit sink based on environment
|
|
if [ -z "$AUDIT_SINK_HOST" ]; then
|
|
case $ENV in
|
|
staging)
|
|
AUDIT_SINK_HOST="ml-staging-audit-sink"
|
|
AUDIT_SINK_PORT="6379"
|
|
;;
|
|
prod)
|
|
AUDIT_SINK_HOST="ml-prod-audit-sink"
|
|
AUDIT_SINK_PORT="6379"
|
|
;;
|
|
*)
|
|
echo -e "${RED}Error: Unknown environment '$ENV'${NC}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
echo "Checking audit sink for environment: $ENV"
|
|
echo "Host: $AUDIT_SINK_HOST"
|
|
echo "Port: $AUDIT_SINK_PORT"
|
|
echo "Timeout: ${TIMEOUT}s"
|
|
|
|
# Check if we can reach the audit sink
|
|
echo ""
|
|
echo "Step 1: Checking network reachability..."
|
|
|
|
if command -v nc &> /dev/null; then
|
|
if timeout $TIMEOUT nc -z "$AUDIT_SINK_HOST" "$AUDIT_SINK_PORT" 2>/dev/null; then
|
|
echo -e "${GREEN}✓ Audit sink is reachable on port $AUDIT_SINK_PORT${NC}"
|
|
else
|
|
echo -e "${RED}✗ Audit sink is NOT reachable on $AUDIT_SINK_HOST:$AUDIT_SINK_PORT${NC}"
|
|
echo "This is a HARD STOP for HIPAA deployments."
|
|
exit 1
|
|
fi
|
|
elif command -v redis-cli &> /dev/null; then
|
|
# Try to ping via redis-cli if available
|
|
if timeout $TIMEOUT redis-cli -h "$AUDIT_SINK_HOST" -p "$AUDIT_SINK_PORT" ping 2>/dev/null | grep -q "PONG"; then
|
|
echo -e "${GREEN}✓ Audit sink responded to Redis ping${NC}"
|
|
else
|
|
echo -e "${RED}✗ Audit sink did not respond to Redis ping${NC}"
|
|
echo "This is a HARD STOP for HIPAA deployments."
|
|
exit 1
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ Neither nc nor redis-cli available - skipping reachability check${NC}"
|
|
echo "For production, ensure one of these tools is installed."
|
|
fi
|
|
|
|
# Check if audit sink is writable (append-only test)
|
|
echo ""
|
|
echo "Step 2: Checking write capability..."
|
|
|
|
# For a proper audit sink, we should be able to write but not modify
|
|
# This is typically implemented with Redis append-only file (AOF) persistence
|
|
# and restricted commands
|
|
|
|
if command -v docker &> /dev/null; then
|
|
# Check if the audit sink container is running
|
|
CONTAINER_NAME="ml-${ENV}-audit-sink"
|
|
|
|
if docker ps | grep -q "$CONTAINER_NAME"; then
|
|
echo -e "${GREEN}✓ Audit sink container '$CONTAINER_NAME' is running${NC}"
|
|
|
|
# Test write capability
|
|
TEST_KEY="audit_test_$(date +%s)"
|
|
TEST_VALUE="test_$(uuidgen 2>/dev/null || echo $RANDOM)"
|
|
|
|
if docker exec "$CONTAINER_NAME" redis-cli SET "$TEST_KEY" "$TEST_VALUE" EX 60 > /dev/null 2>&1; then
|
|
echo -e "${GREEN}✓ Audit sink accepts writes${NC}"
|
|
|
|
# Verify we can read it back
|
|
READ_VALUE=$(docker exec "$CONTAINER_NAME" redis-cli GET "$TEST_KEY" 2>/dev/null)
|
|
if [ "$READ_VALUE" = "$TEST_VALUE" ]; then
|
|
echo -e "${GREEN}✓ Audit sink read-after-write successful${NC}"
|
|
else
|
|
echo -e "${YELLOW}⚠ Audit sink read-after-write mismatch${NC}"
|
|
fi
|
|
|
|
# Clean up
|
|
docker exec "$CONTAINER_NAME" redis-cli DEL "$TEST_KEY" > /dev/null 2>&1 || true
|
|
else
|
|
echo -e "${RED}✗ Audit sink does not accept writes${NC}"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ Audit sink container '$CONTAINER_NAME' not found${NC}"
|
|
echo "Container may not be running or may have a different name."
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ Docker not available - skipping container check${NC}"
|
|
fi
|
|
|
|
# Final summary
|
|
echo ""
|
|
echo "==================================="
|
|
echo "Audit Sink Check Summary"
|
|
echo "==================================="
|
|
echo -e "${GREEN}✓ Audit sink is reachable and writable${NC}"
|
|
echo ""
|
|
echo "Deployment can proceed."
|
|
echo "Note: This check does NOT verify:"
|
|
echo " - Append-only configuration"
|
|
echo " - Log retention policies"
|
|
echo " - Chain integrity"
|
|
echo " - Tamper resistance"
|
|
echo ""
|
|
echo "These must be verified separately for full HIPAA compliance."
|
|
|
|
exit 0
|