#!/usr/bin/env bash # # Phase 3: DNS and Email Deployment (RFC 0041) # # This script deploys DNS and email services including: # - PowerDNS for authoritative DNS # - Stalwart Mail Server for email # - Vault S/MIME PKI configuration # # Usage: # ./deploy-phase3-dns-email.sh [--dry-run] [--skip-powerdns] [--skip-stalwart] [--skip-vault-pki] # # Prerequisites: # - Phase 2 (Core Services) must be deployed and validated # - kubectl configured for EKS cluster # - DNS registrar access for NS record delegation # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" INFRA_DIR="$(dirname "$SCRIPT_DIR")" TERRAFORM_DIR="$INFRA_DIR/terraform" K8S_DIR="$INFRA_DIR/kubernetes" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # Flags DRY_RUN=false SKIP_POWERDNS=false SKIP_STALWART=false SKIP_VAULT_PKI=false # Parse arguments while [[ $# -gt 0 ]]; do case $1 in --dry-run) DRY_RUN=true shift ;; --skip-powerdns) SKIP_POWERDNS=true shift ;; --skip-stalwart) SKIP_STALWART=true shift ;; --skip-vault-pki) SKIP_VAULT_PKI=true shift ;; -h|--help) echo "Usage: $0 [--dry-run] [--skip-powerdns] [--skip-stalwart] [--skip-vault-pki]" exit 0 ;; *) echo -e "${RED}Unknown option: $1${NC}" exit 1 ;; esac done log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } run_cmd() { if [ "$DRY_RUN" = true ]; then echo -e "${YELLOW}[DRY-RUN]${NC} Would run: $*" else "$@" fi } check_prerequisites() { log_info "Checking prerequisites..." # Check kubectl connectivity if ! kubectl cluster-info &> /dev/null; then log_error "kubectl not connected to cluster." exit 1 fi # Check Vault is running and unsealed if [ "$DRY_RUN" = false ]; then local vault_status vault_status=$(kubectl -n vault exec vault-0 -- vault status -format=json 2>/dev/null || echo '{}') local sealed sealed=$(echo "$vault_status" | jq -r '.sealed // true') if [ "$sealed" = "true" ]; then log_error "Vault is sealed. Ensure Phase 2 is complete." exit 1 fi fi # Check Keycloak is running if ! kubectl -n keycloak get pods -l app=keycloak -o jsonpath='{.items[0].status.phase}' 2>/dev/null | grep -q Running; then log_error "Keycloak not running. Ensure Phase 2 is complete." exit 1 fi log_success "All prerequisites met" } deploy_powerdns() { if [ "$SKIP_POWERDNS" = true ]; then log_warn "Skipping PowerDNS deployment" return fi log_info "Deploying PowerDNS..." # Deploy PowerDNS run_cmd kubectl apply -k "$K8S_DIR/powerdns/" # Wait for PowerDNS pods if [ "$DRY_RUN" = false ]; then log_info "Waiting for PowerDNS pods to be ready..." kubectl -n dns wait --for=condition=ready pod -l app=powerdns --timeout=300s fi # Initialize DNS records if [ -f "$K8S_DIR/powerdns/dns-records-job.yaml" ]; then log_info "Initializing DNS records..." run_cmd kubectl apply -f "$K8S_DIR/powerdns/dns-records-job.yaml" if [ "$DRY_RUN" = false ]; then kubectl -n dns wait --for=condition=complete job/dns-records-init --timeout=120s || true fi fi # Enable DNSSEC if [ -f "$K8S_DIR/powerdns/dnssec-setup-job.yaml" ]; then log_info "Enabling DNSSEC..." run_cmd kubectl apply -f "$K8S_DIR/powerdns/dnssec-setup-job.yaml" if [ "$DRY_RUN" = false ]; then kubectl -n dns wait --for=condition=complete job/dnssec-setup --timeout=120s || true fi fi log_success "PowerDNS deployment complete" # Display NS record information echo "" log_info "Important: Update your DNS registrar with the following NS records:" if [ "$DRY_RUN" = false ]; then local nlb_dns nlb_dns=$(kubectl -n dns get svc powerdns-external -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' 2>/dev/null || echo "") echo " NS record should point to: $nlb_dns" fi echo "" } deploy_stalwart() { if [ "$SKIP_STALWART" = true ]; then log_warn "Skipping Stalwart deployment" return fi log_info "Deploying Stalwart Mail Server..." # Deploy Stalwart run_cmd kubectl apply -k "$K8S_DIR/stalwart/" # Wait for Stalwart pods if [ "$DRY_RUN" = false ]; then log_info "Waiting for Stalwart pods to be ready..." kubectl -n email wait --for=condition=ready pod -l app=stalwart --timeout=300s fi # Generate DKIM keys if [ -f "$K8S_DIR/stalwart/dkim-setup-job.yaml" ]; then log_info "Generating DKIM keys..." run_cmd kubectl apply -f "$K8S_DIR/stalwart/dkim-setup-job.yaml" if [ "$DRY_RUN" = false ]; then kubectl -n email wait --for=condition=complete job/dkim-setup --timeout=120s || true # Display DKIM record echo "" log_info "DKIM TXT record to add to DNS:" kubectl -n email logs job/dkim-setup 2>/dev/null | grep -A5 "DKIM TXT record" || echo " Check job logs for DKIM record" fi fi log_success "Stalwart deployment complete" # Display email DNS records echo "" log_info "Ensure the following DNS records are configured:" echo " SPF: v=spf1 mx a ~all" echo " DMARC: v=DMARC1; p=quarantine; rua=mailto:dmarc@coherence.dev" echo "" } deploy_vault_smime_pki() { if [ "$SKIP_VAULT_PKI" = true ]; then log_warn "Skipping Vault S/MIME PKI deployment" return fi log_info "Deploying Vault S/MIME PKI..." cd "$TERRAFORM_DIR" if [ "$DRY_RUN" = true ]; then run_cmd terraform plan -target=module.vault_smime_pki else terraform plan -target=module.vault_smime_pki -out=pki.tfplan terraform apply pki.tfplan rm -f pki.tfplan fi log_success "Vault S/MIME PKI deployment complete" } validate_phase3() { log_info "Running Phase 3 validation..." local validation_script="$SCRIPT_DIR/validate-phase3.sh" if [ -x "$validation_script" ]; then if [ "$DRY_RUN" = true ]; then log_info "Would run validation script: $validation_script" else "$validation_script" fi else log_warn "Validation script not found or not executable: $validation_script" fi } main() { echo "========================================" echo "Phase 3: DNS and Email" echo "RFC 0041 Deployment" echo "========================================" echo "" if [ "$DRY_RUN" = true ]; then log_warn "Running in DRY-RUN mode - no changes will be made" echo "" fi check_prerequisites deploy_powerdns deploy_stalwart deploy_vault_smime_pki validate_phase3 echo "" echo "========================================" log_success "Phase 3 deployment complete!" echo "========================================" echo "" echo "IMPORTANT MANUAL STEPS:" echo " 1. Update DNS registrar with NS records pointing to PowerDNS NLB" echo " 2. Add DKIM TXT record to DNS" echo " 3. Add SPF and DMARC records" echo " 4. Wait for DNS propagation (may take up to 48 hours)" echo "" echo "Next steps:" echo " 1. Run validate-phase3.sh to verify deployment" echo " 2. Tag this deployment: git tag -a v0.3.0-phase3 -m 'Phase 3: DNS and Email'" echo " 3. Proceed to Phase 4: ./deploy-phase4-observability.sh" } main "$@"