diff --git a/api/k8s/application/k8sApplicationRestHandler.go b/api/k8s/application/k8sApplicationRestHandler.go index 0665d8e14b..2fb2d1c718 100644 --- a/api/k8s/application/k8sApplicationRestHandler.go +++ b/api/k8s/application/k8sApplicationRestHandler.go @@ -89,9 +89,10 @@ type K8sApplicationRestHandlerImpl struct { helmAppService client.HelmAppService userService user.UserService k8sCommonService k8s.K8sCommonService + terminalEnvVariables *util.TerminalEnvVariables } -func NewK8sApplicationRestHandlerImpl(logger *zap.SugaredLogger, k8sApplicationService application2.K8sApplicationService, pump connector.Pump, terminalSessionHandler terminal.TerminalSessionHandler, enforcer casbin.Enforcer, enforcerUtilHelm rbac.EnforcerUtilHelm, enforcerUtil rbac.EnforcerUtil, helmAppService client.HelmAppService, userService user.UserService, k8sCommonService k8s.K8sCommonService, validator *validator.Validate) *K8sApplicationRestHandlerImpl { +func NewK8sApplicationRestHandlerImpl(logger *zap.SugaredLogger, k8sApplicationService application2.K8sApplicationService, pump connector.Pump, terminalSessionHandler terminal.TerminalSessionHandler, enforcer casbin.Enforcer, enforcerUtilHelm rbac.EnforcerUtilHelm, enforcerUtil rbac.EnforcerUtil, helmAppService client.HelmAppService, userService user.UserService, k8sCommonService k8s.K8sCommonService, validator *validator.Validate, envVariables *util.EnvironmentVariables) *K8sApplicationRestHandlerImpl { return &K8sApplicationRestHandlerImpl{ logger: logger, k8sApplicationService: k8sApplicationService, @@ -104,6 +105,7 @@ func NewK8sApplicationRestHandlerImpl(logger *zap.SugaredLogger, k8sApplicationS helmAppService: helmAppService, userService: userService, k8sCommonService: k8sCommonService, + terminalEnvVariables: envVariables.TerminalEnvVariables, } } @@ -820,6 +822,17 @@ func (handler *K8sApplicationRestHandlerImpl) requestValidationAndRBAC(w http.Re } } +func (handler *K8sApplicationRestHandlerImpl) restrictTerminalAccessForNonSuperUsers(w http.ResponseWriter, token string) bool { + // if RESTRICT_TERMINAL_ACCESS_FOR_NON_SUPER_USER is set to true, only super admins can access terminal/ephemeral containers + if handler.terminalEnvVariables.RestrictTerminalAccessForNonSuperUser { + if isSuperAdmin := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !isSuperAdmin { + common.WriteJsonResp(w, errors.New("unauthorized, only super-admins can access terminal"), nil, http.StatusForbidden) + return true + } + } + return false +} + func (handler *K8sApplicationRestHandlerImpl) GetTerminalSession(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("token") userId, err := handler.userService.GetLoggedInUser(r) @@ -836,6 +849,11 @@ func (handler *K8sApplicationRestHandlerImpl) GetTerminalSession(w http.Response return } request.ExternalArgoApplicationName = vars.Get("externalArgoApplicationName") + // check for super admin + restricted := handler.restrictTerminalAccessForNonSuperUsers(w, token) + if restricted { + return + } if resourceRequestBean.AppIdentifier != nil { // RBAC enforcer applying For Helm App rbacObject, rbacObject2 := handler.enforcerUtilHelm.GetHelmObjectByClusterIdNamespaceAndAppName(resourceRequestBean.AppIdentifier.ClusterId, resourceRequestBean.AppIdentifier.Namespace, resourceRequestBean.AppIdentifier.ReleaseName) @@ -1013,6 +1031,7 @@ func (handler *K8sApplicationRestHandlerImpl) verifyRbacForCluster(token string, } func (handler *K8sApplicationRestHandlerImpl) CreateEphemeralContainer(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("token") userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) @@ -1034,6 +1053,11 @@ func (handler *K8sApplicationRestHandlerImpl) CreateEphemeralContainer(w http.Re common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return } + // check for super admin + restricted := handler.restrictTerminalAccessForNonSuperUsers(w, token) + if restricted { + return + } //rbac applied in below function resourceRequestBean := handler.handleEphemeralRBAC(request.PodName, request.Namespace, w, r) if resourceRequestBean == nil { @@ -1057,6 +1081,7 @@ func (handler *K8sApplicationRestHandlerImpl) CreateEphemeralContainer(w http.Re } func (handler *K8sApplicationRestHandlerImpl) DeleteEphemeralContainer(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("token") userId, err := handler.userService.GetLoggedInUser(r) if userId == 0 || err != nil { common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) @@ -1078,6 +1103,11 @@ func (handler *K8sApplicationRestHandlerImpl) DeleteEphemeralContainer(w http.Re common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return } + // check for super admin + restricted := handler.restrictTerminalAccessForNonSuperUsers(w, token) + if restricted { + return + } //rbac applied in below function resourceRequestBean := handler.handleEphemeralRBAC(request.PodName, request.Namespace, w, r) if resourceRequestBean == nil { diff --git a/env_gen.md b/env_gen.md index 67cb63d365..877fa684c9 100644 --- a/env_gen.md +++ b/env_gen.md @@ -201,6 +201,7 @@ | REQ_CI_MEM | 3G | | | RESOURCE_LIST_FOR_REPLICAS | Deployment,Rollout,StatefulSet,ReplicaSet | | | RESOURCE_LIST_FOR_REPLICAS_BATCH_SIZE | 5 | | + | RESTRICT_TERMINAL_ACCESS_FOR_NON_SUPER_USER | false | | | REVISION_HISTORY_LIMIT_DEVTRON_APP | 1 | | | REVISION_HISTORY_LIMIT_EXTERNAL_HELM_APP | 0 | | | REVISION_HISTORY_LIMIT_HELM_APP | 1 | | diff --git a/util/GlobalConfig.go b/util/GlobalConfig.go index 971aa46f0f..b4c3cb8381 100644 --- a/util/GlobalConfig.go +++ b/util/GlobalConfig.go @@ -24,6 +24,7 @@ type EnvironmentVariables struct { GlobalEnvVariables *GlobalEnvVariables DevtronSecretConfig *DevtronSecretConfig DeploymentServiceTypeConfig *DeploymentServiceTypeConfig + TerminalEnvVariables *TerminalEnvVariables } type DeploymentServiceTypeConfig struct { @@ -43,11 +44,16 @@ type DevtronSecretConfig struct { DevtronDexSecretNamespace string `env:"DEVTRON_DEX_SECRET_NAMESPACE" envDefault:"devtroncd"` } +type TerminalEnvVariables struct { + RestrictTerminalAccessForNonSuperUser bool `env:"RESTRICT_TERMINAL_ACCESS_FOR_NON_SUPER_USER" envDefault:"false"` +} + func GetEnvironmentVariables() (*EnvironmentVariables, error) { cfg := &EnvironmentVariables{ GlobalEnvVariables: &GlobalEnvVariables{}, DevtronSecretConfig: &DevtronSecretConfig{}, DeploymentServiceTypeConfig: &DeploymentServiceTypeConfig{}, + TerminalEnvVariables: &TerminalEnvVariables{}, } err := env.Parse(cfg) if err != nil { diff --git a/wire_gen.go b/wire_gen.go index cbb0c1a124..4c93837ce9 100644 --- a/wire_gen.go +++ b/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 @@ -825,7 +825,7 @@ func InitializeApp() (*App, error) { coreAppRouterImpl := router.NewCoreAppRouterImpl(coreAppRestHandlerImpl) helmAppRestHandlerImpl := client3.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImplExtended, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, installedAppDBServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig) helmAppRouterImpl := client3.NewHelmAppRouterImpl(helmAppRestHandlerImpl) - k8sApplicationRestHandlerImpl := application3.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate) + k8sApplicationRestHandlerImpl := application3.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate, environmentVariables) k8sApplicationRouterImpl := application3.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) pProfRestHandlerImpl := restHandler.NewPProfRestHandler(userServiceImpl, enforcerImpl) pProfRouterImpl := router.NewPProfRouter(sugaredLogger, pProfRestHandlerImpl)