support download

This commit is contained in:
dwertent
2022-01-05 20:46:56 +02:00
20 changed files with 321 additions and 207 deletions
+13 -9
View File
@@ -104,10 +104,11 @@ func NewLocalConfig(backendAPI getter.IBackend, customerGUID string) *LocalConfi
return lc
}
func (lc *LocalConfig) GetConfigObj() *ConfigObj { return lc.configObj }
func (lc *LocalConfig) GetCustomerGUID() string { return lc.configObj.CustomerGUID }
func (lc *LocalConfig) GetClusterName() string { return "" }
func (lc *LocalConfig) IsConfigFound() bool { return existsConfigFile() }
func (lc *LocalConfig) GetConfigObj() *ConfigObj { return lc.configObj }
func (lc *LocalConfig) GetCustomerGUID() string { return lc.configObj.CustomerGUID }
func (lc *LocalConfig) SetCustomerGUID(customerGUID string) { lc.configObj.CustomerGUID = customerGUID }
func (lc *LocalConfig) GetClusterName() string { return "" }
func (lc *LocalConfig) IsConfigFound() bool { return existsConfigFile() }
func (lc *LocalConfig) SetTenant() error {
// ARMO tenant GUID
if err := getTenantConfigFromBE(lc.backendAPI, lc.configObj); err != nil {
@@ -121,7 +122,8 @@ func (lc *LocalConfig) SetTenant() error {
func getTenantConfigFromBE(backendAPI getter.IBackend, configObj *ConfigObj) error {
// get from armoBE
tenantResponse, err := backendAPI.GetCustomerGUID(configObj.CustomerGUID)
backendAPI.SetCustomerGUID(configObj.CustomerGUID)
tenantResponse, err := backendAPI.GetCustomerGUID()
if err == nil && tenantResponse != nil {
if tenantResponse.AdminMail != "" { // registered tenant
configObj.CustomerAdminEMail = tenantResponse.AdminMail
@@ -197,9 +199,10 @@ func NewClusterConfig(k8s *k8sinterface.KubernetesApi, backendAPI getter.IBacken
return c
}
func (c *ClusterConfig) GetConfigObj() *ConfigObj { return c.configObj }
func (c *ClusterConfig) GetDefaultNS() string { return c.configMapNamespace }
func (c *ClusterConfig) GetCustomerGUID() string { return c.configObj.CustomerGUID }
func (c *ClusterConfig) GetConfigObj() *ConfigObj { return c.configObj }
func (c *ClusterConfig) GetDefaultNS() string { return c.configMapNamespace }
func (c *ClusterConfig) GetCustomerGUID() string { return c.configObj.CustomerGUID }
func (c *ClusterConfig) SetCustomerGUID(customerGUID string) { c.configObj.CustomerGUID = customerGUID }
func (c *ClusterConfig) IsConfigFound() bool {
return existsConfigFile() || c.existsConfigMap()
}
@@ -410,7 +413,8 @@ func (clusterConfig *ClusterConfig) IsSubmitted() bool {
func (clusterConfig *ClusterConfig) IsRegistered() bool {
// get from armoBE
tenantResponse, err := clusterConfig.backendAPI.GetCustomerGUID(clusterConfig.GetCustomerGUID())
clusterConfig.backendAPI.SetCustomerGUID(clusterConfig.GetCustomerGUID())
tenantResponse, err := clusterConfig.backendAPI.GetCustomerGUID()
if err == nil && tenantResponse != nil {
if tenantResponse.AdminMail != "" { // this customer already belongs to some user
return true
+4 -3
View File
@@ -1,7 +1,8 @@
package cautils
type DownloadInfo struct {
Path string
FrameworkName string
ControlName string
Path string
Target string
Name string
Account string
}
+18 -16
View File
@@ -107,7 +107,7 @@ func (armoAPI *ArmoAPI) GetFramework(name string) (*reporthandling.Framework, er
if err = JSONDecoder(respStr).Decode(framework); err != nil {
return nil, err
}
SaveFrameworkInFile(framework, GetDefaultPath(name+".json"))
SaveInFile(framework, GetDefaultPath(name+".json"))
return framework, err
}
@@ -116,12 +116,10 @@ func (armoAPI *ArmoAPI) GetControl(policyName string) (*reporthandling.Control,
return nil, fmt.Errorf("control api is not public")
}
func (armoAPI *ArmoAPI) GetExceptions(customerGUID, clusterName string) ([]armotypes.PostureExceptionPolicy, error) {
func (armoAPI *ArmoAPI) GetExceptions(clusterName string) ([]armotypes.PostureExceptionPolicy, error) {
exceptions := []armotypes.PostureExceptionPolicy{}
if customerGUID == "" {
return exceptions, nil
}
respStr, err := HttpGetter(armoAPI.httpClient, armoAPI.getExceptionsURL(customerGUID, clusterName), nil)
respStr, err := HttpGetter(armoAPI.httpClient, armoAPI.getExceptionsURL(clusterName), nil)
if err != nil {
return nil, err
}
@@ -133,10 +131,10 @@ func (armoAPI *ArmoAPI) GetExceptions(customerGUID, clusterName string) ([]armot
return exceptions, nil
}
func (armoAPI *ArmoAPI) GetCustomerGUID(customerGUID string) (*TenantResponse, error) {
func (armoAPI *ArmoAPI) GetCustomerGUID() (*TenantResponse, error) {
url := armoAPI.getCustomerURL()
if customerGUID != "" {
url = fmt.Sprintf("%s?customerGUID=%s", url, customerGUID)
if armoAPI.customerGUID != "" {
url = fmt.Sprintf("%s?customerGUID=%s", url, armoAPI.customerGUID)
}
respStr, err := HttpGetter(armoAPI.httpClient, url, nil)
if err != nil {
@@ -151,12 +149,12 @@ func (armoAPI *ArmoAPI) GetCustomerGUID(customerGUID string) (*TenantResponse, e
}
// ControlsInputs // map[<control name>][<input arguments>]
func (armoAPI *ArmoAPI) GetAccountConfig(customerGUID, clusterName string) (*armotypes.CustomerConfig, error) {
func (armoAPI *ArmoAPI) GetAccountConfig(clusterName string) (*armotypes.CustomerConfig, error) {
accountConfig := &armotypes.CustomerConfig{}
if customerGUID == "" {
if armoAPI.customerGUID == "" {
return accountConfig, nil
}
respStr, err := HttpGetter(armoAPI.httpClient, armoAPI.getAccountConfig(customerGUID, clusterName), nil)
respStr, err := HttpGetter(armoAPI.httpClient, armoAPI.getAccountConfig(clusterName), nil)
if err != nil {
return nil, err
}
@@ -169,15 +167,15 @@ func (armoAPI *ArmoAPI) GetAccountConfig(customerGUID, clusterName string) (*arm
}
// ControlsInputs // map[<control name>][<input arguments>]
func (armoAPI *ArmoAPI) GetControlsInputs(customerGUID, clusterName string) (map[string][]string, error) {
accountConfig, err := armoAPI.GetAccountConfig(customerGUID, clusterName)
func (armoAPI *ArmoAPI) GetControlsInputs(clusterName string) (map[string][]string, error) {
accountConfig, err := armoAPI.GetAccountConfig(clusterName)
if err == nil {
return accountConfig.Settings.PostureControlInputs, nil
}
return nil, err
}
func (armoAPI *ArmoAPI) ListCustomFrameworks(customerGUID string) ([]string, error) {
func (armoAPI *ArmoAPI) ListCustomFrameworks() ([]string, error) {
respStr, err := HttpGetter(armoAPI.httpClient, armoAPI.getListFrameworkURL(), nil)
if err != nil {
return nil, err
@@ -197,7 +195,7 @@ func (armoAPI *ArmoAPI) ListCustomFrameworks(customerGUID string) ([]string, err
return frameworkList, nil
}
func (armoAPI *ArmoAPI) ListFrameworks(customerGUID string) ([]string, error) {
func (armoAPI *ArmoAPI) ListFrameworks() ([]string, error) {
respStr, err := HttpGetter(armoAPI.httpClient, armoAPI.getListFrameworkURL(), nil)
if err != nil {
return nil, err
@@ -219,6 +217,10 @@ func (armoAPI *ArmoAPI) ListFrameworks(customerGUID string) ([]string, error) {
return frameworkList, nil
}
func (armoAPI *ArmoAPI) ListControls(l ListType) ([]string, error) {
return nil, fmt.Errorf("control api is not public")
}
type TenantResponse struct {
TenantID string `json:"tenantId"`
Token string `json:"token"`
+4 -4
View File
@@ -36,14 +36,14 @@ func (armoAPI *ArmoAPI) getListFrameworkURL() string {
return u.String()
}
func (armoAPI *ArmoAPI) getExceptionsURL(customerGUID, clusterName string) string {
func (armoAPI *ArmoAPI) getExceptionsURL(clusterName string) string {
u := url.URL{}
u.Scheme = "https"
u.Host = armoAPI.apiURL
u.Path = "api/v1/armoPostureExceptions"
q := u.Query()
q.Add("customerGUID", customerGUID)
q.Add("customerGUID", armoAPI.customerGUID)
// if clusterName != "" { // TODO - fix customer name support in Armo BE
// q.Add("clusterName", clusterName)
// }
@@ -52,14 +52,14 @@ func (armoAPI *ArmoAPI) getExceptionsURL(customerGUID, clusterName string) strin
return u.String()
}
func (armoAPI *ArmoAPI) getAccountConfig(customerGUID, clusterName string) string {
func (armoAPI *ArmoAPI) getAccountConfig(clusterName string) string {
u := url.URL{}
u.Scheme = "https"
u.Host = armoAPI.apiURL
u.Path = "api/v1/armoCustomerConfiguration"
q := u.Query()
q.Add("customerGUID", customerGUID)
q.Add("customerGUID", armoAPI.customerGUID)
if clusterName != "" { // TODO - fix customer name support in Armo BE
q.Add("clusterName", clusterName)
}
+14 -1
View File
@@ -41,7 +41,20 @@ func (drp *DownloadReleasedPolicy) GetFramework(name string) (*reporthandling.Fr
return framework, err
}
func (drp *DownloadReleasedPolicy) GetControlsInputs(customerGUID, clusterName string) (map[string][]string, error) {
func (drp *DownloadReleasedPolicy) ListFrameworks() ([]string, error) {
return drp.gs.GetOPAFrameworksNamesList()
}
func (drp *DownloadReleasedPolicy) ListControls(listType ListType) ([]string, error) {
switch listType {
case ListID:
return drp.gs.GetOPAControlsIDsList()
default:
return drp.gs.GetOPAControlsNamesList()
}
}
func (drp *DownloadReleasedPolicy) GetControlsInputs(clusterName string) (map[string][]string, error) {
defaultConfigInputs, err := drp.gs.GetDefaultConfigInputs()
if err != nil {
return nil, err
+13 -3
View File
@@ -5,18 +5,28 @@ import (
"github.com/armosec/opa-utils/reporthandling"
)
// supported listing
type ListType string
const ListID ListType = "id"
const ListName ListType = "name"
type IPolicyGetter interface {
GetFramework(name string) (*reporthandling.Framework, error)
GetControl(name string) (*reporthandling.Control, error)
ListFrameworks() ([]string, error)
ListControls(ListType) ([]string, error)
}
type IExceptionsGetter interface {
GetExceptions(customerGUID, clusterName string) ([]armotypes.PostureExceptionPolicy, error)
GetExceptions(clusterName string) ([]armotypes.PostureExceptionPolicy, error)
}
type IBackend interface {
GetCustomerGUID(customerGUID string) (*TenantResponse, error)
GetCustomerGUID() (*TenantResponse, error)
SetCustomerGUID(customerGUID string)
}
type IControlsInputsGetter interface {
GetControlsInputs(customerGUID, clusterName string) (map[string][]string, error)
GetControlsInputs(clusterName string) (map[string][]string, error)
}
+2 -29
View File
@@ -10,8 +10,6 @@ import (
"path"
"path/filepath"
"strings"
"github.com/armosec/opa-utils/reporthandling"
)
func GetDefaultPath(name string) string {
@@ -22,33 +20,8 @@ func GetDefaultPath(name string) string {
return defaultfilePath
}
// Save control as json in file
func SaveControlInFile(control *reporthandling.Control, pathStr string) error {
encodedData, err := json.Marshal(control)
if err != nil {
return err
}
err = os.WriteFile(pathStr, []byte(fmt.Sprintf("%v", string(encodedData))), 0644)
if err != nil {
if os.IsNotExist(err) {
pathDir := path.Dir(pathStr)
if err := os.Mkdir(pathDir, 0744); err != nil {
return err
}
} else {
return err
}
err = os.WriteFile(pathStr, []byte(fmt.Sprintf("%v", string(encodedData))), 0644)
if err != nil {
return err
}
}
return nil
}
func SaveFrameworkInFile(framework *reporthandling.Framework, pathStr string) error {
encodedData, err := json.Marshal(framework)
func SaveInFile(policy interface{}, pathStr string) error {
encodedData, err := json.Marshal(policy)
if err != nil {
return err
}
+12 -2
View File
@@ -78,7 +78,17 @@ func (lp *LoadPolicy) GetFramework(frameworkName string) (*reporthandling.Framew
return framework, err
}
func (lp *LoadPolicy) GetExceptions(customerGUID, clusterName string) ([]armotypes.PostureExceptionPolicy, error) {
func (lp *LoadPolicy) ListFrameworks() ([]string, error) {
// TODO - Support
return []string{}, fmt.Errorf("loading frameworks list from file is not supported")
}
func (lp *LoadPolicy) ListControls(listType ListType) ([]string, error) {
// TODO - Support
return []string{}, fmt.Errorf("loading controls list from file is not supported")
}
func (lp *LoadPolicy) GetExceptions(clusterName string) ([]armotypes.PostureExceptionPolicy, error) {
filePath := lp.filePath()
exception := []armotypes.PostureExceptionPolicy{}
f, err := os.ReadFile(filePath)
@@ -90,7 +100,7 @@ func (lp *LoadPolicy) GetExceptions(customerGUID, clusterName string) ([]armotyp
return exception, err
}
func (lp *LoadPolicy) GetControlsInputs(customerGUID, clusterName string) (map[string][]string, error) {
func (lp *LoadPolicy) GetControlsInputs(clusterName string) (map[string][]string, error) {
filePath := lp.filePath()
accountConfig := &armotypes.CustomerConfig{}
f, err := os.ReadFile(filePath)
+7
View File
@@ -43,12 +43,19 @@ func (rbacObjects *RBACObjects) ListAllResources() (map[string]workloadinterface
func (rbacObjects *RBACObjects) rbacObjectsToResources(resources *rbacutils.RbacObjects) (map[string]workloadinterface.IMetadata, error) {
allresources := map[string]workloadinterface.IMetadata{}
// wrap rbac aggregated objects in IMetadata and add to allresources
// TODO - DEPRECATE SA2WLIDmap
SA2WLIDmapIMeta, err := rbacutils.SA2WLIDmapIMetadataWrapper(resources.SA2WLIDmap)
if err != nil {
return nil, err
}
allresources[SA2WLIDmapIMeta.GetID()] = SA2WLIDmapIMeta
SAID2WLIDmapIMeta, err := rbacutils.SAID2WLIDmapIMetadataWrapper(resources.SAID2WLIDmap)
if err != nil {
return nil, err
}
allresources[SAID2WLIDmapIMeta.GetID()] = SAID2WLIDmapIMeta
// convert rbac k8s resources to IMetadata and add to allresources
for _, cr := range resources.ClusterRoles.Items {
crmap, err := convertToMap(cr)
-10
View File
@@ -76,20 +76,10 @@ type Getters struct {
func (scanInfo *ScanInfo) Init() {
scanInfo.setUseFrom()
scanInfo.setUseExceptions()
scanInfo.setOutputFile()
}
func (scanInfo *ScanInfo) setUseExceptions() {
if scanInfo.UseExceptions != "" {
// load exceptions from file
scanInfo.ExceptionsGetter = getter.NewLoadPolicy([]string{scanInfo.UseExceptions})
} else {
scanInfo.ExceptionsGetter = getter.GetArmoAPIConnector()
}
}
func (scanInfo *ScanInfo) setUseFrom() {
if scanInfo.UseDefault {
for _, policy := range scanInfo.PolicyIdentifier {
+116
View File
@@ -0,0 +1,116 @@
package clihandler
import (
"fmt"
"os"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/getter"
)
var downloadFunc = map[string]func(*cautils.DownloadInfo) error{
"controls-inputs": downloadConfigInputs,
"exceptions": downloadExceptions,
"control": downloadControl,
"framework": downloadFramework,
}
func DownloadSupportCommands() []string {
commands := []string{}
for k := range downloadFunc {
commands = append(commands, k)
}
return commands
}
func CliDownload(downloadInfo *cautils.DownloadInfo) error {
if f, ok := downloadFunc[downloadInfo.Target]; ok {
if err := f(downloadInfo); err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(fmt.Sprintf("'%s' downloaded successfully and saved at: '%s'", downloadInfo.Target, downloadInfo.Path))
return nil
}
return fmt.Errorf("unknown command to download")
}
func downloadConfigInputs(downloadInfo *cautils.DownloadInfo) error {
tenant := getTenantConfig(downloadInfo.Account, getKubernetesApi()) // change k8sinterface
controlsInputsGetter := getConfigInputsGetter(downloadInfo.Name, tenant.GetCustomerGUID(), nil)
controlInputs, err := controlsInputsGetter.GetControlsInputs(tenant.GetClusterName())
if err != nil {
return err
}
if downloadInfo.Path == "" {
downloadInfo.Path = getter.GetDefaultPath(fmt.Sprintf("%s.json", downloadInfo.Target))
}
// save in file
err = getter.SaveInFile(controlInputs, downloadInfo.Path)
if err != nil {
return err
}
return nil
}
func downloadExceptions(downloadInfo *cautils.DownloadInfo) error {
tenant := getTenantConfig(downloadInfo.Account, getKubernetesApi()) // change k8sinterface
exceptionsGetter := getExceptionsGetter("")
exceptions, err := exceptionsGetter.GetExceptions(tenant.GetClusterName())
if err != nil {
return err
}
if downloadInfo.Path == "" {
downloadInfo.Path = getter.GetDefaultPath(fmt.Sprintf("%s.json", downloadInfo.Target))
}
// save in file
err = getter.SaveInFile(exceptions, downloadInfo.Path)
if err != nil {
return err
}
return nil
}
func downloadFramework(downloadInfo *cautils.DownloadInfo) error {
tenant := getTenantConfig(downloadInfo.Account, getKubernetesApi()) // change k8sinterface
g := getPolicyGetter(nil, tenant.GetCustomerGUID(), true, nil)
if downloadInfo.Name == "" {
// TODO - support
return fmt.Errorf("missing framework name")
}
if downloadInfo.Path == "" {
downloadInfo.Path = getter.GetDefaultPath(downloadInfo.Name + ".json")
}
frameworks, err := g.GetFramework(downloadInfo.Name)
if err != nil {
return err
}
err = getter.SaveInFile(frameworks, downloadInfo.Path)
if err != nil {
return err
}
return nil
}
func downloadControl(downloadInfo *cautils.DownloadInfo) error {
tenant := getTenantConfig(downloadInfo.Account, getKubernetesApi()) // change k8sinterface
g := getPolicyGetter(nil, tenant.GetCustomerGUID(), true, nil)
if downloadInfo.Name == "" {
// TODO - support
return fmt.Errorf("missing control name")
}
if downloadInfo.Path == "" {
downloadInfo.Path = getter.GetDefaultPath(downloadInfo.Name + ".json")
}
controls, err := g.GetControl(downloadInfo.Name)
if err != nil {
return err
}
err = getter.SaveInFile(controls, downloadInfo.Path)
if err != nil {
return err
}
return nil
}
+19 -2
View File
@@ -13,10 +13,27 @@ import (
"github.com/spf13/cobra"
)
var (
controlExample = `
# Scan the 'privileged container' control
kubescape scan control 'privileged container'
# Scan list of controls separated with a comma
kubescape scan control 'privileged container,allowed hostpath'
# Scan list of controls using the control ID separated with a comma
kubescape scan control C-0058,C-0057
Control documentation:
https://hub.armo.cloud/docs/controls
`
)
// controlCmd represents the control command
var controlCmd = &cobra.Command{
Use: "control <control names list>/<control ids list>.\nExamples:\n$ kubescape scan control C-0058,C-0057 [flags]\n$ kubescape scan contol C-0058 [flags]\n$ kubescape scan control 'privileged container,allowed hostpath' [flags]",
Short: fmt.Sprintf("The control you wish to use for scan. It must be present in at least one of the following frameworks: %s", getter.NativeFrameworks),
Use: "control <control names list>/<control ids list>",
Short: "The controls you wish to use. Run 'kubescape list controls' for the list of supported controls",
Example: controlExample,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
controls := strings.Split(args[0], ",")
+18 -64
View File
@@ -6,27 +6,32 @@ import (
"strings"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/getter"
"github.com/armosec/kubescape/clihandler"
"github.com/spf13/cobra"
)
var downloadInfo cautils.DownloadInfo
var downloadInfo = cautils.DownloadInfo{}
var downloadCmd = &cobra.Command{
Use: fmt.Sprintf("download framework/control <framework-name>/<control-name> [flags]\nSupported frameworks: %s", getter.NativeFrameworks),
Short: "Download framework/control",
Use: "download <policy> <policy name>",
Short: fmt.Sprintf("Download %s", strings.Join(clihandler.DownloadSupportCommands(), "/")),
Long: ``,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) != 2 {
return fmt.Errorf("requires two arguments : framework/control <framework-name>/<control-name>")
supported := strings.Join(clihandler.DownloadSupportCommands(), ",")
if len(args) < 1 {
return fmt.Errorf("policy type requeued, supported: %v", supported)
}
if !strings.EqualFold(args[0], "framework") && !strings.EqualFold(args[0], "control") {
return fmt.Errorf("invalid parameter '%s'. Supported parameters: framework, control", args[0])
if cautils.StringInSlice(clihandler.DownloadSupportCommands(), args[0]) == cautils.ValueNotFound {
return fmt.Errorf("invalid parameter '%s'. Supported parameters: %s", args[0], supported)
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
if err := download(args); err != nil {
downloadInfo.Target = args[0]
if len(args) >= 2 {
downloadInfo.Name = args[1]
}
if err := clihandler.CliDownload(&downloadInfo); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
@@ -35,61 +40,10 @@ var downloadCmd = &cobra.Command{
}
func init() {
// cobra.OnInitialize(initConfig)
rootCmd.AddCommand(downloadCmd)
downloadInfo = cautils.DownloadInfo{}
downloadCmd.Flags().StringVarP(&downloadInfo.Path, "output", "o", "", "Output file. If specified, will store save to `~/.kubescape/<framework name>.json`")
}
downloadCmd.Flags().StringVarP(&downloadInfo.Path, "output", "o", "", "Output file. If specified, will store save to `~/.kubescape/<policy name>.json`")
downloadCmd.PersistentFlags().StringVarP(&downloadInfo.Account, "account", "", "", "Armo portal account ID. Default will load account ID from configMap or config file")
func download(args []string) error {
switch strings.ToLower(args[0]) {
case "framework":
return downloadFramework(args[1])
case "control":
return downloadControl(args[1])
// case "exceptions":
// case "artifacts":
default:
return fmt.Errorf("unknown command to download")
}
}
func downloadFramework(frameworkName string) error {
downloadInfo.FrameworkName = strings.ToLower(frameworkName)
g := getter.NewDownloadReleasedPolicy()
if err := g.SetRegoObjects(); err != nil {
return err
}
if downloadInfo.Path == "" {
downloadInfo.Path = getter.GetDefaultPath(downloadInfo.FrameworkName + ".json")
}
frameworks, err := g.GetFramework(downloadInfo.FrameworkName)
if err != nil {
return err
}
err = getter.SaveFrameworkInFile(frameworks, downloadInfo.Path)
if err != nil {
return err
}
return nil
}
func downloadControl(controlName string) error {
downloadInfo.ControlName = strings.ToLower(controlName)
g := getter.NewDownloadReleasedPolicy()
if err := g.SetRegoObjects(); err != nil {
return err
}
if downloadInfo.Path == "" {
downloadInfo.Path = getter.GetDefaultPath(downloadInfo.ControlName + ".json")
}
controls, err := g.GetControl(downloadInfo.ControlName)
if err != nil {
return err
}
err = getter.SaveControlInFile(controls, downloadInfo.Path)
if err != nil {
return err
}
return nil
}
+1 -1
View File
@@ -39,7 +39,7 @@ var (
)
var frameworkCmd = &cobra.Command{
Use: "framework <framework names list> [`<glob pattern>`/`-`] [flags]",
Short: fmt.Sprintf("The framework you wish to use. Supported frameworks: %s", strings.Join(getter.NativeFrameworks, ", ")),
Short: "The framework you wish to use. Run 'kubescape list frameworks' for the list of supported frameworks",
Example: frameworkExample,
Long: "Execute a scan on a running Kubernetes cluster or `yaml`/`json` files (use glob) or `-` for stdin",
ValidArgs: getter.NativeFrameworks,
-5
View File
@@ -35,14 +35,9 @@ 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() {
urlSlices := strings.Split(armoBEURLs, ",")
if len(urlSlices) > 3 {
+10 -5
View File
@@ -34,9 +34,9 @@ type componentInterfaces struct {
func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces {
k8s := getKubernetesApi(scanInfo)
k8s := getKubernetesApi()
tenantConfig := getTenantConfig(scanInfo, k8s)
tenantConfig := getTenantConfig(scanInfo.Account, k8s)
// Set submit behavior AFTER loading tenant config
setSubmitBehavior(scanInfo, tenantConfig)
@@ -92,10 +92,15 @@ func ScanCliSetup(scanInfo *cautils.ScanInfo) error {
interfaces.report.SetCustomerGUID(interfaces.tenantConfig.GetCustomerGUID())
downloadReleasedPolicy := getter.NewDownloadReleasedPolicy() // download config inputs from github release
// set policy getter only after setting the customerGUID
setPolicyGetter(scanInfo, interfaces.tenantConfig.GetCustomerGUID(), downloadReleasedPolicy)
setConfigInputsGetter(scanInfo, interfaces.tenantConfig.GetCustomerGUID(), downloadReleasedPolicy)
// set policy getter only after setting the customerGUID
scanInfo.Getters.PolicyGetter = getPolicyGetter(scanInfo.UseFrom, interfaces.tenantConfig.GetCustomerGUID(), scanInfo.FrameworkScan, downloadReleasedPolicy)
scanInfo.Getters.ControlsInputsGetter = getConfigInputsGetter(scanInfo.ControlsInputs, interfaces.tenantConfig.GetCustomerGUID(), downloadReleasedPolicy)
scanInfo.Getters.ExceptionsGetter = getExceptionsGetter(scanInfo.UseExceptions)
// TODO - list supported frameworks/controls
//
defer func() {
if err := interfaces.hostSensorHandler.TearDown(); err != nil {
errMsg := "failed to tear down host sensor"
+65 -48
View File
@@ -13,21 +13,29 @@ import (
reporterv1 "github.com/armosec/kubescape/resultshandling/reporter/v1"
"github.com/armosec/opa-utils/reporthandling"
"github.com/armosec/rbac-utils/rbacscanner"
"github.com/golang/glog"
// reporterv2 "github.com/armosec/kubescape/resultshandling/reporter/v2"
)
func getKubernetesApi(scanInfo *cautils.ScanInfo) *k8sinterface.KubernetesApi {
if scanInfo.GetScanningEnvironment() == cautils.ScanLocalFiles {
func getKubernetesApi() *k8sinterface.KubernetesApi {
if !k8sinterface.IsConnectedToCluster() {
return nil
}
return k8sinterface.NewKubernetesApi()
}
func getTenantConfig(scanInfo *cautils.ScanInfo, k8s *k8sinterface.KubernetesApi) cautils.ITenantConfig {
if scanInfo.GetScanningEnvironment() == cautils.ScanLocalFiles {
return cautils.NewLocalConfig(getter.GetArmoAPIConnector(), scanInfo.Account)
func getTenantConfig(Account string, k8s *k8sinterface.KubernetesApi) cautils.ITenantConfig {
if !k8sinterface.IsConnectedToCluster() {
return cautils.NewLocalConfig(getter.GetArmoAPIConnector(), Account)
}
return cautils.NewClusterConfig(k8s, getter.GetArmoAPIConnector(), Account)
}
func getExceptionsGetter(useExceptions string) getter.IExceptionsGetter {
if useExceptions != "" {
// load exceptions from file
return getter.NewLoadPolicy([]string{useExceptions})
} else {
return getter.GetArmoAPIConnector()
}
return cautils.NewClusterConfig(k8s, getter.GetArmoAPIConnector(), scanInfo.Account)
}
func getRBACHandler(tenantConfig cautils.ITenantConfig, k8s *k8sinterface.KubernetesApi, submit bool) *cautils.RBACObjects {
@@ -139,55 +147,64 @@ func setSubmitBehavior(scanInfo *cautils.ScanInfo, tenantConfig cautils.ITenantC
}
// setPolicyGetter set the policy getter - local file/github release/ArmoAPI
func setPolicyGetter(scanInfo *cautils.ScanInfo, customerGUID string, downloadReleasedPolicy *getter.DownloadReleasedPolicy) {
if len(scanInfo.UseFrom) > 0 {
scanInfo.PolicyGetter = getter.NewLoadPolicy(scanInfo.UseFrom)
} else {
if customerGUID == "" || !scanInfo.FrameworkScan {
setDownloadReleasedPolicy(scanInfo, downloadReleasedPolicy)
} else {
setGetArmoAPIConnector(scanInfo, customerGUID)
}
func getPolicyGetter(loadPoliciesFromFile []string, accountID string, frameworkScope bool, downloadReleasedPolicy *getter.DownloadReleasedPolicy) getter.IPolicyGetter {
if len(loadPoliciesFromFile) > 0 {
return getter.NewLoadPolicy(loadPoliciesFromFile)
}
if accountID != "" && frameworkScope {
g := getter.GetArmoAPIConnector() // download policy from ARMO backend
g.SetCustomerGUID(accountID)
return g
}
if downloadReleasedPolicy == nil {
downloadReleasedPolicy = getter.NewDownloadReleasedPolicy()
}
return getDownloadReleasedPolicy(downloadReleasedPolicy)
}
// func setGetArmoAPIConnector(scanInfo *cautils.ScanInfo, customerGUID string) {
// g := getter.GetArmoAPIConnector() // download policy from ARMO backend
// g.SetCustomerGUID(customerGUID)
// scanInfo.PolicyGetter = g
// if scanInfo.ScanAll {
// frameworks, err := g.ListCustomFrameworks(customerGUID)
// if err != nil {
// glog.Error("failed to get custom frameworks") // handle error
// return
// }
// scanInfo.SetPolicyIdentifiers(frameworks, reporthandling.KindFramework)
// }
// }
// setConfigInputsGetter sets the config input getter - local file/github release/ArmoAPI
func setConfigInputsGetter(scanInfo *cautils.ScanInfo, customerGUID string, downloadReleasedPolicy *getter.DownloadReleasedPolicy) {
if len(scanInfo.ControlsInputs) > 0 {
scanInfo.Getters.ControlsInputsGetter = getter.NewLoadPolicy([]string{scanInfo.ControlsInputs})
func getConfigInputsGetter(ControlsInputs string, accountID string, downloadReleasedPolicy *getter.DownloadReleasedPolicy) getter.IControlsInputsGetter {
if len(ControlsInputs) > 0 {
return getter.NewLoadPolicy([]string{ControlsInputs})
}
if accountID != "" {
g := getter.GetArmoAPIConnector() // download config from ARMO backend
g.SetCustomerGUID(accountID)
return g
}
if downloadReleasedPolicy == nil {
downloadReleasedPolicy = getter.NewDownloadReleasedPolicy()
}
if err := downloadReleasedPolicy.SetRegoObjects(); err != nil { // if failed to pull config inputs, fallback to BE
cautils.WarningDisplay(os.Stderr, "Warning: failed to get config inputs from github release, this may affect the scanning results\n")
}
return downloadReleasedPolicy
}
func getDownloadReleasedPolicy(downloadReleasedPolicy *getter.DownloadReleasedPolicy) getter.IPolicyGetter {
if err := downloadReleasedPolicy.SetRegoObjects(); err != nil { // if failed to pull policy, fallback to cache
cautils.WarningDisplay(os.Stderr, "Warning: failed to get policies from github release, loading policies from cache\n")
return getter.NewLoadPolicy(getDefaultFrameworksPaths())
} else {
if customerGUID != "" {
scanInfo.Getters.ControlsInputsGetter = getter.GetArmoAPIConnector()
} else {
if err := downloadReleasedPolicy.SetRegoObjects(); err != nil { // if failed to pull config inputs, fallback to BE
cautils.WarningDisplay(os.Stderr, "Warning: failed to get config inputs from github release, this may affect the scanning results\n")
}
scanInfo.Getters.ControlsInputsGetter = downloadReleasedPolicy
}
return downloadReleasedPolicy
}
}
func setDownloadReleasedPolicy(scanInfo *cautils.ScanInfo, downloadReleasedPolicy *getter.DownloadReleasedPolicy) {
if err := downloadReleasedPolicy.SetRegoObjects(); err != nil { // if failed to pull policy, fallback to cache
cautils.WarningDisplay(os.Stderr, "Warning: failed to get policies from github release, loading policies from cache\n")
scanInfo.PolicyGetter = getter.NewLoadPolicy(getDefaultFrameworksPaths())
} else {
scanInfo.PolicyGetter = downloadReleasedPolicy
}
}
func setGetArmoAPIConnector(scanInfo *cautils.ScanInfo, customerGUID string) {
g := getter.GetArmoAPIConnector() // download policy from ARMO backend
g.SetCustomerGUID(customerGUID)
scanInfo.PolicyGetter = g
if scanInfo.ScanAll {
frameworks, err := g.ListCustomFrameworks(customerGUID)
if err != nil {
glog.Error("failed to get custom frameworks") // handle error
return
}
scanInfo.SetPolicyIdentifiers(frameworks, reporthandling.KindFramework)
}
}
func getDefaultFrameworksPaths() []string {
fwPaths := []string{}
for i := range getter.NativeFrameworks {
+1 -1
View File
@@ -6,7 +6,7 @@ require (
github.com/armosec/armoapi-go v0.0.40
github.com/armosec/k8s-interface v0.0.50
github.com/armosec/opa-utils v0.0.88
github.com/armosec/rbac-utils v0.0.10
github.com/armosec/rbac-utils v0.0.11
github.com/armosec/utils-go v0.0.3
github.com/briandowns/spinner v1.18.0
github.com/enescakir/emoji v1.0.0
+2 -2
View File
@@ -95,8 +95,8 @@ github.com/armosec/opa-utils v0.0.64/go.mod h1:6tQP8UDq2EvEfSqh8vrUdr/9QVSCG4sJf
github.com/armosec/opa-utils v0.0.88 h1:IxIml3w7l0HFqbb+XzKuXf+Pw78DHIxPwRIkgudKQRw=
github.com/armosec/opa-utils v0.0.88/go.mod h1:ZOXYVTtuyrV4TldcfbzgRqP6F9Drlf4hB0zr210OXgM=
github.com/armosec/rbac-utils v0.0.1/go.mod h1:pQ8CBiij8kSKV7aeZm9FMvtZN28VgA7LZcYyTWimq40=
github.com/armosec/rbac-utils v0.0.10 h1:bFjesO8+xJS1ryR9vqj4xFEo1cQ0HvClzR+LWHzozW4=
github.com/armosec/rbac-utils v0.0.10/go.mod h1:Ex/IdGWhGv9HZq6Hs8N/ApzCKSIvpNe/ETqDfnuyah0=
github.com/armosec/rbac-utils v0.0.11 h1:SCiVLqUeV+WGpUsWbOBt6jKkFAd62jztuzB6PIgHz7w=
github.com/armosec/rbac-utils v0.0.11/go.mod h1:Ex/IdGWhGv9HZq6Hs8N/ApzCKSIvpNe/ETqDfnuyah0=
github.com/armosec/utils-go v0.0.2/go.mod h1:itWmRLzRdsnwjpEOomL0mBWGnVNNIxSjDAdyc+b0iUo=
github.com/armosec/utils-go v0.0.3 h1:uyQI676yRciQM0sSN9uPoqHkbspTxHO0kmzXhBeE/xU=
github.com/armosec/utils-go v0.0.3/go.mod h1:itWmRLzRdsnwjpEOomL0mBWGnVNNIxSjDAdyc+b0iUo=
+2 -2
View File
@@ -21,13 +21,13 @@ func (policyHandler *PolicyHandler) getPolicies(notification *reporthandling.Pol
policiesAndResources.Frameworks = frameworks
// get exceptions
exceptionPolicies, err := policyHandler.getters.ExceptionsGetter.GetExceptions(cautils.CustomerGUID, cautils.ClusterName)
exceptionPolicies, err := policyHandler.getters.ExceptionsGetter.GetExceptions(cautils.ClusterName)
if err == nil {
policiesAndResources.Exceptions = exceptionPolicies
}
// get account configuration
controlsInputs, err := policyHandler.getters.ControlsInputsGetter.GetControlsInputs(cautils.CustomerGUID, cautils.ClusterName)
controlsInputs, err := policyHandler.getters.ControlsInputsGetter.GetControlsInputs(cautils.ClusterName)
if err == nil {
policiesAndResources.RegoInputData.PostureControlInputs = controlsInputs
}