hearth/scripts/validate-phase2.sh
Eric Garcia e78000831e Initial commit: Port infrastructure from coherence-mcp
Hearth is the infrastructure home for the letemcook ecosystem.

Ported from coherence-mcp/infra:
- Terraform modules (VPC, EKS, IAM, NLB, S3, storage)
- Kubernetes manifests (Forgejo, ingress, cert-manager, karpenter)
- Deployment scripts (phased rollout)

Status: Not deployed. EKS cluster needs to be provisioned.

Next steps:
1. Bootstrap terraform backend
2. Deploy phase 1 (foundation)
3. Deploy phase 2 (core services including Forgejo)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 06:06:13 -05:00

257 lines
7.2 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Phase 2 Validation: Core Services
#
# Validates that RFC 0040 components are deployed and healthy:
# - Vault (unsealed, HA mode)
# - Keycloak (realm exists, healthy)
# - Forgejo (SSO working)
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
PASSED=0
FAILED=0
WARNINGS=0
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_pass() {
echo -e "${GREEN}[PASS]${NC} $1"
((PASSED++))
}
log_fail() {
echo -e "${RED}[FAIL]${NC} $1"
((FAILED++))
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
((WARNINGS++))
}
check_vault() {
log_info "Checking Vault status..."
# Check if namespace exists
if ! kubectl get namespace vault &> /dev/null; then
log_fail "vault namespace does not exist"
return
fi
# Check pod count
local pod_count
pod_count=$(kubectl -n vault get pods -l app=vault -o json | jq '[.items[] | select(.status.phase == "Running")] | length')
if [ "$pod_count" -ge 1 ]; then
log_pass "Vault has $pod_count running pods"
else
log_fail "Vault has no running pods"
return
fi
# Check Vault seal status
local vault_status
vault_status=$(kubectl -n vault exec vault-0 -- vault status -format=json 2>/dev/null || echo '{}')
local initialized
initialized=$(echo "$vault_status" | jq -r '.initialized // false')
local sealed
sealed=$(echo "$vault_status" | jq -r '.sealed // true')
if [ "$initialized" = "true" ]; then
log_pass "Vault is initialized"
else
log_fail "Vault is not initialized"
fi
if [ "$sealed" = "false" ]; then
log_pass "Vault is unsealed"
else
log_fail "Vault is sealed - must be unsealed before services can access secrets"
fi
# Check HA status
local ha_enabled
ha_enabled=$(echo "$vault_status" | jq -r '.ha_enabled // false')
if [ "$ha_enabled" = "true" ]; then
log_pass "Vault HA mode is enabled"
else
log_warn "Vault HA mode is not enabled"
fi
# Check Vault health endpoint
local health_code
health_code=$(kubectl -n vault exec vault-0 -- wget -q -O /dev/null -S http://127.0.0.1:8200/v1/sys/health 2>&1 | grep "HTTP/" | awk '{print $2}' || echo "0")
if [ "$health_code" = "200" ] || [ "$health_code" = "429" ]; then
log_pass "Vault health endpoint responding (HTTP $health_code)"
else
log_warn "Vault health endpoint returned HTTP $health_code"
fi
}
check_keycloak() {
log_info "Checking Keycloak status..."
# Check if namespace exists
if ! kubectl get namespace keycloak &> /dev/null; then
log_fail "keycloak namespace does not exist"
return
fi
# Check pod count and health
local ready_pods
ready_pods=$(kubectl -n keycloak get pods -l app=keycloak -o json | jq '[.items[] | select(.status.phase == "Running") | select(.status.containerStatuses[]?.ready == true)] | length')
if [ "$ready_pods" -ge 1 ]; then
log_pass "Keycloak has $ready_pods ready pods"
else
log_fail "Keycloak has no ready pods"
return
fi
# Check Keycloak service
local svc_exists
svc_exists=$(kubectl -n keycloak get svc keycloak -o name 2>/dev/null || echo "")
if [ -n "$svc_exists" ]; then
log_pass "Keycloak service exists"
else
log_fail "Keycloak service does not exist"
fi
# Check for coherence realm (via API if accessible)
# This requires port-forward or ingress access
log_info "Note: Verify 'coherence' realm exists via Keycloak Web UI"
# Check ingress/route
local ingress_exists
ingress_exists=$(kubectl get ingress -A -o json 2>/dev/null | jq '[.items[] | select(.spec.rules[]?.host | contains("auth"))] | length')
if [ "$ingress_exists" -ge 1 ]; then
log_pass "Keycloak ingress configured"
else
log_warn "No Keycloak ingress found - may be using LoadBalancer service"
fi
}
check_forgejo() {
log_info "Checking Forgejo status..."
# Check if namespace exists
if ! kubectl get namespace forgejo &> /dev/null; then
log_fail "forgejo namespace does not exist"
return
fi
# Check pod health
local ready_pods
ready_pods=$(kubectl -n forgejo get pods -l app=forgejo -o json | jq '[.items[] | select(.status.phase == "Running") | select(.status.containerStatuses[]?.ready == true)] | length')
if [ "$ready_pods" -ge 1 ]; then
log_pass "Forgejo has $ready_pods ready pods"
else
log_fail "Forgejo has no ready pods"
return
fi
# Check Forgejo service
local svc_exists
svc_exists=$(kubectl -n forgejo get svc forgejo -o name 2>/dev/null || echo "")
if [ -n "$svc_exists" ]; then
log_pass "Forgejo service exists"
else
log_fail "Forgejo service does not exist"
fi
# Check PVC
local pvc_bound
pvc_bound=$(kubectl -n forgejo get pvc -o json | jq '[.items[] | select(.status.phase == "Bound")] | length')
if [ "$pvc_bound" -ge 1 ]; then
log_pass "Forgejo PVC is bound"
else
log_warn "No bound PVC found for Forgejo"
fi
# Check OAuth configuration
local oauth_config
oauth_config=$(kubectl -n forgejo get configmap -o json 2>/dev/null | jq '[.items[] | select(.metadata.name | contains("oauth"))] | length')
if [ "$oauth_config" -ge 1 ]; then
log_pass "Forgejo OAuth configuration found"
else
log_warn "No OAuth configuration found - SSO may not be configured"
fi
}
check_sso_integration() {
log_info "Checking SSO integration..."
# This is a placeholder for SSO checks
# In practice, you would test OAuth flows
log_info "Note: Manually verify SSO by logging into Forgejo with Keycloak"
log_info " 1. Navigate to Forgejo web UI"
log_info " 2. Click 'Sign in with Keycloak'"
log_info " 3. Verify redirect to Keycloak login"
log_info " 4. Verify successful login and redirect back"
}
print_summary() {
echo ""
echo "========================================"
echo "Phase 2 Validation Summary"
echo "========================================"
echo -e " ${GREEN}Passed:${NC} $PASSED"
echo -e " ${RED}Failed:${NC} $FAILED"
echo -e " ${YELLOW}Warnings:${NC} $WARNINGS"
echo "========================================"
if [ "$FAILED" -gt 0 ]; then
echo ""
echo -e "${RED}Phase 2 validation FAILED${NC}"
echo "Please fix the issues above before proceeding to Phase 3."
exit 1
elif [ "$WARNINGS" -gt 0 ]; then
echo ""
echo -e "${YELLOW}Phase 2 validation passed with warnings${NC}"
echo "Review warnings above. You may proceed to Phase 3."
exit 0
else
echo ""
echo -e "${GREEN}Phase 2 validation PASSED${NC}"
echo "You may proceed to Phase 3."
exit 0
fi
}
main() {
echo "========================================"
echo "Phase 2 Validation: Core Services"
echo "========================================"
echo ""
check_vault
check_keycloak
check_forgejo
check_sso_integration
print_summary
}
main "$@"