Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate TLS config for AcraConnector and DB #419

Merged
merged 12 commits into from Sep 28, 2020
12 changes: 9 additions & 3 deletions decryptor/base/proxy.go
Expand Up @@ -30,7 +30,8 @@ import (
type ProxySetting interface {
KeyStore() keystore.DecryptionKeyStore
TableSchemaStore() config.TableSchemaStore
TLSConfig() *tls.Config
ClientTLSConfig() *tls.Config
DatabaseTLSConfig() *tls.Config
Censor() acracensor.AcraCensorInterface
DecryptorFactory() DecryptorFactory
}
Expand All @@ -53,8 +54,13 @@ func (p *proxySetting) Censor() acracensor.AcraCensorInterface {
return p.censor
}

// TLSConfig return tls.Config
func (p *proxySetting) TLSConfig() *tls.Config {
// ClientTLSConfig return tls.Config to use for database connection, if any.
func (p *proxySetting) ClientTLSConfig() *tls.Config {
return p.tlsConfig
}

// DatabaseTLSConfig return tls.Config to use for database connection, if any.
ilammy marked this conversation as resolved.
Show resolved Hide resolved
func (p *proxySetting) DatabaseTLSConfig() *tls.Config {
return p.tlsConfig
}

Expand Down
27 changes: 16 additions & 11 deletions decryptor/mysql/response_proxy.go
Expand Up @@ -151,7 +151,8 @@ type Handler struct {
dbTLSHandshakeFinished chan bool
clientConnection net.Conn
dbConnection net.Conn
tlsConfig *tls.Config
clientTLSConfig *tls.Config
dbTLSConfig *tls.Config
logger *logrus.Entry
ctx context.Context
queryObserverManager base.QueryObserverManager
Expand All @@ -160,12 +161,6 @@ type Handler struct {

// NewMysqlProxy returns new Handler
func NewMysqlProxy(ctx context.Context, decryptor base.Decryptor, dbConnection, clientConnection net.Conn, setting base.ProxySetting) (*Handler, error) {
tlsConfig := setting.TLSConfig()
if tlsConfig != nil {
// use less secure protocol versions because some drivers and db images doesn't support secure and modern options
tlsConfig = tlsConfig.Clone()
network.SetMySQLCompatibleTLSSettings(tlsConfig)
}
observerManager, err := base.NewArrayQueryObserverableManager(ctx)
if err != nil {
return nil, err
Expand All @@ -179,14 +174,24 @@ func NewMysqlProxy(ctx context.Context, decryptor base.Decryptor, dbConnection,
acracensor: setting.Censor(),
clientConnection: clientConnection,
dbConnection: dbConnection,
tlsConfig: tlsConfig,
clientTLSConfig: tweakTLSConfigForMySQL(setting.ClientTLSConfig()),
dbTLSConfig: tweakTLSConfigForMySQL(setting.DatabaseTLSConfig()),
ctx: ctx,
logger: logging.GetLoggerFromContext(ctx),
queryObserverManager: observerManager,
decryptionObserver: base.NewColumnDecryptionObserver(),
}, nil
}

func tweakTLSConfigForMySQL(config *tls.Config) *tls.Config {
vixentael marked this conversation as resolved.
Show resolved Hide resolved
if config != nil {
// use less secure protocol versions because some drivers and db images doesn't support secure and modern options
config = config.Clone()
network.SetMySQLCompatibleTLSSettings(config)
}
return config
}

// SubscribeOnColumnDecryption subscribes for OnColumn notifications about the column, indexed from left to right starting with zero.
func (handler *Handler) SubscribeOnColumnDecryption(i int, subscriber base.DecryptionSubscriber) {
handler.decryptionObserver.SubscribeOnColumnDecryption(i, subscriber)
Expand Down Expand Up @@ -273,7 +278,7 @@ func (handler *Handler) ProxyClientConnection(errCh chan<- error) {
handler.clientDeprecateEOF = packet.IsClientDeprecateEOF()
clientLog = clientLog.WithField("deprecate_eof", handler.clientDeprecateEOF)
if packet.IsSSLRequest() {
if handler.tlsConfig == nil {
if handler.clientTLSConfig == nil {
handler.logger.WithField(logging.FieldKeyEventCode, logging.EventCodeErrorDecryptorCantInitializeTLS).Errorln("To support TLS connections you must pass TLS key and certificate for AcraServer that will be used " +
"for connections AcraServer->Database and CA certificate which will be used to verify certificate " +
"from database")
Expand All @@ -287,7 +292,7 @@ func (handler *Handler) ProxyClientConnection(errCh chan<- error) {
errCh <- network.ErrEmptyTLSConfig
return
}
tlsConnection := tls.Server(handler.clientConnection, handler.tlsConfig)
tlsConnection := tls.Server(handler.clientConnection, handler.clientTLSConfig)
if err := tlsConnection.Handshake(); err != nil {
handler.logger.WithError(err).WithField(logging.FieldKeyEventCode, logging.EventCodeErrorDecryptorCantInitializeTLS).
Errorln("Error in tls handshake with client")
Expand Down Expand Up @@ -871,7 +876,7 @@ func (handler *Handler) ProxyDatabaseConnection(errCh chan<- error) {
if netErr.Timeout() && handler.isTLSHandshake {
// reset deadline
handler.dbConnection.SetReadDeadline(time.Time{})
tlsConnection := tls.Client(handler.dbConnection, handler.tlsConfig)
tlsConnection := tls.Client(handler.dbConnection, handler.dbTLSConfig)
if err = tlsConnection.Handshake(); err != nil {
handler.logger.WithError(err).WithField(logging.FieldKeyEventCode, logging.EventCodeErrorDecryptorCantInitializeTLS).
Errorln("Error in tls handshake with db")
Expand Down
16 changes: 9 additions & 7 deletions decryptor/postgresql/pg_decryptor.go
Expand Up @@ -93,7 +93,8 @@ type PgProxy struct {
TLSCh chan bool
ctx context.Context
queryObserverManager base.QueryObserverManager
tlsConfig *tls.Config
clientTLSConfig *tls.Config
dbTLSConfig *tls.Config
censor acracensor.AcraCensorInterface
decryptor base.Decryptor
tlsSwitch bool
Expand All @@ -112,7 +113,8 @@ func NewPgProxy(ctx context.Context, decryptor base.Decryptor, dbConnection, cli
TLSCh: make(chan bool),
ctx: ctx,
queryObserverManager: observerManager,
tlsConfig: setting.TLSConfig(),
clientTLSConfig: setting.ClientTLSConfig(),
dbTLSConfig: setting.DatabaseTLSConfig(),
censor: setting.Censor(),
decryptor: decryptor,
decryptionObserver: base.NewColumnDecryptionObserver(),
Expand Down Expand Up @@ -346,9 +348,9 @@ func checkWholePoisonRecord(block []byte, decryptor base.Decryptor, logger *log.
}

// handleSSLRequest return wrapped with tls (client's, db's connections, nil) or (nil, nil, error)
func (proxy *PgProxy) handleSSLRequest(packet *PacketHandler, tlsConfig *tls.Config, logger *log.Entry) (net.Conn, net.Conn, error) {
func (proxy *PgProxy) handleSSLRequest(packet *PacketHandler, logger *log.Entry) (net.Conn, net.Conn, error) {
// if server allow SSLRequest than we wrap our connections with tls
if tlsConfig == nil {
if proxy.dbTLSConfig == nil {
logger.WithField(logging.FieldKeyEventCode, logging.EventCodeErrorDecryptorCantInitializeTLS).Errorln("To support TLS connections you must pass TLS key and certificate for AcraServer that will be used " +
"for connections AcraServer->Database and CA certificate which will be used to verify certificate " +
"from database")
Expand Down Expand Up @@ -378,7 +380,7 @@ func (proxy *PgProxy) handleSSLRequest(packet *PacketHandler, tlsConfig *tls.Con
}
logger.Debugln("Init tls with client")
// convert to tls connection
tlsClientConnection := tls.Server(proxy.clientConnection, tlsConfig)
tlsClientConnection := tls.Server(proxy.clientConnection, proxy.clientTLSConfig)

// send server's response only after successful interrupting background goroutine that process client's connection
// to take control over connection and avoid two places that communicate with one connection
Expand All @@ -394,7 +396,7 @@ func (proxy *PgProxy) handleSSLRequest(packet *PacketHandler, tlsConfig *tls.Con
}

logger.Debugln("Init tls with db")
dbTLSConnection := tls.Client(proxy.dbConnection, tlsConfig)
dbTLSConnection := tls.Client(proxy.dbConnection, proxy.dbTLSConfig)
if err := dbTLSConnection.Handshake(); err != nil {
logger.WithError(err).WithField(logging.FieldKeyEventCode, logging.EventCodeErrorDecryptorCantInitializeTLS).
Errorln("Can't initialize tls connection with db")
Expand Down Expand Up @@ -467,7 +469,7 @@ func (proxy *PgProxy) ProxyDatabaseConnection(errCh chan<- error) {
//firstByte = true
continue
} else if packetHandler.IsSSLRequestAllowed() {
tlsClientConnection, dbTLSConnection, err := proxy.handleSSLRequest(packetHandler, proxy.tlsConfig, logger)
tlsClientConnection, dbTLSConnection, err := proxy.handleSSLRequest(packetHandler, logger)
if err != nil {
logger.WithField(logging.FieldKeyEventCode, logging.EventCodeErrorDecryptorCantInitializeTLS).WithError(err).Errorln("Can't process SSL request")
errCh <- err
Expand Down