From 73fc38603647c175e69ce9d0ecea45ebda8d207e Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Fri, 9 Aug 2024 20:15:35 +0300 Subject: [PATCH] Add stordb pgSSLCertMode option --- config/config_defaults.go | 9 +++++---- config/config_json_test.go | 2 +- config/configsanity.go | 4 ++++ config/libconfig_json.go | 11 ++++++----- config/stordbcfg.go | 28 +++++++++++++++++++++++----- config/stordbcfg_test.go | 2 +- engine/storage_postgres.go | 5 ++++- engine/storage_utils.go | 2 +- engine/z_stordb_it_test.go | 7 ++++--- services/stordb.go | 1 + utils/consts.go | 1 + 11 files changed, 51 insertions(+), 21 deletions(-) diff --git a/config/config_defaults.go b/config/config_defaults.go index 1ce75f7df..197e50b3f 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -177,10 +177,11 @@ const CGRATES_CFG_JSON = ` "mongoConnScheme": "mongodb", // scheme for MongoDB connection "mysqlLocation": "Local", // the location the time from mysql is retrieved "pgSSLMode": "disable", // determines whether or with what priority a secure SSL TCP/IP connection will be negotiated with the server - "pgSSLCert": "", // file name of the client SSL certificate, replacing the default ~/.postgresql/postgresql.crt - "pgSSLKey": "", // location for the secret key used for the client certificate - "pgSSLPassword": "", // specifies the password for the secret key specified in pgSSLKey - "pgSSLRootCert": "", // name of a file containing SSL certificate authority (CA) certificate(s) + //"pgSSLCert": "", // file name of the client SSL certificate, replacing the default ~/.postgresql/postgresql.crt + //"pgSSLKey": "", // location for the secret key used for the client certificate + //"pgSSLPassword": "", // specifies the password for the secret key specified in pgSSLKey + //"pgSSLCertMode": "allow", // determines whether a client certificate may be sent to the server, and whether the server is required to request one + //"pgSSLRootCert": "", // name of a file containing SSL certificate authority (CA) certificate(s) "pgSchema": "" // postgres schema to use }, "items":{ diff --git a/config/config_json_test.go b/config/config_json_test.go index b5778f79b..57fb118d7 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -588,7 +588,7 @@ func TestDfStorDBJsonCfg(t *testing.T) { MongoConnScheme: utils.StringPointer("mongodb"), SQLConnMaxLifetime: utils.StringPointer("0"), MySQLDSNParams: make(map[string]string), - PgSSLMode: utils.PgSSLModeDisable, + PgSSLMode: utils.StringPointer(utils.PgSSLModeDisable), MySQLLocation: utils.StringPointer("Local"), PgSchema: utils.StringPointer(""), }, diff --git a/config/configsanity.go b/config/configsanity.go index 177623e08..547e58f07 100644 --- a/config/configsanity.go +++ b/config/configsanity.go @@ -969,6 +969,10 @@ func (cfg *CGRConfig) checkConfigSanity() error { utils.PgSSLModeVerifyFull}, cfg.storDbCfg.Opts.PgSSLMode) { return fmt.Errorf("<%s> unsupported pgSSLMode (sslmode) in storDB configuration", utils.StorDB) } + if !slices.Contains([]string{utils.PgSSLModeDisable, utils.PgSSLModeAllow, utils.PgSSLModeRequire, + utils.EmptyString}, cfg.storDbCfg.Opts.PgSSLCertMode) { + return fmt.Errorf("<%s> unsupported pgSSLCertMode (sslcertmode) in storDB configuration", utils.StorDB) + } } // DataDB sanity checks if cfg.dataDbCfg.Type == utils.MetaInternal { diff --git a/config/libconfig_json.go b/config/libconfig_json.go index 92a18971e..4533ae75e 100644 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -123,11 +123,12 @@ type DBOptsJson struct { SQLMaxIdleConns *int `json:"sqlMaxIdleConns"` SQLConnMaxLifetime *string `json:"sqlConnMaxLifetime"` MySQLDSNParams map[string]string `json:"mysqlDSNParams"` - PgSSLMode string `json:"pgSSLMode"` - PgSSLCert string `json:"pgSSLCert"` - PgSSLKey string `json:"pgSSLKey"` - PgSSLPassword string `json:"pgSSLPassword"` - PgSSLRootCert string `json:"pgSSLRootCert"` + PgSSLMode *string `json:"pgSSLMode"` + PgSSLCert *string `json:"pgSSLCert"` + PgSSLKey *string `json:"pgSSLKey"` + PgSSLPassword *string `json:"pgSSLPassword"` + PgSSLCertMode *string `json:"pgSSLCertMode"` + PgSSLRootCert *string `json:"pgSSLRootCert"` PgSchema *string `json:"pgSchema"` MySQLLocation *string `json:"mysqlLocation"` } diff --git a/config/stordbcfg.go b/config/stordbcfg.go index b18ab6a84..836c53111 100644 --- a/config/stordbcfg.go +++ b/config/stordbcfg.go @@ -37,6 +37,7 @@ type StorDBOpts struct { PgSSLCert string PgSSLKey string PgSSLPassword string + PgSSLCertMode string PgSSLRootCert string PgSchema string MySQLLocation string @@ -86,11 +87,24 @@ func (dbOpts *StorDBOpts) loadFromJSONCfg(jsnCfg *DBOptsJson) (err error) { if jsnCfg.MongoConnScheme != nil { dbOpts.MongoConnScheme = *jsnCfg.MongoConnScheme } - dbOpts.PgSSLMode = jsnCfg.PgSSLMode - dbOpts.PgSSLCert = jsnCfg.PgSSLCert - dbOpts.PgSSLKey = jsnCfg.PgSSLKey - dbOpts.PgSSLPassword = jsnCfg.PgSSLPassword - dbOpts.PgSSLRootCert = jsnCfg.PgSSLRootCert + if jsnCfg.PgSSLMode != nil { + dbOpts.PgSSLMode = *jsnCfg.PgSSLMode + } + if jsnCfg.PgSSLCert != nil { + dbOpts.PgSSLCert = *jsnCfg.PgSSLCert + } + if jsnCfg.PgSSLKey != nil { + dbOpts.PgSSLKey = *jsnCfg.PgSSLKey + } + if jsnCfg.PgSSLPassword != nil { + dbOpts.PgSSLPassword = *jsnCfg.PgSSLPassword + } + if jsnCfg.PgSSLCertMode != nil { + dbOpts.PgSSLCertMode = *jsnCfg.PgSSLCertMode + } + if jsnCfg.PgSSLRootCert != nil { + dbOpts.PgSSLRootCert = *jsnCfg.PgSSLRootCert + } if jsnCfg.PgSchema != nil { dbOpts.PgSchema = *jsnCfg.PgSchema } @@ -182,6 +196,7 @@ func (dbOpts *StorDBOpts) Clone() *StorDBOpts { PgSSLCert: dbOpts.PgSSLCert, PgSSLKey: dbOpts.PgSSLKey, PgSSLPassword: dbOpts.PgSSLPassword, + PgSSLCertMode: dbOpts.PgSSLCertMode, PgSSLRootCert: dbOpts.PgSSLRootCert, PgSchema: dbOpts.PgSchema, MySQLLocation: dbOpts.MySQLLocation, @@ -245,6 +260,9 @@ func (dbcfg *StorDbCfg) AsMapInterface() (mp map[string]any) { if dbcfg.Opts.PgSSLPassword != "" { opts[utils.PgSSLPasswordCfg] = dbcfg.Opts.PgSSLPassword } + if dbcfg.Opts.PgSSLCertMode != "" { + opts[utils.PgSSLCertModeCfg] = dbcfg.Opts.PgSSLCertMode + } if dbcfg.Opts.PgSSLRootCert != "" { opts[utils.PgSSLRootCertCfg] = dbcfg.Opts.PgSSLRootCert } diff --git a/config/stordbcfg_test.go b/config/stordbcfg_test.go index 86c45d9b7..70ebb6af7 100644 --- a/config/stordbcfg_test.go +++ b/config/stordbcfg_test.go @@ -54,7 +54,7 @@ func TestStoreDbCfgloadFromJsonCfgCase1(t *testing.T) { MySQLDSNParams: make(map[string]string), MySQLLocation: utils.StringPointer("UTC"), MongoConnScheme: utils.StringPointer("mongodb"), - PgSSLMode: "disable", + PgSSLMode: utils.StringPointer(utils.PgSSLModeDisable), }, } expected := &StorDbCfg{ diff --git a/engine/storage_postgres.go b/engine/storage_postgres.go index 6cb756793..1fd16d36b 100644 --- a/engine/storage_postgres.go +++ b/engine/storage_postgres.go @@ -29,7 +29,7 @@ import ( // NewPostgresStorage returns the posgres storDB func NewPostgresStorage(host, port, name, user, password, pgSchema, - sslmode, sslcert, sslkey, sslpassword, sslrootcert string, + sslmode, sslcert, sslkey, sslpassword, sslcertmode, sslrootcert string, maxConn, maxIdleConn int, connMaxLifetime time.Duration) (*SQLStorage, error) { connStr := fmt.Sprintf( "host=%s port=%s dbname=%s user=%s password=%s sslmode=%s", @@ -43,6 +43,9 @@ func NewPostgresStorage(host, port, name, user, password, pgSchema, if sslpassword != "" { connStr = connStr + " sslpassword=" + sslpassword } + if sslcertmode != "" { + connStr = connStr + " sslcertmode=" + sslcertmode + } if sslrootcert != "" { connStr = connStr + " sslrootcert=" + sslrootcert } diff --git a/engine/storage_utils.go b/engine/storage_utils.go index 724e8a54f..4223c873b 100644 --- a/engine/storage_utils.go +++ b/engine/storage_utils.go @@ -71,7 +71,7 @@ func NewStorDBConn(dbType, host, port, name, user, pass, marshaler string, db, err = NewMongoStorage(opts.MongoConnScheme, host, port, name, user, pass, marshaler, utils.StorDB, stringIndexedFields, opts.MongoQueryTimeout) case utils.MetaPostgres: db, err = NewPostgresStorage(host, port, name, user, pass, opts.PgSchema, opts.PgSSLMode, - opts.PgSSLCert, opts.PgSSLKey, opts.PgSSLPassword, opts.PgSSLRootCert, + opts.PgSSLCert, opts.PgSSLKey, opts.PgSSLPassword, opts.PgSSLCertMode, opts.PgSSLRootCert, opts.SQLMaxOpenConns, opts.SQLMaxIdleConns, opts.SQLConnMaxLifetime) case utils.MetaMySQL: db, err = NewMySQLStorage(host, port, name, user, pass, opts.SQLMaxOpenConns, opts.SQLMaxIdleConns, diff --git a/engine/z_stordb_it_test.go b/engine/z_stordb_it_test.go index 680f76a3b..a5a9f9def 100644 --- a/engine/z_stordb_it_test.go +++ b/engine/z_stordb_it_test.go @@ -108,9 +108,10 @@ func TestStorDBit(t *testing.T) { if storDB, err = NewPostgresStorage(storDBCfg.StorDbCfg().Host, storDBCfg.StorDbCfg().Port, storDBCfg.StorDbCfg().Name, storDBCfg.StorDbCfg().User, storDBCfg.StorDbCfg().Password, - storDBCfg.StorDbCfg().Opts.PgSchema, storDBCfg.StorDbCfg().Opts.PgSSLMode, - storDBCfg.StorDbCfg().Opts.PgSSLCert, storDBCfg.StorDbCfg().Opts.PgSSLKey, - storDBCfg.StorDbCfg().Opts.PgSSLPassword, storDBCfg.StorDbCfg().Opts.PgSSLRootCert, + storDBCfg.StorDbCfg().Opts.PgSchema, + storDBCfg.StorDbCfg().Opts.PgSSLMode, storDBCfg.StorDbCfg().Opts.PgSSLCert, + storDBCfg.StorDbCfg().Opts.PgSSLKey, storDBCfg.StorDbCfg().Opts.PgSSLPassword, + storDBCfg.StorDbCfg().Opts.PgSSLCertMode, storDBCfg.StorDbCfg().Opts.PgSSLRootCert, 100, 10, 0); err != nil { t.Fatal(err) } diff --git a/services/stordb.go b/services/stordb.go index 3dae2b9cb..e2e10a080 100644 --- a/services/stordb.go +++ b/services/stordb.go @@ -200,5 +200,6 @@ func (db *StorDBService) needsConnectionReload() bool { db.oldDBCfg.Opts.PgSSLCert != db.cfg.StorDbCfg().Opts.PgSSLCert || db.oldDBCfg.Opts.PgSSLKey != db.cfg.StorDbCfg().Opts.PgSSLKey || db.oldDBCfg.Opts.PgSSLPassword != db.cfg.StorDbCfg().Opts.PgSSLPassword || + db.oldDBCfg.Opts.PgSSLCertMode != db.cfg.StorDbCfg().Opts.PgSSLCertMode || db.oldDBCfg.Opts.PgSSLRootCert != db.cfg.StorDbCfg().Opts.PgSSLRootCert) } diff --git a/utils/consts.go b/utils/consts.go index faca069a4..dd46f41af 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -2116,6 +2116,7 @@ const ( PgSSLCertCfg = "pgSSLCert" PgSSLKeyCfg = "pgSSLKey" PgSSLPasswordCfg = "pgSSLPassword" + PgSSLCertModeCfg = "pgSSLCertMode" PgSSLRootCertCfg = "pgSSLRootCert" PgSchema = "pgSchema" ItemsCfg = "items"