From ea6a2e705f2c1a774a8bfb20c5593431c38fc9d4 Mon Sep 17 00:00:00 2001 From: Hein Date: Thu, 1 Oct 2026 13:24:26 +0200 Subject: [PATCH] test(security): add SQL Server container conformance test; bind timestamps as UTC in direct backend --- pkg/security/lookup/backends/container_test.go | 15 +++++++++++++++ pkg/security/lookup/direct/base.go | 11 +++++++++++ 2 files changed, 26 insertions(+) diff --git a/pkg/security/lookup/backends/container_test.go b/pkg/security/lookup/backends/container_test.go index a391caa..06b2cb6 100644 --- a/pkg/security/lookup/backends/container_test.go +++ b/pkg/security/lookup/backends/container_test.go @@ -139,3 +139,18 @@ func TestConformancePostgresContainer(t *testing.T) { runOnServer(t, "pgx", dsn("cf_direct"), "postgres", lookup.Config{Mode: lookup.ModeDirect}, true) }) } + +func TestConformanceMSSQLContainer(t *testing.T) { + rt := containerRuntime(t) + port := startContainer(t, rt, "mcr.microsoft.com/mssql/server:2022-latest", "1433", map[string]string{ + "ACCEPT_EULA": "Y", "MSSQL_SA_PASSWORD": containerPassword, + }) + dsn := func(db string) string { + return fmt.Sprintf("sqlserver://sa:%s@127.0.0.1:%s?database=%s&encrypt=disable", containerPassword, port, db) + } + admin := waitReady(t, "sqlserver", dsn("master"), 3*time.Minute) + if _, err := admin.Exec("CREATE DATABASE cf_direct"); err != nil { + t.Fatal(err) + } + runOnServer(t, "sqlserver", dsn("cf_direct"), "mssql", lookup.Config{}, true) +} diff --git a/pkg/security/lookup/direct/base.go b/pkg/security/lookup/direct/base.go index 06538e3..cccf60e 100644 --- a/pkg/security/lookup/direct/base.go +++ b/pkg/security/lookup/direct/base.go @@ -102,6 +102,17 @@ func (b *Base) arg(v any) any { if bv, ok := v.(bool); ok { return b.d.Bool(bv) } + // Timestamp columns carry no zone: bind every instant as UTC so drivers that send an + // offset (SQL Server) and ones that drop it agree on the stored wall clock. + if tv, ok := v.(time.Time); ok { + return tv.UTC() + } + if tp, ok := v.(*time.Time); ok { + if tp == nil { + return nil + } + return tp.UTC() + } return v }