fix(security): phase 1 critical fixes for public release
- Redact PostgreSQL DSN password from stdout/logs - Harden .dockerignore to exclude .ssh/, .claude/, *.db, *.local files - SSRF protection: block private/loopback/link-local IPs by default (UPTOP_ALLOW_PRIVATE_TARGETS=true to override for homelab use) - Fix email header injection via CRLF in monitor names - AES-256-GCM encryption for alert credentials at rest (UPTOP_ENCRYPTION_KEY env var, migrate-secrets subcommand) - TLS support for HTTP server (UPTOP_TLS_CERT/UPTOP_TLS_KEY) with HSTS header when TLS enabled
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testKey() string {
|
||||
key := make([]byte, 32)
|
||||
for i := range key {
|
||||
key[i] = byte(i)
|
||||
}
|
||||
return hex.EncodeToString(key)
|
||||
}
|
||||
|
||||
func TestEncryptorRoundTrip(t *testing.T) {
|
||||
enc, err := NewEncryptor(testKey())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
original := `{"host":"smtp.example.com","pass":"s3cret"}`
|
||||
encrypted, err := enc.Encrypt(original)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !IsEncrypted(encrypted) {
|
||||
t.Error("expected encrypted prefix")
|
||||
}
|
||||
if encrypted == original {
|
||||
t.Error("encrypted should differ from original")
|
||||
}
|
||||
|
||||
decrypted, err := enc.Decrypt(encrypted)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if decrypted != original {
|
||||
t.Errorf("got %q, want %q", decrypted, original)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncryptorDecryptPlaintext(t *testing.T) {
|
||||
enc, err := NewEncryptor(testKey())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
plain := `{"url":"https://hooks.slack.com/test"}`
|
||||
result, err := enc.Decrypt(plain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result != plain {
|
||||
t.Errorf("plaintext passthrough failed: got %q", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncryptorBadKey(t *testing.T) {
|
||||
_, err := NewEncryptor("tooshort")
|
||||
if err == nil {
|
||||
t.Error("expected error for short key")
|
||||
}
|
||||
|
||||
_, err = NewEncryptor("not-hex-at-all-but-long-enough-to-be-64-chars-if-we-keep-going!!")
|
||||
if err == nil {
|
||||
t.Error("expected error for non-hex key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncryptorUniqueCiphertexts(t *testing.T) {
|
||||
enc, err := NewEncryptor(testKey())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a, _ := enc.Encrypt("same")
|
||||
b, _ := enc.Encrypt("same")
|
||||
if a == b {
|
||||
t.Error("two encryptions of same plaintext should produce different ciphertexts")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user