diff --git a/cautils/customerloader.go b/cautils/customerloader.go index 0eef7348..c73c24a8 100644 --- a/cautils/customerloader.go +++ b/cautils/customerloader.go @@ -111,7 +111,7 @@ func (c *EmptyConfig) GetK8sAPI() *k8sinterface.KubernetesApi { return nil } func (c *EmptyConfig) GetDefaultNS() string { return k8sinterface.GetDefaultNamespace() } func (c *EmptyConfig) GetBackendAPI() getter.IBackend { return nil } // TODO: return mock obj func (c *EmptyConfig) GenerateURL() { - message := fmt.Sprintf("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 registering here: https://%s", getter.ArmoFEURL) + message := fmt.Sprintf("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 registering here: https://%s", getter.GetArmoAPIConnector().GetFrontendURL()) InfoTextDisplay(os.Stdout, message+"\n") } @@ -143,7 +143,7 @@ func (c *ClusterConfig) GenerateURL() { u := url.URL{} u.Scheme = "https" - u.Host = getter.ArmoFEURL + u.Host = getter.GetArmoAPIConnector().GetFrontendURL() if c.configObj == nil { return } diff --git a/cautils/getter/armoapi.go b/cautils/getter/armoapi.go index dd06be4c..3a4b1d90 100644 --- a/cautils/getter/armoapi.go +++ b/cautils/getter/armoapi.go @@ -3,9 +3,11 @@ package getter import ( "fmt" "net/http" + "time" "github.com/armosec/kubescape/cautils/armotypes" "github.com/armosec/kubescape/cautils/opapolicy" + "github.com/golang/glog" ) // ======================================================================================================================= @@ -15,22 +17,80 @@ import ( var ( // ATTENTION!!! // Changes in this URLs variable names, or in the usage is affecting the build process! BE CAREFULL - ArmoBEURL = "eggdashbe.eudev3.cyberarmorsoft.com" - ArmoERURL = "report.eudev3.cyberarmorsoft.com" - ArmoFEURL = "armoui.eudev3.cyberarmorsoft.com" - // ArmoURL = "https://dashbe.euprod1.cyberarmorsoft.com" + armoERURL = "report.armo.cloud" + armoBEURL = "api.armo.cloud" + armoFEURL = "portal.armo.cloud" + + armoDevERURL = "report.eudev3.cyberarmorsoft.com" + armoDevBEURL = "eggdashbe.eudev3.cyberarmorsoft.com" + armoDevFEURL = "armoui.eudev3.cyberarmorsoft.com" ) // Armo API for downloading policies type ArmoAPI struct { httpClient *http.Client + apiURL string + erURL string + feURL string } -func NewArmoAPI() *ArmoAPI { +var globalArmoAPIConnecctor *ArmoAPI + +func SetARMOAPIConnector(armoAPI *ArmoAPI) { + globalArmoAPIConnecctor = armoAPI +} + +func GetArmoAPIConnector() *ArmoAPI { + if globalArmoAPIConnecctor == nil { + glog.Error("returning nil API connector") + } + return globalArmoAPIConnecctor +} + +func NewARMOAPIDev() *ArmoAPI { + apiObj := newArmoAPI() + + apiObj.apiURL = armoDevBEURL + apiObj.erURL = armoDevERURL + apiObj.feURL = armoDevFEURL + + return apiObj +} + +func NewARMOAPIProd() *ArmoAPI { + apiObj := newArmoAPI() + + apiObj.apiURL = armoBEURL + apiObj.erURL = armoERURL + apiObj.feURL = armoFEURL + + return apiObj +} + +func NewARMOAPICustomized(armoERURL, armoBEURL, armoFEURL string) *ArmoAPI { + apiObj := newArmoAPI() + + apiObj.erURL = armoERURL + apiObj.apiURL = armoBEURL + apiObj.feURL = armoFEURL + + return apiObj +} + +func newArmoAPI() *ArmoAPI { return &ArmoAPI{ - httpClient: &http.Client{}, + httpClient: &http.Client{Timeout: time.Duration(61) * time.Second}, } } + +func (armoAPI *ArmoAPI) GetFrontendURL() string { + return armoAPI.feURL +} + +func (armoAPI *ArmoAPI) GetReportReceiverURL() string { + return armoAPI.erURL +} + func (armoAPI *ArmoAPI) GetFramework(name string) (*opapolicy.Framework, error) { respStr, err := HttpGetter(armoAPI.httpClient, armoAPI.getFrameworkURL(name)) if err != nil { diff --git a/cautils/getter/armoapiutils.go b/cautils/getter/armoapiutils.go index d54264fd..001a6540 100644 --- a/cautils/getter/armoapiutils.go +++ b/cautils/getter/armoapiutils.go @@ -8,7 +8,7 @@ import ( func (armoAPI *ArmoAPI) getFrameworkURL(frameworkName string) string { u := url.URL{} u.Scheme = "https" - u.Host = ArmoBEURL + u.Host = armoAPI.apiURL u.Path = "v1/armoFrameworks" q := u.Query() q.Add("customerGUID", "11111111-1111-1111-1111-111111111111") @@ -22,7 +22,7 @@ func (armoAPI *ArmoAPI) getFrameworkURL(frameworkName string) string { func (armoAPI *ArmoAPI) getExceptionsURL(customerGUID, clusterName string) string { u := url.URL{} u.Scheme = "https" - u.Host = ArmoBEURL + u.Host = armoAPI.apiURL u.Path = "api/v1/armoPostureExceptions" q := u.Query() @@ -38,7 +38,7 @@ func (armoAPI *ArmoAPI) getExceptionsURL(customerGUID, clusterName string) strin func (armoAPI *ArmoAPI) getCustomerURL() string { u := url.URL{} u.Scheme = "https" - u.Host = ArmoBEURL + u.Host = armoAPI.apiURL u.Path = "api/v1/createTenant" return u.String() } diff --git a/cautils/scaninfo.go b/cautils/scaninfo.go index 5d8607dd..53d8db42 100644 --- a/cautils/scaninfo.go +++ b/cautils/scaninfo.go @@ -43,7 +43,7 @@ func (scanInfo *ScanInfo) setUseExceptions() { // load exceptions from file scanInfo.ExceptionsGetter = getter.NewLoadPolicy(scanInfo.UseExceptions) } else { - scanInfo.ExceptionsGetter = getter.NewArmoAPI() + scanInfo.ExceptionsGetter = getter.GetArmoAPIConnector() } } diff --git a/cmd/cluster_get.go b/cmd/cluster_get.go index 83915524..649e4e4f 100644 --- a/cmd/cluster_get.go +++ b/cmd/cluster_get.go @@ -31,7 +31,7 @@ var getCmd = &cobra.Command{ key := keyValue[0] k8s := k8sinterface.NewKubernetesApi() - clusterConfig := cautils.NewClusterConfig(k8s, getter.NewArmoAPI()) + clusterConfig := cautils.NewClusterConfig(k8s, getter.GetArmoAPIConnector()) val, err := clusterConfig.GetValueByKeyFromConfigMap(key) if err != nil { if err.Error() == "value does not exist." { diff --git a/cmd/cluster_set.go b/cmd/cluster_set.go index f7c94b84..e0315a6e 100644 --- a/cmd/cluster_set.go +++ b/cmd/cluster_set.go @@ -30,7 +30,7 @@ var setCmd = &cobra.Command{ data := keyValue[1] k8s := k8sinterface.NewKubernetesApi() - clusterConfig := cautils.NewClusterConfig(k8s, getter.NewArmoAPI()) + clusterConfig := cautils.NewClusterConfig(k8s, getter.GetArmoAPIConnector()) if err := clusterConfig.SetKeyValueInConfigmap(key, data); err != nil { return err } diff --git a/cmd/framework.go b/cmd/framework.go index 6ac188a6..f60e1051 100644 --- a/cmd/framework.go +++ b/cmd/framework.go @@ -1,7 +1,6 @@ package cmd import ( - "flag" "fmt" "io" "os" @@ -32,7 +31,7 @@ type CLIHandler struct { var frameworkCmd = &cobra.Command{ - Use: fmt.Sprintf("framework [``/`-`] [flags]\nSupported frameworks: %s", validFrameworks), + Use: fmt.Sprintf("framework [``/`-`] [flags]\nSupported frameworks: %s", validFrameworks), Short: fmt.Sprintf("The framework you wish to use. Supported frameworks: %s", strings.Join(supportedFrameworks, ", ")), Long: "Execute a scan on a running Kubernetes cluster or `yaml`/`json` files (use glob) or `-` for stdin", ValidArgs: supportedFrameworks, @@ -103,7 +102,6 @@ func init() { } func CliSetup() error { - flag.Parse() flagValidation() var k8s *k8sinterface.KubernetesApi @@ -120,7 +118,7 @@ func CliSetup() error { policyHandler := policyhandler.NewPolicyHandler(&processNotification, k8s) // setup cluster config - clusterConfig := cautils.ClusterConfigSetup(&scanInfo, k8s, getter.NewArmoAPI()) + clusterConfig := cautils.ClusterConfigSetup(&scanInfo, k8s, getter.GetArmoAPIConnector()) if err := clusterConfig.SetCustomerGUID(scanInfo.Account); err != nil { fmt.Println(err) } diff --git a/cmd/root.go b/cmd/root.go index 88b9db54..c760e45a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,15 +1,22 @@ package cmd import ( + "flag" + "os" + "strings" + + "github.com/armosec/kubescape/cautils/getter" + "github.com/golang/glog" "github.com/spf13/cobra" ) var cfgFile string +var armoBEURLs = "" var rootCmd = &cobra.Command{ Use: "kubescape", Short: "Kubescape is a tool for testing Kubernetes security posture", - Long: `Kubescape is a tool for testing Kubernetes security posture based on NSA specifications.`, + Long: `Kubescape is a tool for testing Kubernetes security posture based on NSA \ MITRE ATT&CKĀ® specifications.`, } func Execute() { @@ -17,9 +24,41 @@ func Execute() { } func init() { + flag.CommandLine.StringVar(&armoBEURLs, "environment", "", envFlagUsage) + rootCmd.PersistentFlags().StringVar(&armoBEURLs, "environment", "", envFlagUsage) + rootCmd.PersistentFlags().MarkHidden("environment") cobra.OnInitialize(initConfig) + } // initConfig reads in config file and ENV variables if set. func initConfig() { } + +func InitArmoBEConnector() { + if armoBEURLs == "" && rootCmd.Flag("environment") != nil { + armoBEURLs = rootCmd.Flag("environment").Value.String() + } + urlSlices := strings.Split(armoBEURLs, ",") + if len(urlSlices) > 3 { + glog.Errorf("Too many URLs") + os.Exit(1) + } + switch len(urlSlices) { + case 1: + switch urlSlices[0] { + case "dev": + getter.SetARMOAPIConnector(getter.NewARMOAPIDev()) + case "": + getter.SetARMOAPIConnector(getter.NewARMOAPIProd()) + default: + glog.Errorf("--environment flag usage: %s", envFlagUsage) + os.Exit(1) + } + case 2: + glog.Errorf("--environment flag usage: %s", envFlagUsage) + os.Exit(1) + case 3: + getter.SetARMOAPIConnector(getter.NewARMOAPICustomized(urlSlices[0], urlSlices[1], urlSlices[2])) + } +} diff --git a/cmd/scan.go b/cmd/scan.go index e421f852..ca14f8e3 100644 --- a/cmd/scan.go +++ b/cmd/scan.go @@ -4,6 +4,8 @@ import ( "github.com/spf13/cobra" ) +const envFlagUsage = "Send report results to specific URL. Format:,,.\n\t\tExample:report.armo.cloud,api.armo.cloud,portal.armo.cloud" + // scanCmd represents the scan command var scanCmd = &cobra.Command{ Use: "scan", diff --git a/main.go b/main.go index 114f855c..6565b817 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "flag" "fmt" "os" @@ -9,6 +10,8 @@ import ( func main() { CheckLatestVersion() + flag.Parse() + cmd.InitArmoBEConnector() cmd.Execute() } diff --git a/resultshandling/reporter/reporteventreceiverutils.go b/resultshandling/reporter/reporteventreceiverutils.go index ee26e203..96fa75be 100644 --- a/resultshandling/reporter/reporteventreceiverutils.go +++ b/resultshandling/reporter/reporteventreceiverutils.go @@ -37,7 +37,7 @@ func initEventReceiverURL() *url.URL { urlObj := url.URL{} urlObj.Scheme = "https" - urlObj.Host = getter.ArmoERURL + urlObj.Host = getter.GetArmoAPIConnector().GetReportReceiverURL() urlObj.Path = "/k8s/postureReport" q := urlObj.Query() q.Add("customerGUID", uuid.FromStringOrNil(cautils.CustomerGUID).String())