From 1450f53b7fe15aa06a9a53b99f25d1ace6faab3b Mon Sep 17 00:00:00 2001 From: Jakub Nyckowski Date: Thu, 3 Mar 2022 22:55:29 -0500 Subject: [PATCH 1/4] Add client certificate to DB insecure mode. --- lib/srv/db/common/auth.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/srv/db/common/auth.go b/lib/srv/db/common/auth.go index 445e3d59c2500..495cdd6fcebac 100644 --- a/lib/srv/db/common/auth.go +++ b/lib/srv/db/common/auth.go @@ -287,7 +287,7 @@ func (a *dbAuth) GetAzureAccessToken(ctx context.Context, sessionCtx *Session) ( // GetTLSConfig builds the client TLS configuration for the session. // // For RDS/Aurora, the config must contain RDS root certificate as a trusted -// authority. For onprem we generate a client certificate signed by the host +// authority. For on-prem we generate a client certificate signed by the host // CA used to authenticate. func (a *dbAuth) GetTLSConfig(ctx context.Context, sessionCtx *Session) (*tls.Config, error) { dbTLSConfig := sessionCtx.Database.GetTLS() @@ -295,7 +295,7 @@ func (a *dbAuth) GetTLSConfig(ctx context.Context, sessionCtx *Session) (*tls.Co // Mode won't be set for older clients. We will default to VerifyFull then - the same as before. switch dbTLSConfig.Mode { case types.DatabaseTLSMode_INSECURE: - return getTLSConfigInsecure(), nil + return a.getTLSConfigInsecure(ctx, sessionCtx) case types.DatabaseTLSMode_VERIFY_CA: return a.getTLSConfigVerifyCA(ctx, sessionCtx) default: @@ -381,7 +381,7 @@ func (a *dbAuth) getTLSConfigVerifyFull(ctx context.Context, sessionCtx *Session // getTLSConfigInsecure generates tls.Config when TLS mode is equal to 'insecure'. // Generated configuration will accept any certificate provided by database. -func getTLSConfigInsecure() *tls.Config { +func (a *dbAuth) getTLSConfigInsecure(ctx context.Context, sessionCtx *Session) (*tls.Config, error) { tlsConfig := &tls.Config{ RootCAs: x509.NewCertPool(), } @@ -389,7 +389,7 @@ func getTLSConfigInsecure() *tls.Config { // Accept any certificate provided by database. tlsConfig.InsecureSkipVerify = true - return tlsConfig + return a.appendClientCert(ctx, sessionCtx, tlsConfig) } // getTLSConfigVerifyCA generates tls.Config when TLS mode is equal to 'verify-ca'. From 52f910f6c91aa8a7f850bf3666bfcc51044fbb20 Mon Sep 17 00:00:00 2001 From: Jakub Nyckowski Date: Fri, 4 Mar 2022 01:40:14 -0500 Subject: [PATCH 2/4] Tweak insecure certificate validation. --- lib/srv/db/common/auth.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/srv/db/common/auth.go b/lib/srv/db/common/auth.go index 495cdd6fcebac..db4c3e272ee05 100644 --- a/lib/srv/db/common/auth.go +++ b/lib/srv/db/common/auth.go @@ -382,12 +382,15 @@ func (a *dbAuth) getTLSConfigVerifyFull(ctx context.Context, sessionCtx *Session // getTLSConfigInsecure generates tls.Config when TLS mode is equal to 'insecure'. // Generated configuration will accept any certificate provided by database. func (a *dbAuth) getTLSConfigInsecure(ctx context.Context, sessionCtx *Session) (*tls.Config, error) { - tlsConfig := &tls.Config{ - RootCAs: x509.NewCertPool(), + tlsConfig, err := a.getTLSConfigVerifyFull(ctx, sessionCtx) + if err != nil { + return nil, trace.Wrap(err) } // Accept any certificate provided by database. tlsConfig.InsecureSkipVerify = true + // Remove certificate validation if set. + tlsConfig.VerifyConnection = nil return a.appendClientCert(ctx, sessionCtx, tlsConfig) } From 10eef5073c91127376a34625d60986a9f444994f Mon Sep 17 00:00:00 2001 From: Jakub Nyckowski Date: Mon, 7 Mar 2022 01:49:39 -0500 Subject: [PATCH 3/4] Force client certificate validation in DB tests. --- lib/srv/db/access_test.go | 4 ++++ lib/srv/db/common/test.go | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/srv/db/access_test.go b/lib/srv/db/access_test.go index d7f0884f2ee2c..45ce04b786ba6 100644 --- a/lib/srv/db/access_test.go +++ b/lib/srv/db/access_test.go @@ -1807,6 +1807,7 @@ func withSelfHostedPostgres(name string) withDatabaseOption { postgresServer, err := postgres.NewTestServer(common.TestServerConfig{ Name: name, AuthClient: testCtx.authClient, + ClientAuth: tls.RequireAndVerifyClientCert, }) require.NoError(t, err) go postgresServer.Serve() @@ -1961,6 +1962,7 @@ func withSelfHostedMySQL(name string) withDatabaseOption { mysqlServer, err := mysql.NewTestServer(common.TestServerConfig{ Name: name, AuthClient: testCtx.authClient, + ClientAuth: tls.RequireAndVerifyClientCert, }) require.NoError(t, err) go mysqlServer.Serve() @@ -2128,6 +2130,7 @@ func withSelfHostedMongo(name string, opts ...mongodb.TestServerOption) withData mongoServer, err := mongodb.NewTestServer(common.TestServerConfig{ Name: name, AuthClient: testCtx.authClient, + ClientAuth: tls.RequireAndVerifyClientCert, }, opts...) require.NoError(t, err) go mongoServer.Serve() @@ -2153,6 +2156,7 @@ func withSelfHostedRedis(name string, opts ...redis.TestServerOption) withDataba redisServer, err := redis.NewTestServer(t, common.TestServerConfig{ Name: name, AuthClient: testCtx.authClient, + ClientAuth: tls.RequireAndVerifyClientCert, }, opts...) require.NoError(t, err) diff --git a/lib/srv/db/common/test.go b/lib/srv/db/common/test.go index 26568f9cb83d9..c3547e4593b59 100644 --- a/lib/srv/db/common/test.go +++ b/lib/srv/db/common/test.go @@ -46,7 +46,7 @@ type TestServerConfig struct { AuthUser string // AuthToken is used in tests simulating IAM token authentication. AuthToken string - // CN allows to set specific CommonName in the database server certificate. + // CN allows setting specific CommonName in the database server certificate. // // Used when simulating test Cloud SQL database which should contains // : in its certificate. @@ -54,6 +54,9 @@ type TestServerConfig struct { // ListenTLS creates a TLS listener when true instead of using a net listener. // This is used to simulate MySQL connections through the GCP Cloud SQL Proxy. ListenTLS bool + // ClientAuth sets tls.ClientAuth in server's tls.Config. It can be used to force client + // certificate validation in tests. + ClientAuth tls.ClientAuthType } // MakeTestServerTLSConfig returns TLS config suitable for configuring test @@ -94,6 +97,7 @@ func MakeTestServerTLSConfig(config TestServerConfig) (*tls.Config, error) { } return &tls.Config{ ClientCAs: pool, + ClientAuth: config.ClientAuth, Certificates: []tls.Certificate{cert}, }, nil } From 6fbbfaa9af7c73a48bf08d9da16d58da25cdba43 Mon Sep 17 00:00:00 2001 From: Jakub Nyckowski Date: Mon, 4 Apr 2022 15:57:45 -0400 Subject: [PATCH 4/4] Remove extra call to appendClientCert() in insecure mode. --- lib/srv/db/common/auth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/srv/db/common/auth.go b/lib/srv/db/common/auth.go index db4c3e272ee05..f49c0e5357792 100644 --- a/lib/srv/db/common/auth.go +++ b/lib/srv/db/common/auth.go @@ -392,7 +392,7 @@ func (a *dbAuth) getTLSConfigInsecure(ctx context.Context, sessionCtx *Session) // Remove certificate validation if set. tlsConfig.VerifyConnection = nil - return a.appendClientCert(ctx, sessionCtx, tlsConfig) + return tlsConfig, nil } // getTLSConfigVerifyCA generates tls.Config when TLS mode is equal to 'verify-ca'.