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

Add support for TLS with MySQL #325

Merged
merged 6 commits into from
Feb 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions deploy/kubernetes/console/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ spec:
value: {{ default "3306" .Values.mariadb.port | quote }}
- name: DATABASE_PROVIDER
value: {{ default "mysql" .Values.mariadb.type | quote }}
- name: DB_SSL_MODE
value: {{ default "false" .Values.mariadb.tls | quote }}
- name: HTTP_CONNECTION_TIMEOUT_IN_SECS
value: "10"
- name: HTTP_CLIENT_TIMEOUT_IN_SECS
Expand Down
5 changes: 2 additions & 3 deletions deploy/kubernetes/console/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,12 @@ mariadb:
userPassword:
# Leave password blank to auto-generate (not needed for external database)
rootPassword:

# DB Host (when using an external database)
host:

# Override port (default 3306) (when using an external database)
port:

# TLS Mode - can be true, false, skip-verify or preferred
tls:
# Override DB type - default is mysql
type:

Expand Down
62 changes: 7 additions & 55 deletions src/jetstream/datastore/20190522121200_LocalUsers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import (
"bitbucket.org/liamstask/goose/lib/goose"
)

// NOTE: This migration script has been modified
// We originally had a triiger, which is removed in a later migration script
// This requires a certain level of privilege to create, so it has been removed in this scipt for new installs.
// Upgrades will still remove the trigger if it exists

func init() {
RegisterMigration(20190522121200, "LocalUsers", func(txn *sql.Tx, conf *goose.DBConf) error {
binaryDataType := "BYTEA"
Expand All @@ -31,34 +36,10 @@ func init() {
createLocalUsers += "last_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
createLocalUsers += "PRIMARY KEY (user_guid) )"

//Trigger to update last_updated timestamp
createUpdateModifiedTrigger := "CREATE TRIGGER update_last_updated "
createUpdateModifiedTrigger += "AFTER UPDATE ON local_users "
createUpdateModifiedTrigger += "BEGIN UPDATE local_users SET last_updated = DATETIME('now') WHERE _rowid_ = new._rowid_; "
createUpdateModifiedTrigger += "END;"

//Configure Postgres migration options
//Configure Postgres migration options
if strings.Contains(conf.Driver.Name, "postgres") {
createLocalUsers += " WITH (OIDS=FALSE);"

//Postgres requires a trigger function
//Create trigger function and generate trigger statement
postgresTrigger, err := setupPostgresTrigger(txn)
if err != nil {
return err
}
createUpdateModifiedTrigger = postgresTrigger

} else if strings.Contains(conf.Driver.Name, "mysql") {
// MySQL
createUpdateModifiedTrigger = "CREATE TRIGGER update_last_updated "
createUpdateModifiedTrigger += "AFTER UPDATE ON local_users "
createUpdateModifiedTrigger += "FOR EACH ROW BEGIN "
createUpdateModifiedTrigger += "UPDATE local_users SET last_updated = NOW() WHERE user_guid = NEW.user_guid; "
createUpdateModifiedTrigger += "END;"

createLocalUsers += ";"
} else {
} else {
createLocalUsers += ";"
}

Expand All @@ -67,11 +48,6 @@ func init() {
return err
}

_, err = txn.Exec(createUpdateModifiedTrigger)
if err != nil {
return err
}

createIndex := "CREATE INDEX local_users_user_guid ON local_users (user_guid);"
_, err = txn.Exec(createIndex)
if err != nil {
Expand All @@ -86,27 +62,3 @@ func init() {
return nil
})
}

func setupPostgresTrigger(txn *sql.Tx) (string, error) {

createPostgresUpdateModifiedTrigger := "CREATE TRIGGER update_trigger "
createPostgresUpdateModifiedTrigger += "AFTER UPDATE ON local_users FOR EACH ROW "
createPostgresUpdateModifiedTrigger += "EXECUTE PROCEDURE update_last_modified_time(); "

postgresTriggerFunction := "CREATE OR REPLACE FUNCTION update_last_modified_time() "
postgresTriggerFunction += "RETURNS trigger AS "
postgresTriggerFunction += "$BODY$ "
postgresTriggerFunction += "BEGIN "
postgresTriggerFunction += "UPDATE local_users "
postgresTriggerFunction += "SET last_updated = CURRENT_TIMESTAMP WHERE new.user_guid = old.user_guid; "
postgresTriggerFunction += "RETURN NEW; END; $BODY$ "
postgresTriggerFunction += "LANGUAGE plpgsql VOLATILE COST 100;"

_, err := txn.Exec(postgresTriggerFunction)
if err != nil {
return "", err
}

return createPostgresUpdateModifiedTrigger, err
}

Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ func init() {

if strings.Contains(conf.Driver.Name, "sqlite") {
//SQLITE
dropTrigger = "DROP TRIGGER update_last_updated;"
dropTrigger = "DROP TRIGGER IF EXISTS update_last_updated;"
}
if strings.Contains(conf.Driver.Name, "postgres") {
// POSTGRESQL
dropTrigger = "DROP TRIGGER update_trigger ON local_users;"
dropTrigger = "DROP TRIGGER IF EXISTS update_trigger ON local_users;"
} else if strings.Contains(conf.Driver.Name, "mysql") {
// MYSQL
dropTrigger = "DROP TRIGGER update_last_updated;"
dropTrigger = "DROP TRIGGER IF EXISTS update_last_updated;"
// Ignore error - most likely permission bug issue on Mysql
txn.Exec(dropTrigger)
return nil
}

if len(dropTrigger) > 0 {
Expand Down
30 changes: 16 additions & 14 deletions src/jetstream/datastore/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type DatabaseConfig struct {
type SSLValidationMode string

const (
// PGSQL SSL Modes
// SSLDisabled means no checking of SSL
SSLDisabled SSLValidationMode = "disable"
// SSLRequired requires SSL without validation
Expand Down Expand Up @@ -105,12 +106,15 @@ func NewDatabaseConnectionParametersFromConfig(dc DatabaseConfig) (DatabaseConfi
if dc.SSLMode == string(SSLDisabled) || dc.SSLMode == string(SSLRequired) ||
dc.SSLMode == string(SSLVerifyCA) || dc.SSLMode == string(SSLVerifyFull) {
return dc, nil
} else {
// Invalid SSL mode
return dc, fmt.Errorf("Invalid SSL mode: %s", dc.SSLMode)
}
// Invalid SSL mode
return dc, fmt.Errorf("Invalid SSL mode: %s", dc.SSLMode)
} else if dc.DatabaseProvider == MYSQL {
return dc, nil
if dc.SSLMode == "true" || dc.SSLMode == "false" || dc.SSLMode == "skip-verify" || dc.SSLMode == "preferred" {
return dc, nil
}
// Invalid SSL mode
return dc, fmt.Errorf("Invalid SSL mode: %s", dc.SSLMode)
}
return dc, fmt.Errorf("Invalid provider %v", dc)
}
Expand Down Expand Up @@ -268,25 +272,23 @@ func buildConnectionString(dc DatabaseConfig) string {
}

func buildConnectionStringForMysql(dc DatabaseConfig) string {
log.Debug("buildConnectionString")
log.Debug("buildConnectionStringForMysql")
escapeStr := func(in string) string {
return strings.Replace(in, `'`, `\'`, -1)
}

connStr := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?parseTime=true",
connStr := fmt.Sprintf("%s:%%s@tcp(%s:%d)/%s?parseTime=true",
escapeStr(dc.Username),
escapeStr(dc.Password),
dc.Host,
dc.Port,
escapeStr(dc.Database))

log.Printf("DB Connection string: %s:*********@tcp(%s:%d)/%s?parseTime=true",
escapeStr(dc.Username),
dc.Host,
dc.Port,
escapeStr(dc.Database))

return connStr
if len(dc.SSLMode) > 0 {
log.Infof("Setting SSL Mode for mysql: %s", dc.SSLMode)
connStr = fmt.Sprintf("%s&tls=%s", connStr, dc.SSLMode)
}
log.Infof(connStr, "*********")
return fmt.Sprintf(connStr, escapeStr(dc.Password))
}

// Ping - ping the database to ensure the connection/pool works.
Expand Down
2 changes: 1 addition & 1 deletion src/jetstream/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ require (
github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76 // indirect
github.com/elazarl/goproxy/ext v0.0.0-20191011121108-aa519ddbe484 // indirect
github.com/fatih/color v1.7.0 // indirect
github.com/go-sql-driver/mysql v1.4.1
github.com/go-sql-driver/mysql v1.5.0
github.com/google/go-querystring v1.0.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e // indirect
github.com/gorilla/context v1.1.1
Expand Down
2 changes: 2 additions & 0 deletions src/jetstream/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
Expand Down
2 changes: 1 addition & 1 deletion src/jetstream/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func TestLoadDatabaseConfig(t *testing.T) {
"DB_HOST": "localhost",
"DB_PORT": "5432",
"DB_CONNECT_TIMEOUT_IN_SECS": "5",
"DB_SSL_MODE": "disable",
"DB_SSL_MODE": "false",
})))

if err != nil {
Expand Down