From 5c4bed4c83367021464d310d58ddd2632642c43c Mon Sep 17 00:00:00 2001 From: Jakub Nyckowski Date: Tue, 5 Apr 2022 20:28:19 -0400 Subject: [PATCH] Add client cert in insecure mode (#10899) Add client certificate to DB insecure mode. --- lib/srv/db/access_test.go | 3 +++ lib/srv/db/common/auth.go | 15 +++++++++------ lib/srv/db/common/test.go | 6 +++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/srv/db/access_test.go b/lib/srv/db/access_test.go index ec863b71e7a98..392113d2c1444 100644 --- a/lib/srv/db/access_test.go +++ b/lib/srv/db/access_test.go @@ -1185,6 +1185,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() @@ -1339,6 +1340,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() @@ -1506,6 +1508,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() diff --git a/lib/srv/db/common/auth.go b/lib/srv/db/common/auth.go index 9828762d5951c..4b515f14454a3 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: @@ -378,15 +378,18 @@ 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 { - tlsConfig := &tls.Config{ - RootCAs: x509.NewCertPool(), +func (a *dbAuth) getTLSConfigInsecure(ctx context.Context, sessionCtx *Session) (*tls.Config, error) { + 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 tlsConfig + return tlsConfig, nil } // getTLSConfigVerifyCA generates tls.Config when TLS mode is equal to 'verify-ca'. diff --git a/lib/srv/db/common/test.go b/lib/srv/db/common/test.go index 4acc74c338272..c51429d05320c 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 }