package server import ( "encoding/json" "net/http" "net/http/httptest" "strings" "testing" "git.wntrmute.dev/kyle/mcias/internal/vault" ) func TestHandleHealthSealed(t *testing.T) { srv, _, _, _ := newTestServer(t) srv.vault.Seal() req := httptest.NewRequest(http.MethodGet, "/v1/health", nil) rr := httptest.NewRecorder() srv.Handler().ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("health status = %d, want 200", rr.Code) } var resp map[string]string if err := json.NewDecoder(rr.Body).Decode(&resp); err != nil { t.Fatalf("decode health: %v", err) } if resp["status"] != "sealed" { t.Fatalf("health status = %q, want sealed", resp["status"]) } } func TestHandleHealthUnsealed(t *testing.T) { srv, _, _, _ := newTestServer(t) req := httptest.NewRequest(http.MethodGet, "/v1/health", nil) rr := httptest.NewRecorder() srv.Handler().ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("health status = %d, want 200", rr.Code) } var resp map[string]string if err := json.NewDecoder(rr.Body).Decode(&resp); err != nil { t.Fatalf("decode health: %v", err) } if resp["status"] != "ok" { t.Fatalf("health status = %q, want ok", resp["status"]) } } func TestVaultStatusEndpoint(t *testing.T) { srv, _, _, _ := newTestServer(t) // Unsealed req := httptest.NewRequest(http.MethodGet, "/v1/vault/status", nil) rr := httptest.NewRecorder() srv.Handler().ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("status code = %d, want 200", rr.Code) } var resp map[string]bool if err := json.NewDecoder(rr.Body).Decode(&resp); err != nil { t.Fatalf("decode: %v", err) } if resp["sealed"] { t.Fatal("vault should be unsealed") } // Seal and check again srv.vault.Seal() req = httptest.NewRequest(http.MethodGet, "/v1/vault/status", nil) rr = httptest.NewRecorder() srv.Handler().ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("status code = %d, want 200", rr.Code) } resp = nil if err := json.NewDecoder(rr.Body).Decode(&resp); err != nil { t.Fatalf("decode: %v", err) } if !resp["sealed"] { t.Fatal("vault should be sealed") } } func TestSealedMiddlewareAPIReturns503(t *testing.T) { srv, _, _, _ := newTestServer(t) srv.vault.Seal() req := httptest.NewRequest(http.MethodGet, "/v1/accounts", nil) rr := httptest.NewRecorder() srv.Handler().ServeHTTP(rr, req) if rr.Code != http.StatusServiceUnavailable { t.Fatalf("sealed API status = %d, want 503", rr.Code) } var resp map[string]string if err := json.NewDecoder(rr.Body).Decode(&resp); err != nil { t.Fatalf("decode: %v", err) } if resp["code"] != "vault_sealed" { t.Fatalf("error code = %q, want vault_sealed", resp["code"]) } } func TestSealedMiddlewareUIRedirects(t *testing.T) { srv, _, _, _ := newTestServer(t) srv.vault.Seal() req := httptest.NewRequest(http.MethodGet, "/dashboard", nil) rr := httptest.NewRecorder() srv.Handler().ServeHTTP(rr, req) if rr.Code != http.StatusFound { t.Fatalf("sealed UI status = %d, want 302", rr.Code) } loc := rr.Header().Get("Location") if loc != "/unseal" { t.Fatalf("redirect location = %q, want /unseal", loc) } } func TestUnsealBadPassphrase(t *testing.T) { srv, _, _, _ := newTestServer(t) // Start sealed. v := vault.NewSealed() srv.vault = v body := `{"passphrase":"wrong-passphrase"}` req := httptest.NewRequest(http.MethodPost, "/v1/vault/unseal", strings.NewReader(body)) req.Header.Set("Content-Type", "application/json") rr := httptest.NewRecorder() srv.Handler().ServeHTTP(rr, req) if rr.Code != http.StatusUnauthorized { t.Fatalf("unseal with bad passphrase status = %d, want 401", rr.Code) } } func TestSealAlreadySealedNoop(t *testing.T) { srv, _, priv, _ := newTestServer(t) // Seal via API (needs admin token) adminToken, _ := issueAdminToken(t, srv, priv, "admin") req := httptest.NewRequest(http.MethodPost, "/v1/vault/seal", nil) req.Header.Set("Authorization", "Bearer "+adminToken) rr := httptest.NewRecorder() srv.Handler().ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("seal status = %d, want 200", rr.Code) } var resp map[string]string if err := json.NewDecoder(rr.Body).Decode(&resp); err != nil { t.Fatalf("decode: %v", err) } if resp["status"] != "sealed" { t.Fatalf("seal response status = %q, want sealed", resp["status"]) } // Vault should be sealed now if !srv.vault.IsSealed() { t.Fatal("vault should be sealed after seal API call") } }