diff --git a/integration/db/db_integration_test.go b/integration/db/db_integration_test.go index 086816df6d4bb..739e61c02a2ef 100644 --- a/integration/db/db_integration_test.go +++ b/integration/db/db_integration_test.go @@ -66,6 +66,7 @@ func TestDatabaseAccess(t *testing.T) { WithRootConfig(func(config *servicecfg.Config) { config.PollingPeriod = 5 * time.Second config.RotationConnectionInterval = 2 * time.Second + config.Proxy.MySQLServerVersion = "8.0.1" }), ) pack.WaitForLeaf(t) @@ -461,6 +462,9 @@ func (p *DatabasePack) testMySQLRootCluster(t *testing.T) { require.Equal(t, wantRootQueryCount, p.Root.mysql.QueryCount()) require.Equal(t, wantLeafQueryCount, p.Leaf.mysql.QueryCount()) + // Check if default Proxy MYSQL Engine Version was overridden the proxy settings. + require.Equal(t, "8.0.1", client.GetServerVersion()) + // Disconnect. err = client.Close() require.NoError(t, err) diff --git a/integration/proxy/proxy_test.go b/integration/proxy/proxy_test.go index b4c82311c1174..16638ba9e18c7 100644 --- a/integration/proxy/proxy_test.go +++ b/integration/proxy/proxy_test.go @@ -635,6 +635,8 @@ func TestALPNSNIProxyDatabaseAccess(t *testing.T) { require.NoError(t, err) require.Equal(t, mysql.TestQueryResponse, result) + require.Equal(t, mysql.DefaultServerVersion, client.GetServerVersion()) + // Disconnect. err = client.Close() require.NoError(t, err) diff --git a/lib/config/configuration.go b/lib/config/configuration.go index 779a483293062..2d72baa8fa882 100644 --- a/lib/config/configuration.go +++ b/lib/config/configuration.go @@ -887,6 +887,10 @@ func applyProxyConfig(fc *FileConfig, cfg *servicecfg.Config) error { cfg.Proxy.UI = webclient.UIConfig(*fc.Proxy.UI) } + if fc.Proxy.MySQLServerVersion != "" { + cfg.Proxy.MySQLServerVersion = fc.Proxy.MySQLServerVersion + } + // This is the legacy format. Continue to support it forever, but ideally // users now use the list format below. if fc.Proxy.KeyFile != "" || fc.Proxy.CertFile != "" { diff --git a/lib/config/fileconf.go b/lib/config/fileconf.go index e6150861f9fe7..0b013a6b3dda7 100644 --- a/lib/config/fileconf.go +++ b/lib/config/fileconf.go @@ -2017,6 +2017,9 @@ type Proxy struct { // client connections. MySQLPublicAddr apiutils.Strings `yaml:"mysql_public_addr,omitempty"` + // MySQLServerVersion allow to overwrite proxy default mysql engine version reported by Teleport proxy. + MySQLServerVersion string `yaml:"mysql_server_version,omitempty"` + // PostgresAddr is Postgres proxy listen address. PostgresAddr string `yaml:"postgres_listen_addr,omitempty"` // PostgresPublicAddr is the hostport the proxy advertises for Postgres diff --git a/lib/service/service.go b/lib/service/service.go index 6319297bfc3ea..6dd3c285cfa8a 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -4133,14 +4133,15 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { dbProxyServer, err := db.NewProxyServer(process.ExitContext(), db.ProxyServerConfig{ - AuthClient: conn.Client, - AccessPoint: accessPoint, - Authorizer: authorizer, - Tunnel: tsrv, - TLSConfig: tlsConfig, - Limiter: connLimiter, - IngressReporter: ingressReporter, - ConnectionMonitor: connMonitor, + AuthClient: conn.Client, + AccessPoint: accessPoint, + Authorizer: authorizer, + Tunnel: tsrv, + TLSConfig: tlsConfig, + Limiter: connLimiter, + IngressReporter: ingressReporter, + ConnectionMonitor: connMonitor, + MySQLServerVersion: process.Config.Proxy.MySQLServerVersion, }) if err != nil { return trace.Wrap(err) diff --git a/lib/service/servicecfg/proxy.go b/lib/service/servicecfg/proxy.go index 4ac8e22e969ff..ba38a3607a66f 100644 --- a/lib/service/servicecfg/proxy.go +++ b/lib/service/servicecfg/proxy.go @@ -64,6 +64,9 @@ type ProxyConfig struct { // MySQLAddr is address of MySQL proxy. MySQLAddr utils.NetAddr + // MySQLServerVersion allows to override the default MySQL Engine Version propagated by Teleport Proxy. + MySQLServerVersion string + // PostgresAddr is address of Postgres proxy. PostgresAddr utils.NetAddr diff --git a/lib/srv/db/mysql/proxy.go b/lib/srv/db/mysql/proxy.go index 3c4c540214274..29340ffd014b7 100644 --- a/lib/srv/db/mysql/proxy.go +++ b/lib/srv/db/mysql/proxy.go @@ -55,6 +55,9 @@ type Proxy struct { Limiter *limiter.Limiter // IngressReporter reports new and active connections. IngressReporter *ingress.Reporter + // ServerVersion allows to overwrite the default Proxy MySQL Engine Version. Note that for TLS Routing connection + // the dynamic service version propagation by ALPN extension will take precedes over Proxy ServerVersion. + ServerVersion string } // HandleConnection accepts connection from a MySQL client, authenticates @@ -69,7 +72,7 @@ func (p *Proxy) HandleConnection(ctx context.Context, clientConn net.Conn) (err // by peeking into the first few bytes. This is needed to be able to detect // proxy protocol which otherwise would interfere with MySQL protocol. conn := multiplexer.NewConn(clientConn) - mysqlServerVersion := getServerVersionFromCtx(ctx) + mysqlServerVersion := getServerVersionFromCtx(ctx, p.ServerVersion) mysqlServer := p.makeServer(conn, mysqlServerVersion) // If any error happens, make sure to send it back to the client, so it @@ -140,9 +143,12 @@ func (p *Proxy) HandleConnection(ctx context.Context, clientConn net.Conn) (err // getServerVersionFromCtx tries to extract MySQL server version from the passed context. // The default version is returned if context doesn't have it. -func getServerVersionFromCtx(ctx context.Context) string { - // Set default server version. - mysqlServerVersion := serverVersion +func getServerVersionFromCtx(ctx context.Context, configEngineVersion string) string { + // Set default server version or use the Proxy MySQL Engine Version if it was provided. + mysqlServerVersion := DefaultServerVersion + if configEngineVersion != "" { + mysqlServerVersion = configEngineVersion + } if mysqlVerCtx := ctx.Value(dbutils.ContextMySQLServerVersion); mysqlVerCtx != nil { version, ok := mysqlVerCtx.(string) @@ -275,9 +281,9 @@ func (p *Proxy) waitForOK(server *server.Conn, serviceConn net.Conn) error { } const ( - // serverVersion is advertised to MySQL clients during handshake. + // DefaultServerVersion is advertised to MySQL clients during handshake. // // Some clients may refuse to work with older servers (e.g. MySQL // Workbench requires > 5.5). - serverVersion = "8.0.0-Teleport" + DefaultServerVersion = "8.0.0-Teleport" ) diff --git a/lib/srv/db/proxyserver.go b/lib/srv/db/proxyserver.go index 113f5322e2a4f..40dd90c614f8c 100644 --- a/lib/srv/db/proxyserver.go +++ b/lib/srv/db/proxyserver.go @@ -93,6 +93,8 @@ type ProxyServerConfig struct { // ConnectionMonitor monitors and closes connections if session controls // prevent the connections. ConnectionMonitor ConnMonitor + // MySQLServerVersion allows to override the default MySQL Engine Version propagated by Teleport Proxy. + MySQLServerVersion string } // ShuffleFunc defines a function that shuffles a list of database servers. @@ -402,6 +404,7 @@ func (s *ProxyServer) MySQLProxy() *mysql.Proxy { Limiter: s.cfg.Limiter, Log: s.log, IngressReporter: s.cfg.IngressReporter, + ServerVersion: s.cfg.MySQLServerVersion, } }