From 8b00134036802a759fdf0a1be0fcf421da1b2126 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 | 4 ++++ lib/srv/db/common/auth.go | 15 +++++++++------ lib/srv/db/common/test.go | 6 +++++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/srv/db/access_test.go b/lib/srv/db/access_test.go index f94c0e10673..c7090120966 100644 --- a/lib/srv/db/access_test.go +++ b/lib/srv/db/access_test.go @@ -1809,6 +1809,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() @@ -1963,6 +1964,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() @@ -2130,6 +2132,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() @@ -2155,6 +2158,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/auth.go b/lib/srv/db/common/auth.go index 445e3d59c25..f49c0e53577 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,15 +381,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 2d047d0818f..a4e0f4bb963 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 }