Skip to content

Commit c0839d0

Browse files
committed
wip
1 parent 8926cad commit c0839d0

File tree

11 files changed

+212
-152
lines changed

11 files changed

+212
-152
lines changed

authentik/lib/default.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ postgresql:
2121
user: authentik
2222
port: 5432
2323
password: "env://POSTGRES_PASSWORD"
24+
sslmode: disable
2425
use_pool: False
2526
test:
2627
name: test_authentik

internal/config/config.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,17 @@ func (c *Config) parseScheme(rawVal string) string {
169169
case "env":
170170
e, ok := os.LookupEnv(u.Host)
171171
if ok {
172+
log.WithFields(log.Fields{
173+
"env_var": u.Host,
174+
"found": true,
175+
}).Trace("Resolved environment variable")
172176
return e
173177
}
178+
log.WithFields(log.Fields{
179+
"env_var": u.Host,
180+
"found": false,
181+
"fallback": u.RawQuery,
182+
}).Warn("Environment variable not found, using fallback")
174183
return u.RawQuery
175184
case "file":
176185
d, err := os.ReadFile(u.Path)

internal/outpost/proxyv2/application/session_postgres_test.go

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"github.com/google/uuid"
1010
"github.com/stretchr/testify/assert"
1111
"github.com/stretchr/testify/require"
12-
"gorm.io/driver/postgres"
1312
"gorm.io/gorm"
1413
"gorm.io/gorm/logger"
1514

@@ -19,9 +18,8 @@ import (
1918
"goauthentik.io/internal/outpost/proxyv2/types"
2019
)
2120

22-
func SetupTestDB(t *testing.T) *gorm.DB {
21+
func SetupTestDB(t *testing.T) (*gorm.DB, *postgresstore.RefreshableConnPool) {
2322
cfg := config.Get().PostgreSQL
24-
dsn := buildDSN(cfg)
2523

2624
gormConfig := &gorm.Config{
2725
Logger: logger.Default.LogMode(logger.Silent),
@@ -30,34 +28,25 @@ func SetupTestDB(t *testing.T) *gorm.DB {
3028
},
3129
}
3230

33-
db, err := gorm.Open(postgres.Open(dsn), gormConfig)
31+
// Use standardized setup
32+
db, pool, err := postgresstore.SetupGORMWithRefreshablePool(cfg, gormConfig, 10, 100, time.Hour)
3433
require.NoError(t, err)
3534

36-
return db
35+
return db, pool
3736
}
3837

39-
func CleanupTestDB(t *testing.T, db *gorm.DB) {
38+
func CleanupTestDB(t *testing.T, db *gorm.DB, pool *postgresstore.RefreshableConnPool) {
4039
assert.NoError(t, db.Exec("DELETE FROM authentik_providers_proxy_proxysession").Error)
41-
sdb, err := db.DB()
42-
assert.NoError(t, err)
43-
assert.NoError(t, sdb.Close())
40+
assert.NoError(t, pool.Close())
4441
}
4542

46-
func buildDSN(cfg config.PostgreSQLConfig) string {
47-
dsn, err := postgresstore.BuildDSN(cfg)
48-
if err != nil {
49-
panic(err)
50-
}
51-
return dsn
52-
}
53-
54-
func NewTestStore(db *gorm.DB) *postgresstore.PostgresStore {
55-
return postgresstore.NewTestStore(db)
43+
func NewTestStore(db *gorm.DB, pool *postgresstore.RefreshableConnPool) *postgresstore.PostgresStore {
44+
return postgresstore.NewTestStore(db, pool)
5645
}
5746

5847
func TestPostgresStore_SessionLifecycle(t *testing.T) {
59-
db := SetupTestDB(t)
60-
defer CleanupTestDB(t, db)
48+
db, pool := SetupTestDB(t)
49+
defer CleanupTestDB(t, db, pool)
6150

6251
// Create sessions directly in the database for testing
6352
userID := uuid.New()
@@ -111,8 +100,8 @@ func TestPostgresStore_SessionLifecycle(t *testing.T) {
111100
}
112101

113102
func TestPostgresStore_LogoutSessions(t *testing.T) {
114-
db := SetupTestDB(t)
115-
defer CleanupTestDB(t, db)
103+
db, pool := SetupTestDB(t)
104+
defer CleanupTestDB(t, db, pool)
116105

117106
// Create multiple sessions for different users
118107
user1 := uuid.New()
@@ -164,7 +153,7 @@ func TestPostgresStore_LogoutSessions(t *testing.T) {
164153
assert.Equal(t, int64(3), totalCount)
165154

166155
// Logout user1 sessions using LogoutSessions method
167-
store := NewTestStore(db)
156+
store := NewTestStore(db, pool)
168157
err := store.LogoutSessions(context.Background(), func(c types.Claims) bool {
169158
return c.Sub == user1.String()
170159
})
@@ -182,8 +171,8 @@ func TestPostgresStore_LogoutSessions(t *testing.T) {
182171
}
183172

184173
func TestPostgresStore_SessionExpiration(t *testing.T) {
185-
db := SetupTestDB(t)
186-
defer CleanupTestDB(t, db)
174+
db, pool := SetupTestDB(t)
175+
defer CleanupTestDB(t, db, pool)
187176

188177
// Create expired and valid sessions
189178
expiredSession := postgresstore.ProxySession{
@@ -234,8 +223,8 @@ func TestPostgresStore_SessionExpiration(t *testing.T) {
234223
}
235224

236225
func TestPostgresStore_SessionClaims(t *testing.T) {
237-
db := SetupTestDB(t)
238-
defer CleanupTestDB(t, db)
226+
db, pool := SetupTestDB(t)
227+
defer CleanupTestDB(t, db, pool)
239228

240229
// Create session with complex claims
241230
userID := uuid.New()

internal/outpost/proxyv2/filesystemstore/filesystemstore.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ func NewStore(storePath string, keyPairs ...[]byte) (*Store, error) {
7777
}
7878

7979
// CleanupExpired implements the CleanupStore interface for use with CleanupManager
80-
func (s *Store) CleanupExpired() error {
81-
return s.SessionCleanup(context.Background())
80+
func (s *Store) CleanupExpired(ctx context.Context) error {
81+
return s.SessionCleanup(ctx)
8282
}
8383

8484
// SessionCleanup acquires a file lock to ensure only one instance runs at a time,

internal/outpost/proxyv2/postgresstore/connpool.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type RefreshableConnPool struct {
3737

3838
// NewRefreshableConnPool creates a new connection pool that refreshes credentials from config
3939
func NewRefreshableConnPool(initialDSN string, gormConfig *gorm.Config, maxIdleConns, maxOpenConns int, connMaxLifetime time.Duration) (*RefreshableConnPool, error) {
40-
db, err := sql.Open("postgres", initialDSN)
40+
db, err := sql.Open("pgx", initialDSN)
4141
if err != nil {
4242
return nil, err
4343
}
@@ -112,7 +112,7 @@ func (p *RefreshableConnPool) refreshCredentials(ctx context.Context) error {
112112
p.log.Info("PostgreSQL credentials changed, reconnecting...")
113113

114114
// Open new connection with fresh credentials
115-
newDB, err := sql.Open("postgres", newDSN)
115+
newDB, err := sql.Open("pgx", newDSN)
116116
if err != nil {
117117
p.log.WithError(err).Error("Failed to open new database connection with refreshed credentials")
118118
return err

internal/outpost/proxyv2/postgresstore/connpool_test.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"os"
66
"path/filepath"
7+
"sync"
78
"testing"
89
"time"
910

@@ -17,20 +18,19 @@ import (
1718
)
1819

1920
func TestRefreshableConnPool_CredentialRefresh(t *testing.T) {
20-
// Skip if no PostgreSQL available
21-
if os.Getenv("AUTHENTIK_POSTGRESQL__HOST") == "" {
22-
t.Skip("Skipping test: no PostgreSQL configured")
23-
}
24-
2521
// Create a temporary file for password rotation
2622
tmpDir := t.TempDir()
2723
passwordFile := filepath.Join(tmpDir, "db_password")
2824

29-
// Write initial password
30-
initialPassword := os.Getenv("AUTHENTIK_POSTGRESQL__PASSWORD")
25+
cfg := config.Get()
26+
initialConfig := cfg.RefreshPostgreSQLConfig()
27+
28+
// Determine the current database password as the baseline for the rotation test.
29+
initialPassword := initialConfig.Password
3130
if initialPassword == "" {
3231
initialPassword = "postgres"
3332
}
33+
3434
err := os.WriteFile(passwordFile, []byte(initialPassword), 0600)
3535
require.NoError(t, err)
3636

@@ -46,11 +46,10 @@ func TestRefreshableConnPool_CredentialRefresh(t *testing.T) {
4646
}()
4747

4848
// Reload config
49-
cfg := &config.Config{}
50-
cfg.Setup()
49+
refreshedConfig := cfg.RefreshPostgreSQLConfig()
5150

5251
// Build initial DSN
53-
dsn, err := BuildDSN(cfg.PostgreSQL)
52+
dsn, err := BuildDSN(refreshedConfig)
5453
require.NoError(t, err)
5554

5655
gormConfig := &gorm.Config{
@@ -105,11 +104,6 @@ func TestRefreshableConnPool_Interfaces(t *testing.T) {
105104
}
106105

107106
func TestRefreshableConnPool_ConcurrentAccess(t *testing.T) {
108-
// Skip if no PostgreSQL available
109-
if os.Getenv("AUTHENTIK_POSTGRESQL__HOST") == "" {
110-
t.Skip("Skipping test: no PostgreSQL configured")
111-
}
112-
113107
cfg := config.Get()
114108
dsn, err := BuildDSN(cfg.PostgreSQL)
115109
require.NoError(t, err)
@@ -125,27 +119,35 @@ func TestRefreshableConnPool_ConcurrentAccess(t *testing.T) {
125119
db, err := pool.NewGORMDB()
126120
require.NoError(t, err)
127121

128-
// Test concurrent queries
122+
// Test that the connection is working
129123
ctx := context.Background()
124+
var result int
125+
err = db.WithContext(ctx).Raw("SELECT 1").Scan(&result).Error
126+
require.NoError(t, err, "Initial connection test should succeed")
127+
128+
// Test concurrent queries
130129
numGoroutines := 10
131130
numQueries := 5
132131

132+
var wg sync.WaitGroup
133133
errChan := make(chan error, numGoroutines*numQueries)
134134

135135
for i := 0; i < numGoroutines; i++ {
136+
wg.Add(1)
136137
go func(goroutineID int) {
138+
defer wg.Done()
137139
for j := 0; j < numQueries; j++ {
138140
var result int
139-
err := db.WithContext(ctx).Raw("SELECT ?", goroutineID*numQueries+j).Scan(&result).Error
141+
err := db.WithContext(ctx).Raw("SELECT 1").Scan(&result).Error
140142
if err != nil {
141143
errChan <- err
142144
}
143145
}
144146
}(i)
145147
}
146148

147-
// Wait a bit for goroutines to complete
148-
time.Sleep(2 * time.Second)
149+
// Wait for all goroutines to complete, then close the channel
150+
wg.Wait()
149151
close(errChan)
150152

151153
// Check for any errors

0 commit comments

Comments
 (0)