diff --git a/src/cluster/clusterMgmtHandler.go b/src/cluster/clusterMgmtHandler.go index 99745b70..6d14eb21 100644 --- a/src/cluster/clusterMgmtHandler.go +++ b/src/cluster/clusterMgmtHandler.go @@ -91,7 +91,7 @@ func getResponseBytes(method string, url string, data map[string]interface{}) [] dumpHttpClient(nil, resp) defer func() { if err := resp.Body.Close(); err != nil { - log.Warn().Msgf("Error closing http stream %s\n", err) + log.Error().Msgf("Error closing http response: %s", err) } }() diff --git a/src/cluster/k8sClientHandler.go b/src/cluster/k8sClientHandler.go index a42c81fe..0fe64426 100644 --- a/src/cluster/k8sClientHandler.go +++ b/src/cluster/k8sClientHandler.go @@ -12,6 +12,7 @@ import ( "github.com/accuknox/auto-policy-discovery/src/libs" "github.com/accuknox/auto-policy-discovery/src/types" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" rest "k8s.io/client-go/rest" @@ -459,3 +460,18 @@ func GetDeploymentsFromK8sClient() []types.Deployment { } return results } + +// ================= // +// == Nodes == // +// ================= // + +func GetNodesFromK8sClient() (*v1.NodeList, error) { + + client := ConnectK8sClient() + nodeList, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) + if err != nil { + log.Error().Msg(err.Error()) + return &v1.NodeList{}, err + } + return nodeList, nil +} diff --git a/src/conf/local-file.yaml b/src/conf/local-file.yaml index 978d2102..0830999c 100644 --- a/src/conf/local-file.yaml +++ b/src/conf/local-file.yaml @@ -117,4 +117,5 @@ feed-consumer: # Recommended policies configuration recommend: operation-mode: 1 # 1: cronjob | 2: one-time-job - cron-job-time-interval: "1h0m00s" # format: XhYmZs \ No newline at end of file + cron-job-time-interval: "1h0m00s" # format: XhYmZs + recommend-host-policy: true \ No newline at end of file diff --git a/src/conf/local.yaml b/src/conf/local.yaml index cf903fbc..73b82d95 100644 --- a/src/conf/local.yaml +++ b/src/conf/local.yaml @@ -70,3 +70,4 @@ kubearmor: recommend: operation-mode: 1 # 1: cronjob | 2: one-time-job cron-job-time-interval: "1h0m00s" # format: XhYmZs + recommend-host-policy: true diff --git a/src/config/configManager.go b/src/config/configManager.go index 6cad25bb..3eb73224 100644 --- a/src/config/configManager.go +++ b/src/config/configManager.go @@ -212,6 +212,7 @@ func LoadConfigFromFile() { CronJobTimeInterval: "@every " + viper.GetString("recommend.cron-job-time-interval"), OneTimeJobTimeSelection: "", // e.g., 2021-01-20 07:00:23|2021-01-20 07:00:25 OperationMode: viper.GetInt("recommend.operation-mode"), + RecommendHostPolicy: viper.GetBool("recommend.recommend-host-policy"), } // load database @@ -512,3 +513,7 @@ func GetCfgRecCronJobTime() string { func GetCfgRecOneTime() string { return CurrentCfg.ConfigRecommendPolicy.OneTimeJobTimeSelection } + +func GetCfgRecommendHostPolicy() bool { + return CurrentCfg.ConfigRecommendPolicy.RecommendHostPolicy +} diff --git a/src/libs/common.go b/src/libs/common.go index e3715508..12725e0e 100644 --- a/src/libs/common.go +++ b/src/libs/common.go @@ -10,6 +10,7 @@ import ( "os" "os/exec" "os/signal" + "path/filepath" "reflect" "sort" "strings" @@ -149,6 +150,7 @@ func SetDefaultConfig() { viper.SetDefault("recommend.cron-job-time-interval", "1h0m00s") viper.SetDefault("recommend.operation-mode", 1) + viper.SetDefault("recommend.recommend-host-policy", true) } @@ -480,7 +482,7 @@ func WriteKnoxNetPolicyToYamlFile(namespace string, policies []types.KnoxNetwork } // create policy file - f, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY, 0600) + f, err := os.OpenFile(filepath.Clean(fileName), os.O_CREATE|os.O_WRONLY, 0600) if err != nil { log.Error().Msg(err.Error()) return @@ -516,7 +518,7 @@ func WriteCiliumPolicyToYamlFile(namespace string, policies []types.CiliumNetwor } } - f, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY, 0600) + f, err := os.OpenFile(filepath.Clean(fileName), os.O_CREATE|os.O_WRONLY, 0600) if err != nil { log.Error().Msg(err.Error()) return @@ -551,7 +553,7 @@ func WriteKubeArmorPolicyToYamlFile(fname string, policies []types.KubeArmorPoli } } - f, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY, 0600) + f, err := os.OpenFile(filepath.Clean(fileName), os.O_CREATE|os.O_WRONLY, 0600) if err != nil { log.Error().Msg(err.Error()) return @@ -586,7 +588,7 @@ func WriteSysObsDataToJsonFile(obsData types.SysInsightResponseData) { } } - f, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY, 0600) + f, err := os.OpenFile(filepath.Clean(fileName), os.O_CREATE|os.O_WRONLY, 0600) if err != nil { log.Error().Msg(err.Error()) return diff --git a/src/logging/logger.go b/src/logging/logger.go index 277d71b3..bee0ec77 100644 --- a/src/logging/logger.go +++ b/src/logging/logger.go @@ -1,3 +1,4 @@ +// Package logging contains logging information package logging import ( @@ -53,7 +54,7 @@ func configure(config Config) *zerolog.Logger { } func newRollingFile(config Config) io.Writer { - if err := os.MkdirAll(config.Directory, 0700); err != nil { + if err := os.MkdirAll(config.Directory, 0740); err != nil { log.Error().Err(err).Str("path", config.Directory).Msg("can't create log directory") return nil } @@ -70,6 +71,7 @@ func newRollingFile(config Config) io.Writer { var customLogger *zerolog.Logger var once sync.Once +// SetLogLevel sets the log level to {TRACE, DEBUG, INFO, ERROR, FATAL, PANIC, NO, DISABLED} func SetLogLevel(logLevel string) { switch logLevel { case "TRACE": @@ -93,6 +95,7 @@ func SetLogLevel(logLevel string) { } } +// GetInstance returns a custom logger variable func GetInstance() *zerolog.Logger { once.Do(func() { config := Config{ diff --git a/src/plugin/kubearmor.go b/src/plugin/kubearmor.go index 1226aef2..55c92157 100644 --- a/src/plugin/kubearmor.go +++ b/src/plugin/kubearmor.go @@ -50,8 +50,14 @@ func ConvertKnoxSystemPolicyToKubeArmorPolicy(knoxPolicies []types.KnoxSystemPol Kind: "KubeArmorPolicy", Metadata: map[string]string{}, } + if policy.Kind != "" { + kubePolicy.Kind = policy.Kind + } + + if policy.Kind != types.KindKubeArmorHostPolicy { + kubePolicy.Metadata["namespace"] = policy.Metadata["namespace"] + } - kubePolicy.Metadata["namespace"] = policy.Metadata["namespace"] kubePolicy.Metadata["name"] = policy.Metadata["name"] if policy.Metadata["namespace"] == types.PolicyDiscoveryVMNamespace { @@ -60,7 +66,7 @@ func ConvertKnoxSystemPolicyToKubeArmorPolicy(knoxPolicies []types.KnoxSystemPol kubePolicy.Spec = policy.Spec - if kubePolicy.Kind == "KubeArmorPolicy" && policy.Spec.Action == "Allow" { + if kubePolicy.Kind == types.KindKubeArmorPolicy && policy.Spec.Action == "Allow" { dirRule := types.KnoxMatchDirectories{ Dir: types.PreConfiguredKubearmorRule, Recursive: true, diff --git a/src/recommendpolicy/downloadTemplates.go b/src/recommendpolicy/downloadTemplates.go index 2d30c348..052444d4 100644 --- a/src/recommendpolicy/downloadTemplates.go +++ b/src/recommendpolicy/downloadTemplates.go @@ -93,7 +93,7 @@ func DownloadAndUnzipRelease() (string, error) { LatestVersion = latestRelease() } _ = removeData(getCachePath()) - err := os.MkdirAll(filepath.Dir(getCachePath()), 0750) + err := os.MkdirAll(filepath.Dir(getCachePath()), 0740) if err != nil { return "", err } @@ -145,7 +145,7 @@ func unZip(source, dest string) error { if err != nil { return err } - _ = os.MkdirAll(path.Dir(name), 0750) + _ = os.MkdirAll(path.Dir(name), 0740) create, err := os.Create(filepath.Clean(name)) if err != nil { return err @@ -212,6 +212,7 @@ func updatePolicyRules(filePath string) error { } ms.Yaml = "" ms.Spec = newPolicyFile.Spec + ms.Kind = newPolicyFile.Kind } completePolicy = append(completePolicy, ms) } diff --git a/src/recommendpolicy/helperFunctions.go b/src/recommendpolicy/helperFunctions.go index 01e6bb8a..99b0bfa8 100644 --- a/src/recommendpolicy/helperFunctions.go +++ b/src/recommendpolicy/helperFunctions.go @@ -12,6 +12,7 @@ import ( "k8s.io/apimachinery/pkg/watch" "github.com/accuknox/auto-policy-discovery/src/cluster" + cfg "github.com/accuknox/auto-policy-discovery/src/config" "github.com/accuknox/auto-policy-discovery/src/types" "sigs.k8s.io/yaml" ) @@ -73,6 +74,21 @@ func generatePolicy(name, namespace string, labels LabelMap) ([]types.KnoxSystem return []types.KnoxSystemPolicy{}, err } policies = append(policies, policy) + } else if ms.Kind == types.KindKubeArmorHostPolicy && cfg.GetCfgRecommendHostPolicy() { + + nodeList, err := cluster.GetNodesFromK8sClient() + if err != nil { + log.Error().Msg(err.Error()) + return []types.KnoxSystemPolicy{}, err + } + for _, node := range nodeList.Items { + policy, err := createPolicy(ms, node.Name, "", node.Labels) + if err != nil { + log.Error().Msg(err.Error()) + return []types.KnoxSystemPolicy{}, err + } + policies = append(policies, policy) + } } } @@ -89,11 +105,17 @@ func createPolicy(ms types.MatchSpec, name, namespace string, labels LabelMap) ( }, } policy.APIVersion = "v1" - policy.Kind = "KubeArmorPolicy" + policy.Kind = ms.Kind - policy.Metadata = map[string]string{ - "name": fmt.Sprintf("%v-%v-%v", types.HardeningPolicy, name, ms.Name), - "namespace": namespace, + if policy.Kind != types.KindKubeArmorHostPolicy { + policy.Metadata = map[string]string{ + "name": fmt.Sprintf("%v-%v-%v", types.HardeningPolicy, name, ms.Name), + "namespace": namespace, + } + } else { + policy.Metadata = map[string]string{ + "name": fmt.Sprintf("%v-host-%v-%v", types.HardeningPolicy, name, ms.Name), + } } policy.Spec.Action = ms.Spec.Action diff --git a/src/recommendpolicy/recommendPolicy.go b/src/recommendpolicy/recommendPolicy.go index 2ec49dc1..821c64aa 100644 --- a/src/recommendpolicy/recommendPolicy.go +++ b/src/recommendpolicy/recommendPolicy.go @@ -62,7 +62,7 @@ func init() { // StartRecommendWorker starts the recommended worker func StartRecommendWorker() { if RecommendWorkerStatus != STATUS_IDLE { - log.Info().Msg("There is no idle system policy discovery worker") + log.Info().Msg("There is no idle recommend policy worker") return } @@ -81,7 +81,7 @@ func StartRecommendWorker() { // StopRecommendWorker stops the recommendation worker func StopRecommendWorker() { - if cfg.GetCfgSysOperationMode() == OP_MODE_CRONJOB { // every time intervals + if cfg.GetCfgRecOperationMode() == OP_MODE_CRONJOB { // every time intervals StopRecommendCronJob() } else { if RecommendWorkerStatus != STATUS_RUNNING { diff --git a/src/systempolicy/systemPolicy.go b/src/systempolicy/systemPolicy.go index 0ac291f7..c0a124e1 100644 --- a/src/systempolicy/systemPolicy.go +++ b/src/systempolicy/systemPolicy.go @@ -5,6 +5,7 @@ import ( "hash/fnv" "io/ioutil" "os" + "path/filepath" "reflect" "regexp" "sort" @@ -180,7 +181,7 @@ func getSystemLogs() []types.KnoxSystemLog { log.Info().Msg("Get system logs from the json file : " + SystemLogFile) // Opens jsonFile - logFile, err := os.Open(SystemLogFile) + logFile, err := os.Open(filepath.Clean(SystemLogFile)) if err != nil { log.Error().Msg(err.Error()) if err := logFile.Close(); err != nil { diff --git a/src/types/configData.go b/src/types/configData.go index 3371d829..50f032e6 100644 --- a/src/types/configData.go +++ b/src/types/configData.go @@ -120,6 +120,7 @@ type ConfigRecommendPolicy struct { OperationMode int `json:"operation_mode,omitempty" bson:"operation_mode,omitempty"` CronJobTimeInterval string `json:"cronjob_time_interval,omitempty" bson:"cronjob_time_interval,omitempty"` OneTimeJobTimeSelection string `json:"one_time_job_time_selection,omitempty" bson:"one_time_job_time_selection,omitempty"` + RecommendHostPolicy bool `json:"recommend_host_policy,omitempty" bson:"recommend_host_policy,omitempty"` } type Configuration struct { diff --git a/src/types/policyData.go b/src/types/policyData.go index 53dedf52..7eb5152c 100644 --- a/src/types/policyData.go +++ b/src/types/policyData.go @@ -344,6 +344,7 @@ type MatchSpec struct { Description Description `json:"description" yaml:"description"` Yaml string `json:"yaml" yaml:"yaml"` Spec KnoxSystemSpec `json:"spec,omitempty" yaml:"spec,omitempty"` + Kind string `json:"kind,omitempty" yaml:"kind,omitempty" bson:"kind,omitempty"` } // Ref for the policy rules