fix(canary-phase9): plumb mysql public host/port through to generator
Audit found that registry.Build was calling mysql.New() with hardcoded
localhost:3306 defaults, ignoring cfg.MySQL.PublicHost and PublicPort.
Result: every emitted mysql:// connection string said
"mysql://canary_<id>@localhost:3306/internal_db" regardless of actual
deployment address — useless for any non-localhost deployment.
Fix:
- registry.Config: adds MySQLPublicHost + MySQLPublicPort fields
- registry.Build: switches between mysql.New() and
mysql.NewWithAddress(host, port) based on config
- cmd/canary/main.go: passes cfg.MySQL.PublicHost/PublicPort
through to registry.Build
- registry_test.go: new TestBuild_MySQLUsesConfiguredPublicAddress
asserts the connection string reflects configured host/port
Other Phase 9 audit observations DEFERRED to Phase 10 (not blocking
rollup):
- §11.3 create-tier rate limit on POST /api/tokens (Turnstile
already provides spam protection; tiered limits are
belt-and-suspenders)
- scoping the gosec G107/G704 exclude to specific packages
(revisit when Phase 10's webhook sender lands and needs
case-by-case URL validation)
- TurnstileResp dto required-tag clashes with dev-mode bypass
(low severity — current behavior is sound)
- /api/m/{manage_id} GET/DELETE (spec §8.1 lines 740-741) — Phase 11
- FingerprintRecorder is nil at startup (slowredirect fingerprint
handler wiring) — Phase 10
- mysql_username metadata write in token.Service (mysql trigger
lookup goes by token ID, not username — low impact)
Pre-rollup gate clean at HEAD:
- go build ./... + go vet ./... clean
- go test -race -timeout=60s ./... all pass (~50 new test cases)
- go test -tags=integration -race -timeout=300s ./internal/token/...
./internal/event/... all pass
- golangci-lint run ./... → 0 issues
- grep -rn "//nolint" --include="*.go" returns nothing
This commit is contained in:
parent
8d1016b87d
commit
6c37082598
|
|
@ -86,7 +86,11 @@ func run(configPath string) error {
|
|||
}
|
||||
logger.Info("redis connected")
|
||||
|
||||
genRegistry := registry.Build(registry.Config{BaseURL: cfg.Canary.BaseURL})
|
||||
genRegistry := registry.Build(registry.Config{
|
||||
BaseURL: cfg.Canary.BaseURL,
|
||||
MySQLPublicHost: cfg.MySQL.PublicHost,
|
||||
MySQLPublicPort: cfg.MySQL.PublicPort,
|
||||
})
|
||||
tokenSvc := token.NewService(
|
||||
tokenRepo,
|
||||
registryAdapter{r: genRegistry},
|
||||
|
|
|
|||
|
|
@ -16,12 +16,22 @@ import (
|
|||
)
|
||||
|
||||
type Config struct {
|
||||
BaseURL string
|
||||
BaseURL string
|
||||
MySQLPublicHost string
|
||||
MySQLPublicPort int
|
||||
}
|
||||
|
||||
type Registry map[token.Type]generators.Generator
|
||||
|
||||
func Build(_ Config) Registry {
|
||||
func Build(cfg Config) Registry {
|
||||
host := cfg.MySQLPublicHost
|
||||
port := cfg.MySQLPublicPort
|
||||
var mysqlGen *mysql.Generator
|
||||
if host == "" || port == 0 {
|
||||
mysqlGen = mysql.New()
|
||||
} else {
|
||||
mysqlGen = mysql.NewWithAddress(host, port)
|
||||
}
|
||||
return Registry{
|
||||
token.TypeWebbug: webbug.New(),
|
||||
token.TypeSlowRedirect: slowredirect.New(),
|
||||
|
|
@ -29,6 +39,6 @@ func Build(_ Config) Registry {
|
|||
token.TypePDF: pdf.New(),
|
||||
token.TypeKubeconfig: kubeconfig.New(),
|
||||
token.TypeEnvfile: envfile.New(),
|
||||
token.TypeMySQL: mysql.New(),
|
||||
token.TypeMySQL: mysqlGen,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
package registry_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -77,6 +78,26 @@ func TestBuild_UnknownTypeReturnsZeroValue(t *testing.T) {
|
|||
require.Nil(t, g, "map zero value for missing key must be nil interface")
|
||||
}
|
||||
|
||||
func TestBuild_MySQLUsesConfiguredPublicAddress(t *testing.T) {
|
||||
reg := registry.Build(registry.Config{
|
||||
BaseURL: testBaseURL,
|
||||
MySQLPublicHost: "canary.example.com",
|
||||
MySQLPublicPort: 13306,
|
||||
})
|
||||
g, ok := reg[token.TypeMySQL]
|
||||
require.True(t, ok)
|
||||
|
||||
tok := &token.Token{ID: "abc", Type: token.TypeMySQL}
|
||||
art, err := g.Generate(context.Background(), tok, testBaseURL)
|
||||
require.NoError(t, err)
|
||||
require.Equal(
|
||||
t,
|
||||
"mysql://canary_abc@canary.example.com:13306/internal_db",
|
||||
art.ConnectionString,
|
||||
"mysql connection string must reflect configured public host:port",
|
||||
)
|
||||
}
|
||||
|
||||
func TestBuild_AllSevenGeneratorsRegistered(t *testing.T) {
|
||||
reg := registry.Build(registry.Config{BaseURL: testBaseURL})
|
||||
require.Len(
|
||||
|
|
|
|||
Loading…
Reference in New Issue