diff --git a/App.go b/App.go index 924319f39f..39f22085db 100644 --- a/App.go +++ b/App.go @@ -23,6 +23,7 @@ import ( "fmt" "github.com/devtron-labs/common-lib/middlewares" pubsub "github.com/devtron-labs/common-lib/pubsub-lib" + "github.com/devtron-labs/common-lib/securestore" posthogTelemetry "github.com/devtron-labs/common-lib/telemetry" "github.com/devtron-labs/devtron/pkg/eventProcessor" "github.com/devtron-labs/devtron/pkg/eventProcessor/in" @@ -47,6 +48,13 @@ import ( "go.uber.org/zap" ) +func init() { + err := securestore.SetEncryptionKey() + if err != nil { + log.Println("error in setting encryption key", "err", err) + } +} + type App struct { MuxRouter *router.MuxRouter Logger *zap.SugaredLogger diff --git a/Makefile b/Makefile index 354aeb4011..f5514e61d2 100755 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all: fetch-all-env build -TARGET_BRANCH?=develop +TARGET_BRANCH?=main TAG?=$(shell bash -c 'git log --pretty=format:'%h' -n 1') FLAGS= ENVVAR= diff --git a/api/helm-app/service/HelmAppService.go b/api/helm-app/service/HelmAppService.go index 3e997ed451..5393b7a7c6 100644 --- a/api/helm-app/service/HelmAppService.go +++ b/api/helm-app/service/HelmAppService.go @@ -965,10 +965,10 @@ func (impl *HelmAppServiceImpl) TemplateChart(ctx context.Context, templateChart registryCredential = &gRPC.RegistryCredential{ RegistryUrl: appStoreAppVersion.AppStore.DockerArtifactStore.RegistryURL, Username: appStoreAppVersion.AppStore.DockerArtifactStore.Username, - Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password, + Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password.String(), AwsRegion: appStoreAppVersion.AppStore.DockerArtifactStore.AWSRegion, AccessKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSAccessKeyId, - SecretKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey, + SecretKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey.String(), RegistryType: string(appStoreAppVersion.AppStore.DockerArtifactStore.RegistryType), RepoName: appStoreAppVersion.AppStore.Name, IsPublic: ociRegistryConfig.IsPublic, diff --git a/cmd/external-app/externalApp.go b/cmd/external-app/externalApp.go index 9c5746cded..a69c8cd8bd 100644 --- a/cmd/external-app/externalApp.go +++ b/cmd/external-app/externalApp.go @@ -20,6 +20,8 @@ import ( "context" "errors" "fmt" + "github.com/devtron-labs/common-lib/securestore" + "log" "net/http" "os" "time" @@ -35,6 +37,13 @@ import ( "go.uber.org/zap" ) +func init() { + err := securestore.SetEncryptionKey() + if err != nil { + log.Println("error in setting encryption key", "err", err) + } +} + type App struct { db *pg.DB sessionManager *authMiddleware.SessionManager diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index 926f4b207c..f6bb87d895 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -1,6 +1,6 @@ // Code generated by Wire. DO NOT EDIT. -//go:generate go run github.com/google/wire/cmd/wire +//go:generate go run -mod=mod github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject diff --git a/go.mod b/go.mod index cd8121ab47..e45c9e55f7 100644 --- a/go.mod +++ b/go.mod @@ -335,7 +335,7 @@ require ( replace ( github.com/argoproj/argo-workflows/v3 v3.5.13 => github.com/devtron-labs/argo-workflows/v3 v3.5.13 github.com/cyphar/filepath-securejoin v0.4.1 => github.com/cyphar/filepath-securejoin v0.3.6 // indirect - github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250911133753-9256a0667454 - github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250911133753-9256a0667454 + github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20251013071936-4564399cd269 + github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20251013071936-4564399cd269 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 ) diff --git a/go.sum b/go.sum index 1ca828313b..7a605743de 100644 --- a/go.sum +++ b/go.sum @@ -237,10 +237,10 @@ github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzq github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/devtron-labs/argo-workflows/v3 v3.5.13 h1:3pINq0gXOSeTw2z/vYe+j80lRpSN5Rp/8mfQORh8SmU= github.com/devtron-labs/argo-workflows/v3 v3.5.13/go.mod h1:/vqxcovDPT4zqr4DjR5v7CF8ggpY1l3TSa2CIG3jmjA= -github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250911133753-9256a0667454 h1:FfSiQrZpr6rDjmtFR6u3vG1WaoUBkv4ZR6rGZ5eRX8I= -github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250911133753-9256a0667454/go.mod h1:9LCkYfiWaEKIBkmxw9jX1GujvEMyHwmDtVsatffAkeU= -github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250911133753-9256a0667454 h1:qpYqvcezyTM9yDBSsDHJvp7GjSypx9SxiU/L4xoZR9s= -github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250911133753-9256a0667454/go.mod h1:/Ciy9tD9OxZOWBDPIasM448H7uvSo4+ZJiExpfwBZpA= +github.com/devtron-labs/devtron-services/authenticator v0.0.0-20251013071936-4564399cd269 h1:DWDnjdZ+AAa4w+WiqFPLS4kBRVeY+BvHQGrfEsFTREE= +github.com/devtron-labs/devtron-services/authenticator v0.0.0-20251013071936-4564399cd269/go.mod h1:9LCkYfiWaEKIBkmxw9jX1GujvEMyHwmDtVsatffAkeU= +github.com/devtron-labs/devtron-services/common-lib v0.0.0-20251013071936-4564399cd269 h1:9+YW3jipbllOHJ1l3mYFSeSris1wUCaM/MQuI4p+Hxc= +github.com/devtron-labs/devtron-services/common-lib v0.0.0-20251013071936-4564399cd269/go.mod h1:/Ciy9tD9OxZOWBDPIasM448H7uvSo4+ZJiExpfwBZpA= github.com/devtron-labs/go-bitbucket v0.9.60-beta h1:VEx1jvDgdtDPS6A1uUFoaEi0l1/oLhbr+90xOwr6sDU= github.com/devtron-labs/go-bitbucket v0.9.60-beta/go.mod h1:GnuiCesvh8xyHeMCb+twm8lBR/kQzJYSKL28ZfObp1Y= github.com/devtron-labs/protos v0.0.3-0.20250323220609-ecf8a0f7305e h1:U6UdYbW8a7xn5IzFPd8cywjVVPfutGJCudjePAfL/Hs= diff --git a/internal/sql/repository/GitOpsConfigRepository.go b/internal/sql/repository/GitOpsConfigRepository.go index c8b6d7cf15..5483f962ea 100644 --- a/internal/sql/repository/GitOpsConfigRepository.go +++ b/internal/sql/repository/GitOpsConfigRepository.go @@ -17,6 +17,7 @@ package repository import ( + "github.com/devtron-labs/common-lib/securestore" "github.com/devtron-labs/devtron/pkg/sql" "github.com/go-pg/pg" "go.uber.org/zap" @@ -41,24 +42,24 @@ type GitOpsConfigRepositoryImpl struct { } type GitOpsConfig struct { - tableName struct{} `sql:"gitops_config" pg:",discard_unknown_columns"` - Id int `sql:"id,pk"` - Provider string `sql:"provider"` - Username string `sql:"username"` - Token string `sql:"token"` - GitLabGroupId string `sql:"gitlab_group_id"` - GitHubOrgId string `sql:"github_org_id"` - AzureProject string `sql:"azure_project"` - Host string `sql:"host"` - Active bool `sql:"active,notnull"` - AllowCustomRepository bool `sql:"allow_custom_repository,notnull"` - BitBucketWorkspaceId string `sql:"bitbucket_workspace_id"` - BitBucketProjectKey string `sql:"bitbucket_project_key"` - EmailId string `sql:"email_id"` - EnableTLSVerification bool `sql:"enable_tls_verification"` - TlsCert string `sql:"tls_cert"` - TlsKey string `sql:"tls_key"` - CaCert string `sql:"ca_cert"` + tableName struct{} `sql:"gitops_config" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + Provider string `sql:"provider"` + Username string `sql:"username"` + Token securestore.EncryptedString `sql:"token"` + GitLabGroupId string `sql:"gitlab_group_id"` + GitHubOrgId string `sql:"github_org_id"` + AzureProject string `sql:"azure_project"` + Host string `sql:"host"` + Active bool `sql:"active,notnull"` + AllowCustomRepository bool `sql:"allow_custom_repository,notnull"` + BitBucketWorkspaceId string `sql:"bitbucket_workspace_id"` + BitBucketProjectKey string `sql:"bitbucket_project_key"` + EmailId string `sql:"email_id"` + EnableTLSVerification bool `sql:"enable_tls_verification"` + TlsCert string `sql:"tls_cert"` + TlsKey string `sql:"tls_key"` + CaCert string `sql:"ca_cert"` sql.AuditLog } @@ -71,15 +72,24 @@ func (impl *GitOpsConfigRepositoryImpl) GetConnection() *pg.DB { } func (impl *GitOpsConfigRepositoryImpl) CreateGitOpsConfig(model *GitOpsConfig, tx *pg.Tx) (*GitOpsConfig, error) { - err := tx.Insert(model) + var err error + model.Token, err = securestore.EncryptString(model.Token.String()) + if err != nil { + return model, err + } + err = tx.Insert(model) if err != nil { impl.logger.Error(err) return model, err } return model, nil } -func (impl *GitOpsConfigRepositoryImpl) UpdateGitOpsConfig(model *GitOpsConfig, tx *pg.Tx) error { - err := tx.Update(model) +func (impl *GitOpsConfigRepositoryImpl) UpdateGitOpsConfig(model *GitOpsConfig, tx *pg.Tx) (err error) { + model.Token, err = securestore.EncryptString(model.Token.String()) + if err != nil { + return err + } + err = tx.Update(model) if err != nil { impl.logger.Error(err) return err diff --git a/internal/sql/repository/dockerRegistry/DockerArtifactStoreRepository.go b/internal/sql/repository/dockerRegistry/DockerArtifactStoreRepository.go index 1ca0ffd20d..6ae8c6f354 100644 --- a/internal/sql/repository/dockerRegistry/DockerArtifactStoreRepository.go +++ b/internal/sql/repository/dockerRegistry/DockerArtifactStoreRepository.go @@ -18,6 +18,7 @@ package repository import ( "fmt" + "github.com/devtron-labs/common-lib/securestore" "github.com/devtron-labs/devtron/pkg/sql" "github.com/devtron-labs/devtron/util" "github.com/go-pg/pg/orm" @@ -46,21 +47,21 @@ type RegistryType string var OCI_REGISRTY_REPO_TYPE_LIST = []string{OCI_REGISRTY_REPO_TYPE_CONTAINER, OCI_REGISRTY_REPO_TYPE_CHART} type DockerArtifactStore struct { - tableName struct{} `sql:"docker_artifact_store" json:",omitempty" pg:",discard_unknown_columns"` - Id string `sql:"id,pk" json:"id,,omitempty"` - PluginId string `sql:"plugin_id,notnull" json:"pluginId,omitempty"` - RegistryURL string `sql:"registry_url" json:"registryUrl,omitempty"` - RegistryType RegistryType `sql:"registry_type,notnull" json:"registryType,omitempty"` - IsOCICompliantRegistry bool `sql:"is_oci_compliant_registry,notnull" json:"isOCICompliantRegistry,omitempty"` - AWSAccessKeyId string `sql:"aws_accesskey_id" json:"awsAccessKeyId,omitempty" ` - AWSSecretAccessKey string `sql:"aws_secret_accesskey" json:"awsSecretAccessKey,omitempty"` - AWSRegion string `sql:"aws_region" json:"awsRegion,omitempty"` - Username string `sql:"username" json:"username,omitempty"` - Password string `sql:"password" json:"password,omitempty"` - IsDefault bool `sql:"is_default,notnull" json:"isDefault"` - Connection string `sql:"connection" json:"connection,omitempty"` - Cert string `sql:"cert" json:"cert,omitempty"` - Active bool `sql:"active,notnull" json:"active"` + tableName struct{} `sql:"docker_artifact_store" json:",omitempty" pg:",discard_unknown_columns"` + Id string `sql:"id,pk" json:"id,,omitempty"` + PluginId string `sql:"plugin_id,notnull" json:"pluginId,omitempty"` + RegistryURL string `sql:"registry_url" json:"registryUrl,omitempty"` + RegistryType RegistryType `sql:"registry_type,notnull" json:"registryType,omitempty"` + IsOCICompliantRegistry bool `sql:"is_oci_compliant_registry,notnull" json:"isOCICompliantRegistry,omitempty"` + AWSAccessKeyId string `sql:"aws_accesskey_id" json:"awsAccessKeyId,omitempty" ` + AWSSecretAccessKey securestore.EncryptedString `sql:"aws_secret_accesskey" json:"awsSecretAccessKey,omitempty"` + AWSRegion string `sql:"aws_region" json:"awsRegion,omitempty"` + Username string `sql:"username" json:"username,omitempty"` + Password securestore.EncryptedString `sql:"password" json:"password,omitempty"` + IsDefault bool `sql:"is_default,notnull" json:"isDefault"` + Connection string `sql:"connection" json:"connection,omitempty"` + Cert string `sql:"cert" json:"cert,omitempty"` + Active bool `sql:"active,notnull" json:"active"` IpsConfig *DockerRegistryIpsConfig OCIRegistryConfig []*OCIRegistryConfig sql.AuditLog @@ -109,7 +110,16 @@ func (impl DockerArtifactStoreRepositoryImpl) GetConnection() *pg.DB { return impl.dbConnection } -func (impl DockerArtifactStoreRepositoryImpl) Save(artifactStore *DockerArtifactStore, tx *pg.Tx) error { +func (impl DockerArtifactStoreRepositoryImpl) Save(artifactStore *DockerArtifactStore, tx *pg.Tx) (err error) { + artifactStore.Password, err = securestore.EncryptString(artifactStore.Password.String()) + if err != nil { + return err + } + artifactStore.AWSSecretAccessKey, err = securestore.EncryptString(artifactStore.AWSSecretAccessKey.String()) + if err != nil { + return err + } + if util.IsBaseStack() { return tx.Insert(artifactStore) } @@ -235,7 +245,15 @@ func (impl DockerArtifactStoreRepositoryImpl) FindOneInactive(storeId string) (* return &provider, err } -func (impl DockerArtifactStoreRepositoryImpl) Update(artifactStore *DockerArtifactStore, tx *pg.Tx) error { +func (impl DockerArtifactStoreRepositoryImpl) Update(artifactStore *DockerArtifactStore, tx *pg.Tx) (err error) { + artifactStore.Password, err = securestore.EncryptString(artifactStore.Password.String()) + if err != nil { + return err + } + artifactStore.AWSSecretAccessKey, err = securestore.EncryptString(artifactStore.AWSSecretAccessKey.String()) + if err != nil { + return err + } //TODO check for unique default //there can be only one default diff --git a/pkg/appStore/adapter/Adapter.go b/pkg/appStore/adapter/Adapter.go index 83ed138e79..1f6acce017 100644 --- a/pkg/appStore/adapter/Adapter.go +++ b/pkg/appStore/adapter/Adapter.go @@ -159,7 +159,7 @@ func GenerateInstallAppVersionDTO(installedApp *repository.InstalledApps, instal chartVersionApp.AppStore.DockerArtifactStore.RegistryURL, chartVersionApp.AppStore.Name) Username = chartVersionApp.AppStore.DockerArtifactStore.Username - Password = chartVersionApp.AppStore.DockerArtifactStore.Password + Password = chartVersionApp.AppStore.DockerArtifactStore.Password.String() } envBean := adapter2.NewEnvironmentBean(&installedApp.Environment) installAppDto := &appStoreBean.InstallAppVersionDTO{ diff --git a/pkg/appStore/installedApp/service/AppStoreDeploymentService.go b/pkg/appStore/installedApp/service/AppStoreDeploymentService.go index d1096d4060..6a5b036cfb 100644 --- a/pkg/appStore/installedApp/service/AppStoreDeploymentService.go +++ b/pkg/appStore/installedApp/service/AppStoreDeploymentService.go @@ -992,10 +992,10 @@ func (impl *AppStoreDeploymentServiceImpl) linkHelmApplicationToChartStore(insta registryCredential = &bean4.RegistryCredential{ RegistryUrl: appStoreAppVersion.AppStore.DockerArtifactStore.RegistryURL, Username: appStoreAppVersion.AppStore.DockerArtifactStore.Username, - Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password, + Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password.String(), AwsRegion: appStoreAppVersion.AppStore.DockerArtifactStore.AWSRegion, AccessKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSAccessKeyId, - SecretKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey, + SecretKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey.String(), RegistryType: string(appStoreAppVersion.AppStore.DockerArtifactStore.RegistryType), RepoName: appStoreAppVersion.AppStore.Name, IsPublic: ociRegistryConfig.IsPublic, diff --git a/pkg/appStore/installedApp/service/EAMode/deployment/EAModeDeploymentService.go b/pkg/appStore/installedApp/service/EAMode/deployment/EAModeDeploymentService.go index d3286f43e6..f707a47e92 100644 --- a/pkg/appStore/installedApp/service/EAMode/deployment/EAModeDeploymentService.go +++ b/pkg/appStore/installedApp/service/EAMode/deployment/EAModeDeploymentService.go @@ -124,10 +124,10 @@ func (impl *EAModeDeploymentServiceImpl) InstallApp(installAppVersionRequest *ap registryCredential = &gRPC.RegistryCredential{ RegistryUrl: appStoreAppVersion.AppStore.DockerArtifactStore.RegistryURL, Username: appStoreAppVersion.AppStore.DockerArtifactStore.Username, - Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password, + Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password.String(), AwsRegion: appStoreAppVersion.AppStore.DockerArtifactStore.AWSRegion, AccessKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSAccessKeyId, - SecretKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey, + SecretKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey.String(), RegistryType: string(appStoreAppVersion.AppStore.DockerArtifactStore.RegistryType), RepoName: appStoreAppVersion.AppStore.Name, IsPublic: ociRegistryConfig.IsPublic, @@ -356,10 +356,10 @@ func (impl *EAModeDeploymentServiceImpl) updateApplicationWithChartInfo(ctx cont registryCredential = &gRPC.RegistryCredential{ RegistryUrl: appStoreApplicationVersion.AppStore.DockerArtifactStore.RegistryURL, Username: appStoreApplicationVersion.AppStore.DockerArtifactStore.Username, - Password: appStoreApplicationVersion.AppStore.DockerArtifactStore.Password, + Password: appStoreApplicationVersion.AppStore.DockerArtifactStore.Password.String(), AwsRegion: appStoreApplicationVersion.AppStore.DockerArtifactStore.AWSRegion, AccessKey: appStoreApplicationVersion.AppStore.DockerArtifactStore.AWSAccessKeyId, - SecretKey: appStoreApplicationVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey, + SecretKey: appStoreApplicationVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey.String(), RegistryType: string(appStoreApplicationVersion.AppStore.DockerArtifactStore.RegistryType), RepoName: appStoreApplicationVersion.AppStore.Name, IsPublic: ociRegistryConfig.IsPublic, diff --git a/pkg/appStore/installedApp/service/FullMode/deployment/InstalledAppGitOpsService.go b/pkg/appStore/installedApp/service/FullMode/deployment/InstalledAppGitOpsService.go index 159739901f..caae5043cb 100644 --- a/pkg/appStore/installedApp/service/FullMode/deployment/InstalledAppGitOpsService.go +++ b/pkg/appStore/installedApp/service/FullMode/deployment/InstalledAppGitOpsService.go @@ -414,7 +414,7 @@ func (impl *FullModeDeploymentServiceImpl) CreateArgoRepoSecretIfNeeded(appStore err = impl.argoClientWrapperService.AddOrUpdateOCIRegistry( dockerArtifactStore.Username, - dockerArtifactStore.Password, + dockerArtifactStore.Password.String(), dockerArtifactStore.OCIRegistryConfig[0].Id, dockerArtifactStore.RegistryURL, appStore.Name, diff --git a/pkg/appStore/installedApp/service/FullMode/resource/NotesService.go b/pkg/appStore/installedApp/service/FullMode/resource/NotesService.go index 66c4db4c2b..1ad93808e6 100644 --- a/pkg/appStore/installedApp/service/FullMode/resource/NotesService.go +++ b/pkg/appStore/installedApp/service/FullMode/resource/NotesService.go @@ -124,10 +124,10 @@ func (impl *InstalledAppResourceServiceImpl) findNotesForArgoApplication(install registryCredential = &gRPC.RegistryCredential{ RegistryUrl: appStoreAppVersion.AppStore.DockerArtifactStore.RegistryURL, Username: appStoreAppVersion.AppStore.DockerArtifactStore.Username, - Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password, + Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password.String(), AwsRegion: appStoreAppVersion.AppStore.DockerArtifactStore.AWSRegion, AccessKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSAccessKeyId, - SecretKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey, + SecretKey: appStoreAppVersion.AppStore.DockerArtifactStore.AWSSecretAccessKey.String(), RegistryType: string(appStoreAppVersion.AppStore.DockerArtifactStore.RegistryType), RepoName: appStoreAppVersion.AppStore.Name, IsPublic: ociRegistryConfig.IsPublic, diff --git a/pkg/build/git/gitProvider/GitRegistryConfig.go b/pkg/build/git/gitProvider/GitRegistryConfig.go index adb726af3f..502109f567 100644 --- a/pkg/build/git/gitProvider/GitRegistryConfig.go +++ b/pkg/build/git/gitProvider/GitRegistryConfig.go @@ -18,6 +18,7 @@ package gitProvider import ( "context" + "github.com/devtron-labs/common-lib/securestore" "github.com/devtron-labs/devtron/client/gitSensor" "github.com/devtron-labs/devtron/internal/constants" constants2 "github.com/devtron-labs/devtron/internal/sql/constants" @@ -79,9 +80,9 @@ func (impl GitRegistryConfigImpl) Create(request *bean2.GitRegistry) (*bean2.Git Name: request.Name, Url: request.Url, UserName: request.UserName, - Password: request.Password, - SshPrivateKey: request.SshPrivateKey, - AccessToken: request.AccessToken, + Password: securestore.ToEncryptedString(request.Password), + SshPrivateKey: securestore.ToEncryptedString(request.SshPrivateKey), + AccessToken: securestore.ToEncryptedString(request.AccessToken), AuthMode: request.AuthMode, Active: request.Active, Deleted: false, @@ -127,7 +128,7 @@ func (impl GitRegistryConfigImpl) Create(request *bean2.GitRegistry) (*bean2.Git } } - provider.SshPrivateKey = ModifySshPrivateKey(provider.SshPrivateKey, provider.AuthMode) + provider.SshPrivateKey = securestore.ToEncryptedString(ModifySshPrivateKey(provider.SshPrivateKey.String(), provider.AuthMode)) err = impl.gitProviderRepo.Save(provider) if err != nil { impl.logger.Errorw("error in saving git repo config", "data", provider, "err", err) @@ -179,23 +180,23 @@ func (impl GitRegistryConfigImpl) Update(request *bean2.GitRegistry) (*bean2.Git return nil, err0 } if request.Password == "" { - request.Password = existingProvider.Password + request.Password = existingProvider.Password.String() } if request.SshPrivateKey == "" { - request.SshPrivateKey = existingProvider.SshPrivateKey + request.SshPrivateKey = existingProvider.SshPrivateKey.String() } if request.AccessToken == "" { - request.AccessToken = existingProvider.AccessToken + request.AccessToken = existingProvider.AccessToken.String() } provider := &repository.GitProvider{ Name: request.Name, Url: request.Url, Id: request.Id, AuthMode: request.AuthMode, - Password: request.Password, + Password: securestore.ToEncryptedString(request.Password), Active: request.Active, - AccessToken: request.AccessToken, - SshPrivateKey: request.SshPrivateKey, + AccessToken: securestore.ToEncryptedString(request.AccessToken), + SshPrivateKey: securestore.ToEncryptedString(request.SshPrivateKey), UserName: request.UserName, GitHostId: request.GitHostId, EnableTLSVerification: request.EnableTLSVerification, @@ -251,7 +252,7 @@ func (impl GitRegistryConfigImpl) Update(request *bean2.GitRegistry) (*bean2.Git } } - provider.SshPrivateKey = ModifySshPrivateKey(provider.SshPrivateKey, provider.AuthMode) + provider.SshPrivateKey = securestore.ToEncryptedString(ModifySshPrivateKey(provider.SshPrivateKey.String(), provider.AuthMode)) err := impl.gitProviderRepo.Update(provider) if err != nil { impl.logger.Errorw("error in updating git repo config", "data", provider, "err", err) @@ -311,9 +312,9 @@ func (impl GitRegistryConfigImpl) UpdateGitSensor(provider *repository.GitProvid Name: provider.Name, Url: provider.Url, UserName: provider.UserName, - Password: provider.Password, - SshPrivateKey: provider.SshPrivateKey, - AccessToken: provider.AccessToken, + Password: provider.Password.String(), + SshPrivateKey: provider.SshPrivateKey.String(), + AccessToken: provider.AccessToken.String(), Active: provider.Active, AuthMode: provider.AuthMode, CaCert: provider.CaCert, diff --git a/pkg/build/git/gitProvider/adapter/adapter.go b/pkg/build/git/gitProvider/adapter/adapter.go index b38112d910..389aaa953a 100644 --- a/pkg/build/git/gitProvider/adapter/adapter.go +++ b/pkg/build/git/gitProvider/adapter/adapter.go @@ -30,9 +30,9 @@ func ConvertGitRegistryDtoToBean(provider repository.GitProvider, withSensitiveD IsTLSCertDataPresent: len(provider.TlsCert) > 0, } if withSensitiveData { - registryBean.Password = provider.Password - registryBean.AccessToken = provider.AccessToken - registryBean.SshPrivateKey = provider.SshPrivateKey + registryBean.Password = provider.Password.String() + registryBean.AccessToken = provider.AccessToken.String() + registryBean.SshPrivateKey = provider.SshPrivateKey.String() } return registryBean } diff --git a/pkg/build/git/gitProvider/repository/GitProviderRepository.go b/pkg/build/git/gitProvider/repository/GitProviderRepository.go index 09eb1462c2..afe0473b81 100644 --- a/pkg/build/git/gitProvider/repository/GitProviderRepository.go +++ b/pkg/build/git/gitProvider/repository/GitProviderRepository.go @@ -17,28 +17,29 @@ package repository import ( + "github.com/devtron-labs/common-lib/securestore" "github.com/devtron-labs/devtron/internal/sql/constants" "github.com/devtron-labs/devtron/pkg/sql" "github.com/go-pg/pg" ) type GitProvider struct { - tableName struct{} `sql:"git_provider" pg:",discard_unknown_columns"` - Id int `sql:"id,pk"` - Name string `sql:"name,notnull"` - Url string `sql:"url,notnull"` - UserName string `sql:"user_name"` - Password string `sql:"password"` - SshPrivateKey string `sql:"ssh_private_key"` - AccessToken string `sql:"access_token"` - AuthMode constants.AuthMode `sql:"auth_mode,notnull"` - Active bool `sql:"active,notnull"` - Deleted bool `sql:"deleted,notnull"` - GitHostId int `sql:"git_host_id"` //id stored in db git_host( foreign key) - TlsCert string `sql:"tls_cert"` - TlsKey string `sql:"tls_key"` - CaCert string `sql:"ca_cert"` - EnableTLSVerification bool `sql:"enable_tls_verification"` + tableName struct{} `sql:"git_provider" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + Name string `sql:"name,notnull"` + Url string `sql:"url,notnull"` + UserName string `sql:"user_name"` + Password securestore.EncryptedString `sql:"password"` + SshPrivateKey securestore.EncryptedString `sql:"ssh_private_key"` + AccessToken securestore.EncryptedString `sql:"access_token"` + AuthMode constants.AuthMode `sql:"auth_mode,notnull"` + Active bool `sql:"active,notnull"` + Deleted bool `sql:"deleted,notnull"` + GitHostId int `sql:"git_host_id"` //id stored in db git_host( foreign key) + TlsCert string `sql:"tls_cert"` + TlsKey string `sql:"tls_key"` + CaCert string `sql:"ca_cert"` + EnableTLSVerification bool `sql:"enable_tls_verification"` sql.AuditLog } @@ -63,7 +64,11 @@ func NewGitProviderRepositoryImpl(dbConnection *pg.DB) *GitProviderRepositoryImp } func (impl GitProviderRepositoryImpl) Save(gitProvider *GitProvider) error { - err := impl.dbConnection.Insert(gitProvider) + err := encryptFieldsInGitProvider(gitProvider) + if err != nil { + return err + } + err = impl.dbConnection.Insert(gitProvider) return err } @@ -115,7 +120,11 @@ func (impl GitProviderRepositoryImpl) FindByUrl(providerUrl string) (GitProvider } func (impl GitProviderRepositoryImpl) Update(gitProvider *GitProvider) error { - err := impl.dbConnection.Update(gitProvider) + err := encryptFieldsInGitProvider(gitProvider) + if err != nil { + return err + } + err = impl.dbConnection.Update(gitProvider) return err } @@ -123,3 +132,20 @@ func (impl GitProviderRepositoryImpl) MarkProviderDeleted(gitProvider *GitProvid gitProvider.Deleted = true return impl.dbConnection.Update(gitProvider) } + +func encryptFieldsInGitProvider(gitProvider *GitProvider) error { + var err error + gitProvider.Password, err = securestore.EncryptString(gitProvider.Password.String()) + if err != nil { + return err + } + gitProvider.AccessToken, err = securestore.EncryptString(gitProvider.AccessToken.String()) + if err != nil { + return err + } + gitProvider.SshPrivateKey, err = securestore.EncryptString(gitProvider.SshPrivateKey.String()) + if err != nil { + return err + } + return nil +} diff --git a/pkg/build/trigger/HandlerService.go b/pkg/build/trigger/HandlerService.go index 0e82e62cd2..3f5ee96395 100644 --- a/pkg/build/trigger/HandlerService.go +++ b/pkg/build/trigger/HandlerService.go @@ -1018,9 +1018,9 @@ func (impl *HandlerServiceImpl) buildWfRequestForCiPipeline(pipeline *pipelineCo CommitTime: commitHashForPipelineId.Date.Format(bean.LayoutRFC3339), GitOptions: pipelineConfigBean.GitOptions{ UserName: ciMaterial.GitMaterial.GitProvider.UserName, - Password: ciMaterial.GitMaterial.GitProvider.Password, - SshPrivateKey: ciMaterial.GitMaterial.GitProvider.SshPrivateKey, - AccessToken: ciMaterial.GitMaterial.GitProvider.AccessToken, + Password: ciMaterial.GitMaterial.GitProvider.Password.String(), + SshPrivateKey: ciMaterial.GitMaterial.GitProvider.SshPrivateKey.String(), + AccessToken: ciMaterial.GitMaterial.GitProvider.AccessToken.String(), AuthMode: ciMaterial.GitMaterial.GitProvider.AuthMode, EnableTLSVerification: ciMaterial.GitMaterial.GitProvider.EnableTLSVerification, TlsKey: ciMaterial.GitMaterial.GitProvider.TlsKey, @@ -1306,10 +1306,10 @@ func (impl *HandlerServiceImpl) buildWfRequestForCiPipeline(pipeline *pipelineCo workflowRequest.DockerRepository = dockerRepository workflowRequest.CheckoutPath = checkoutPath workflowRequest.DockerUsername = dockerRegistry.Username - workflowRequest.DockerPassword = dockerRegistry.Password + workflowRequest.DockerPassword = dockerRegistry.Password.String() workflowRequest.AwsRegion = dockerRegistry.AWSRegion workflowRequest.AccessKey = dockerRegistry.AWSAccessKeyId - workflowRequest.SecretKey = dockerRegistry.AWSSecretAccessKey + workflowRequest.SecretKey = dockerRegistry.AWSSecretAccessKey.String() workflowRequest.DockerConnection = dockerRegistry.Connection workflowRequest.DockerCert = dockerRegistry.Cert diff --git a/pkg/cluster/repository/ClusterRepository.go b/pkg/cluster/repository/ClusterRepository.go index 1680a44ff2..5a9cbeb3a3 100644 --- a/pkg/cluster/repository/ClusterRepository.go +++ b/pkg/cluster/repository/ClusterRepository.go @@ -17,6 +17,7 @@ package repository import ( + "github.com/devtron-labs/common-lib/securestore" "github.com/devtron-labs/devtron/pkg/sql" "github.com/go-pg/pg" "go.uber.org/zap" @@ -24,25 +25,25 @@ import ( ) type Cluster struct { - tableName struct{} `sql:"cluster" pg:",discard_unknown_columns"` - Id int `sql:"id,pk"` - ClusterName string `sql:"cluster_name"` - Description string `sql:"description"` - ServerUrl string `sql:"server_url"` - PrometheusEndpoint string `sql:"prometheus_endpoint"` - Active bool `sql:"active,notnull"` - CdArgoSetup bool `sql:"cd_argo_setup,notnull"` - Config map[string]string `sql:"config"` - PUserName string `sql:"p_username"` - PPassword string `sql:"p_password"` - PTlsClientCert string `sql:"p_tls_client_cert"` - PTlsClientKey string `sql:"p_tls_client_key"` - AgentInstallationStage int `sql:"agent_installation_stage"` - K8sVersion string `sql:"k8s_version"` - ErrorInConnecting string `sql:"error_in_connecting"` - IsVirtualCluster bool `sql:"is_virtual_cluster"` - InsecureSkipTlsVerify bool `sql:"insecure_skip_tls_verify"` - IsProd bool `sql:"is_prod"` + tableName struct{} `sql:"cluster" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + ClusterName string `sql:"cluster_name"` + Description string `sql:"description"` + ServerUrl string `sql:"server_url"` + PrometheusEndpoint string `sql:"prometheus_endpoint"` + Active bool `sql:"active,notnull"` + CdArgoSetup bool `sql:"cd_argo_setup,notnull"` + Config securestore.EncryptedMap `sql:"config"` + PUserName string `sql:"p_username"` + PPassword string `sql:"p_password"` + PTlsClientCert string `sql:"p_tls_client_cert"` + PTlsClientKey string `sql:"p_tls_client_key"` + AgentInstallationStage int `sql:"agent_installation_stage"` + K8sVersion string `sql:"k8s_version"` + ErrorInConnecting string `sql:"error_in_connecting"` + IsVirtualCluster bool `sql:"is_virtual_cluster"` + InsecureSkipTlsVerify bool `sql:"insecure_skip_tls_verify"` + IsProd bool `sql:"is_prod"` sql.AuditLog } @@ -85,7 +86,11 @@ type ClusterRepositoryImpl struct { logger *zap.SugaredLogger } -func (impl ClusterRepositoryImpl) Save(model *Cluster) error { +func (impl ClusterRepositoryImpl) Save(model *Cluster) (err error) { + model.Config, err = securestore.EncryptMap(model.Config) + if err != nil { + return err + } return impl.dbConnection.Insert(model) } @@ -99,7 +104,13 @@ func (impl ClusterRepositoryImpl) FindOne(clusterName string) (*Cluster, error) Select() return cluster, err } -func (impl ClusterRepositoryImpl) SaveAll(models []*Cluster) error { +func (impl ClusterRepositoryImpl) SaveAll(models []*Cluster) (err error) { + for i := range models { + models[i].Config, err = securestore.EncryptMap(models[i].Config) + if err != nil { + return err + } + } return impl.dbConnection.Insert(models) } @@ -179,7 +190,11 @@ func (impl ClusterRepositoryImpl) FindByIds(id []int) ([]Cluster, error) { return cluster, err } -func (impl ClusterRepositoryImpl) Update(model *Cluster) error { +func (impl ClusterRepositoryImpl) Update(model *Cluster) (err error) { + model.Config, err = securestore.EncryptMap(model.Config) + if err != nil { + return err + } return impl.dbConnection.Update(model) } diff --git a/pkg/deployment/gitOps/adapter/adapter.go b/pkg/deployment/gitOps/adapter/adapter.go index 48c06ba350..4afbd2ded2 100644 --- a/pkg/deployment/gitOps/adapter/adapter.go +++ b/pkg/deployment/gitOps/adapter/adapter.go @@ -29,7 +29,7 @@ func GetGitOpsConfigBean(model *repository.GitOpsConfig) *apiGitOpsBean.GitOpsCo GitHubOrgId: model.GitHubOrgId, GitLabGroupId: model.GitLabGroupId, Active: model.Active, - Token: model.Token, + Token: model.Token.String(), Host: model.Host, Username: model.Username, UserId: model.CreatedBy, diff --git a/pkg/deployment/gitOps/config/GitOpsConfigReadService.go b/pkg/deployment/gitOps/config/GitOpsConfigReadService.go index 489ca824e4..7051bef734 100644 --- a/pkg/deployment/gitOps/config/GitOpsConfigReadService.go +++ b/pkg/deployment/gitOps/config/GitOpsConfigReadService.go @@ -177,7 +177,7 @@ func (impl *GitOpsConfigReadServiceImpl) GetAllGitOpsConfig() ([]*bean2.GitOpsCo GitHubOrgId: model.GitHubOrgId, GitLabGroupId: model.GitLabGroupId, Active: model.Active, - Token: model.Token, + Token: model.Token.String(), Host: model.Host, Username: model.Username, UserId: model.CreatedBy, diff --git a/pkg/deployment/trigger/devtronApps/preStageHandlerCode.go b/pkg/deployment/trigger/devtronApps/preStageHandlerCode.go index e91f9e67b9..424a22f5d1 100644 --- a/pkg/deployment/trigger/devtronApps/preStageHandlerCode.go +++ b/pkg/deployment/trigger/devtronApps/preStageHandlerCode.go @@ -561,9 +561,9 @@ func (impl *HandlerServiceImpl) buildWFRequest(runner *pipelineConfig.CdWorkflow Type: string(m.Type), GitOptions: pipelineConfigBean.GitOptions{ UserName: gitMaterial.GitProvider.UserName, - Password: gitMaterial.GitProvider.Password, - SshPrivateKey: gitMaterial.GitProvider.SshPrivateKey, - AccessToken: gitMaterial.GitProvider.AccessToken, + Password: gitMaterial.GitProvider.Password.String(), + SshPrivateKey: gitMaterial.GitProvider.SshPrivateKey.String(), + AccessToken: gitMaterial.GitProvider.AccessToken.String(), AuthMode: gitMaterial.GitProvider.AuthMode, }, } diff --git a/pkg/dockerRegistry/DockerRegistryIpsConfigService.go b/pkg/dockerRegistry/DockerRegistryIpsConfigService.go index 8e8dcd57ee..1d10236b2a 100644 --- a/pkg/dockerRegistry/DockerRegistryIpsConfigService.go +++ b/pkg/dockerRegistry/DockerRegistryIpsConfigService.go @@ -148,7 +148,7 @@ func (impl DockerRegistryIpsConfigServiceImpl) createOrUpdateDockerRegistryImage impl.logger.Infow("creating/updating ips", "ipsName", ipsName, "clusterId", clusterId) username := dockerRegistryBean.Username - password := dockerRegistryBean.Password + password := dockerRegistryBean.Password.String() registryURL := dockerRegistryBean.RegistryURL var email string @@ -187,7 +187,7 @@ func (impl DockerRegistryIpsConfigServiceImpl) createOrUpdateDockerRegistryImage } // create credential for ecr impl.logger.Info("creating ecr credential") - ecrUsername, ecrPassword, err := CreateCredentialForEcr(dockerRegistryBean.AWSRegion, awsAccessKeyId, awsSecretAccessKey) + ecrUsername, ecrPassword, err := CreateCredentialForEcr(dockerRegistryBean.AWSRegion, awsAccessKeyId, awsSecretAccessKey.String()) if err != nil { impl.logger.Errorw("error in creating ecr credential", "clusterId", clusterId, "error", err) return err diff --git a/pkg/gitops/GitOpsConfigService.go b/pkg/gitops/GitOpsConfigService.go index 24a96e375c..fc19931a83 100644 --- a/pkg/gitops/GitOpsConfigService.go +++ b/pkg/gitops/GitOpsConfigService.go @@ -25,6 +25,7 @@ import ( cluster3 "github.com/argoproj/argo-cd/v2/pkg/apiclient/cluster" repocreds2 "github.com/argoproj/argo-cd/v2/pkg/apiclient/repocreds" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" + "github.com/devtron-labs/common-lib/securestore" util4 "github.com/devtron-labs/common-lib/utils/k8s" "github.com/devtron-labs/devtron/api/bean" apiBean "github.com/devtron-labs/devtron/api/bean/gitOps" @@ -187,7 +188,7 @@ func (impl *GitOpsConfigServiceImpl) ValidateAndUpdateGitOpsConfig(config *apiBe return apiBean.DetailedErrorGitOpsConfigResponse{}, err } if isTokenEmpty { - config.Token = model.Token + config.Token = model.Token.String() } if isTlsDetailsEmpty { caData := model.CaCert @@ -247,7 +248,7 @@ func (impl *GitOpsConfigServiceImpl) registerGitOpsClientConfig(ctx context.Cont Creds: &v1alpha1.RepoCreds{ URL: request.Host, Username: model.Username, - Password: model.Token, + Password: model.Token.String(), TLSClientCertData: model.TlsCert, TLSClientCertKey: model.TlsKey, }, @@ -406,7 +407,7 @@ func (impl *GitOpsConfigServiceImpl) createGitOpsConfig(ctx context.Context, req model := &repository.GitOpsConfig{ Provider: strings.ToUpper(request.Provider), Username: request.Username, - Token: request.Token, + Token: securestore.ToEncryptedString(request.Token), GitLabGroupId: request.GitLabGroupId, GitHubOrgId: request.GitHubOrgId, AzureProject: request.AzureProjectName, @@ -534,7 +535,7 @@ func (impl *GitOpsConfigServiceImpl) patchGitOpsClientConfig(model *repository.G Creds: &v1alpha1.RepoCreds{ URL: request.Host, Username: model.Username, - Password: model.Token, + Password: model.Token.String(), TLSClientCertData: model.TlsCert, TLSClientCertKey: model.TlsKey, }, @@ -678,7 +679,7 @@ func (impl *GitOpsConfigServiceImpl) updateGitOpsConfig(request *apiBean.GitOpsC model.Provider = strings.ToUpper(request.Provider) model.Username = request.Username - model.Token = request.Token + model.Token = securestore.ToEncryptedString(request.Token) model.GitLabGroupId = request.GitLabGroupId model.GitHubOrgId = request.GitHubOrgId model.Host = request.Host @@ -782,7 +783,7 @@ func (impl *GitOpsConfigServiceImpl) GetGitOpsConfigById(id int) (*apiBean.GitOp GitHubOrgId: model.GitHubOrgId, GitLabGroupId: model.GitLabGroupId, Username: model.Username, - Token: model.Token, + Token: model.Token.String(), Host: model.Host, Active: model.Active, UserId: model.CreatedBy, @@ -852,7 +853,7 @@ func (impl *GitOpsConfigServiceImpl) GetGitOpsConfigByProvider(provider string) GitHubOrgId: model.GitHubOrgId, GitLabGroupId: model.GitLabGroupId, Username: model.Username, - Token: model.Token, + Token: model.Token.String(), Host: model.Host, Active: model.Active, UserId: model.CreatedBy, @@ -890,7 +891,7 @@ func (impl *GitOpsConfigServiceImpl) GitOpsValidateDryRun(isArgoModuleInstalled return apiBean.DetailedErrorGitOpsConfigResponse{} } if isTokenEmpty { - config.Token = model.Token + config.Token = model.Token.String() } if isTlsDetailsEmpty { caData := model.CaCert diff --git a/pkg/pipeline/BuildPipelineConfigService.go b/pkg/pipeline/BuildPipelineConfigService.go index b003cbeedb..fbb5d37aa7 100644 --- a/pkg/pipeline/BuildPipelineConfigService.go +++ b/pkg/pipeline/BuildPipelineConfigService.go @@ -1180,7 +1180,7 @@ func (impl *CiPipelineConfigServiceImpl) UpdateCiTemplate(updateRequest *bean.Ci } if dockerArtifaceStore.RegistryType == dockerRegistryRepository.REGISTRYTYPE_ECR { - err := impl.ciCdPipelineOrchestrator.CreateEcrRepo(repo, dockerArtifaceStore.AWSRegion, dockerArtifaceStore.AWSAccessKeyId, dockerArtifaceStore.AWSSecretAccessKey) + err := impl.ciCdPipelineOrchestrator.CreateEcrRepo(repo, dockerArtifaceStore.AWSRegion, dockerArtifaceStore.AWSAccessKeyId, dockerArtifaceStore.AWSSecretAccessKey.String()) if err != nil { impl.logger.Errorw("ecr repo creation failed while updating ci template", "repo", repo, "err", err) return nil, err @@ -1410,7 +1410,7 @@ func (impl *CiPipelineConfigServiceImpl) CreateCiPipeline(createRequest *bean.Ci } if store.RegistryType == dockerRegistryRepository.REGISTRYTYPE_ECR { - err := impl.ciCdPipelineOrchestrator.CreateEcrRepo(repo, store.AWSRegion, store.AWSAccessKeyId, store.AWSSecretAccessKey) + err := impl.ciCdPipelineOrchestrator.CreateEcrRepo(repo, store.AWSRegion, store.AWSAccessKeyId, store.AWSSecretAccessKey.String()) if err != nil { impl.logger.Errorw("ecr repo creation failed while creating ci pipeline", "repo", repo, "err", err) return nil, err diff --git a/pkg/pipeline/CiCdPipelineOrchestrator.go b/pkg/pipeline/CiCdPipelineOrchestrator.go index 3d8750ea81..82222aaffd 100644 --- a/pkg/pipeline/CiCdPipelineOrchestrator.go +++ b/pkg/pipeline/CiCdPipelineOrchestrator.go @@ -2268,7 +2268,7 @@ func (impl CiCdPipelineOrchestratorImpl) createDockerRepoIfNeeded(dockerRegistry return err } if dockerArtifactStore.RegistryType == dockerRegistryRepository.REGISTRYTYPE_ECR { - err := impl.CreateEcrRepo(dockerRepository, dockerArtifactStore.AWSRegion, dockerArtifactStore.AWSAccessKeyId, dockerArtifactStore.AWSSecretAccessKey) + err := impl.CreateEcrRepo(dockerRepository, dockerArtifactStore.AWSRegion, dockerArtifactStore.AWSAccessKeyId, dockerArtifactStore.AWSSecretAccessKey.String()) if err != nil { impl.logger.Errorw("ecr repo creation failed while updating ci template", "err", err, "repo", dockerRepository) return err diff --git a/pkg/pipeline/DockerRegistryConfig.go b/pkg/pipeline/DockerRegistryConfig.go index 63c13e30ff..c5fc6fad66 100644 --- a/pkg/pipeline/DockerRegistryConfig.go +++ b/pkg/pipeline/DockerRegistryConfig.go @@ -19,6 +19,7 @@ package pipeline import ( "context" "fmt" + "github.com/devtron-labs/common-lib/securestore" bean2 "github.com/devtron-labs/devtron/api/helm-app/gRPC" client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/client/argocdServer" @@ -90,10 +91,10 @@ func NewDockerArtifactStore(bean *types.DockerArtifactStoreBean, isActive bool, RegistryType: bean.RegistryType, IsOCICompliantRegistry: bean.IsOCICompliantRegistry, AWSAccessKeyId: bean.AWSAccessKeyId, - AWSSecretAccessKey: bean.AWSSecretAccessKey, + AWSSecretAccessKey: securestore.ToEncryptedString(bean.AWSSecretAccessKey), AWSRegion: bean.AWSRegion, Username: bean.Username, - Password: bean.Password, + Password: securestore.ToEncryptedString(bean.Password), IsDefault: bean.IsDefault, Connection: bean.Connection, Cert: bean.Cert, @@ -487,10 +488,10 @@ func (impl DockerRegistryConfigImpl) FetchOneDockerAccount(storeId string) (*typ RegistryURL: store.RegistryURL, RegistryType: store.RegistryType, AWSAccessKeyId: store.AWSAccessKeyId, - AWSSecretAccessKey: store.AWSSecretAccessKey, + AWSSecretAccessKey: store.AWSSecretAccessKey.String(), AWSRegion: store.AWSRegion, Username: store.Username, - Password: store.Password, + Password: store.Password.String(), IsDefault: store.IsDefault, Connection: store.Connection, Cert: store.Cert, @@ -536,11 +537,11 @@ func (impl DockerRegistryConfigImpl) Update(bean *types.DockerArtifactStoreBean) // 3- update docker_registry_config if bean.Password == "" { - bean.Password = existingStore.Password + bean.Password = existingStore.Password.String() } if bean.AWSSecretAccessKey == "" { - bean.AWSSecretAccessKey = existingStore.AWSSecretAccessKey + bean.AWSSecretAccessKey = existingStore.AWSSecretAccessKey.String() } if bean.Cert == "" { diff --git a/pkg/pipeline/PipelineBuilder.go b/pkg/pipeline/PipelineBuilder.go index 6fe330b399..231d3e40e1 100644 --- a/pkg/pipeline/PipelineBuilder.go +++ b/pkg/pipeline/PipelineBuilder.go @@ -157,10 +157,10 @@ func (impl *PipelineBuilderImpl) getGitMaterialsForApp(appId int) ([]*bean.GitMa var password string userName := material.GitProvider.UserName if material.GitProvider.AuthMode == constants.AUTH_MODE_USERNAME_PASSWORD { - password = material.GitProvider.Password + password = material.GitProvider.Password.String() } else if material.GitProvider.AuthMode == constants.AUTH_MODE_ACCESS_TOKEN { - password = material.GitProvider.AccessToken + password = material.GitProvider.AccessToken.String() if userName == "" { userName = "devtron-boat" } diff --git a/pkg/pipeline/adapter/adapter.go b/pkg/pipeline/adapter/adapter.go index 4188e90c48..0b966d721c 100644 --- a/pkg/pipeline/adapter/adapter.go +++ b/pkg/pipeline/adapter/adapter.go @@ -39,12 +39,12 @@ func GetDockerConfigBean(dockerRegistry *dockerRegistryRepository.DockerArtifact RegistryType: dockerRegistry.RegistryType, RegistryURL: dockerRegistry.RegistryURL, Username: dockerRegistry.Username, - Password: dockerRegistry.Password, + Password: dockerRegistry.Password.String(), AWSRegion: dockerRegistry.AWSRegion, Connection: dockerRegistry.Connection, Cert: dockerRegistry.Cert, AWSAccessKeyId: dockerRegistry.AWSAccessKeyId, - AWSSecretAccessKey: dockerRegistry.AWSSecretAccessKey, + AWSSecretAccessKey: dockerRegistry.AWSSecretAccessKey.String(), } } diff --git a/vendor/github.com/devtron-labs/common-lib/middlewares/recovery.go b/vendor/github.com/devtron-labs/common-lib/middlewares/recovery.go index 39d7604113..c8e055be87 100644 --- a/vendor/github.com/devtron-labs/common-lib/middlewares/recovery.go +++ b/vendor/github.com/devtron-labs/common-lib/middlewares/recovery.go @@ -35,7 +35,8 @@ func Recovery(next http.Handler) http.Handler { if errors.Is(err.(error), http.ErrAbortHandler) { // suppress logging for http.ErrAbortHandler panic // separate metric for reverse proxy panic recovery - metrics.IncReverseProxyPanicRecoveryCount("proxy", r.Host, r.Method, r.RequestURI) + //metrics.IncReverseProxyPanicRecoveryCount("proxy", r.Host, r.Method, r.RequestURI) + log.Print("Reverse Proxy Panic Recovery count increased ", "Host: ", r.Host, "Method: ", r.Method, "Path: ", r.RequestURI) } else { // log and increment panic recovery count metrics.IncPanicRecoveryCount("handler", r.Host, r.Method, r.RequestURI) diff --git a/vendor/github.com/devtron-labs/common-lib/securestore/AttributesRepoDBConnection.go b/vendor/github.com/devtron-labs/common-lib/securestore/AttributesRepoDBConnection.go new file mode 100644 index 0000000000..907d202bd4 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/securestore/AttributesRepoDBConnection.go @@ -0,0 +1,75 @@ +package securestore + +import ( + "github.com/caarlos0/env" + "github.com/devtron-labs/common-lib/utils" + "github.com/devtron-labs/common-lib/utils/bean" + "github.com/go-pg/pg" + "log" +) + +func NewAttributesRepositoryImplForDatabase(databaseName string) (*AttributesRepositoryImpl, error) { + dbConn, err := newDbConnection(databaseName) + if err != nil { + return nil, err + } + return NewAttributesRepositoryImpl(dbConn), nil +} + +type config struct { + Addr string `env:"PG_ADDR" envDefault:"127.0.0.1"` + Port string `env:"PG_PORT" envDefault:"5432"` + User string `env:"PG_USER" envDefault:""` + Password string `env:"PG_PASSWORD" envDefault:"" secretData:"-"` + Database string `env:"PG_DATABASE" envDefault:"orchestrator"` + ApplicationName string `env:"APP" envDefault:"orchestrator"` + bean.PgQueryMonitoringConfig + LocalDev bool `env:"RUNTIME_CONFIG_LOCAL_DEV" envDefault:"false"` +} + +func getDbConfig(databaseName string) (*config, error) { + cfg := &config{} + err := env.Parse(cfg) + if err != nil { + return cfg, err + } + monitoringCfg, err := bean.GetPgQueryMonitoringConfig(cfg.ApplicationName) + if err != nil { + return cfg, err + } + cfg.PgQueryMonitoringConfig = monitoringCfg + if !cfg.LocalDev { + cfg.Database = databaseName //overriding database + } + return cfg, err +} + +func newDbConnection(databaseName string) (*pg.DB, error) { + cfg, err := getDbConfig(databaseName) + if err != nil { + return nil, err + } + options := pg.Options{ + Addr: cfg.Addr + ":" + cfg.Port, + User: cfg.User, + Password: cfg.Password, + Database: cfg.Database, + ApplicationName: cfg.ApplicationName, + } + dbConnection := pg.Connect(&options) + //check db connection + var test string + _, err = dbConnection.QueryOne(&test, `SELECT 1`) + + if err != nil { + log.Println("error in connecting orchestrator db ", "err", err) + return nil, err + } else { + log.Println("connected with orchestrator db") + } + //-------------- + if cfg.LogSlowQuery { + dbConnection.OnQueryProcessed(utils.GetPGPostQueryProcessor(cfg.PgQueryMonitoringConfig)) + } + return dbConnection, err +} diff --git a/vendor/github.com/devtron-labs/common-lib/securestore/AttributesRepository.go b/vendor/github.com/devtron-labs/common-lib/securestore/AttributesRepository.go new file mode 100644 index 0000000000..eadf7a8f4b --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/securestore/AttributesRepository.go @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2020-2024. Devtron Inc. + */ + +package securestore + +import ( + sql2 "github.com/devtron-labs/common-lib/utils/sql" + "github.com/go-pg/pg" + "time" +) + +const ENCRYPTION_KEY string = "encryptionKey" // AES-256 encryption key for sensitive data + +type Attributes struct { + tableName struct{} `sql:"attributes" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + Key string `sql:"key,notnull"` + Value string `sql:"value,notnull"` + Active bool `sql:"active, notnull"` + sql2.AuditLog +} + +type AttributesRepository interface { + Save(model *Attributes, tx *pg.Tx) (*Attributes, error) + Update(model *Attributes, tx *pg.Tx) error + FindByKey(key string) (*Attributes, error) + GetConnection() (dbConnection *pg.DB) + SaveEncryptionKeyIfNotExists(value string) error + GetEncryptionKey() (string, error) +} + +type AttributesRepositoryImpl struct { + dbConnection *pg.DB +} + +func NewAttributesRepositoryImpl(dbConnection *pg.DB) *AttributesRepositoryImpl { + return &AttributesRepositoryImpl{dbConnection: dbConnection} +} + +func (impl *AttributesRepositoryImpl) GetConnection() (dbConnection *pg.DB) { + return impl.dbConnection +} + +func (repo AttributesRepositoryImpl) Save(model *Attributes, tx *pg.Tx) (*Attributes, error) { + err := tx.Insert(model) + if err != nil { + return model, err + } + return model, nil +} + +func (repo AttributesRepositoryImpl) Update(model *Attributes, tx *pg.Tx) error { + err := tx.Update(model) + if err != nil { + return err + } + return nil +} + +func (repo AttributesRepositoryImpl) FindByKey(key string) (*Attributes, error) { + model := &Attributes{} + err := repo.dbConnection. + Model(model). + Where("key = ?", key). + Where("active = ?", true). + Select() + if err != nil { + return model, err + } + return model, nil +} + +// SaveEncryptionKeyIfNotExists saves an encryption key in the attributes table if not exists +func (repo AttributesRepositoryImpl) SaveEncryptionKeyIfNotExists(value string) error { + dbConnection := repo.GetConnection() + tx, err := dbConnection.Begin() + if err != nil { + return err + } + defer tx.Rollback() + + //deleting all keys if exists for safe side + _, err = tx.Model(&Attributes{}).Where("key = ?", ENCRYPTION_KEY).Delete() + // Create new encryption key entry + model := &Attributes{ + Key: ENCRYPTION_KEY, + Value: value, + Active: true, + AuditLog: sql2.AuditLog{ + CreatedBy: 1, + UpdatedBy: 1, + CreatedOn: time.Now(), + UpdatedOn: time.Now(), + }, + } + _, err = repo.Save(model, tx) + if err != nil { + return err + } + return tx.Commit() +} + +// GetEncryptionKey retrieves the active encryption key from the attributes table +func (repo AttributesRepositoryImpl) GetEncryptionKey() (string, error) { + model, err := repo.FindByKey(ENCRYPTION_KEY) + if err != nil { + return "", err + } + return model.Value, nil +} diff --git a/vendor/github.com/devtron-labs/common-lib/securestore/EncryptionKeyService.go b/vendor/github.com/devtron-labs/common-lib/securestore/EncryptionKeyService.go new file mode 100644 index 0000000000..f8a37acece --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/securestore/EncryptionKeyService.go @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024. Devtron Inc. + */ + +package securestore + +import ( + "crypto/rand" + "encoding/hex" + "fmt" + "github.com/go-pg/pg" + log "github.com/sirupsen/logrus" +) + +func SetEncryptionKey() error { + repo, err := NewAttributesRepositoryImplForDatabase("orchestrator") //hardcoded for orchestrator as need to pick a common key for every service + if err != nil { + log.Println("error in creating attributes repository", "err", err) + return err + } + encryptionService := NewEncryptionKeyServiceImpl(repo) + err = encryptionService.CreateAndStoreEncryptionKey() + if err != nil { + log.Println("error in creating and storing encryption key", "err", err) + return err + } + return nil +} + +type EncryptionKeyService interface { + // CreateAndStoreEncryptionKey generates a new AES-256 encryption key and stores it in the attributes repository + CreateAndStoreEncryptionKey() error + + // RotateEncryptionKey generates a new encryption key and stores it (deactivating the old one) + RotateEncryptionKey(userId int32) (string, error) + + // GenerateEncryptionKey generates a new AES-256 encryption key (32 bytes) + GenerateEncryptionKey() (string, error) + + GetEncryptionKey() (string, error) +} + +type EncryptionKeyServiceImpl struct { + attributesRepository AttributesRepository +} + +func NewEncryptionKeyServiceImpl(attributesRepository AttributesRepository) *EncryptionKeyServiceImpl { + impl := &EncryptionKeyServiceImpl{ + attributesRepository: attributesRepository, + } + return impl +} + +// GenerateEncryptionKey generates a new AES-256 encryption key (32 bytes = 256 bits) +func (impl *EncryptionKeyServiceImpl) GenerateEncryptionKey() (string, error) { + // Generate 32 random bytes for AES-256 + key := make([]byte, 32) + _, err := rand.Read(key) + if err != nil { + log.Error("error generating random encryption key", "err", err) + return "", fmt.Errorf("failed to generate encryption key: %w", err) + } + // Encode to hex string for storage + keyHex := hex.EncodeToString(key) + return keyHex, nil +} + +// CreateAndStoreEncryptionKey generates a new AES-256 encryption key and stores it in the attributes repository +func (impl *EncryptionKeyServiceImpl) CreateAndStoreEncryptionKey() error { + // Check if encryption key already exists + encryptionKeyModel, err := impl.attributesRepository.FindByKey(ENCRYPTION_KEY) + if err != nil && err != pg.ErrNoRows { + log.Error("error checking for existing encryption key", "err", err) + return err + } + var encryptionKeyEncoded string + if encryptionKeyModel != nil && encryptionKeyModel.Id > 0 && len(encryptionKeyModel.Value) > 0 { + encryptionKeyEncoded = encryptionKeyModel.Value + log.Println("encryption key already exists", "keyId", encryptionKeyModel.Id) + } else { + // Generate new encryption key + encryptionKeyNew, err := impl.GenerateEncryptionKey() + if err != nil { + return err + } + // Store in repository + err = impl.attributesRepository.SaveEncryptionKeyIfNotExists(encryptionKeyNew) + if err != nil { + log.Error("error storing encryption key", "err", err) + return fmt.Errorf("failed to store encryption key: %w", err) + } + encryptionKeyEncoded = encryptionKeyNew + log.Println("Successfully created and stored encryption key") + } + + encryptionKey, err = hex.DecodeString(encryptionKeyEncoded) + if err != nil || len(encryptionKey) != 32 { + return fmt.Errorf("encryptionKey is incorrect : %v", err) + } + return nil +} + +// RotateEncryptionKey generates a new encryption key and stores it (deactivating the old one) +func (impl *EncryptionKeyServiceImpl) RotateEncryptionKey(userId int32) (string, error) { + log.Println("Rotating encryption key", "userId", userId) + + // Generate new encryption key + newEncryptionKey, err := impl.GenerateEncryptionKey() + if err != nil { + return "", err + } + + // Store in repository (this will deactivate the old key) + err = impl.attributesRepository.SaveEncryptionKeyIfNotExists(newEncryptionKey) + if err != nil { + log.Error("error rotating encryption key", "err", err) + return "", fmt.Errorf("failed to rotate encryption key: %w", err) + } + //TODO: also need to rotate encryption's already done + log.Println("Successfully rotated encryption key", "userId", userId) + return newEncryptionKey, nil +} + +// GetEncryptionKey retrieves the active encryption key from the repository +func (impl *EncryptionKeyServiceImpl) GetEncryptionKey() (string, error) { + key, err := impl.attributesRepository.GetEncryptionKey() + if err != nil { + if err == pg.ErrNoRows { + log.Error("encryption key not found in repository") + return "", fmt.Errorf("encryption key not found, please create one first") + } + log.Error("error retrieving encryption key", "err", err) + return "", err + } + return key, nil +} diff --git a/vendor/github.com/devtron-labs/common-lib/securestore/common.go b/vendor/github.com/devtron-labs/common-lib/securestore/common.go new file mode 100644 index 0000000000..4444765e3d --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/securestore/common.go @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024. Devtron Inc. + */ + +package securestore + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "github.com/go-pg/pg/types" + "io" +) + +var decryptionFailErr = fmt.Errorf("Decryption failed") + +func DidDecryptionFail(err error) bool { + return errors.Is(err, decryptionFailErr) +} + +var encryptionKey []byte + +func encrypt(data []byte) (string, error) { + if len(data) == 0 { + return "", nil + } + block, err := aes.NewCipher(encryptionKey) + if err != nil { + return "", err + } + aesGCM, err := cipher.NewGCM(block) + if err != nil { + return "", err + } + nonce := make([]byte, aesGCM.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return "", err + } + ciphertext := aesGCM.Seal(nonce, nonce, data, nil) + return base64.StdEncoding.EncodeToString(ciphertext), nil +} + +func decrypt(cipherBase64 string) (string, error) { + // Try decrypting (normal encrypted flow) + cipherData, err := base64.StdEncoding.DecodeString(cipherBase64) + if err == nil { + block, err := aes.NewCipher(encryptionKey) + if err != nil { + return "", err + } + aesGCM, err := cipher.NewGCM(block) + if err != nil { + return "", err + } + nonceSize := aesGCM.NonceSize() + if len(cipherData) >= nonceSize { + nonce, ciphertext := cipherData[:nonceSize], cipherData[nonceSize:] + plainText, err := aesGCM.Open(nil, nonce, ciphertext, nil) + if err == nil { + return string(plainText), nil // Successfully decrypted + } + } + } + return cipherBase64, decryptionFailErr +} + +// AppendValue : can be used for auto encryption of fields but is only supported in go-pg/v10. Not being used anywhere as of now, to be tested when start using. +func (e EncryptedMap) AppendValue(b []byte, quote int) ([]byte, error) { + jsonBytes, err := json.Marshal(e) + if err != nil { + return nil, err + } + + encryptedString, err := encrypt(jsonBytes) + if err != nil { + return nil, err + } + + return types.AppendString(b, encryptedString, quote), nil +} diff --git a/vendor/github.com/devtron-labs/common-lib/securestore/map.go b/vendor/github.com/devtron-labs/common-lib/securestore/map.go new file mode 100644 index 0000000000..dd9c258461 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/securestore/map.go @@ -0,0 +1,73 @@ +package securestore + +import ( + "encoding/json" + "fmt" +) + +type EncryptedMap map[string]string + +const ( + ENCRYPTED_KEY = "encrypted_data" +) + +func EncryptMap(m EncryptedMap) (map[string]string, error) { + bytesM, err := json.Marshal(m) + if err != nil { + return nil, err + } + encryptedData, err := encrypt(bytesM) + if err != nil { + return nil, err + } + return EncryptedMap{ENCRYPTED_KEY: encryptedData}, nil +} + +func decryptMap(mCipher []byte) (map[string]string, error) { + var m map[string]string + err := json.Unmarshal(mCipher, &m) + if err != nil { + return nil, err + } + if len(m[ENCRYPTED_KEY]) > 0 { + decryptedMapBytes, err := decrypt(m[ENCRYPTED_KEY]) + if err != nil && !DidDecryptionFail(err) { + return nil, err + } + if err == nil { + var decryptedMap map[string]string + err = json.Unmarshal([]byte(decryptedMapBytes), &decryptedMap) + if err != nil { + return nil, err + } + return decryptedMap, nil + } + } else { + // Fallback: maybe it's just raw JSON + // Validate that it's a valid JSON map[string]string + // Neither decrypted nor valid plaintext JSON + return m, nil + } + return nil, fmt.Errorf("decryption failed and data is not valid plaintext JSON") +} + +func (e *EncryptedMap) Scan(value interface{}) error { + if value == nil { + return nil + } + var encrypted []byte + switch v := value.(type) { + case string: + encrypted = []byte(v) + case []byte: + encrypted = v + default: + return fmt.Errorf("unsupported type: %T", v) + } + var err error + *e, err = decryptMap(encrypted) + if err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/devtron-labs/common-lib/securestore/strings.go b/vendor/github.com/devtron-labs/common-lib/securestore/strings.go new file mode 100644 index 0000000000..e7c5128b20 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/securestore/strings.go @@ -0,0 +1,60 @@ +package securestore + +import ( + "fmt" +) + +type EncryptedString string + +func (e *EncryptedString) String() string { + return string(*e) +} + +func ToEncryptedString(s string) EncryptedString { + return EncryptedString(s) +} + +func EncryptString(data string) (EncryptedString, error) { + encryptedStr, err := encrypt([]byte(data)) + if err != nil { + return "", err + } + return EncryptedString(encryptedStr), nil +} + +func decryptString(cipherBase64 string) (string, error) { + decryptedBytes, err := decrypt(cipherBase64) + if err != nil && !DidDecryptionFail(err) { + return "", err + } + // Fallback: decrypting failed, considering it as just normal string + if DidDecryptionFail(err) { + return cipherBase64, nil + } else { + return decryptedBytes, nil + } +} + +func (e *EncryptedString) Scan(value interface{}) error { + if value == nil { + return nil + } + var encrypted []byte + switch v := value.(type) { + case string: + encrypted = []byte(v) + case []byte: + encrypted = v + default: + return fmt.Errorf("unsupported type: %T", v) + } + decryptedBytes, err := decryptString(string(encrypted)) + if err != nil { + return err + } + if decryptedBytes == "" { + return nil + } + *e = EncryptedString(decryptedBytes) + return nil +} diff --git a/vendor/github.com/devtron-labs/common-lib/utils/sql/AuditLog.go b/vendor/github.com/devtron-labs/common-lib/utils/sql/AuditLog.go new file mode 100644 index 0000000000..fb3a38e79d --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/utils/sql/AuditLog.go @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020-2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sql + +import ( + "time" +) + +type AuditLog struct { + CreatedOn time.Time `sql:"created_on,type:timestamptz"` + CreatedBy int32 `sql:"created_by,type:integer"` + UpdatedOn time.Time `sql:"updated_on,type:timestamptz"` + UpdatedBy int32 `sql:"updated_by,type:integer"` +} + +func NewDefaultAuditLog(userId int32) AuditLog { + return AuditLog{ + CreatedOn: time.Now(), + CreatedBy: userId, + UpdatedOn: time.Now(), + UpdatedBy: userId, + } +} + +// CreateAuditLog can be used by any repository to create AuditLog for insert operation +func (model *AuditLog) CreateAuditLog(userId int32) { + model.CreatedOn = time.Now() + model.UpdatedOn = time.Now() + model.CreatedBy = userId + model.UpdatedBy = userId +} + +// UpdateAuditLog can be used by any repository to update AuditLog for update operation +func (model *AuditLog) UpdateAuditLog(userId int32) { + model.UpdatedOn = time.Now() + model.UpdatedBy = userId +} diff --git a/vendor/github.com/devtron-labs/common-lib/utils/sql/TransactionWrapper.go b/vendor/github.com/devtron-labs/common-lib/utils/sql/TransactionWrapper.go new file mode 100644 index 0000000000..3c797e1e12 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/utils/sql/TransactionWrapper.go @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sql + +import "github.com/go-pg/pg" + +type TransactionWrapper interface { + StartTx() (*pg.Tx, error) + RollbackTx(tx *pg.Tx) error + CommitTx(tx *pg.Tx) error +} + +type TransactionUtilImpl struct { + dbConnection *pg.DB +} + +func NewTransactionUtilImpl(db *pg.DB) *TransactionUtilImpl { + return &TransactionUtilImpl{ + dbConnection: db, + } +} +func (impl *TransactionUtilImpl) RollbackTx(tx *pg.Tx) error { + return tx.Rollback() +} +func (impl *TransactionUtilImpl) CommitTx(tx *pg.Tx) error { + return tx.Commit() +} +func (impl *TransactionUtilImpl) StartTx() (*pg.Tx, error) { + return impl.dbConnection.Begin() +} diff --git a/vendor/github.com/devtron-labs/common-lib/utils/sql/connection.go b/vendor/github.com/devtron-labs/common-lib/utils/sql/connection.go new file mode 100644 index 0000000000..fa6858e5de --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/utils/sql/connection.go @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020-2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sql + +import ( + "github.com/devtron-labs/common-lib/utils" + "github.com/devtron-labs/common-lib/utils/bean" + "go.uber.org/zap" + "reflect" + "time" + + "github.com/caarlos0/env" + "github.com/go-pg/pg" +) + +// CATEGORY=POSTGRES +type Config struct { + Addr string `env:"PG_ADDR" envDefault:"127.0.0.1" description:"address of postgres service" example:"postgresql-postgresql.devtroncd" deprecated:"false"` + Port string `env:"PG_PORT" envDefault:"5432" description:"port of postgresql service" example:"5432"` + User string `env:"PG_USER" envDefault:"" description:"user for postgres" example:"postgres"` + Password string `env:"PG_PASSWORD" envDefault:"" secretData:"-" description:"password for postgres, associated with PG_USER" example:"confidential ;)"` + Database string `env:"PG_DATABASE" envDefault:"orchestrator" description:"postgres database to be made connection with" example:"orchestrator, casbin, git_sensor, lens"` + CasbinDatabase string `env:"CASBIN_DATABASE" envDefault:"casbin""` + ApplicationName string `env:"APP" envDefault:"orchestrator" description:"Application name"` + ReadTimeout int64 `env:"PG_READ_TIMEOUT" envDefault:"30"` + WriteTimeout int64 `env:"PG_WRITE_TIMEOUT" envDefault:"30"` + bean.PgQueryMonitoringConfig +} + +func GetConfig() (*Config, error) { + cfg := &Config{} + err := env.Parse(cfg) + if err != nil { + return cfg, err + } + monitoringCfg, err := bean.GetPgQueryMonitoringConfig(cfg.ApplicationName) + if err != nil { + return cfg, err + } + cfg.PgQueryMonitoringConfig = monitoringCfg + return cfg, err +} + +func NewDbConnection(cfg *Config, logger *zap.SugaredLogger) (*pg.DB, error) { + options := pg.Options{ + Addr: cfg.Addr + ":" + cfg.Port, + User: cfg.User, + Password: cfg.Password, + Database: cfg.Database, + ApplicationName: cfg.ApplicationName, + ReadTimeout: time.Duration(cfg.ReadTimeout) * time.Second, + WriteTimeout: time.Duration(cfg.WriteTimeout) * time.Second, + } + dbConnection := pg.Connect(&options) + // check db connection + var test string + _, err := dbConnection.QueryOne(&test, `SELECT 1`) + + if err != nil { + logger.Errorw("error in connecting db ", "db", obfuscateSecretTags(cfg), "err", err) + return nil, err + } else { + logger.Infow("connected with db", "db", obfuscateSecretTags(cfg)) + } + + // -------------- + dbConnection.OnQueryProcessed(utils.GetPGPostQueryProcessor(cfg.PgQueryMonitoringConfig)) + return dbConnection, err +} + +func obfuscateSecretTags(cfg interface{}) interface{} { + + cfgDpl := reflect.New(reflect.ValueOf(cfg).Elem().Type()).Interface() + cfgDplElm := reflect.ValueOf(cfgDpl).Elem() + t := cfgDplElm.Type() + for i := 0; i < t.NumField(); i++ { + if _, ok := t.Field(i).Tag.Lookup("secretData"); ok { + cfgDplElm.Field(i).SetString("********") + } else { + cfgDplElm.Field(i).Set(reflect.ValueOf(cfg).Elem().Field(i)) + } + } + return cfgDpl +} + +/*type DbConnectionHolder struct { + connection *pg.DB +} + +func (holder *DbConnectionHolder) CloseConnection() error { + return holder.connection.Close() +}*/ diff --git a/vendor/github.com/devtron-labs/common-lib/utils/sql/wire_sql.go b/vendor/github.com/devtron-labs/common-lib/utils/sql/wire_sql.go new file mode 100644 index 0000000000..32aee8f5b5 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/utils/sql/wire_sql.go @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024. Devtron Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sql + +import ( + "github.com/google/wire" +) + +var PgSqlWireSet = wire.NewSet( + GetConfig, + NewDbConnection, +) diff --git a/vendor/modules.txt b/vendor/modules.txt index d246a7f6f5..2c07d04059 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -523,7 +523,7 @@ github.com/davecgh/go-spew/spew # github.com/deckarep/golang-set v1.8.0 ## explicit; go 1.17 github.com/deckarep/golang-set -# github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250911133753-9256a0667454 +# github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20251013071936-4564399cd269 ## explicit; go 1.24.0 github.com/devtron-labs/authenticator/apiToken github.com/devtron-labs/authenticator/client @@ -531,7 +531,7 @@ github.com/devtron-labs/authenticator/jwt github.com/devtron-labs/authenticator/middleware github.com/devtron-labs/authenticator/oidc github.com/devtron-labs/authenticator/password -# github.com/devtron-labs/common-lib v0.18.1-0.20241001061923-eda545dc839e => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250911133753-9256a0667454 +# github.com/devtron-labs/common-lib v0.18.1-0.20241001061923-eda545dc839e => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20251013071936-4564399cd269 ## explicit; go 1.24.0 github.com/devtron-labs/common-lib/async github.com/devtron-labs/common-lib/blob-storage @@ -548,6 +548,7 @@ github.com/devtron-labs/common-lib/middlewares github.com/devtron-labs/common-lib/pubsub-lib github.com/devtron-labs/common-lib/pubsub-lib/metrics github.com/devtron-labs/common-lib/pubsub-lib/model +github.com/devtron-labs/common-lib/securestore github.com/devtron-labs/common-lib/telemetry github.com/devtron-labs/common-lib/utils github.com/devtron-labs/common-lib/utils/bean @@ -562,6 +563,7 @@ github.com/devtron-labs/common-lib/utils/registry github.com/devtron-labs/common-lib/utils/remoteConnection/bean github.com/devtron-labs/common-lib/utils/retryFunc github.com/devtron-labs/common-lib/utils/runTime +github.com/devtron-labs/common-lib/utils/sql github.com/devtron-labs/common-lib/utils/workFlow github.com/devtron-labs/common-lib/utils/yaml github.com/devtron-labs/common-lib/workflow @@ -2654,5 +2656,5 @@ xorm.io/xorm/log xorm.io/xorm/names xorm.io/xorm/schemas xorm.io/xorm/tags -# github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20250911133753-9256a0667454 -# github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20250911133753-9256a0667454 +# github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20251013071936-4564399cd269 +# github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20251013071936-4564399cd269