#!/usr/bin/env bash # # Phase 5: E2EE Webmail Deployment (RFC 0043) # # This script deploys the E2EE webmail application including: # - Webmail frontend (React/TypeScript) # - Key service backend (Rust) # - Integration with Stalwart and Vault # # Usage: # ./deploy-phase5-e2ee-webmail.sh [--dry-run] [--build-local] [--skip-frontend] [--skip-key-service] # # Prerequisites: # - Phase 4 (Observability) should be deployed # - Stalwart email server running (Phase 3) # - Vault S/MIME PKI configured (Phase 3) # - kubectl configured for EKS cluster # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" INFRA_DIR="$(dirname "$SCRIPT_DIR")" K8S_DIR="$INFRA_DIR/kubernetes" APPS_DIR="$(dirname "$INFRA_DIR")/apps" # 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 BUILD_LOCAL=false SKIP_FRONTEND=false SKIP_KEY_SERVICE=false # Configuration REGISTRY="${REGISTRY:-ghcr.io/coherence}" VERSION="${VERSION:-latest}" # Parse arguments while [[ $# -gt 0 ]]; do case $1 in --dry-run) DRY_RUN=true shift ;; --build-local) BUILD_LOCAL=true shift ;; --skip-frontend) SKIP_FRONTEND=true shift ;; --skip-key-service) SKIP_KEY_SERVICE=true shift ;; -h|--help) echo "Usage: $0 [--dry-run] [--build-local] [--skip-frontend] [--skip-key-service]" 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 Stalwart is running if ! kubectl -n email get pods -l app=stalwart -o jsonpath='{.items[0].status.phase}' 2>/dev/null | grep -q Running; then log_error "Stalwart email server not running. Ensure Phase 3 is complete." exit 1 fi # Check Vault is running 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 it is unsealed." exit 1 fi fi # Check build tools if building locally if [ "$BUILD_LOCAL" = true ]; then if ! command -v npm &> /dev/null; then log_error "npm not found. Required for building frontend." exit 1 fi if ! command -v cargo &> /dev/null; then log_error "cargo not found. Required for building key service." exit 1 fi if ! command -v docker &> /dev/null; then log_error "docker not found. Required for building images." exit 1 fi fi log_success "All prerequisites met" } build_frontend() { if [ "$SKIP_FRONTEND" = true ]; then log_warn "Skipping frontend build" return fi if [ "$BUILD_LOCAL" = false ]; then log_info "Using pre-built frontend image: $REGISTRY/webmail-frontend:$VERSION" return fi log_info "Building webmail frontend..." local webmail_dir="$APPS_DIR/webmail" if [ ! -d "$webmail_dir" ]; then log_warn "Webmail directory not found: $webmail_dir" log_warn "Skipping frontend build" return fi cd "$webmail_dir" # Install dependencies log_info "Installing npm dependencies..." run_cmd npm install # Build production bundle log_info "Building production bundle..." run_cmd npm run build # Build Docker image log_info "Building Docker image..." run_cmd docker build -t "$REGISTRY/webmail-frontend:$VERSION" . # Push to registry if [ "$DRY_RUN" = false ]; then log_info "Pushing image to registry..." run_cmd docker push "$REGISTRY/webmail-frontend:$VERSION" fi log_success "Frontend build complete" } build_key_service() { if [ "$SKIP_KEY_SERVICE" = true ]; then log_warn "Skipping key service build" return fi if [ "$BUILD_LOCAL" = false ]; then log_info "Using pre-built key service image: $REGISTRY/key-service:$VERSION" return fi log_info "Building key service..." local key_service_dir="$APPS_DIR/key-service" if [ ! -d "$key_service_dir" ]; then log_warn "Key service directory not found: $key_service_dir" log_warn "Skipping key service build" return fi cd "$key_service_dir" # Build Rust binary log_info "Building Rust binary (release)..." run_cmd cargo build --release # Build Docker image log_info "Building Docker image..." run_cmd docker build -t "$REGISTRY/key-service:$VERSION" . # Push to registry if [ "$DRY_RUN" = false ]; then log_info "Pushing image to registry..." run_cmd docker push "$REGISTRY/key-service:$VERSION" fi log_success "Key service build complete" } deploy_webmail() { log_info "Deploying webmail components..." # Check if webmail manifests exist if [ ! -d "$K8S_DIR/webmail" ]; then log_warn "Webmail Kubernetes manifests not found: $K8S_DIR/webmail" log_warn "Creating placeholder manifests..." mkdir -p "$K8S_DIR/webmail" fi # Deploy webmail run_cmd kubectl apply -k "$K8S_DIR/webmail/" || run_cmd kubectl apply -f "$K8S_DIR/webmail/" || true # Wait for pods if [ "$DRY_RUN" = false ]; then log_info "Waiting for webmail pods to be ready..." kubectl -n webmail wait --for=condition=ready pod -l app=webmail --timeout=300s 2>/dev/null || true kubectl -n webmail wait --for=condition=ready pod -l app=key-service --timeout=300s 2>/dev/null || true fi log_success "Webmail deployment complete" } validate_phase5() { log_info "Running Phase 5 validation..." local validation_script="$SCRIPT_DIR/validate-phase5.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 5: E2EE Webmail (Optional)" echo "RFC 0043 Deployment" echo "========================================" echo "" if [ "$DRY_RUN" = true ]; then log_warn "Running in DRY-RUN mode - no changes will be made" echo "" fi check_prerequisites build_frontend build_key_service deploy_webmail validate_phase5 echo "" echo "========================================" log_success "Phase 5 deployment complete!" echo "========================================" echo "" echo "Post-deployment steps:" echo " 1. Access webmail at https://mail.coherence.dev" echo " 2. Login via Keycloak SSO" echo " 3. Verify E2EE key generation works" echo " 4. Send a test encrypted email" echo "" echo "Next steps:" echo " 1. Run validate-phase5.sh to verify deployment" echo " 2. Tag this deployment: git tag -a v0.5.0-phase5 -m 'Phase 5: E2EE Webmail'" echo " 3. Tag final release: git tag -a v1.0.0 -m 'Initial Release: Full Infrastructure Stack'" } main "$@"