github.com/square/finch@v0.0.0-20240412205204-6530c03e2b96/dbconn/mycnf.go (about) 1 // Copyright 2023 Block, Inc. 2 3 package dbconn 4 5 import ( 6 "strings" 7 8 "github.com/go-ini/ini" 9 10 "github.com/square/finch" 11 "github.com/square/finch/config" 12 ) 13 14 // ParseMyCnf parses a MySQL my.cnf file. It only reads the "[client]" section, 15 // same as the mysql CLI. 16 func ParseMyCnf(file string) (config.MySQL, error) { 17 opts := ini.LoadOptions{AllowBooleanKeys: true} 18 mycnf, err := ini.LoadSources(opts, file) 19 if err != nil { 20 return config.MySQL{}, err 21 } 22 23 cfg := config.MySQL{ 24 Username: mycnf.Section("client").Key("user").String(), 25 Password: mycnf.Section("client").Key("password").String(), 26 Hostname: mycnf.Section("client").Key("host").String(), 27 Socket: mycnf.Section("client").Key("socket").String(), 28 } 29 30 port := mycnf.Section("client").Key("port").String() 31 if port != "" { 32 cfg.Hostname += ":" + port 33 } 34 35 // Translate MySQL ssl-* vars to config.TLS. The vars don't line up 36 // perfectly because MySQL has several levels of TLS verification: 37 // https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-mode 38 // But Go tls.Config (which is derived from config.TLS) has only two 39 // options: specify tls.Confg.ServerName _or_ .InsecureSkipVerify=true. 40 mysqlTLS(file, mycnf, &cfg) 41 42 finch.Debug("mycnf %s: %s %+v", file, cfg.Redacted()) 43 return cfg, nil 44 } 45 46 func mysqlTLS(file string, mycnf *ini.File, cfg *config.MySQL) (tls config.TLS) { 47 // USING IMPLICIT RETURN -----------------------------------^ 48 49 tls.MySQLMode = strings.ToUpper(mycnf.Section("client").Key("ssl-mode").String()) 50 if tls.MySQLMode == "" { 51 tls.MySQLMode = "PREFERRED" // MySQL default 52 } 53 54 // Explicitly disabled = not TLS even if other vars set 55 if tls.MySQLMode == "DISABLED" { 56 finch.Debug("mycnf %s: ssl-mode=DISABLED", file) 57 return 58 } 59 60 // As per the MySQL manual: 61 // "Connections over Unix socket files are not encrypted with a mode of PREFERRED. 62 // To enforce encryption for Unix socket-file connections, use a mode of REQUIRED or stricter. 63 if cfg.Socket != "" && tls.MySQLMode == "PREFERRED" { 64 finch.Debug("mycnf %s: ignoring TLS on socket %s", file, cfg.Socket) 65 return 66 } 67 68 // Not TLS unless at least 1 of the 3 files is set (no validation yet) 69 tls.CA = mycnf.Section("client").Key("ssl-ca").String() 70 tls.Cert = mycnf.Section("client").Key("ssl-cert").String() 71 tls.Key = mycnf.Section("client").Key("ssl-key").String() 72 if !tls.Set() { 73 finch.Debug("mycnf %s: TLS not set", file) 74 return 75 } 76 77 // Probably legit/normal MySQL TLS config: hostname + at least 1 file. 78 // But it's unclear if, for example, PREFERRED = SkipVerify=true? 79 return 80 }