diff --git a/README.md b/README.md
index e4ae2289..2860d179 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ curl -s https://raw.githubusercontent.com/armosec/kubescape/master/install.sh |
## Run:
```
-kubescape scan framework nsa --submit
+kubescape scan --submit
```
diff --git a/cautils/datastructures.go b/cautils/datastructures.go
index 2f9c2b71..918edc4a 100644
--- a/cautils/datastructures.go
+++ b/cautils/datastructures.go
@@ -6,8 +6,8 @@ import (
"github.com/armosec/opa-utils/reporthandling"
)
-// K8SResources map[//]<[]resource objects>
-type K8SResources map[string][]workloadinterface.IMetadata
+// K8SResources map[//][]
+type K8SResources map[string][]string
type OPASessionObj struct {
K8SResources *K8SResources // input k8s objects
diff --git a/clihandler/cmd/control.go b/clihandler/cmd/control.go
index a0772767..bc0cb876 100644
--- a/clihandler/cmd/control.go
+++ b/clihandler/cmd/control.go
@@ -16,7 +16,7 @@ import (
// controlCmd represents the control command
var controlCmd = &cobra.Command{
Use: "control /.\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 folloiwng frameworks: %s", getter.NativeFrameworks),
+ 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),
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
controls := strings.Split(args[0], ",")
diff --git a/clihandler/cmd/framework.go b/clihandler/cmd/framework.go
index e381ecff..03d2e1d2 100644
--- a/clihandler/cmd/framework.go
+++ b/clihandler/cmd/framework.go
@@ -13,9 +13,34 @@ import (
"github.com/spf13/cobra"
)
+var (
+ frameworkExample = `
+ # Scan all frameworks and submit the results
+ kubescape scan --submit
+
+ # Scan the NSA framework
+ kubescape scan framework nsa
+
+ # Scan the NSA and MITRE framework
+ kubescape scan framework nsa,mitre
+
+ # Scan kubernetes YAML manifest files
+ kubescape scan framework nsa *.yaml
+
+ # Scan and save the results in the JSON format
+ kubescape scan --format json --output results.json
+
+ # Save scan results in JSON format
+ kubescape scan --format json --output results.json
+
+ # Display all resources
+ kubescape scan --verbose
+`
+)
var frameworkCmd = &cobra.Command{
- Use: fmt.Sprintf("framework [``/`-`] [flags]\nExamples:\n$ kubescape scan framework nsa [flags]\n$ kubescape scan framework mitre,nsa [flags]\n$ kubescape scan framework 'nsa, mitre' [flags]\nSupported frameworks: %s", getter.NativeFrameworks),
+ Use: "framework [``/`-`] [flags]",
Short: fmt.Sprintf("The framework you wish to use. Supported frameworks: %s", strings.Join(getter.NativeFrameworks, ", ")),
+ Example: frameworkExample,
Long: "Execute a scan on a running Kubernetes cluster or `yaml`/`json` files (use glob) or `-` for stdin",
ValidArgs: getter.NativeFrameworks,
Args: func(cmd *cobra.Command, args []string) error {
diff --git a/clihandler/cmd/rbac.go b/clihandler/cmd/rbac.go
index fdfc5aeb..56a988f7 100644
--- a/clihandler/cmd/rbac.go
+++ b/clihandler/cmd/rbac.go
@@ -72,6 +72,7 @@ func (rbacObjects *RBACObjects) rbacObjectsToResources(resources *rbacutils.Rbac
if err != nil {
return nil, err
}
+ crmap["apiVersion"] = "rbac.authorization.k8s.io/v1"
crIMeta := workloadinterface.NewWorkloadObj(crmap)
crIMeta.SetKind("ClusterRole")
allresources[crIMeta.GetID()] = crIMeta
@@ -81,6 +82,7 @@ func (rbacObjects *RBACObjects) rbacObjectsToResources(resources *rbacutils.Rbac
if err != nil {
return nil, err
}
+ crmap["apiVersion"] = "rbac.authorization.k8s.io/v1"
crIMeta := workloadinterface.NewWorkloadObj(crmap)
crIMeta.SetKind("Role")
allresources[crIMeta.GetID()] = crIMeta
@@ -90,6 +92,7 @@ func (rbacObjects *RBACObjects) rbacObjectsToResources(resources *rbacutils.Rbac
if err != nil {
return nil, err
}
+ crmap["apiVersion"] = "rbac.authorization.k8s.io/v1"
crIMeta := workloadinterface.NewWorkloadObj(crmap)
crIMeta.SetKind("ClusterRoleBinding")
allresources[crIMeta.GetID()] = crIMeta
@@ -99,6 +102,7 @@ func (rbacObjects *RBACObjects) rbacObjectsToResources(resources *rbacutils.Rbac
if err != nil {
return nil, err
}
+ crmap["apiVersion"] = "rbac.authorization.k8s.io/v1"
crIMeta := workloadinterface.NewWorkloadObj(crmap)
crIMeta.SetKind("RoleBinding")
allresources[crIMeta.GetID()] = crIMeta
diff --git a/clihandler/initcli.go b/clihandler/initcli.go
index 6b4ede54..c0bc3a15 100644
--- a/clihandler/initcli.go
+++ b/clihandler/initcli.go
@@ -53,6 +53,7 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces {
var tenantConfig cautils.ITenantConfig
hostSensorHandler = &hostsensorutils.HostSensorHandlerMock{}
+
// scanning environment
scanningTarget := scanInfo.GetScanningEnvironment()
switch scanningTarget {
@@ -67,11 +68,12 @@ func getInterfaces(scanInfo *cautils.ScanInfo) componentInterfaces {
resourceHandler = resourcehandler.NewFileResourceHandler(scanInfo.InputPatterns)
case cautils.ScanCluster:
k8s := k8sinterface.NewKubernetesApi() // initialize kubernetes api object
+
// pull k8s resources
- resourceHandler = resourcehandler.NewK8sResourceHandler(k8s, getFieldSelector(scanInfo))
+ hostSensorHandler = initHostSensor(scanInfo, k8s)
+ resourceHandler = resourcehandler.NewK8sResourceHandler(k8s, getFieldSelector(scanInfo), hostSensorHandler)
// use clusterConfig struct
tenantConfig = cautils.NewClusterConfig(k8s, getter.GetArmoAPIConnector(), scanInfo.Account)
- hostSensorHandler = initHostSensor(scanInfo, k8s)
}
// reporting behavior - setup reporter
reportHandler := getReporter(scanInfo, tenantConfig)
@@ -131,7 +133,7 @@ func ScanCliSetup(scanInfo *cautils.ScanInfo) error {
// cli handler setup
go func() {
// policy handler setup
- policyHandler := policyhandler.NewPolicyHandler(&processNotification, interfaces.resourceHandler, interfaces.hostSensorHandler)
+ policyHandler := policyhandler.NewPolicyHandler(&processNotification, interfaces.resourceHandler)
if err := Scan(policyHandler, scanInfo); err != nil {
fmt.Println(err)
diff --git a/go.mod b/go.mod
index 605315c0..0f278b9c 100644
--- a/go.mod
+++ b/go.mod
@@ -4,8 +4,8 @@ go 1.17
require (
github.com/armosec/armoapi-go v0.0.23
- github.com/armosec/k8s-interface v0.0.29
- github.com/armosec/opa-utils v0.0.57
+ github.com/armosec/k8s-interface v0.0.32
+ github.com/armosec/opa-utils v0.0.61
github.com/armosec/rbac-utils v0.0.8
github.com/armosec/utils-go v0.0.3
github.com/briandowns/spinner v1.16.0
@@ -23,7 +23,7 @@ require (
k8s.io/api v0.22.2
k8s.io/apimachinery v0.22.2
k8s.io/client-go v0.22.2
- sigs.k8s.io/yaml v1.2.0
+ sigs.k8s.io/yaml v1.2.0
)
require (
@@ -36,7 +36,6 @@ require (
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/armosec/utils-k8s-go v0.0.1 // indirect
- github.com/aws/aws-sdk-go v1.41.11 // indirect
github.com/coreos/go-oidc v2.2.1+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/docker v20.10.9+incompatible // indirect
@@ -49,15 +48,12 @@ require (
github.com/go-logr/logr v0.4.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.5 // indirect
github.com/google/gofuzz v1.1.0 // indirect
- github.com/googleapis/gax-go/v2 v2.0.5 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
- github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.11 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
@@ -73,7 +69,6 @@ require (
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b // indirect
- go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.19.1 // indirect
@@ -85,10 +80,7 @@ require (
golang.org/x/text v0.3.6 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
gonum.org/v1/gonum v0.9.1 // indirect
- google.golang.org/api v0.44.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
- google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
- google.golang.org/grpc v1.38.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
@@ -96,5 +88,5 @@ require (
k8s.io/klog/v2 v2.9.0 // indirect
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect
sigs.k8s.io/controller-runtime v0.10.2 // indirect
- sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect
+ sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect
)
diff --git a/go.sum b/go.sum
index 7657a126..ac5b4203 100644
--- a/go.sum
+++ b/go.sum
@@ -88,11 +88,11 @@ github.com/armosec/armoapi-go v0.0.23 h1:jqoLIWM5CR7DCD9fpFgN0ePqtHvOCoZv/XzCwsU
github.com/armosec/armoapi-go v0.0.23/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw=
github.com/armosec/k8s-interface v0.0.8/go.mod h1:xxS+V5QT3gVQTwZyAMMDrYLWGrfKOpiJ7Jfhfa0w9sM=
github.com/armosec/k8s-interface v0.0.19/go.mod h1:0ztwEWLez2lpMMKHbs0DoZV64S0YIA4s72vCs9iAAiE=
-github.com/armosec/k8s-interface v0.0.24/go.mod h1:0ztwEWLez2lpMMKHbs0DoZV64S0YIA4s72vCs9iAAiE=
-github.com/armosec/k8s-interface v0.0.29 h1:YUwTyIA5Wd9w7AwcWZMJ79w4JhMhTyIccPUASXucNRQ=
-github.com/armosec/k8s-interface v0.0.29/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU=
-github.com/armosec/opa-utils v0.0.57 h1:7lDEKxblqfsEXLn+6lkj17ctBSnhDuYanfdqG55kW2g=
-github.com/armosec/opa-utils v0.0.57/go.mod h1:UAT4Xokq91ysLa4Xg0WLqVsjJCnbFgsevkiIJFxTghU=
+github.com/armosec/k8s-interface v0.0.26/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU=
+github.com/armosec/k8s-interface v0.0.32 h1:dvSDRTXVZWrHyWOgu1QDrd4M2De4KYClrnB/k5Dq5fk=
+github.com/armosec/k8s-interface v0.0.32/go.mod h1:vHxGWqD/uh6+GQb9Sqv7OGMs+Rvc2dsFVc0XtgRh1ZU=
+github.com/armosec/opa-utils v0.0.61 h1:qIjsiv6BdSE7r+8k6FZtn0ZllYiai7Iyd8rl5YI4qPU=
+github.com/armosec/opa-utils v0.0.61/go.mod h1:P63qZDPG3vjPtSQqwx2N4Nfm8VaboDul7R7kmnUvvWc=
github.com/armosec/rbac-utils v0.0.1/go.mod h1:pQ8CBiij8kSKV7aeZm9FMvtZN28VgA7LZcYyTWimq40=
github.com/armosec/rbac-utils v0.0.8 h1:Hpr2p9F3Elp9NxbDAZiMlNUcQOdfyu9rWFE2fM2nNGw=
github.com/armosec/rbac-utils v0.0.8/go.mod h1:fmLZDgT5ILNo5gzR19boIIn7TOpfWh2pIgprxLrYN/g=
@@ -103,7 +103,6 @@ github.com/armosec/utils-k8s-go v0.0.1 h1:Ay3y7fW+4+FjVc0+obOWm8YsnEvM31vPAVoKTy
github.com/armosec/utils-k8s-go v0.0.1/go.mod h1:qrU4pmY2iZsOb39Eltpm0sTTNM3E4pmeyWx4dgDUC2U=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.41.1/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
-github.com/aws/aws-sdk-go v1.41.11 h1:QLouWsiYQ8i22kD8k58Dpdhio1A0MpT7bg9ZNXqEjuI=
github.com/aws/aws-sdk-go v1.41.11/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
@@ -336,11 +335,9 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
-github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
@@ -385,9 +382,7 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
-github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
-github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
@@ -1018,7 +1013,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
-google.golang.org/api v0.44.0 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA=
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1076,7 +1070,6 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
@@ -1101,7 +1094,6 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
diff --git a/install.sh b/install.sh
index 2d0173bd..ec1d55c0 100755
--- a/install.sh
+++ b/install.sh
@@ -53,6 +53,6 @@ echo -e "\033[0m"
$KUBESCAPE_EXEC version
echo
-echo -e "\033[35mUsage: $ $KUBESCAPE_EXEC scan framework nsa"
+echo -e "\033[35mUsage: $ $KUBESCAPE_EXEC scan --submit"
echo -e "\033[0m"
diff --git a/opaprocessor/processorhandler.go b/opaprocessor/processorhandler.go
index dfde0555..0c32f354 100644
--- a/opaprocessor/processorhandler.go
+++ b/opaprocessor/processorhandler.go
@@ -6,14 +6,13 @@ import (
"time"
"github.com/armosec/kubescape/cautils"
- "github.com/armosec/opa-utils/exceptions"
"github.com/armosec/opa-utils/reporthandling"
+ "github.com/golang/glog"
"github.com/armosec/k8s-interface/k8sinterface"
"github.com/armosec/k8s-interface/workloadinterface"
"github.com/armosec/opa-utils/resources"
- "github.com/golang/glog"
"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/rego"
uuid "github.com/satori/go.uuid"
@@ -58,7 +57,7 @@ func (opaHandler *OPAProcessorHandler) ProcessRulesListenner() {
// process
if err := opap.Process(); err != nil {
- fmt.Println(err)
+ // fmt.Println(err)
}
// edit results
@@ -81,7 +80,7 @@ func (opap *OPAProcessor) Process() error {
for i := range opap.Frameworks {
frameworkReport, err := opap.processFramework(&opap.Frameworks[i])
if err != nil {
- errs = fmt.Errorf("%v\n%s", errs, err.Error())
+ appendError(&errs, err)
}
frameworkReports = append(frameworkReports, *frameworkReport)
}
@@ -95,6 +94,16 @@ func (opap *OPAProcessor) Process() error {
return errs
}
+func appendError(errs *error, err error) {
+ if err == nil {
+ return
+ }
+ if errs == nil {
+ errs = &err
+ } else {
+ *errs = fmt.Errorf("%v\n%s", *errs, err.Error())
+ }
+}
func (opap *OPAProcessor) processFramework(framework *reporthandling.Framework) (*reporthandling.FrameworkReport, error) {
var errs error
@@ -105,7 +114,8 @@ func (opap *OPAProcessor) processFramework(framework *reporthandling.Framework)
for i := range framework.Controls {
controlReport, err := opap.processControl(&framework.Controls[i])
if err != nil {
- errs = fmt.Errorf("%v\n%s", errs, err.Error())
+ appendError(&errs, err)
+ // errs = fmt.Errorf("%v\n%s", errs, err.Error())
}
if controlReport != nil {
controlReports = append(controlReports, *controlReport)
@@ -133,7 +143,7 @@ func (opap *OPAProcessor) processControl(control *reporthandling.Control) (*repo
for i := range control.Rules {
ruleReport, err := opap.processRule(&control.Rules[i])
if err != nil {
- errs = fmt.Errorf("%v\n%s", errs, err.Error())
+ appendError(&errs, err)
}
if ruleReport != nil {
ruleReports = append(ruleReports, *ruleReport)
@@ -151,12 +161,18 @@ func (opap *OPAProcessor) processRule(rule *reporthandling.PolicyRule) (*reporth
return nil, nil
}
- inputResources, err := reporthandling.RegoResourcesAggregator(rule, getKubernetesObjects(opap.K8SResources, rule.Match))
+ inputResources, err := reporthandling.RegoResourcesAggregator(rule, getKubernetesObjects(opap.K8SResources, opap.AllResources, rule.Match))
if err != nil {
return nil, fmt.Errorf("error getting aggregated k8sObjects: %s", err.Error())
}
- ruleReport, err := opap.runOPAOnSingleRule(rule, workloadinterface.ListMetaToMap(inputResources))
+ inputRawResources := workloadinterface.ListMetaToMap(inputResources)
+
+ if inputRawResources, err = opap.executePreRun(rule, inputRawResources); err != nil {
+ return nil, err
+ }
+
+ ruleReport, err := opap.runOPAOnSingleRule(rule, inputRawResources, ruleData)
if err != nil {
// ruleReport.RuleStatus.Status = reporthandling.StatusFailed
ruleReport.RuleStatus.Status = "failure"
@@ -165,25 +181,32 @@ func (opap *OPAProcessor) processRule(rule *reporthandling.PolicyRule) (*reporth
} else {
ruleReport.RuleStatus.Status = reporthandling.StatusPassed
}
+
+ inputResources = workloadinterface.ListMapToMeta(inputRawResources)
ruleReport.ListInputKinds = workloadinterface.ListMetaIDs(inputResources)
+ // remove all data from responses, leave only the metadata
+ keepFields := []string{"kind", "apiVersion", "metadata"}
+ keepMetadataFields := []string{"name", "namespace", "labels"}
+ ruleReport.RemoveData(keepFields, keepMetadataFields)
+
for i := range inputResources {
- removeData(inputResources[i])
opap.AllResources[inputResources[i].GetID()] = inputResources[i]
}
return &ruleReport, err
}
-func (opap *OPAProcessor) runOPAOnSingleRule(rule *reporthandling.PolicyRule, k8sObjects []map[string]interface{}) (reporthandling.RuleReport, error) {
+func (opap *OPAProcessor) runOPAOnSingleRule(rule *reporthandling.PolicyRule, k8sObjects []map[string]interface{}, getRuleData func(*reporthandling.PolicyRule) string) (reporthandling.RuleReport, error) {
switch rule.RuleLanguage {
case reporthandling.RegoLanguage, reporthandling.RegoLanguage2:
- return opap.runRegoOnK8s(rule, k8sObjects)
+ return opap.runRegoOnK8s(rule, k8sObjects, getRuleData)
default:
return reporthandling.RuleReport{}, fmt.Errorf("rule: '%s', language '%v' not supported", rule.Name, rule.RuleLanguage)
}
}
-func (opap *OPAProcessor) runRegoOnK8s(rule *reporthandling.PolicyRule, k8sObjects []map[string]interface{}) (reporthandling.RuleReport, error) {
+
+func (opap *OPAProcessor) runRegoOnK8s(rule *reporthandling.PolicyRule, k8sObjects []map[string]interface{}, getRuleData func(*reporthandling.PolicyRule) string) (reporthandling.RuleReport, error) {
var errs error
ruleReport := reporthandling.RuleReport{
Name: rule.Name,
@@ -194,7 +217,7 @@ func (opap *OPAProcessor) runRegoOnK8s(rule *reporthandling.PolicyRule, k8sObjec
if err != nil {
return ruleReport, fmt.Errorf("rule: '%s', %s", rule.Name, err.Error())
}
- modules[rule.Name] = rule.Rule
+ modules[rule.Name] = getRuleData(rule)
compiled, err := ast.CompileModules(modules)
if err != nil {
return ruleReport, fmt.Errorf("in 'runRegoOnSingleRule', failed to compile rule, name: %s, reason: %s", rule.Name, err.Error())
@@ -228,11 +251,9 @@ func (opap *OPAProcessor) regoEval(inputObj []map[string]interface{}, compiledRe
// Run evaluation
resultSet, err := rego.Eval(context.Background())
if err != nil {
- return nil, fmt.Errorf("in 'regoEval', failed to evaluate rule, reason: %s", err.Error())
+ return nil, err
}
results, err := reporthandling.ParseRegoResult(&resultSet)
-
- // results, err := ParseRegoResult(&resultSet)
if err != nil {
return results, err
}
@@ -240,27 +261,14 @@ func (opap *OPAProcessor) regoEval(inputObj []map[string]interface{}, compiledRe
return results, nil
}
-func (opap *OPAProcessor) updateResults() {
- for f := range opap.PostureReport.FrameworkReports {
- // set exceptions
- exceptions.SetFrameworkExceptions(&opap.PostureReport.FrameworkReports[f], opap.Exceptions, cautils.ClusterName)
-
- // set counters
- reporthandling.SetUniqueResourcesCounter(&opap.PostureReport.FrameworkReports[f])
-
- // set default score
- reporthandling.SetDefaultScore(&opap.PostureReport.FrameworkReports[f])
-
- // edit results - remove data
-
- // TODO - move function to pkg - use RemoveData
- for c := range opap.PostureReport.FrameworkReports[f].ControlReports {
- for r, ruleReport := range opap.PostureReport.FrameworkReports[f].ControlReports[c].RuleReports {
- // editing the responses -> removing duplications, clearing secret data, etc.
- opap.PostureReport.FrameworkReports[f].ControlReports[c].RuleReports[r].RuleResponses = editRuleResponses(ruleReport.RuleResponses)
- }
- }
+func (opap *OPAProcessor) executePreRun(rule *reporthandling.PolicyRule, k8sObjects []map[string]interface{}) ([]map[string]interface{}, error) {
+ if preRuleData(rule) == "" {
+ return k8sObjects, nil
}
-
+ ruleReport, err := opap.runOPAOnSingleRule(rule, k8sObjects, preRuleData)
+ if err != nil {
+ return nil, err
+ }
+ return ruleReport.GetFailedResources(), nil
}
diff --git a/opaprocessor/processorhandler_test.go b/opaprocessor/processorhandler_test.go
index afa73d14..320f2baf 100644
--- a/opaprocessor/processorhandler_test.go
+++ b/opaprocessor/processorhandler_test.go
@@ -19,12 +19,18 @@ func TestProcess(t *testing.T) {
// set k8s
k8sResources := make(cautils.K8SResources)
- k8sResources["/v1/pods"] = workloadinterface.ListMapToMeta(k8sinterface.ConvertUnstructuredSliceToMap(k8sinterface.V1KubeSystemNamespaceMock().Items))
+ allResources := make(map[string]workloadinterface.IMetadata)
+ imetaObj := workloadinterface.ListMapToMeta(k8sinterface.ConvertUnstructuredSliceToMap(k8sinterface.V1KubeSystemNamespaceMock().Items))
+ for i := range imetaObj {
+ allResources[imetaObj[i].GetID()] = imetaObj[i]
+ }
+ k8sResources["/v1/pods"] = workloadinterface.ListMetaIDs(imetaObj)
// set opaSessionObj
opaSessionObj := cautils.NewOPASessionObjMock()
opaSessionObj.Frameworks = []reporthandling.Framework{*reporthandling.MockFrameworkA()}
opaSessionObj.K8SResources = &k8sResources
+ opaSessionObj.AllResources = allResources
opap := NewOPAProcessor(opaSessionObj, resources.NewRegoDependenciesDataMock())
opap.Process()
diff --git a/opaprocessor/processorhandlerutils.go b/opaprocessor/processorhandlerutils.go
index a6f5ad2a..ffa8f727 100644
--- a/opaprocessor/processorhandlerutils.go
+++ b/opaprocessor/processorhandlerutils.go
@@ -7,13 +7,32 @@ import (
"github.com/armosec/k8s-interface/k8sinterface"
"github.com/armosec/k8s-interface/workloadinterface"
+ "github.com/armosec/opa-utils/exceptions"
"github.com/armosec/opa-utils/reporthandling"
resources "github.com/armosec/opa-utils/resources"
"github.com/golang/glog"
)
-func getKubernetesObjects(k8sResources *cautils.K8SResources, match []reporthandling.RuleMatchObjects) []workloadinterface.IMetadata {
+func (opap *OPAProcessor) updateResults() {
+ // remove data from all objects
+ for i := range opap.AllResources {
+ removeData(opap.AllResources[i])
+ }
+
+ for f := range opap.PostureReport.FrameworkReports {
+ // set exceptions
+ exceptions.SetFrameworkExceptions(&opap.PostureReport.FrameworkReports[f], opap.Exceptions, cautils.ClusterName)
+
+ // set counters
+ reporthandling.SetUniqueResourcesCounter(&opap.PostureReport.FrameworkReports[f])
+
+ // set default score
+ reporthandling.SetDefaultScore(&opap.PostureReport.FrameworkReports[f])
+ }
+}
+
+func getKubernetesObjects(k8sResources *cautils.K8SResources, allResources map[string]workloadinterface.IMetadata, match []reporthandling.RuleMatchObjects) []workloadinterface.IMetadata {
k8sObjects := []workloadinterface.IMetadata{}
for m := range match {
for _, groups := range match[m].APIGroups {
@@ -26,7 +45,9 @@ func getKubernetesObjects(k8sResources *cautils.K8SResources, match []reporthand
continue
// glog.Errorf("Resource '%s' is nil, probably failed to pull the resource", groupResource)
}
- k8sObjects = append(k8sObjects, k8sObj...)
+ for i := range k8sObj {
+ k8sObjects = append(k8sObjects, allResources[k8sObj[i]])
+ }
}
}
}
@@ -45,28 +66,6 @@ func getRuleDependencies() (map[string]string, error) {
return modules, nil
}
-//editRuleResponses editing the responses -> removing duplications, clearing secret data, etc.
-func editRuleResponses(ruleResponses []reporthandling.RuleResponse) []reporthandling.RuleResponse {
- lenRuleResponses := len(ruleResponses)
- for i := 0; i < lenRuleResponses; i++ {
- for j := range ruleResponses[i].AlertObject.K8SApiObjects {
- w := workloadinterface.NewWorkloadObj(ruleResponses[i].AlertObject.K8SApiObjects[j])
- if w == nil {
- continue
- }
-
- cleanRuleResponses(w)
- ruleResponses[i].AlertObject.K8SApiObjects[j] = w.GetWorkload()
- }
- }
- return ruleResponses
-}
-func cleanRuleResponses(workload k8sinterface.IWorkload) {
- if workload.GetKind() == "Secret" {
- workload.RemoveSecretData()
- }
-}
-
func ruleWithArmoOpaDependency(annotations map[string]interface{}) bool {
if annotations == nil {
return false
@@ -107,36 +106,25 @@ func removeData(obj workloadinterface.IMetadata) {
workload := workloadinterface.NewWorkloadObj(obj.GetObject())
switch workload.GetKind() {
case "Secret":
- removeSecretData(obj)
+ removeSecretData(workload)
case "ConfigMap":
- removeConfigMapData(obj)
+ removeConfigMapData(workload)
default:
- removePodData(obj)
+ removePodData(workload)
}
}
-func removeConfigMapData(obj workloadinterface.IMetadata) {
- if !workloadinterface.IsTypeWorkload(obj.GetObject()) {
- return // remove data only from kubernetes objects
- }
- workload := workloadinterface.NewWorkloadObj(obj.GetObject())
+func removeConfigMapData(workload workloadinterface.IWorkload) {
workload.RemoveAnnotation("kubectl.kubernetes.io/last-applied-configuration")
workloadinterface.RemoveFromMap(workload.GetObject(), "data")
workloadinterface.RemoveFromMap(workload.GetObject(), "metadata", "managedFields")
}
-func removeSecretData(obj workloadinterface.IMetadata) {
- if !workloadinterface.IsTypeWorkload(obj.GetObject()) {
- return // remove data only from kubernetes objects
- }
- workloadinterface.NewWorkloadObj(obj.GetObject()).RemoveSecretData()
- workloadinterface.RemoveFromMap(obj.GetObject(), "metadata", "managedFields")
+func removeSecretData(workload workloadinterface.IWorkload) {
+ workloadinterface.NewWorkloadObj(workload.GetObject()).RemoveSecretData()
+ workloadinterface.RemoveFromMap(workload.GetObject(), "metadata", "managedFields")
}
-func removePodData(obj workloadinterface.IMetadata) {
- if !workloadinterface.IsTypeWorkload(obj.GetObject()) {
- return // remove data only from kubernetes objects
- }
- workload := workloadinterface.NewWorkloadObj(obj.GetObject())
+func removePodData(workload workloadinterface.IWorkload) {
workload.RemoveAnnotation("kubectl.kubernetes.io/last-applied-configuration")
workloadinterface.RemoveFromMap(workload.GetObject(), "metadata", "managedFields")
@@ -151,3 +139,14 @@ func removePodData(obj workloadinterface.IMetadata) {
}
workloadinterface.SetInMap(workload.GetObject(), workloadinterface.PodSpec(workload.GetKind()), "containers", containers)
}
+
+func ruleData(rule *reporthandling.PolicyRule) string {
+ return rule.Rule
+}
+
+func preRuleData(rule *reporthandling.PolicyRule) string {
+ if len(rule.PreRun) > 0 {
+ return rule.PreRun[0]
+ }
+ return ""
+}
diff --git a/policyhandler/handlenotification.go b/policyhandler/handlenotification.go
index 6346af3d..2c27bdda 100644
--- a/policyhandler/handlenotification.go
+++ b/policyhandler/handlenotification.go
@@ -3,29 +3,24 @@ package policyhandler
import (
"fmt"
- "github.com/armosec/k8s-interface/k8sinterface"
- "github.com/armosec/k8s-interface/workloadinterface"
"github.com/armosec/kubescape/cautils"
- "github.com/armosec/kubescape/hostsensorutils"
"github.com/armosec/kubescape/resourcehandler"
"github.com/armosec/opa-utils/reporthandling"
)
// PolicyHandler -
type PolicyHandler struct {
- resourceHandler resourcehandler.IResourceHandler
- hostSensorHandler hostsensorutils.IHostSensor
+ resourceHandler resourcehandler.IResourceHandler
// we are listening on this chan in opaprocessor/processorhandler.go/ProcessRulesListenner func
processPolicy *chan *cautils.OPASessionObj
getters *cautils.Getters
}
// CreatePolicyHandler Create ws-handler obj
-func NewPolicyHandler(processPolicy *chan *cautils.OPASessionObj, resourceHandler resourcehandler.IResourceHandler, hostSensorHandler hostsensorutils.IHostSensor) *PolicyHandler {
+func NewPolicyHandler(processPolicy *chan *cautils.OPASessionObj, resourceHandler resourcehandler.IResourceHandler) *PolicyHandler {
return &PolicyHandler{
- resourceHandler: resourceHandler,
- processPolicy: processPolicy,
- hostSensorHandler: hostSensorHandler,
+ resourceHandler: resourceHandler,
+ processPolicy: processPolicy,
}
}
@@ -40,47 +35,30 @@ func (policyHandler *PolicyHandler) HandleNotificationRequest(notification *repo
return err
}
- k8sResources, err := policyHandler.getResources(notification, opaSessionObj, scanInfo)
+ err := policyHandler.getResources(notification, opaSessionObj, scanInfo)
if err != nil {
return err
}
- if k8sResources == nil || len(*k8sResources) == 0 {
+ if opaSessionObj.K8SResources == nil || len(*opaSessionObj.K8SResources) == 0 {
return fmt.Errorf("empty list of resources")
}
- opaSessionObj.K8SResources = k8sResources
- for i := range *k8sResources {
- for resourceIdx := range (*k8sResources)[i] {
- // TODO: add remove data function
- opaSessionObj.AllResources[(*k8sResources)[i][resourceIdx].GetID()] = (*k8sResources)[i][resourceIdx]
- }
- }
+
// update channel
*policyHandler.processPolicy <- opaSessionObj
return nil
}
-func (policyHandler *PolicyHandler) getResources(notification *reporthandling.PolicyNotification, opaSessionObj *cautils.OPASessionObj, scanInfo *cautils.ScanInfo) (*cautils.K8SResources, error) {
+func (policyHandler *PolicyHandler) getResources(notification *reporthandling.PolicyNotification, opaSessionObj *cautils.OPASessionObj, scanInfo *cautils.ScanInfo) error {
opaSessionObj.PostureReport.ClusterAPIServerInfo = policyHandler.resourceHandler.GetClusterAPIServerInfo()
- resourcesMap, err := policyHandler.resourceHandler.GetResources(opaSessionObj.Frameworks, ¬ification.Designators)
+ resourcesMap, allResources, err := policyHandler.resourceHandler.GetResources(opaSessionObj.Frameworks, ¬ification.Designators)
if err != nil {
- return resourcesMap, err
- }
- hostResources, err := policyHandler.hostSensorHandler.CollectResources()
- if err != nil {
- return resourcesMap, err
- }
- for rscIdx := range hostResources {
- groupResources := k8sinterface.ResourceGroupToString(hostResources[rscIdx].Group, hostResources[rscIdx].GetApiVersion(), hostResources[rscIdx].GetKind())
- for _, groupResource := range groupResources {
- grpReasorceList, ok := (*resourcesMap)[groupResource]
- if !ok {
- grpReasorceList = make([]workloadinterface.IMetadata, 0)
- }
- grpReasorceList = append(grpReasorceList, &hostResources[rscIdx])
- (*resourcesMap)[groupResource] = grpReasorceList
- }
+ return err
}
+
+ opaSessionObj.K8SResources = resourcesMap
+ opaSessionObj.AllResources = allResources
+
cautils.SuccessTextDisplay("Let’s start!!!")
- return resourcesMap, nil
+ return nil
}
diff --git a/resourcehandler/filesloader.go b/resourcehandler/filesloader.go
index 2a268ea5..2b9ebf3a 100644
--- a/resourcehandler/filesloader.go
+++ b/resourcehandler/filesloader.go
@@ -43,13 +43,19 @@ func NewFileResourceHandler(inputPatterns []string) *FileResourceHandler {
}
}
-func (fileHandler *FileResourceHandler) GetResources(frameworks []reporthandling.Framework, designator *armotypes.PortalDesignator) (*cautils.K8SResources, error) {
+func (fileHandler *FileResourceHandler) GetResources(frameworks []reporthandling.Framework, designator *armotypes.PortalDesignator) (*cautils.K8SResources, map[string]workloadinterface.IMetadata, error) {
+
+ // build resources map
+ // map resources based on framework required resources: map["/group/version/kind"][]
+ k8sResources := setResourceMap(frameworks)
+ allResources := map[string]workloadinterface.IMetadata{}
+
workloads := []workloadinterface.IMetadata{}
// load resource from local file system
w, err := loadResourcesFromFiles(fileHandler.inputPatterns)
if err != nil {
- return nil, err
+ return nil, allResources, err
}
if w != nil {
workloads = append(workloads, w...)
@@ -58,31 +64,32 @@ func (fileHandler *FileResourceHandler) GetResources(frameworks []reporthandling
// load resources from url
w, err = loadResourcesFromUrl(fileHandler.inputPatterns)
if err != nil {
- return nil, err
+ return nil, allResources, err
}
if w != nil {
workloads = append(workloads, w...)
}
if len(workloads) == 0 {
- return nil, fmt.Errorf("empty list of workloads - no workloads found")
+ return nil, allResources, fmt.Errorf("empty list of workloads - no workloads found")
}
// map all resources: map["/group/version/kind"][]
- allResources := mapResources(workloads)
-
- // build resources map
- // map resources based on framework required resources: map["/group/version/kind"][]
- k8sResources := setResourceMap(frameworks) // TODO - support designators
+ mappedResources := mapResources(workloads)
// save only relevant resources
- for i := range allResources {
+ for i := range mappedResources {
if _, ok := (*k8sResources)[i]; ok {
- (*k8sResources)[i] = allResources[i]
+ ids := []string{}
+ for j := range mappedResources[i] {
+ ids = append(ids, mappedResources[i][j].GetID())
+ allResources[mappedResources[i][j].GetID()] = mappedResources[i][j]
+ }
+ (*k8sResources)[i] = ids
}
}
- return k8sResources, nil
+ return k8sResources, allResources, nil
}
@@ -108,6 +115,7 @@ func loadResourcesFromFiles(inputPatterns []string) ([]workloadinterface.IMetada
// build resources map
func mapResources(workloads []workloadinterface.IMetadata) map[string][]workloadinterface.IMetadata {
+
allResources := map[string][]workloadinterface.IMetadata{}
for i := range workloads {
groupVersionResource, err := k8sinterface.GetGroupVersionResource(workloads[i].GetKind())
@@ -125,10 +133,9 @@ func mapResources(workloads []workloadinterface.IMetadata) map[string][]workload
}
resourceTriplets := k8sinterface.JoinResourceTriplets(groupVersionResource.Group, groupVersionResource.Version, groupVersionResource.Resource)
if r, ok := allResources[resourceTriplets]; ok {
- r = append(r, workloads...)
- allResources[resourceTriplets] = r
+ allResources[resourceTriplets] = append(r, workloads[i])
} else {
- allResources[resourceTriplets] = workloads
+ allResources[resourceTriplets] = []workloadinterface.IMetadata{workloads[i]}
}
}
return allResources
diff --git a/resourcehandler/filesloader_test.go b/resourcehandler/filesloader_test.go
index 04d64082..6ff81e08 100644
--- a/resourcehandler/filesloader_test.go
+++ b/resourcehandler/filesloader_test.go
@@ -41,7 +41,7 @@ func TestLoadFile(t *testing.T) {
t.Errorf("%v", err)
}
}
-func TestLoadResources(t *testing.T) {
+func TestMapResources(t *testing.T) {
// policyHandler := &PolicyHandler{}
// k8sResources, err := policyHandler.loadResources(opaSessionObj.Frameworks, scanInfo)
// files, _ := listFiles([]string{onlineBoutiquePath()})
diff --git a/resourcehandler/k8sresources.go b/resourcehandler/k8sresources.go
index cd0a8c9f..5eb71242 100644
--- a/resourcehandler/k8sresources.go
+++ b/resourcehandler/k8sresources.go
@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/armosec/kubescape/cautils"
+ "github.com/armosec/kubescape/hostsensorutils"
"github.com/armosec/opa-utils/reporthandling"
"github.com/armosec/k8s-interface/k8sinterface"
@@ -21,34 +22,42 @@ import (
)
type K8sResourceHandler struct {
- k8s *k8sinterface.KubernetesApi
- fieldSelector IFieldSelector
+ k8s *k8sinterface.KubernetesApi
+ hostSensorHandler hostsensorutils.IHostSensor
+ fieldSelector IFieldSelector
}
-func NewK8sResourceHandler(k8s *k8sinterface.KubernetesApi, fieldSelector IFieldSelector) *K8sResourceHandler {
+func NewK8sResourceHandler(k8s *k8sinterface.KubernetesApi, fieldSelector IFieldSelector, hostSensorHandler hostsensorutils.IHostSensor) *K8sResourceHandler {
return &K8sResourceHandler{
- k8s: k8s,
- fieldSelector: fieldSelector,
+ k8s: k8s,
+ fieldSelector: fieldSelector,
+ hostSensorHandler: hostSensorHandler,
}
}
-func (k8sHandler *K8sResourceHandler) GetResources(frameworks []reporthandling.Framework, designator *armotypes.PortalDesignator) (*cautils.K8SResources, error) {
+func (k8sHandler *K8sResourceHandler) GetResources(frameworks []reporthandling.Framework, designator *armotypes.PortalDesignator) (*cautils.K8SResources, map[string]workloadinterface.IMetadata, error) {
+ allResources := map[string]workloadinterface.IMetadata{}
+
// get k8s resources
cautils.ProgressTextDisplay("Accessing Kubernetes objects")
// build resources map
+ // map resources based on framework required resources: map["/group/version/kind"][]
k8sResourcesMap := setResourceMap(frameworks)
// get namespace and labels from designator (ignore cluster labels)
_, namespace, labels := armotypes.DigestPortalDesignator(designator)
// pull k8s recourses
- if err := k8sHandler.pullResources(k8sResourcesMap, namespace, labels); err != nil {
- return k8sResourcesMap, err
+ if err := k8sHandler.pullResources(k8sResourcesMap, allResources, namespace, labels); err != nil {
+ return k8sResourcesMap, allResources, err
+ }
+ if err := k8sHandler.collectHostResources(allResources, k8sResourcesMap); err != nil {
+ return k8sResourcesMap, allResources, err
}
cautils.SuccessTextDisplay("Accessed successfully to Kubernetes objects")
- return k8sResourcesMap, nil
+ return k8sResourcesMap, allResources, nil
}
func (k8sHandler *K8sResourceHandler) GetClusterAPIServerInfo() *version.Info {
@@ -59,7 +68,7 @@ func (k8sHandler *K8sResourceHandler) GetClusterAPIServerInfo() *version.Info {
}
return clusterAPIServerInfo
}
-func (k8sHandler *K8sResourceHandler) pullResources(k8sResources *cautils.K8SResources, namespace string, labels map[string]string) error {
+func (k8sHandler *K8sResourceHandler) pullResources(k8sResources *cautils.K8SResources, allResources map[string]workloadinterface.IMetadata, namespace string, labels map[string]string) error {
var errs error
for groupResource := range *k8sResources {
@@ -73,10 +82,14 @@ func (k8sHandler *K8sResourceHandler) pullResources(k8sResources *cautils.K8SRes
} else {
errs = fmt.Errorf("%s\n%s", errs, err.Error())
}
- } else {
- // store result as []map[string]interface{}
- (*k8sResources)[groupResource] = ConvertMapListToMeta(k8sinterface.ConvertUnstructuredSliceToMap(k8sinterface.FilterOutOwneredResources(result)))
+ continue
}
+ // store result as []map[string]interface{}
+ metaObjs := ConvertMapListToMeta(k8sinterface.ConvertUnstructuredSliceToMap(k8sinterface.FilterOutOwneredResources(result)))
+ for i := range metaObjs {
+ allResources[metaObjs[i].GetID()] = metaObjs[i]
+ }
+ (*k8sResources)[groupResource] = workloadinterface.ListMetaIDs(metaObjs)
}
return errs
}
@@ -125,3 +138,23 @@ func ConvertMapListToMeta(resourceMap []map[string]interface{}) []workloadinterf
}
return workloads
}
+
+func (k8sHandler *K8sResourceHandler) collectHostResources(allResources map[string]workloadinterface.IMetadata, resourcesMap *cautils.K8SResources) error {
+ hostResources, err := k8sHandler.hostSensorHandler.CollectResources()
+ if err != nil {
+ return err
+ }
+ for rscIdx := range hostResources {
+ groupResources := k8sinterface.ResourceGroupToString(hostResources[rscIdx].Group, hostResources[rscIdx].GetApiVersion(), hostResources[rscIdx].GetKind())
+ for _, groupResource := range groupResources {
+ allResources[hostResources[rscIdx].GetID()] = &hostResources[rscIdx]
+
+ grpResourceList, ok := (*resourcesMap)[groupResource]
+ if !ok {
+ grpResourceList = make([]string, 0)
+ }
+ (*resourcesMap)[groupResource] = append(grpResourceList, hostResources[rscIdx].GetID())
+ }
+ }
+ return nil
+}
diff --git a/resourcehandler/resourceshandler.go b/resourcehandler/resourceshandler.go
index c2ddf15f..723066eb 100644
--- a/resourcehandler/resourceshandler.go
+++ b/resourcehandler/resourceshandler.go
@@ -2,12 +2,13 @@ package resourcehandler
import (
"github.com/armosec/armoapi-go/armotypes"
+ "github.com/armosec/k8s-interface/workloadinterface"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/opa-utils/reporthandling"
"k8s.io/apimachinery/pkg/version"
)
type IResourceHandler interface {
- GetResources(frameworks []reporthandling.Framework, designator *armotypes.PortalDesignator) (*cautils.K8SResources, error)
+ GetResources([]reporthandling.Framework, *armotypes.PortalDesignator) (*cautils.K8SResources, map[string]workloadinterface.IMetadata, error)
GetClusterAPIServerInfo() *version.Info
}
diff --git a/resultshandling/reporter/reporteventreceiver.go b/resultshandling/reporter/reporteventreceiver.go
index 8373f8fe..05ef1fe9 100644
--- a/resultshandling/reporter/reporteventreceiver.go
+++ b/resultshandling/reporter/reporteventreceiver.go
@@ -42,10 +42,6 @@ func NewReportEventReceiver(tenantConfig *cautils.ConfigObj) *ReportEventReceive
}
func (report *ReportEventReceiver) ActionSendReport(opaSessionObj *cautils.OPASessionObj) error {
- // Remove data before reporting
- keepFields := []string{"kind", "apiVersion", "metadata"}
- keepMetadataFields := []string{"name", "namespace", "labels"}
- opaSessionObj.PostureReport.RemoveData(keepFields, keepMetadataFields)
if err := report.prepareReport(opaSessionObj.PostureReport, opaSessionObj.AllResources); err != nil {
return err