package main import ( "io" "log/slog" "strings" "testing" "vctp/internal/secrets" ) func testLogger() *slog.Logger { return slog.New(slog.NewTextHandler(io.Discard, nil)) } func mustEncrypt(t *testing.T, s *secrets.Secrets, plain string) string { t.Helper() enc, err := s.Encrypt([]byte(plain)) if err != nil { t.Fatalf("encrypt failed: %v", err) } return enc } func TestResolveVcenterPasswordPlaintextRewrite(t *testing.T) { logger := testLogger() key := []byte("0123456789abcdef0123456789abcdef") cipher := secrets.New(logger, key) pass, rewritten, err := resolveVcenterPassword(logger, cipher, nil, "my-password") if err != nil { t.Fatalf("resolve failed: %v", err) } if string(pass) != "my-password" { t.Fatalf("unexpected plaintext returned: %q", string(pass)) } if !strings.HasPrefix(rewritten, encryptedVcenterPasswordPrefix) { t.Fatalf("expected rewritten prefixed credential, got: %q", rewritten) } } func TestResolveVcenterPasswordUnprefixedLegacyCiphertextRewrite(t *testing.T) { logger := testLogger() activeKey := []byte("0123456789abcdef0123456789abcdef") legacyKey := []byte("abcdef0123456789abcdef0123456789") activeCipher := secrets.New(logger, activeKey) legacyCipher := secrets.New(logger, legacyKey) legacyCiphertext := mustEncrypt(t, legacyCipher, "legacy-secret") pass, rewritten, err := resolveVcenterPassword(logger, activeCipher, [][]byte{legacyKey}, legacyCiphertext) if err != nil { t.Fatalf("resolve failed: %v", err) } if string(pass) != "legacy-secret" { t.Fatalf("unexpected plaintext returned: %q", string(pass)) } if !strings.HasPrefix(rewritten, encryptedVcenterPasswordPrefix) { t.Fatalf("expected rewritten prefixed credential, got: %q", rewritten) } decoded, err := activeCipher.Decrypt(strings.TrimPrefix(rewritten, encryptedVcenterPasswordPrefix)) if err != nil { t.Fatalf("rewritten ciphertext did not decrypt with active key: %v", err) } if string(decoded) != "legacy-secret" { t.Fatalf("unexpected rewritten decrypt value: %q", string(decoded)) } } func TestResolveVcenterPasswordPrefixedLegacyCiphertextRewrite(t *testing.T) { logger := testLogger() activeKey := []byte("0123456789abcdef0123456789abcdef") legacyKey := []byte("abcdef0123456789abcdef0123456789") activeCipher := secrets.New(logger, activeKey) legacyCipher := secrets.New(logger, legacyKey) legacyCiphertext := mustEncrypt(t, legacyCipher, "legacy-prefixed-secret") raw := encryptedVcenterPasswordPrefix + legacyCiphertext pass, rewritten, err := resolveVcenterPassword(logger, activeCipher, [][]byte{legacyKey}, raw) if err != nil { t.Fatalf("resolve failed: %v", err) } if string(pass) != "legacy-prefixed-secret" { t.Fatalf("unexpected plaintext returned: %q", string(pass)) } if !strings.HasPrefix(rewritten, encryptedVcenterPasswordPrefix) { t.Fatalf("expected rewritten prefixed credential, got: %q", rewritten) } decoded, err := activeCipher.Decrypt(strings.TrimPrefix(rewritten, encryptedVcenterPasswordPrefix)) if err != nil { t.Fatalf("rewritten ciphertext did not decrypt with active key: %v", err) } if string(decoded) != "legacy-prefixed-secret" { t.Fatalf("unexpected rewritten decrypt value: %q", string(decoded)) } } func TestResolveVcenterPasswordShortPlaintextRejected(t *testing.T) { logger := testLogger() key := []byte("0123456789abcdef0123456789abcdef") cipher := secrets.New(logger, key) _, _, err := resolveVcenterPassword(logger, cipher, nil, "ab") if err == nil { t.Fatal("expected short plaintext error, got nil") } if !strings.Contains(err.Error(), "too short") { t.Fatalf("unexpected error: %v", err) } }