diff --git a/go.mod b/go.mod index bd2033e..7a00002 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/godaddy/asherah/go/appencryption v0.3.0 github.com/godaddy/asherah/go/securememory v0.1.4 github.com/godaddy/cobhan-go v0.4.2 + github.com/lib/pq v1.10.9 ) require ( diff --git a/go.sum b/go.sum index d1fdbfb..3e1c504 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/internal/asherah/asherah.go b/internal/asherah/asherah.go index 4c531cb..f1fcecd 100644 --- a/internal/asherah/asherah.go +++ b/internal/asherah/asherah.go @@ -111,8 +111,13 @@ func Decrypt(partitionId string, drr *appencryption.DataRowRecord) ([]byte, erro func NewMetastore(opts *Options) appencryption.Metastore { switch opts.Metastore { case "rdbms": - // TODO: support other databases - db, err := newMysql(opts.ConnectionString) + var dbType string + if len(opts.SQLMetastoreDBType) > 1 { + dbType = opts.SQLMetastoreDBType + } else { + dbType = "mysql" + } + db, err := newConnection(dbType, opts.ConnectionString) if err != nil { log.ErrorLogf("PANIC: Failed to connect to database: %v", err.Error()) panic(err) @@ -127,7 +132,7 @@ func NewMetastore(opts *Options) appencryption.Metastore { } } - return persistence.NewSQLMetastore(db) + return persistence.NewSQLMetastore(db, persistence.WithSQLMetastoreDBType(persistence.SQLMetastoreDBType(dbType))) case "dynamodb": awsOpts := awssession.Options{ SharedConfigState: awssession.SharedConfigEnable, diff --git a/internal/asherah/database.go b/internal/asherah/database.go index e4bf92f..e258efc 100644 --- a/internal/asherah/database.go +++ b/internal/asherah/database.go @@ -3,7 +3,8 @@ package asherah import ( "database/sql" - "github.com/go-sql-driver/mysql" + _ "github.com/go-sql-driver/mysql" + _ "github.com/lib/pq" ) const ( @@ -15,19 +16,12 @@ const ( var ( dbconnection *sql.DB - dbdriver = "mysql" ) -func newMysql(connStr string) (*sql.DB, error) { +func newConnection(dbdriver string, connStr string) (*sql.DB, error) { + var err error if dbconnection == nil { - dsn, err := mysql.ParseDSN(connStr) - if err != nil { - return nil, err - } - - dsn.ParseTime = true - - dbconnection, err = sql.Open(dbdriver, dsn.FormatDSN()) + dbconnection, err = sql.Open(dbdriver, connStr) if err != nil { return nil, err } diff --git a/internal/asherah/options.go b/internal/asherah/options.go index ecec455..60c4363 100644 --- a/internal/asherah/options.go +++ b/internal/asherah/options.go @@ -13,6 +13,7 @@ type Options struct { Metastore string `long:"metastore" choice:"rdbms" choice:"dynamodb" choice:"memory" required:"yes" description:"Determines the type of metastore to use for persisting keys" env:"ASHERAH_METASTORE_MODE"` ConnectionString string `long:"conn" default-mask:"-" description:"The database connection string (required if --metastore=rdbms)" env:"ASHERAH_CONNECTION_STRING"` ReplicaReadConsistency string `long:"replica-read-consistency" choice:"eventual" choice:"global" choice:"session" description:"Required for Aurora sessions using write forwarding" env:"ASHERAH_REPLICA_READ_CONSISTENCY"` + SQLMetastoreDBType string `long:"sql-metastore-db-type" default:"mysql" choice:"mysql" choice:"postgres" choice:"oracle" description:"Determines the specific type of database/sql driver to use" env:"ASHERAH_SQL_METASTORE_DB_TYPE"` DynamoDBEndpoint string `long:"dynamodb-endpoint" description:"An optional endpoint URL (hostname only or fully qualified URI) (only supported by --metastore=dynamodb)" env:"ASHERAH_DYNAMODB_ENDPOINT"` DynamoDBRegion string `long:"dynamodb-region" description:"The AWS region for DynamoDB requests (defaults to globally configured region) (only supported by --metastore=dynamodb)" env:"ASHERAH_DYNAMODB_REGION"` DynamoDBTableName string `long:"dynamodb-table-name" description:"The table name for DynamoDB (only supported by --metastore=dynamodb)" env:"ASHERAH_DYNAMODB_TABLE_NAME"` diff --git a/libasherah_test.go b/libasherah_test.go index d9ad88c..6188204 100644 --- a/libasherah_test.go +++ b/libasherah_test.go @@ -85,6 +85,68 @@ func TestSetupJsonAlternateConfiguration(t *testing.T) { Shutdown() } +func TestSetupJsonRdbmWithMysqlDefaultDbType(t *testing.T) { + config := &asherah.Options{} + + config.KMS = "static" + config.ServiceName = "TestService" + config.ProductID = "TestProduct" + config.Metastore = "rdbms" + config.ConnectionString = "user@tcp(localhost:3306)/db" + config.EnableSessionCaching = true + config.Verbose = Verbose + + buf := testAllocateJsonBuffer(t, config) + + result := SetupJson(cobhan.Ptr(&buf)) + if result != cobhan.ERR_NONE { + t.Errorf("SetupJson returned %v", result) + } + Shutdown() +} + +func TestSetupJsonRdbmWithMysqlDbType(t *testing.T) { + config := &asherah.Options{} + + config.KMS = "static" + config.ServiceName = "TestService" + config.ProductID = "TestProduct" + config.Metastore = "rdbms" + config.ConnectionString = "user@tcp(localhost:3306)/db" + config.SQLMetastoreDBType = "mysql" + config.EnableSessionCaching = true + config.Verbose = Verbose + + buf := testAllocateJsonBuffer(t, config) + + result := SetupJson(cobhan.Ptr(&buf)) + if result != cobhan.ERR_NONE { + t.Errorf("SetupJson returned %v", result) + } + Shutdown() +} + +func TestSetupJsonRdbmWithPostgresDbType(t *testing.T) { + config := &asherah.Options{} + + config.KMS = "static" + config.ServiceName = "TestService" + config.ProductID = "TestProduct" + config.Metastore = "rdbms" + config.ConnectionString = "postgres://user@localhost:5432/db" + config.SQLMetastoreDBType = "postgres" + config.EnableSessionCaching = true + config.Verbose = Verbose + + buf := testAllocateJsonBuffer(t, config) + + result := SetupJson(cobhan.Ptr(&buf)) + if result != cobhan.ERR_NONE { + t.Errorf("SetupJson returned %v", result) + } + Shutdown() +} + func TestSetupJsonTwice(t *testing.T) { config := &asherah.Options{}