From 6b8d8f22108199a622236195f76816924354fc84 Mon Sep 17 00:00:00 2001 From: RealAnna <89971034+RealAnna@users.noreply.github.com> Date: Thu, 23 Feb 2023 11:49:41 +0100 Subject: [PATCH] feat: add possibility to read mongo secret from file (#566) * feat: add possibility to read mongo secret from file Signed-off-by: realanna * feat: add possibility to read mongo secret from file Signed-off-by: realanna * Update pkg/common/mongoutils/mongo.go Co-authored-by: Giovanni Liva Signed-off-by: realanna * Update pkg/common/mongoutils/mongo.go Co-authored-by: Giovanni Liva Signed-off-by: realanna * review Signed-off-by: realanna --------- Signed-off-by: realanna Co-authored-by: Giovanni Liva --- pkg/common/mongoutils/mongo.go | 30 ++++++- pkg/common/mongoutils/mongo_test.go | 126 ++++++++++++++++++++++++++-- 2 files changed, 148 insertions(+), 8 deletions(-) diff --git a/pkg/common/mongoutils/mongo.go b/pkg/common/mongoutils/mongo.go index 32d223f6..0e3ba869 100644 --- a/pkg/common/mongoutils/mongo.go +++ b/pkg/common/mongoutils/mongo.go @@ -3,10 +3,17 @@ package mongoutils import ( "errors" "fmt" + "github.com/keptn/go-utils/pkg/common/strutils" + logger "github.com/sirupsen/logrus" + "os" ) +const mongoUser = "/mongodb-user" +const mongoPw = "/mongodb-passwords" +const mongoExtCon = "/external_connection_string" + // GetMongoConnectionStringFromEnv returns a mongodb connection string and the database name by considering the following environment variables: // MONGODB_DATABASE - The name of the database within the mongodb service (e.g. keptn) // MONGODB_EXTERNAL_CONNECTION_STRING - If this variable is set, the function will return this value. Otherwise, it will construct the connection string from the following variables. @@ -20,15 +27,32 @@ func GetMongoConnectionStringFromEnv() (string, string, error) { if mongoDBName == "" { return "", "", errors.New("env var 'MONGODB_DATABASE' env var must be set") } - if externalConnectionString := os.Getenv("MONGODB_EXTERNAL_CONNECTION_STRING"); externalConnectionString != "" { + configdir := os.Getenv("MONGO_CONFIG_DIR") + + if externalConnectionString := getFromFileOrEnv("MONGODB_EXTERNAL_CONNECTION_STRING", configdir+mongoExtCon); externalConnectionString != "" { return externalConnectionString, mongoDBName, nil } mongoDBHost := os.Getenv("MONGODB_HOST") - mongoDBUser := os.Getenv("MONGODB_USER") - mongoDBPassword := os.Getenv("MONGODB_PASSWORD") + mongoDBUser := getFromFileOrEnv("MONGODB_USER", configdir+mongoUser) + mongoDBPassword := getFromFileOrEnv("MONGODB_PASSWORD", configdir+mongoPw) if !strutils.AllSet(mongoDBHost, mongoDBUser, mongoDBPassword) { return "", "", errors.New("could not construct mongodb connection string: env vars 'MONGODB_HOST', 'MONGODB_USER' and 'MONGODB_PASSWORD' have to be set") } return fmt.Sprintf("mongodb://%s:%s@%s/%s", mongoDBUser, mongoDBPassword, mongoDBHost, mongoDBName), mongoDBName, nil } + +func readMountedSecret(file string) string { + body, err := os.ReadFile(file) + if err != nil { + logger.Fatalf("unable to read mounted secret: %v", err) + } + return string(body) +} + +func getFromFileOrEnv(env string, path string) string { + if _, err := os.Stat(path); err == nil { + return readMountedSecret(path) + } + return os.Getenv(env) +} diff --git a/pkg/common/mongoutils/mongo_test.go b/pkg/common/mongoutils/mongo_test.go index 3f12a206..6fd5395d 100644 --- a/pkg/common/mongoutils/mongo_test.go +++ b/pkg/common/mongoutils/mongo_test.go @@ -82,11 +82,11 @@ func TestGetMongoConnectionStringFromEnv(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - os.Setenv("MONGODB_EXTERNAL_CONNECTION_STRING", tt.externalConnectionStringEnvVar) - os.Setenv("MONGODB_HOST", tt.mongoDbHostEnvVar) - os.Setenv("MONGODB_DATABASE", tt.mongoDbNameEnvVar) - os.Setenv("MONGODB_USER", tt.mongoDbUserEnvVar) - os.Setenv("MONGODB_PASSWORD", tt.mongoDbPasswordEnvVar) + t.Setenv("MONGODB_EXTERNAL_CONNECTION_STRING", tt.externalConnectionStringEnvVar) + t.Setenv("MONGODB_HOST", tt.mongoDbHostEnvVar) + t.Setenv("MONGODB_DATABASE", tt.mongoDbNameEnvVar) + t.Setenv("MONGODB_USER", tt.mongoDbUserEnvVar) + t.Setenv("MONGODB_PASSWORD", tt.mongoDbPasswordEnvVar) gotConnectionString, gotDbName, err := GetMongoConnectionStringFromEnv() if (err != nil) != tt.wantErr { t.Errorf("GetMongoConnectionStringFromEnv() error = %v, wantErr %v", err, tt.wantErr) @@ -101,3 +101,119 @@ func TestGetMongoConnectionStringFromEnv(t *testing.T) { }) } } + +func TestGetMongoConnectionStringFromEnv_File(t *testing.T) { + tests := []struct { + name string + externalConnectionStringEnvVar string + mongoDbHostEnvVar string + mongoDbNameEnvVar string + mongoDbUserEnvVar string + mongoDbPasswordEnvVar string + wantConnectionString string + wantDbName string + wantErr bool + }{ + { + name: "get external connection string", + externalConnectionStringEnvVar: "mongodb+srv://user:password@keptn.1erb6.mongodb.net/keptn?retryWrites=true&w=majority", + mongoDbHostEnvVar: "mongo:27017", + mongoDbNameEnvVar: "keptn", + mongoDbUserEnvVar: "", + mongoDbPasswordEnvVar: "", + wantConnectionString: "mongodb+srv://user:password@keptn.1erb6.mongodb.net/keptn?retryWrites=true&w=majority", + wantDbName: "keptn", + wantErr: false, + }, + { + name: "get internal connection string", + externalConnectionStringEnvVar: "", + mongoDbHostEnvVar: "mongo:27017", + mongoDbNameEnvVar: "keptn", + mongoDbUserEnvVar: "user", + mongoDbPasswordEnvVar: "pw", + wantConnectionString: "mongodb://user:pw@mongo:27017/keptn", + wantDbName: "keptn", + wantErr: false, + }, + { + name: "get internal connection string - host not set", + externalConnectionStringEnvVar: "", + mongoDbHostEnvVar: "", + mongoDbNameEnvVar: "keptn", + mongoDbUserEnvVar: "user", + mongoDbPasswordEnvVar: "pw", + wantConnectionString: "", + wantErr: true, + }, + { + name: "get internal connection string - db name not set", + externalConnectionStringEnvVar: "", + mongoDbHostEnvVar: "mongo:27017", + mongoDbNameEnvVar: "", + mongoDbUserEnvVar: "user", + mongoDbPasswordEnvVar: "pw", + wantConnectionString: "", + wantErr: true, + }, + { + name: "get internal connection string - user not set", + externalConnectionStringEnvVar: "", + mongoDbHostEnvVar: "mongo:27017", + mongoDbNameEnvVar: "keptn", + mongoDbUserEnvVar: "", + mongoDbPasswordEnvVar: "pw", + wantConnectionString: "", + wantErr: true, + }, + { + name: "get internal connection string - password not set", + externalConnectionStringEnvVar: "", + mongoDbHostEnvVar: "mongo:27017", + mongoDbNameEnvVar: "keptn", + mongoDbUserEnvVar: "user", + mongoDbPasswordEnvVar: "", + wantConnectionString: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmp := t.TempDir() + t.Setenv("MONGODB_HOST", tt.mongoDbHostEnvVar) + t.Setenv("MONGODB_DATABASE", tt.mongoDbNameEnvVar) + t.Setenv("MONGO_CONFIG_DIR", tmp) + + writeMongoData(tmp+mongoExtCon, tt.externalConnectionStringEnvVar) + writeMongoData(tmp+mongoUser, tt.mongoDbUserEnvVar) + writeMongoData(tmp+mongoPw, tt.mongoDbPasswordEnvVar) + + gotConnectionString, gotDbName, err := GetMongoConnectionStringFromEnv() + if (err != nil) != tt.wantErr { + t.Errorf("GetMongoConnectionStringFromEnv() error = %v, wantErr %v", err, tt.wantErr) + return + } + if gotConnectionString != tt.wantConnectionString { + t.Errorf("GetMongoConnectionStringFromEnv() gotConnectionString = %v, wantConnectionString %v", gotConnectionString, tt.wantConnectionString) + } + if gotDbName != tt.wantDbName { + t.Errorf("GetMongoConnectionStringFromEnv() got DbName= %v, wantDbName %v", gotDbName, tt.wantDbName) + } + }) + } +} + +func check(e error) { + if e != nil { + panic(e) + } +} + +func writeMongoData(path string, data string) { + f, err := os.Create(path) + check(err) + defer f.Close() + d2 := []byte(data) + _, err = f.Write(d2) + check(err) +}