f99010fae1
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Windows) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Has been cancelled
247 lines
5.4 KiB
Go
247 lines
5.4 KiB
Go
package postgres
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestCheckSSL(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dsn string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
"loopback localhost",
|
|
"postgres://user:pass@localhost:5432/db",
|
|
false,
|
|
},
|
|
{
|
|
"loopback 127.0.0.1",
|
|
"postgres://user:pass@127.0.0.1:5432/db",
|
|
false,
|
|
},
|
|
{
|
|
"loopback ::1",
|
|
"postgres://user:pass@[::1]:5432/db",
|
|
false,
|
|
},
|
|
{
|
|
"empty host defaults local",
|
|
"",
|
|
false,
|
|
},
|
|
{
|
|
"remote with require",
|
|
"postgres://u:p@remote:5432/db?sslmode=require",
|
|
false,
|
|
},
|
|
{
|
|
"remote with verify-full",
|
|
"postgres://u:p@remote:5432/db?sslmode=verify-full",
|
|
false,
|
|
},
|
|
{
|
|
"remote no sslmode",
|
|
"postgres://u:p@remote:5432/db",
|
|
true,
|
|
},
|
|
{
|
|
"remote sslmode=disable",
|
|
"postgres://u:p@remote:5432/db?sslmode=disable",
|
|
true,
|
|
},
|
|
{
|
|
"remote sslmode=prefer",
|
|
"postgres://u:p@remote:5432/db?sslmode=prefer",
|
|
true,
|
|
},
|
|
{
|
|
"remote sslmode=allow",
|
|
"postgres://u:p@remote:5432/db?sslmode=allow",
|
|
true,
|
|
},
|
|
{
|
|
"kv remote require",
|
|
"host=remote sslmode=require",
|
|
false,
|
|
},
|
|
{
|
|
"kv remote disable",
|
|
"host=remote sslmode=disable",
|
|
true,
|
|
},
|
|
{
|
|
"kv unix socket",
|
|
"host=/var/run/postgresql sslmode=disable",
|
|
false,
|
|
},
|
|
{
|
|
"uri query host disable",
|
|
"postgres:///db?host=remote&sslmode=disable",
|
|
true,
|
|
},
|
|
{
|
|
"uri query host require",
|
|
"postgres:///db?host=remote&sslmode=require",
|
|
false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := CheckSSL(tt.dsn)
|
|
assert.Equal(t, tt.wantErr, err != nil, "err = %v", err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRedactDSN(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dsn string
|
|
want string
|
|
}{
|
|
{
|
|
"strips credentials",
|
|
"postgres://user:secret@myhost:5432/db",
|
|
"myhost",
|
|
},
|
|
{
|
|
"empty dsn",
|
|
"",
|
|
"",
|
|
},
|
|
{
|
|
"invalid dsn",
|
|
"://bad",
|
|
"",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert.Equal(t, tt.want, RedactDSN(tt.dsn))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsLoopback(t *testing.T) {
|
|
tests := []struct {
|
|
host string
|
|
want bool
|
|
}{
|
|
{"", true},
|
|
{"localhost", true},
|
|
{"127.0.0.1", true},
|
|
{"::1", true},
|
|
{"/var/run/postgresql", true},
|
|
{"remote.host.com", false},
|
|
{"10.0.0.1", false},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.host, func(t *testing.T) {
|
|
assert.Equal(t, tt.want, isLoopback(tt.host))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestQuoteIdentifier(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{"simple", "agentsview", `"agentsview"`, false},
|
|
{"underscore", "my_schema", `"my_schema"`, false},
|
|
{"empty", "", "", true},
|
|
{"has spaces", "bad schema", "", true},
|
|
{"has semicolon", "bad;drop", "", true},
|
|
{"starts with digit", "1bad", "", true},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := quoteIdentifier(tt.input)
|
|
assert.Equal(t, tt.wantErr, err != nil, "err = %v", err)
|
|
assert.Equal(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPGTargetFingerprint(t *testing.T) {
|
|
base, err := pgTargetFingerprint(
|
|
"postgres://alice:secret@db.example.com:5432/agents?sslmode=require&application_name=agentsview",
|
|
"agentsview",
|
|
)
|
|
assert.NoError(t, err)
|
|
|
|
samePasswordChanged, err := pgTargetFingerprint(
|
|
"postgres://alice:new-secret@db.example.com:5432/agents?sslmode=require&application_name=other",
|
|
"agentsview",
|
|
)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, base, samePasswordChanged)
|
|
|
|
baseWithFallback, err := pgTargetFingerprint(
|
|
"postgres://alice:secret@db.example.com:5432/agents?sslmode=require&application_name=agentsview&host=db.example.com,standby-a.example.com&port=5432,6432",
|
|
"agentsview",
|
|
)
|
|
assert.NoError(t, err)
|
|
|
|
sameFallbackNoiseChanged, err := pgTargetFingerprint(
|
|
"postgres://alice:new-secret@db.example.com:5432/agents?sslmode=require&application_name=other&host=DB.EXAMPLE.COM,standby-a.example.com&port=5432,6432",
|
|
"agentsview",
|
|
)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, baseWithFallback, sameFallbackNoiseChanged)
|
|
|
|
cases := []struct {
|
|
name string
|
|
dsn string
|
|
schema string
|
|
}{
|
|
{
|
|
name: "host change",
|
|
dsn: "postgres://alice:secret@db2.example.com:5432/agents?sslmode=require",
|
|
schema: "agentsview",
|
|
},
|
|
{
|
|
name: "database change",
|
|
dsn: "postgres://alice:secret@db.example.com:5432/agents_archive?sslmode=require",
|
|
schema: "agentsview",
|
|
},
|
|
{
|
|
name: "user change",
|
|
dsn: "postgres://bob:secret@db.example.com:5432/agents?sslmode=require",
|
|
schema: "agentsview",
|
|
},
|
|
{
|
|
name: "schema change",
|
|
dsn: "postgres://alice:secret@db.example.com:5432/agents?sslmode=require",
|
|
schema: "agentsview_alt",
|
|
},
|
|
{
|
|
name: "fallback host change",
|
|
dsn: "postgres://alice:secret@db.example.com:5432/agents?sslmode=require&host=db.example.com,standby-b.example.com&port=5432,6432",
|
|
schema: "agentsview",
|
|
},
|
|
{
|
|
name: "fallback port change",
|
|
dsn: "postgres://alice:secret@db.example.com:5432/agents?sslmode=require&host=db.example.com,standby-a.example.com&port=5432,7432",
|
|
schema: "agentsview",
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got, err := pgTargetFingerprint(tc.dsn, tc.schema)
|
|
assert.NoError(t, err)
|
|
wantDifferentFrom := base
|
|
if tc.name == "fallback host change" || tc.name == "fallback port change" {
|
|
wantDifferentFrom = baseWithFallback
|
|
}
|
|
assert.NotEqual(t, wantDifferentFrom, got)
|
|
})
|
|
}
|
|
}
|