Skip to content

Commit 1bc3958

Browse files
Copilotmickamy
andauthored
Add complex password and caching_sha2_password full auth tests
Agent-Logs-Url: https://github.com/mickamy/sql-tap/sessions/5369e94a-1ada-4774-b2c1-f151125a958f Co-authored-by: mickamy <11856337+mickamy@users.noreply.github.com>
1 parent c47b145 commit 1bc3958

1 file changed

Lines changed: 124 additions & 0 deletions

File tree

proxy/mysql/proxy_test.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,127 @@ func TestErrorCapture(t *testing.T) {
342342
t.Error("expected non-empty error")
343343
}
344344
}
345+
346+
func TestComplexPasswordAuth(t *testing.T) {
347+
t.Parallel()
348+
complexPassword := `bbbH.A.|?ZAAAAi*RN)<*9(xxx`
349+
350+
ctx := t.Context()
351+
ctr, err := mysql.Run(ctx, "mysql:8",
352+
mysql.WithDatabase(testDB),
353+
mysql.WithUsername(testUser),
354+
mysql.WithPassword(complexPassword),
355+
)
356+
if err != nil {
357+
t.Fatalf("start mysql container: %v", err)
358+
}
359+
t.Cleanup(func() {
360+
if err := ctr.Terminate(context.Background()); err != nil {
361+
t.Logf("terminate mysql container: %v", err)
362+
}
363+
})
364+
365+
host, err := ctr.Host(ctx)
366+
if err != nil {
367+
t.Fatalf("get host: %v", err)
368+
}
369+
port, err := ctr.MappedPort(ctx, "3306/tcp")
370+
if err != nil {
371+
t.Fatalf("get port: %v", err)
372+
}
373+
upstream := fmt.Sprintf("%s:%s", host, port.Port())
374+
_, proxyAddr := startProxy(t, upstream)
375+
376+
// Connect through the proxy with the complex password.
377+
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?timeout=10s", testUser, complexPassword, proxyAddr, testDB)
378+
db, err := sql.Open("mysql", dsn)
379+
if err != nil {
380+
t.Fatalf("open db: %v", err)
381+
}
382+
defer func() { _ = db.Close() }()
383+
384+
if err := db.PingContext(ctx); err != nil {
385+
t.Fatalf("ping through proxy with complex password: %v", err)
386+
}
387+
388+
var result int
389+
if err := db.QueryRowContext(ctx, "SELECT 1").Scan(&result); err != nil {
390+
t.Fatalf("query through proxy with complex password: %v", err)
391+
}
392+
if result != 1 {
393+
t.Errorf("expected 1, got %d", result)
394+
}
395+
}
396+
397+
func TestCachingSHA2PasswordFullAuth(t *testing.T) {
398+
t.Parallel()
399+
ctx := t.Context()
400+
401+
// Start MySQL container with root user
402+
ctr, err := mysql.Run(ctx, "mysql:8",
403+
mysql.WithDatabase(testDB),
404+
mysql.WithUsername(testUser),
405+
mysql.WithPassword(testPassword),
406+
)
407+
if err != nil {
408+
t.Fatalf("start mysql container: %v", err)
409+
}
410+
t.Cleanup(func() {
411+
if err := ctr.Terminate(context.Background()); err != nil {
412+
t.Logf("terminate mysql container: %v", err)
413+
}
414+
})
415+
416+
host, err := ctr.Host(ctx)
417+
if err != nil {
418+
t.Fatalf("get host: %v", err)
419+
}
420+
port, err := ctr.MappedPort(ctx, "3306/tcp")
421+
if err != nil {
422+
t.Fatalf("get port: %v", err)
423+
}
424+
upstream := fmt.Sprintf("%s:%s", host, port.Port())
425+
426+
// Direct connection to inspect root's auth plugin and create a test user
427+
directDSN := fmt.Sprintf("%s:%s@tcp(%s)/%s?timeout=10s", testUser, testPassword, upstream, testDB)
428+
directDB, err := sql.Open("mysql", directDSN)
429+
if err != nil {
430+
t.Fatalf("open direct db: %v", err)
431+
}
432+
defer func() { _ = directDB.Close() }()
433+
434+
// Check root user's auth plugin
435+
var rootPlugin string
436+
if err := directDB.QueryRowContext(ctx,
437+
"SELECT plugin FROM mysql.user WHERE user='root' LIMIT 1").Scan(&rootPlugin); err != nil {
438+
t.Fatalf("query auth plugin: %v", err)
439+
}
440+
t.Logf("Root user auth plugin: %s", rootPlugin)
441+
442+
// Create a dedicated caching_sha2_password user with a complex password (never cached)
443+
complexPassword := `bbbH.A.|?ZAAAAi*RN)<*9(xxx`
444+
if _, err := directDB.ExecContext(ctx,
445+
"CREATE USER 'sha2user'@'%' IDENTIFIED WITH caching_sha2_password BY '"+complexPassword+"'"); err != nil {
446+
t.Fatalf("create sha2user: %v", err)
447+
}
448+
if _, err := directDB.ExecContext(ctx, "GRANT ALL ON "+testDB+".* TO 'sha2user'@'%'"); err != nil {
449+
t.Fatalf("grant sha2user: %v", err)
450+
}
451+
452+
// Start proxy
453+
_, proxyAddr := startProxy(t, upstream)
454+
455+
// Connect as sha2user through proxy - password is NOT in caching_sha2_password cache
456+
// This forces the full auth path (RSA key exchange)
457+
proxyCachingDSN := fmt.Sprintf("sha2user:%s@tcp(%s)/%s?timeout=10s", complexPassword, proxyAddr, testDB)
458+
proxyCachingDB, err := sql.Open("mysql", proxyCachingDSN)
459+
if err != nil {
460+
t.Fatalf("open caching_sha2_password db via proxy: %v", err)
461+
}
462+
defer func() { _ = proxyCachingDB.Close() }()
463+
464+
if err := proxyCachingDB.PingContext(ctx); err != nil {
465+
t.Fatalf("ping through proxy (caching_sha2_password full auth): %v", err)
466+
}
467+
t.Logf("caching_sha2_password full auth through proxy: OK")
468+
}

0 commit comments

Comments
 (0)