diff --git a/physical/mysql/mysql.go b/physical/mysql/mysql.go index 310f52a098..fce3f02648 100644 --- a/physical/mysql/mysql.go +++ b/physical/mysql/mysql.go @@ -251,14 +251,18 @@ func NewMySQLClient(conf map[string]string, logger log.Logger) (*sql.DB, error) } dsnParams := url.Values{} - tlsCaFile, ok := conf["tls_ca_file"] - if ok { + tlsCaFile, tlsOk := conf["tls_ca_file"] + if tlsOk { if err := setupMySQLTLSConfig(tlsCaFile); err != nil { return nil, errwrap.Wrapf("failed register TLS config: {{err}}", err) } dsnParams.Add("tls", mysqlTLSKey) } + ptAllowed, ptOk := conf["plaintext_connection_allowed"] + if !(ptOk && strings.ToLower(ptAllowed) == "true") && !tlsOk { + logger.Warn("No TLS specified, credentials will be sent in plaintext. To mute this warning add 'plaintext_connection_allowed' with a true value to your MySQL configuration in your config file.") + } // Create MySQL handle for the database. dsn := username + ":" + password + "@tcp(" + address + ")/?" + dsnParams.Encode() diff --git a/physical/mysql/mysql_test.go b/physical/mysql/mysql_test.go index 9ca8a8c57c..51222639a2 100644 --- a/physical/mysql/mysql_test.go +++ b/physical/mysql/mysql_test.go @@ -1,7 +1,9 @@ package mysql import ( + "bytes" "os" + "strings" "testing" "time" @@ -15,6 +17,48 @@ import ( mysqlhelper "github.com/hashicorp/vault/helper/testhelpers/mysql" ) +func TestMySQLPlaintextCatch(t *testing.T) { + address := os.Getenv("MYSQL_ADDR") + if address == "" { + t.SkipNow() + } + + database := os.Getenv("MYSQL_DB") + if database == "" { + database = "test" + } + + table := os.Getenv("MYSQL_TABLE") + if table == "" { + table = "test" + } + + username := os.Getenv("MYSQL_USERNAME") + password := os.Getenv("MYSQL_PASSWORD") + + // Run vault tests + var buf bytes.Buffer + log.DefaultOutput = &buf + + logger := logging.NewVaultLogger(log.Debug) + + NewMySQLBackend(map[string]string{ + "address": address, + "database": database, + "table": table, + "username": username, + "password": password, + "plaintext_connection_allowed": "false", + }, logger) + + str := buf.String() + dataIdx := strings.IndexByte(str, ' ') + rest := str[dataIdx+1:] + + if !strings.Contains(rest, "credentials will be sent in plaintext") { + t.Fatalf("No warning of plaintext credentials occurred") + } +} func TestMySQLBackend(t *testing.T) { address := os.Getenv("MYSQL_ADDR") if address == "" { @@ -43,6 +87,7 @@ func TestMySQLBackend(t *testing.T) { "table": table, "username": username, "password": password, + "plaintext_connection_allowed": "true", }, logger) if err != nil { @@ -89,6 +134,7 @@ func TestMySQLHABackend(t *testing.T) { "username": username, "password": password, "ha_enabled": "true", + "plaintext_connection_allowed": "true", } b, err := NewMySQLBackend(config, logger) @@ -136,6 +182,7 @@ func TestMySQLHABackend_LockFailPanic(t *testing.T) { "username": cfg.User, "password": cfg.Passwd, "ha_enabled": "true", + "plaintext_connection_allowed": "true", } b, err := NewMySQLBackend(config, logger) diff --git a/website/pages/docs/configuration/storage/mysql.mdx b/website/pages/docs/configuration/storage/mysql.mdx index 563f4c4550..47a1bf60e0 100644 --- a/website/pages/docs/configuration/storage/mysql.mdx +++ b/website/pages/docs/configuration/storage/mysql.mdx @@ -45,6 +45,13 @@ storage "mysql" { - `tls_ca_file` `(string: "")` – Specifies the path to the CA certificate to connect using TLS. +- `plaintext_credentials_transmission` `(string: "")` - Provides authorization + to send credentials over plaintext. Failure to provide a value AND a failure + to provide a TLS CA certificate will warn that the credentials are being sent + over plain text. In the future, failure to do acknowledge or use TLS will + result in server start being prevented. This will be done to ensure credentials + are not leaked accidentally. + - `max_parallel` `(string: "128")` – Specifies the maximum number of concurrent requests to MySQL.