diff --git a/cmd/scan/scan.go b/cmd/scan/scan.go index 251bb769..216d3056 100644 --- a/cmd/scan/scan.go +++ b/cmd/scan/scan.go @@ -83,6 +83,7 @@ func GetScanCommand(ks meta.IKubescape) *cobra.Command { scanCmd.PersistentFlags().BoolVarP(&scanInfo.Submit, "submit", "", false, "Send the scan results to ARMO management portal where you can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more. By default the results are not submitted") scanCmd.PersistentFlags().StringVar(&scanInfo.HostSensorYamlPath, "host-scan-yaml", "", "Override default host scanner DaemonSet. Use this flag cautiously") scanCmd.PersistentFlags().StringVar(&scanInfo.FormatVersion, "format-version", "v1", "Output object can be differnet between versions, this is for maintaining backward and forward compatibility. Supported:'v1'/'v2'") + scanCmd.PersistentFlags().StringVar(&scanInfo.CustomClusterName, "cluster-name", "", "Set the custom name of the cluster. Not same as the kube-context flag") // Deprecated flags - remove 1.May.2022 scanCmd.PersistentFlags().BoolVarP(&scanInfo.Silent, "silent", "s", false, "Silent progress messages") diff --git a/cmd/submit/rbac.go b/cmd/submit/rbac.go index b0f33a14..d18af31c 100644 --- a/cmd/submit/rbac.go +++ b/cmd/submit/rbac.go @@ -40,7 +40,7 @@ func getRBACCmd(ks meta.IKubescape, submitInfo *v1.Submit) *cobra.Command { k8s := k8sinterface.NewKubernetesApi() // get config - clusterConfig := getTenantConfig(&submitInfo.Credentials, "", k8s) + clusterConfig := getTenantConfig(&submitInfo.Credentials, "", "", k8s) if err := clusterConfig.SetTenant(); err != nil { logger.L().Error("failed setting account ID", helpers.Error(err)) } @@ -77,9 +77,9 @@ func getKubernetesApi() *k8sinterface.KubernetesApi { } return k8sinterface.NewKubernetesApi() } -func getTenantConfig(credentials *cautils.Credentials, clusterName string, k8s *k8sinterface.KubernetesApi) cautils.ITenantConfig { +func getTenantConfig(credentials *cautils.Credentials, clusterName string, customClusterName string, k8s *k8sinterface.KubernetesApi) cautils.ITenantConfig { if !k8sinterface.IsConnectedToCluster() || k8s == nil { - return cautils.NewLocalConfig(getter.GetKSCloudAPIConnector(), credentials, clusterName) + return cautils.NewLocalConfig(getter.GetKSCloudAPIConnector(), credentials, clusterName, customClusterName) } - return cautils.NewClusterConfig(k8s, getter.GetKSCloudAPIConnector(), credentials, clusterName) + return cautils.NewClusterConfig(k8s, getter.GetKSCloudAPIConnector(), credentials, clusterName, customClusterName) } diff --git a/cmd/submit/results.go b/cmd/submit/results.go index c8aa2430..15102ef8 100644 --- a/cmd/submit/results.go +++ b/cmd/submit/results.go @@ -61,7 +61,7 @@ func getResultsCmd(ks meta.IKubescape, submitInfo *v1.Submit) *cobra.Command { k8s := getKubernetesApi() // get config - clusterConfig := getTenantConfig(&submitInfo.Credentials, "", k8s) + clusterConfig := getTenantConfig(&submitInfo.Credentials, "", "", k8s) if err := clusterConfig.SetTenant(); err != nil { logger.L().Error("failed setting account ID", helpers.Error(err)) } diff --git a/core/cautils/customerloader.go b/core/cautils/customerloader.go index a2a0fe8b..9e4f789d 100644 --- a/core/cautils/customerloader.go +++ b/core/cautils/customerloader.go @@ -7,6 +7,7 @@ import ( "os" "regexp" "strings" + "regexp" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -91,7 +92,7 @@ type LocalConfig struct { } func NewLocalConfig( - backendAPI getter.IBackend, credentials *Credentials, clusterName string) *LocalConfig { + backendAPI getter.IBackend, credentials *Credentials, clusterName string, customClusterName string) *LocalConfig { lc := &LocalConfig{ backendAPI: backendAPI, @@ -104,7 +105,10 @@ func NewLocalConfig( updateCredentials(lc.configObj, credentials) - if clusterName != "" { + // If a custom cluster name is provided then set that name, else use the cluster's original name + if customClusterName != ""{ + lc.configObj.ClusterName = AdoptCustomClusterName(customClusterName) + }else if clusterName != "" { lc.configObj.ClusterName = AdoptClusterName(clusterName) // override config clusterName } @@ -190,7 +194,7 @@ type ClusterConfig struct { configMapNamespace string } -func NewClusterConfig(k8s *k8sinterface.KubernetesApi, backendAPI getter.IBackend, credentials *Credentials, clusterName string) *ClusterConfig { +func NewClusterConfig(k8s *k8sinterface.KubernetesApi, backendAPI getter.IBackend, credentials *Credentials, clusterName string, customClusterName string) *ClusterConfig { // var configObj *ConfigObj c := &ClusterConfig{ k8s: k8s, @@ -211,7 +215,10 @@ func NewClusterConfig(k8s *k8sinterface.KubernetesApi, backendAPI getter.IBacken } updateCredentials(c.configObj, credentials) - if clusterName != "" { + // If a custom cluster name is provided then set that name, else use the cluster's original name + if customClusterName != "" { + c.configObj.ClusterName = AdoptCustomClusterName(customClusterName) + } else if clusterName != "" { c.configObj.ClusterName = AdoptClusterName(clusterName) // override config clusterName } @@ -468,6 +475,19 @@ func DeleteConfigFile() error { return os.Remove(ConfigFileFullPath()) } +// To check if the custom cluster name is valid: +func AdoptCustomClusterName(customClusterName string) string{ + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(customClusterName) + + // Check it does not contain special-characters + if is_alphanumeric == false { + logger.L().Fatal("custom cluster name cannot contain special characters") + } else if len(customClusterName) >= 256 { // Check it contains less than 256 characters + logger.L().Fatal("custom cluster name cannot contain more than 255 characters") + } + return customClusterName +} + func AdoptClusterName(clusterName string) string { re, err := regexp.Compile(`[^\w]+`) if err != nil { diff --git a/core/cautils/scaninfo.go b/core/cautils/scaninfo.go index 5a44c553..e66aaceb 100644 --- a/core/cautils/scaninfo.go +++ b/core/cautils/scaninfo.go @@ -126,6 +126,7 @@ type ScanInfo struct { KubeContext string // context name FrameworkScan bool // false if scanning control ScanAll bool // true if scan all frameworks + CustomClusterName string // Custom name of the cluster } type Getters struct { diff --git a/core/core/cachedconfig.go b/core/core/cachedconfig.go index b575eb9c..94d057f1 100644 --- a/core/core/cachedconfig.go +++ b/core/core/cachedconfig.go @@ -8,7 +8,7 @@ import ( func (ks *Kubescape) SetCachedConfig(setConfig *metav1.SetConfig) error { - tenant := getTenantConfig(nil, "", getKubernetesApi()) + tenant := getTenantConfig(nil, "", "", getKubernetesApi()) if setConfig.Account != "" { tenant.GetConfigObj().AccountID = setConfig.Account @@ -25,13 +25,13 @@ func (ks *Kubescape) SetCachedConfig(setConfig *metav1.SetConfig) error { // View cached configurations func (ks *Kubescape) ViewCachedConfig(viewConfig *metav1.ViewConfig) error { - tenant := getTenantConfig(nil, "", getKubernetesApi()) // change k8sinterface + tenant := getTenantConfig(nil, "", "", getKubernetesApi()) // change k8sinterface fmt.Fprintf(viewConfig.Writer, "%s\n", tenant.GetConfigObj().Config()) return nil } func (ks *Kubescape) DeleteCachedConfig(deleteConfig *metav1.DeleteConfig) error { - tenant := getTenantConfig(nil, "", getKubernetesApi()) // change k8sinterface + tenant := getTenantConfig(nil, "", "", getKubernetesApi()) // change k8sinterface return tenant.DeleteCachedConfig() } diff --git a/core/core/delete.go b/core/core/delete.go index 0439db68..53fc774f 100644 --- a/core/core/delete.go +++ b/core/core/delete.go @@ -12,7 +12,7 @@ import ( func (ks *Kubescape) DeleteExceptions(delExceptions *v1.DeleteExceptions) error { // load cached config - getTenantConfig(&delExceptions.Credentials, "", getKubernetesApi()) + getTenantConfig(&delExceptions.Credentials, "", "", getKubernetesApi()) // login kubescape SaaS ksCloudAPI := getter.GetKSCloudAPIConnector() diff --git a/core/core/download.go b/core/core/download.go index d5760a65..3e71a100 100644 --- a/core/core/download.go +++ b/core/core/download.go @@ -80,7 +80,7 @@ func downloadArtifacts(downloadInfo *metav1.DownloadInfo) error { } func downloadConfigInputs(downloadInfo *metav1.DownloadInfo) error { - tenant := getTenantConfig(&downloadInfo.Credentials, "", getKubernetesApi()) + tenant := getTenantConfig(&downloadInfo.Credentials, "", "", getKubernetesApi()) controlsInputsGetter := getConfigInputsGetter(downloadInfo.Name, tenant.GetAccountID(), nil) controlInputs, err := controlsInputsGetter.GetControlsInputs(tenant.GetContextName()) @@ -104,7 +104,7 @@ func downloadConfigInputs(downloadInfo *metav1.DownloadInfo) error { func downloadExceptions(downloadInfo *metav1.DownloadInfo) error { var err error - tenant := getTenantConfig(&downloadInfo.Credentials, "", getKubernetesApi()) + tenant := getTenantConfig(&downloadInfo.Credentials, "", "", getKubernetesApi()) exceptionsGetter := getExceptionsGetter("") exceptions := []armotypes.PostureExceptionPolicy{} @@ -128,7 +128,7 @@ func downloadExceptions(downloadInfo *metav1.DownloadInfo) error { func downloadFramework(downloadInfo *metav1.DownloadInfo) error { - tenant := getTenantConfig(&downloadInfo.Credentials, "", getKubernetesApi()) + tenant := getTenantConfig(&downloadInfo.Credentials, "", "", getKubernetesApi()) g := getPolicyGetter(nil, tenant.GetTenantEmail(), true, nil) @@ -170,7 +170,7 @@ func downloadFramework(downloadInfo *metav1.DownloadInfo) error { func downloadControl(downloadInfo *metav1.DownloadInfo) error { - tenant := getTenantConfig(&downloadInfo.Credentials, "", getKubernetesApi()) + tenant := getTenantConfig(&downloadInfo.Credentials, "", "", getKubernetesApi()) g := getPolicyGetter(nil, tenant.GetTenantEmail(), false, nil) diff --git a/core/core/initutils.go b/core/core/initutils.go index 1a8aedd8..b46b925a 100644 --- a/core/core/initutils.go +++ b/core/core/initutils.go @@ -25,11 +25,11 @@ func getKubernetesApi() *k8sinterface.KubernetesApi { } return k8sinterface.NewKubernetesApi() } -func getTenantConfig(credentials *cautils.Credentials, clusterName string, k8s *k8sinterface.KubernetesApi) cautils.ITenantConfig { +func getTenantConfig(credentials *cautils.Credentials, clusterName string, customClusterName string, k8s *k8sinterface.KubernetesApi) cautils.ITenantConfig { if !k8sinterface.IsConnectedToCluster() || k8s == nil { - return cautils.NewLocalConfig(getter.GetKSCloudAPIConnector(), credentials, clusterName) + return cautils.NewLocalConfig(getter.GetKSCloudAPIConnector(), credentials, clusterName, customClusterName) } - return cautils.NewClusterConfig(k8s, getter.GetKSCloudAPIConnector(), credentials, clusterName) + return cautils.NewClusterConfig(k8s, getter.GetKSCloudAPIConnector(), credentials, clusterName, customClusterName) } func getExceptionsGetter(useExceptions string) getter.IExceptionsGetter { diff --git a/core/core/list.go b/core/core/list.go index a0383bf3..d4dd9afc 100644 --- a/core/core/list.go +++ b/core/core/list.go @@ -44,14 +44,14 @@ func (ks *Kubescape) List(listPolicies *metav1.ListPolicies) error { } func listFrameworks(listPolicies *metav1.ListPolicies) ([]string, error) { - tenant := getTenantConfig(&listPolicies.Credentials, "", getKubernetesApi()) // change k8sinterface + tenant := getTenantConfig(&listPolicies.Credentials, "", "", getKubernetesApi()) // change k8sinterface g := getPolicyGetter(nil, tenant.GetTenantEmail(), true, nil) return listFrameworksNames(g), nil } func listControls(listPolicies *metav1.ListPolicies) ([]string, error) { - tenant := getTenantConfig(&listPolicies.Credentials, "", getKubernetesApi()) // change k8sinterface + tenant := getTenantConfig(&listPolicies.Credentials, "", "", getKubernetesApi()) // change k8sinterface g := getPolicyGetter(nil, tenant.GetTenantEmail(), false, nil) l := getter.ListName @@ -63,7 +63,7 @@ func listControls(listPolicies *metav1.ListPolicies) ([]string, error) { func listExceptions(listPolicies *metav1.ListPolicies) ([]string, error) { // load tenant metav1 - getTenantConfig(&listPolicies.Credentials, "", getKubernetesApi()) + getTenantConfig(&listPolicies.Credentials, "", "", getKubernetesApi()) var exceptionsNames []string ksCloudAPI := getExceptionsGetter("") diff --git a/core/core/scan.go b/core/core/scan.go index 685e0c15..49fa69ab 100644 --- a/core/core/scan.go +++ b/core/core/scan.go @@ -44,7 +44,7 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces { // ================== setup tenant object ====================================== - tenantConfig := getTenantConfig(&scanInfo.Credentials, scanInfo.KubeContext, k8s) + tenantConfig := getTenantConfig(&scanInfo.Credentials, scanInfo.KubeContext, scanInfo.CustomClusterName, k8s) // Set submit behavior AFTER loading tenant config setSubmitBehavior(scanInfo, tenantConfig) diff --git a/core/core/submit.go b/core/core/submit.go index 115fc00f..13258f43 100644 --- a/core/core/submit.go +++ b/core/core/submit.go @@ -39,7 +39,7 @@ func (ks *Kubescape) SubmitExceptions(credentials *cautils.Credentials, excPath logger.L().Info("submitting exceptions", helpers.String("path", excPath)) // load cached config - tenantConfig := getTenantConfig(credentials, "", getKubernetesApi()) + tenantConfig := getTenantConfig(credentials, "", "", getKubernetesApi()) if err := tenantConfig.SetTenant(); err != nil { logger.L().Error("failed setting account ID", helpers.Error(err)) }