package securityevents import ( "context" "encoding/base64" "encoding/json" "net/http" "net/http/httptest" "os" "path/filepath" "sync" "testing" ) func TestKubernetesSecretStoreUsesOnePreprovisionedSecret(t *testing.T) { var mutex sync.Mutex data := map[string]string{} server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/v1/namespaces/easyai/secrets/easyai-gateway-security-events" || r.Header.Get("Authorization") != "Bearer service-account-token" { t.Fatalf("unexpected Kubernetes request: %s authorization=%t", r.URL.Path, r.Header.Get("Authorization") != "") } mutex.Lock() defer mutex.Unlock() switch r.Method { case http.MethodGet: _ = json.NewEncoder(w).Encode(map[string]any{"data": data}) case http.MethodPatch: var patch struct { Data map[string]*string `json:"data"` } if err := json.NewDecoder(r.Body).Decode(&patch); err != nil { t.Fatal(err) } for key, value := range patch.Data { if value == nil { delete(data, key) } else { data[key] = *value } } _ = json.NewEncoder(w).Encode(map[string]any{"data": data}) default: http.Error(w, "unsupported", http.StatusMethodNotAllowed) } })) defer server.Close() tokenFile := filepath.Join(t.TempDir(), "token") if err := os.WriteFile(tokenFile, []byte("service-account-token\n"), 0o600); err != nil { t.Fatal(err) } secrets, err := NewKubernetesSecretStore(KubernetesSecretStoreConfig{ Namespace: "easyai", SecretName: "easyai-gateway-security-events", APIServer: server.URL, TokenFile: tokenFile, HTTPClient: server.Client(), }) if err != nil { t.Fatal(err) } value := []byte("0123456789abcdef0123456789abcdef") if err := secrets.Put(context.Background(), "ssf-push-connection", value); err != nil { t.Fatal(err) } if data["ssf-push-connection"] != base64.StdEncoding.EncodeToString(value) { t.Fatal("Push Bearer was not stored in Kubernetes Secret data") } loaded, err := secrets.Get(context.Background(), "ssf-push-connection") if err != nil || string(loaded) != string(value) { t.Fatalf("loaded secret mismatch: err=%v", err) } clear(loaded) if err := secrets.Delete(context.Background(), "ssf-push-connection"); err != nil { t.Fatal(err) } if _, ok := data["ssf-push-connection"]; ok { t.Fatal("Push Bearer key was not removed") } } func TestKubernetesSecretStoreRejectsUnprovisionedSecret(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { http.NotFound(w, nil) })) defer server.Close() tokenFile := filepath.Join(t.TempDir(), "token") if err := os.WriteFile(tokenFile, []byte("token"), 0o600); err != nil { t.Fatal(err) } secrets, err := NewKubernetesSecretStore(KubernetesSecretStoreConfig{ Namespace: "easyai", SecretName: "easyai-gateway-security-events", APIServer: server.URL, TokenFile: tokenFile, HTTPClient: server.Client(), }) if err != nil { t.Fatal(err) } if err := secrets.Put(context.Background(), "ssf-push-connection", []byte("0123456789abcdef0123456789abcdef")); err == nil { t.Fatal("missing pre-provisioned Kubernetes Secret was accepted") } }