168 lines
4.4 KiB
Go
168 lines
4.4 KiB
Go
package cluster
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"proxui/backend/internal/encryption"
|
|
)
|
|
|
|
func TestRepositoryEncryptsStoredTokenAndDecryptsOnLoad(t *testing.T) {
|
|
cipher := testCipher(t, 1)
|
|
storage := newMemoryStorage()
|
|
repository := NewRepositoryWithStorage(storage, cipher)
|
|
|
|
saved, err := repository.UpsertCluster(context.Background(), Cluster{
|
|
ID: "cluster-1",
|
|
Name: "Lab",
|
|
APIEndpoint: "https://pve.example.test:8006",
|
|
TLSFingerprint: "AA:BB",
|
|
TokenID: "root@pam!proxui",
|
|
TokenSecret: "secret-token",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("UpsertCluster() error = %v", err)
|
|
}
|
|
|
|
stored := storage.records[saved.ID]
|
|
if bytes.Contains(stored.EncryptedToken, []byte("secret-token")) {
|
|
t.Fatal("stored encrypted token contains plaintext")
|
|
}
|
|
|
|
got, found, err := repository.GetCluster(context.Background(), saved.ID)
|
|
if err != nil {
|
|
t.Fatalf("GetCluster() error = %v", err)
|
|
}
|
|
if !found {
|
|
t.Fatal("GetCluster() found = false, want true")
|
|
}
|
|
if got.TokenSecret != "secret-token" {
|
|
t.Fatalf("TokenSecret = %q, want secret-token", got.TokenSecret)
|
|
}
|
|
if got.TokenID != "root@pam!proxui" {
|
|
t.Fatalf("TokenID = %q, want root@pam!proxui", got.TokenID)
|
|
}
|
|
}
|
|
|
|
func TestRepositoryRejectsMissingTokenSecret(t *testing.T) {
|
|
repository := NewRepositoryWithStorage(newMemoryStorage(), testCipher(t, 1))
|
|
|
|
_, err := repository.UpsertCluster(context.Background(), Cluster{
|
|
ID: "cluster-1",
|
|
Name: "Lab",
|
|
APIEndpoint: "https://pve.example.test:8006",
|
|
TokenID: "root@pam!proxui",
|
|
})
|
|
if err == nil {
|
|
t.Fatal("UpsertCluster() error = nil, want error")
|
|
}
|
|
}
|
|
|
|
func TestRepositoryReturnsErrorWhenStoredTokenUsesWrongKey(t *testing.T) {
|
|
storage := newMemoryStorage()
|
|
writer := NewRepositoryWithStorage(storage, testCipher(t, 1))
|
|
reader := NewRepositoryWithStorage(storage, testCipher(t, 2))
|
|
|
|
saved, err := writer.UpsertCluster(context.Background(), Cluster{
|
|
ID: "cluster-1",
|
|
Name: "Lab",
|
|
APIEndpoint: "https://pve.example.test:8006",
|
|
TLSFingerprint: "AA:BB",
|
|
TokenID: "root@pam!proxui",
|
|
TokenSecret: "secret-token",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("UpsertCluster() error = %v", err)
|
|
}
|
|
|
|
if _, _, err := reader.GetCluster(context.Background(), saved.ID); err == nil {
|
|
t.Fatal("GetCluster() error = nil, want error")
|
|
}
|
|
}
|
|
|
|
func TestRepositorySetsClusterStatusWithoutDecryptingToken(t *testing.T) {
|
|
storage := newMemoryStorage()
|
|
repository := NewRepositoryWithStorage(storage, testCipher(t, 1))
|
|
|
|
_, err := repository.UpsertCluster(context.Background(), Cluster{
|
|
ID: "cluster-1",
|
|
Name: "Lab",
|
|
APIEndpoint: "https://pve.example.test:8006",
|
|
TLSFingerprint: "AA:BB",
|
|
TokenID: "root@pam!proxui",
|
|
TokenSecret: "secret-token",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("UpsertCluster() error = %v", err)
|
|
}
|
|
|
|
updated, found, err := repository.SetClusterStatus(context.Background(), "cluster-1", "disabled")
|
|
if err != nil {
|
|
t.Fatalf("SetClusterStatus() error = %v", err)
|
|
}
|
|
if !found {
|
|
t.Fatal("SetClusterStatus() found = false, want true")
|
|
}
|
|
if updated.Status != "disabled" {
|
|
t.Fatalf("Status = %q, want disabled", updated.Status)
|
|
}
|
|
if updated.TokenSecret != "" {
|
|
t.Fatal("SetClusterStatus() returned token secret")
|
|
}
|
|
}
|
|
|
|
func testCipher(t *testing.T, value byte) encryption.Cipher {
|
|
t.Helper()
|
|
|
|
cipher, err := encryption.New(bytes.Repeat([]byte{value}, 32))
|
|
if err != nil {
|
|
t.Fatalf("encryption.New() error = %v", err)
|
|
}
|
|
return cipher
|
|
}
|
|
|
|
type memoryStorage struct {
|
|
records map[string]StoredCluster
|
|
nextID int
|
|
}
|
|
|
|
func newMemoryStorage() *memoryStorage {
|
|
return &memoryStorage{
|
|
records: make(map[string]StoredCluster),
|
|
}
|
|
}
|
|
|
|
func (s *memoryStorage) Get(_ context.Context, id string) (StoredCluster, bool, error) {
|
|
cluster, ok := s.records[id]
|
|
return cluster, ok, nil
|
|
}
|
|
|
|
func (s *memoryStorage) Upsert(_ context.Context, cluster StoredCluster) (StoredCluster, error) {
|
|
if cluster.ID == "" {
|
|
s.nextID++
|
|
cluster.ID = fmt.Sprintf("cluster-%d", s.nextID)
|
|
}
|
|
if cluster.Status == "" {
|
|
cluster.Status = "active"
|
|
}
|
|
if cluster.CreatedAt.IsZero() {
|
|
cluster.CreatedAt = time.Now()
|
|
}
|
|
|
|
s.records[cluster.ID] = cluster
|
|
return cluster, nil
|
|
}
|
|
|
|
func (s *memoryStorage) SetStatus(_ context.Context, id string, status string) (StoredCluster, bool, error) {
|
|
cluster, ok := s.records[id]
|
|
if !ok {
|
|
return StoredCluster{}, false, nil
|
|
}
|
|
cluster.Status = status
|
|
s.records[id] = cluster
|
|
return cluster, true, nil
|
|
}
|