mirror of
https://github.com/kubescape/kubescape.git
synced 2026-02-14 18:09:55 +00:00
support exceptions
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
package armotypes
|
||||
|
||||
type EnforcmentsRule struct {
|
||||
type EnforcementsRule struct {
|
||||
MonitoredObject []string `json:"monitoredObject"`
|
||||
MonitoredObjectExistence []string `json:"objectExistence"`
|
||||
MonitoredObjectEvent []string `json:"event"`
|
||||
@@ -12,5 +12,5 @@ type ExecutionPolicy struct {
|
||||
Designators []PortalDesignator `json:"designators"`
|
||||
PolicyType string `json:"policyType"`
|
||||
CreationTime string `json:"creation_time"`
|
||||
ExecutionEnforcmentsRules []EnforcmentsRule `json:"enforcementRules"`
|
||||
ExecutionEnforcementsRule []EnforcementsRule `json:"enforcementRules"`
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"github.com/armosec/kubescape/cautils/armotypes"
|
||||
"github.com/armosec/kubescape/cautils/opapolicy"
|
||||
)
|
||||
|
||||
@@ -10,6 +11,7 @@ type K8SResources map[string]interface{}
|
||||
type OPASessionObj struct {
|
||||
Frameworks []opapolicy.Framework
|
||||
K8SResources *K8SResources
|
||||
Exceptions []armotypes.PostureExceptionPolicy
|
||||
PostureReport *opapolicy.PostureReport
|
||||
}
|
||||
|
||||
|
||||
55
cautils/getter/armoapi.go
Normal file
55
cautils/getter/armoapi.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package getter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/armotypes"
|
||||
"github.com/armosec/kubescape/cautils/opapolicy"
|
||||
)
|
||||
|
||||
// =======================================================================================================================
|
||||
// =============================================== ArmoAPI ===============================================================
|
||||
// =======================================================================================================================
|
||||
|
||||
// Armo API for downloading policies
|
||||
type ArmoAPI struct {
|
||||
httpClient *http.Client
|
||||
hostURL string
|
||||
}
|
||||
|
||||
func NewArmoAPI() *ArmoAPI {
|
||||
return &ArmoAPI{
|
||||
httpClient: &http.Client{},
|
||||
hostURL: "https://dashbe.eustage2.cyberarmorsoft.com",
|
||||
}
|
||||
}
|
||||
func (armoAPI *ArmoAPI) GetFramework(name string) (*opapolicy.Framework, error) {
|
||||
armoAPI.setURL(name)
|
||||
respStr, err := HttpGetter(armoAPI.httpClient, armoAPI.hostURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
framework := &opapolicy.Framework{}
|
||||
if err = JSONDecoder(respStr).Decode(framework); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
SaveFrameworkInFile(framework, GetDefaultPath(name))
|
||||
|
||||
return framework, err
|
||||
}
|
||||
|
||||
func (armoAPI *ArmoAPI) setURL(frameworkName string) {
|
||||
requestURI := "v1/armoFrameworks"
|
||||
requestURI += fmt.Sprintf("?customerGUID=%s", "11111111-1111-1111-1111-111111111111")
|
||||
requestURI += fmt.Sprintf("&frameworkName=%s", strings.ToUpper(frameworkName))
|
||||
requestURI += "&getRules=true"
|
||||
|
||||
armoAPI.hostURL = urlEncoder(fmt.Sprintf("%s/%s", armoAPI.hostURL, requestURI))
|
||||
}
|
||||
|
||||
func (armoAPI *ArmoAPI) GetExceptions(scope, customerName, namespace string) ([]armotypes.PostureExceptionPolicy, error) {
|
||||
return []armotypes.PostureExceptionPolicy{}, nil
|
||||
}
|
||||
87
cautils/getter/downloadreleasedpolicy.go
Normal file
87
cautils/getter/downloadreleasedpolicy.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package getter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/armotypes"
|
||||
"github.com/armosec/kubescape/cautils/opapolicy"
|
||||
)
|
||||
|
||||
// =======================================================================================================================
|
||||
// ======================================== DownloadReleasedPolicy =======================================================
|
||||
// =======================================================================================================================
|
||||
|
||||
// Download released version
|
||||
type DownloadReleasedPolicy struct {
|
||||
hostURL string
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func NewDownloadReleasedPolicy() *DownloadReleasedPolicy {
|
||||
return &DownloadReleasedPolicy{
|
||||
hostURL: "",
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
}
|
||||
|
||||
func (drp *DownloadReleasedPolicy) GetExceptions(policyType, customerGUID, clusterName string) ([]armotypes.PostureExceptionPolicy, error) {
|
||||
return []armotypes.PostureExceptionPolicy{}, nil
|
||||
}
|
||||
|
||||
func (drp *DownloadReleasedPolicy) GetFramework(name string) (*opapolicy.Framework, error) {
|
||||
drp.setURL(name)
|
||||
respStr, err := HttpGetter(drp.httpClient, drp.hostURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
framework := &opapolicy.Framework{}
|
||||
if err = JSONDecoder(respStr).Decode(framework); err != nil {
|
||||
return framework, err
|
||||
}
|
||||
|
||||
SaveFrameworkInFile(framework, GetDefaultPath(name))
|
||||
return framework, err
|
||||
}
|
||||
|
||||
func (drp *DownloadReleasedPolicy) setURL(frameworkName string) error {
|
||||
|
||||
latestReleases := "https://api.github.com/repos/armosec/regolibrary/releases/latest"
|
||||
resp, err := http.Get(latestReleases)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get latest releases from '%s', reason: %s", latestReleases, err.Error())
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode < 200 || 301 < resp.StatusCode {
|
||||
return fmt.Errorf("failed to download file, status code: %s", resp.Status)
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read response body from '%s', reason: %s", latestReleases, err.Error())
|
||||
}
|
||||
var data map[string]interface{}
|
||||
err = json.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal response body from '%s', reason: %s", latestReleases, err.Error())
|
||||
}
|
||||
|
||||
if assets, ok := data["assets"].([]interface{}); ok {
|
||||
for i := range assets {
|
||||
if asset, ok := assets[i].(map[string]interface{}); ok {
|
||||
if name, ok := asset["name"].(string); ok {
|
||||
if name == frameworkName {
|
||||
if url, ok := asset["browser_download_url"].(string); ok {
|
||||
drp.hostURL = url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
@@ -1,160 +1,12 @@
|
||||
package getter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/armotypes"
|
||||
"github.com/armosec/kubescape/cautils/opapolicy"
|
||||
)
|
||||
|
||||
const DefaultLocalStore = ".kubescape"
|
||||
|
||||
type IPolicyGetter interface {
|
||||
GetFramework(name string) (*opapolicy.Framework, error)
|
||||
}
|
||||
|
||||
// =======================================================================================================================
|
||||
// ======================================== DownloadReleasedPolicy =======================================================
|
||||
// =======================================================================================================================
|
||||
|
||||
// Download released version
|
||||
type DownloadReleasedPolicy struct {
|
||||
hostURL string
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func NewDownloadReleasedPolicy() *DownloadReleasedPolicy {
|
||||
return &DownloadReleasedPolicy{
|
||||
hostURL: "",
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
}
|
||||
|
||||
func (drp *DownloadReleasedPolicy) GetFramework(name string) (*opapolicy.Framework, error) {
|
||||
drp.setURL(name)
|
||||
respStr, err := HttpGetter(drp.httpClient, drp.hostURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
framework := &opapolicy.Framework{}
|
||||
if err = JSONDecoder(respStr).Decode(framework); err != nil {
|
||||
return framework, err
|
||||
}
|
||||
|
||||
SaveFrameworkInFile(framework, GetDefaultPath(name))
|
||||
return framework, err
|
||||
}
|
||||
|
||||
func (drp *DownloadReleasedPolicy) setURL(frameworkName string) error {
|
||||
|
||||
latestReleases := "https://api.github.com/repos/armosec/regolibrary/releases/latest"
|
||||
resp, err := http.Get(latestReleases)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get latest releases from '%s', reason: %s", latestReleases, err.Error())
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode < 200 || 301 < resp.StatusCode {
|
||||
return fmt.Errorf("failed to download file, status code: %s", resp.Status)
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read response body from '%s', reason: %s", latestReleases, err.Error())
|
||||
}
|
||||
var data map[string]interface{}
|
||||
err = json.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal response body from '%s', reason: %s", latestReleases, err.Error())
|
||||
}
|
||||
|
||||
if assets, ok := data["assets"].([]interface{}); ok {
|
||||
for i := range assets {
|
||||
if asset, ok := assets[i].(map[string]interface{}); ok {
|
||||
if name, ok := asset["name"].(string); ok {
|
||||
if name == frameworkName {
|
||||
if url, ok := asset["browser_download_url"].(string); ok {
|
||||
drp.hostURL = url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// =======================================================================================================================
|
||||
// ============================================== LoadPolicy =============================================================
|
||||
// =======================================================================================================================
|
||||
|
||||
// Load policies from a local repository
|
||||
type LoadPolicy struct {
|
||||
filePath string
|
||||
}
|
||||
|
||||
func NewLoadPolicy(filePath string) *LoadPolicy {
|
||||
return &LoadPolicy{
|
||||
filePath: filePath,
|
||||
}
|
||||
}
|
||||
|
||||
func (lp *LoadPolicy) GetFramework(frameworkName string) (*opapolicy.Framework, error) {
|
||||
|
||||
framework := &opapolicy.Framework{}
|
||||
f, err := ioutil.ReadFile(lp.filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(f, framework)
|
||||
if frameworkName != "" && !strings.EqualFold(frameworkName, framework.Name) {
|
||||
return nil, fmt.Errorf("framework from file not matching")
|
||||
}
|
||||
return framework, err
|
||||
}
|
||||
|
||||
// =======================================================================================================================
|
||||
// =============================================== ArmoAPI ===============================================================
|
||||
// =======================================================================================================================
|
||||
|
||||
// Armo API for downloading policies
|
||||
type ArmoAPI struct {
|
||||
httpClient *http.Client
|
||||
hostURL string
|
||||
}
|
||||
|
||||
func NewArmoAPI() *ArmoAPI {
|
||||
return &ArmoAPI{
|
||||
httpClient: &http.Client{},
|
||||
hostURL: "https://dashbe.eustage2.cyberarmorsoft.com",
|
||||
}
|
||||
}
|
||||
func (armoAPI *ArmoAPI) GetFramework(name string) (*opapolicy.Framework, error) {
|
||||
armoAPI.setURL(name)
|
||||
respStr, err := HttpGetter(armoAPI.httpClient, armoAPI.hostURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
framework := &opapolicy.Framework{}
|
||||
if err = JSONDecoder(respStr).Decode(framework); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
SaveFrameworkInFile(framework, GetDefaultPath(name))
|
||||
|
||||
return framework, err
|
||||
}
|
||||
|
||||
func (armoAPI *ArmoAPI) setURL(frameworkName string) {
|
||||
requestURI := "v1/armoFrameworks"
|
||||
requestURI += fmt.Sprintf("?customerGUID=%s", "11111111-1111-1111-1111-111111111111")
|
||||
requestURI += fmt.Sprintf("&frameworkName=%s", strings.ToUpper(frameworkName))
|
||||
requestURI += "&getRules=true"
|
||||
|
||||
armoAPI.hostURL = urlEncoder(fmt.Sprintf("%s/%s", armoAPI.hostURL, requestURI))
|
||||
GetExceptions(policyType, customerGUID, clusterName string) ([]armotypes.PostureExceptionPolicy, error)
|
||||
// GetScores(scope, customerName, namespace string) ([]armotypes.PostureExceptionPolicy, error)
|
||||
}
|
||||
|
||||
46
cautils/getter/loadpolicy.go
Normal file
46
cautils/getter/loadpolicy.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package getter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/armotypes"
|
||||
"github.com/armosec/kubescape/cautils/opapolicy"
|
||||
)
|
||||
|
||||
// =======================================================================================================================
|
||||
// ============================================== LoadPolicy =============================================================
|
||||
// =======================================================================================================================
|
||||
const DefaultLocalStore = ".kubescape"
|
||||
|
||||
// Load policies from a local repository
|
||||
type LoadPolicy struct {
|
||||
filePath string
|
||||
}
|
||||
|
||||
func NewLoadPolicy(filePath string) *LoadPolicy {
|
||||
return &LoadPolicy{
|
||||
filePath: filePath,
|
||||
}
|
||||
}
|
||||
|
||||
func (lp *LoadPolicy) GetFramework(frameworkName string) (*opapolicy.Framework, error) {
|
||||
|
||||
framework := &opapolicy.Framework{}
|
||||
f, err := ioutil.ReadFile(lp.filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(f, framework)
|
||||
if frameworkName != "" && !strings.EqualFold(frameworkName, framework.Name) {
|
||||
return nil, fmt.Errorf("framework from file not matching")
|
||||
}
|
||||
return framework, err
|
||||
}
|
||||
|
||||
func (lp *LoadPolicy) GetExceptions(policyType, customerGUID, clusterName string) ([]armotypes.PostureExceptionPolicy, error) {
|
||||
return []armotypes.PostureExceptionPolicy{}, nil
|
||||
}
|
||||
@@ -3,10 +3,6 @@ package opapolicy
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/open-policy-agent/opa/rego"
|
||||
)
|
||||
|
||||
func (pn *PolicyNotification) ToJSONBytesBuffer() (*bytes.Buffer, error) {
|
||||
@@ -53,34 +49,6 @@ func (ruleReport *RuleReport) GetRuleStatus() (string, []RuleResponse, []RuleRes
|
||||
}
|
||||
return status, failed, exceptions
|
||||
}
|
||||
func ParseRegoResult(regoResult *rego.ResultSet) ([]RuleResponse, error) {
|
||||
var errs error
|
||||
ruleResponses := []RuleResponse{}
|
||||
for _, result := range *regoResult {
|
||||
for desicionIdx := range result.Expressions {
|
||||
if resMap, ok := result.Expressions[desicionIdx].Value.(map[string]interface{}); ok {
|
||||
for objName := range resMap {
|
||||
jsonBytes, err := json.Marshal(resMap[objName])
|
||||
if err != nil {
|
||||
err = fmt.Errorf("in parseRegoResult, json.Marshal failed. name: %s, obj: %v, reason: %s", objName, resMap[objName], err)
|
||||
glog.Error(err)
|
||||
errs = fmt.Errorf("%s\n%s", errs, err)
|
||||
continue
|
||||
}
|
||||
desObj := make([]RuleResponse, 0)
|
||||
if err := json.Unmarshal(jsonBytes, &desObj); err != nil {
|
||||
err = fmt.Errorf("in parseRegoResult, json.Unmarshal failed. name: %s, obj: %v, reason: %s", objName, resMap[objName], err)
|
||||
glog.Error(err)
|
||||
errs = fmt.Errorf("%s\n%s", errs, err)
|
||||
continue
|
||||
}
|
||||
ruleResponses = append(ruleResponses, desObj...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ruleResponses, errs
|
||||
}
|
||||
|
||||
func (controlReport *ControlReport) GetNumberOfResources() int {
|
||||
sum := 0
|
||||
|
||||
@@ -8,8 +8,9 @@ import (
|
||||
)
|
||||
|
||||
type ScanInfo struct {
|
||||
PolicyGetter getter.IPolicyGetter
|
||||
Getters
|
||||
PolicyIdentifier opapolicy.PolicyIdentifier
|
||||
UseExceptions string
|
||||
UseFrom string
|
||||
UseDefault bool
|
||||
Format string
|
||||
@@ -20,12 +21,28 @@ type ScanInfo struct {
|
||||
FailThreshold uint16
|
||||
}
|
||||
|
||||
type Getters struct {
|
||||
ExceptionsGetter getter.IPolicyGetter
|
||||
PolicyGetter getter.IPolicyGetter
|
||||
}
|
||||
|
||||
func (scanInfo *ScanInfo) Init() {
|
||||
// scanInfo.setSilentMode()
|
||||
scanInfo.setUseFrom()
|
||||
scanInfo.setUseExceptions()
|
||||
scanInfo.setOutputFile()
|
||||
scanInfo.setGetter()
|
||||
|
||||
}
|
||||
|
||||
func (scanInfo *ScanInfo) setUseExceptions() {
|
||||
if scanInfo.UseExceptions != "" {
|
||||
// load exceptions from file
|
||||
scanInfo.ExceptionsGetter = getter.NewLoadPolicy(scanInfo.UseExceptions)
|
||||
} else {
|
||||
scanInfo.ExceptionsGetter = getter.NewArmoAPI()
|
||||
}
|
||||
|
||||
}
|
||||
func (scanInfo *ScanInfo) setUseFrom() {
|
||||
if scanInfo.UseFrom != "" {
|
||||
|
||||
@@ -83,8 +83,9 @@ func isValidFramework(framework string) bool {
|
||||
func init() {
|
||||
scanCmd.AddCommand(frameworkCmd)
|
||||
scanInfo = cautils.ScanInfo{}
|
||||
frameworkCmd.Flags().StringVarP(&scanInfo.UseFrom, "use-from", "", "", "Path to load framework from")
|
||||
frameworkCmd.Flags().BoolVarP(&scanInfo.UseDefault, "use-default", "", false, "Load framework from default path")
|
||||
frameworkCmd.Flags().StringVar(&scanInfo.UseFrom, "use-from", "", "Path to load framework from")
|
||||
frameworkCmd.Flags().BoolVar(&scanInfo.UseDefault, "use-default", false, "Load framework from default path")
|
||||
frameworkCmd.Flags().StringVar(&scanInfo.UseExceptions, "exceptions", "", "Path to file containing list of exceptions")
|
||||
frameworkCmd.Flags().StringVarP(&scanInfo.ExcludedNamespaces, "exclude-namespaces", "e", "", "Namespaces to exclude from check")
|
||||
frameworkCmd.Flags().StringVarP(&scanInfo.Format, "format", "f", "pretty-printer", `Output format. supported formats: "pretty-printer"/"json"/"junit"`)
|
||||
frameworkCmd.Flags().StringVarP(&scanInfo.Output, "output", "o", "", "Output file. print output to file and not stdout")
|
||||
@@ -120,7 +121,7 @@ func CliSetup() error {
|
||||
|
||||
// processor setup - rego run
|
||||
go func() {
|
||||
reporterObj := opaprocessor.NewOPAProcessor(&processNotification, &reportResults)
|
||||
reporterObj := opaprocessor.NewOPAProcessorHandler(&processNotification, &reportResults)
|
||||
reporterObj.ProcessRulesListenner()
|
||||
}()
|
||||
p := printer.NewPrinter(&reportResults, scanInfo.Format, scanInfo.Output)
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/armosec/kubescape/cautils"
|
||||
"github.com/armosec/kubescape/scapepkg/exceptions"
|
||||
"github.com/armosec/kubescape/scapepkg/score"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/k8sinterface"
|
||||
|
||||
@@ -18,93 +20,149 @@ import (
|
||||
"github.com/open-policy-agent/opa/storage"
|
||||
)
|
||||
|
||||
type OPAProcessor struct {
|
||||
processedPolicy *chan *cautils.OPASessionObj
|
||||
reportResults *chan *cautils.OPASessionObj
|
||||
regoK8sCredentials storage.Store
|
||||
const ScoreConfigPath = "/resources/config"
|
||||
|
||||
var RegoK8sCredentials storage.Store
|
||||
|
||||
type OPAProcessorHandler struct {
|
||||
processedPolicy *chan *cautils.OPASessionObj
|
||||
reportResults *chan *cautils.OPASessionObj
|
||||
// componentConfig cautils.ComponentConfig
|
||||
}
|
||||
|
||||
func NewOPAProcessor(processedPolicy, reportResults *chan *cautils.OPASessionObj) *OPAProcessor {
|
||||
type OPAProcessor struct {
|
||||
*cautils.OPASessionObj
|
||||
}
|
||||
|
||||
func NewOPAProcessor(sessionObj *cautils.OPASessionObj) *OPAProcessor {
|
||||
return &OPAProcessor{
|
||||
OPASessionObj: sessionObj,
|
||||
}
|
||||
}
|
||||
|
||||
func NewOPAProcessorHandler(processedPolicy, reportResults *chan *cautils.OPASessionObj) *OPAProcessorHandler {
|
||||
|
||||
regoDependenciesData := resources.NewRegoDependenciesData(k8sinterface.K8SConfig)
|
||||
store, err := regoDependenciesData.TOStorage()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &OPAProcessor{
|
||||
processedPolicy: processedPolicy,
|
||||
reportResults: reportResults,
|
||||
regoK8sCredentials: store,
|
||||
RegoK8sCredentials = store
|
||||
|
||||
return &OPAProcessorHandler{
|
||||
processedPolicy: processedPolicy,
|
||||
reportResults: reportResults,
|
||||
}
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) ProcessRulesListenner() {
|
||||
func (opaHandler *OPAProcessorHandler) ProcessRulesListenner() {
|
||||
// recover
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
glog.Errorf("RECOVER in ProcessRulesListenner, reason: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
// recover
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
glog.Errorf("RECOVER in ProcessRulesListenner, reason: %v", err)
|
||||
}
|
||||
}()
|
||||
opaSessionObj := <-*opap.processedPolicy
|
||||
go func() {
|
||||
if err := opap.ProcessRulesHandler(opaSessionObj); err != nil {
|
||||
// opaSessionObj.Reporter.SendError(nil, true, true)
|
||||
}
|
||||
*opap.reportResults <- opaSessionObj
|
||||
}()
|
||||
opaSessionObj := <-*opaHandler.processedPolicy
|
||||
opap := NewOPAProcessor(opaSessionObj)
|
||||
|
||||
// process
|
||||
if err := opap.Process(); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
// edit results
|
||||
opap.updateResults()
|
||||
|
||||
// update score
|
||||
opap.updateScore()
|
||||
|
||||
// report
|
||||
*opaHandler.reportResults <- opaSessionObj
|
||||
}
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) ProcessRulesHandler(opaSessionObj *cautils.OPASessionObj) error {
|
||||
func (opap *OPAProcessor) Process() error {
|
||||
// glog.Infof(fmt.Sprintf("Starting 'Process'. reportID: %s", opap.PostureReport.ReportID))
|
||||
cautils.ProgressTextDisplay(fmt.Sprintf("Scanning cluster %s", cautils.ClusterName))
|
||||
cautils.StartSpinner()
|
||||
frameworkReports := []opapolicy.FrameworkReport{}
|
||||
var errs error
|
||||
for _, framework := range opaSessionObj.Frameworks {
|
||||
frameworkReport := opapolicy.FrameworkReport{}
|
||||
frameworkReport.Name = framework.Name
|
||||
controlReports := []opapolicy.ControlReport{}
|
||||
for _, control := range framework.Controls {
|
||||
// cautils.SimpleDisplay(os.Stdout, fmt.Sprintf("\033[2K\r%s", control.Name))
|
||||
controlReport := opapolicy.ControlReport{}
|
||||
controlReport.Name = control.Name
|
||||
controlReport.Description = control.Description
|
||||
controlReport.Remediation = control.Remediation
|
||||
ruleReports := []opapolicy.RuleReport{}
|
||||
for _, rule := range control.Rules {
|
||||
if ruleWithArmoOpaDependency(rule.Attributes) {
|
||||
continue
|
||||
}
|
||||
k8sObjects := getKubernetesObjects(opaSessionObj.K8SResources, rule.Match)
|
||||
ruleReport, err := opap.runOPAOnSingleRule(&rule, k8sObjects)
|
||||
if err != nil {
|
||||
ruleReport.RuleStatus.Status = "failure"
|
||||
ruleReport.RuleStatus.Message = err.Error()
|
||||
glog.Error(err)
|
||||
|
||||
errs = fmt.Errorf("%v\n%s", errs, err.Error())
|
||||
} else {
|
||||
ruleReport.RuleStatus.Status = "success"
|
||||
}
|
||||
ruleReport.ListInputResources = k8sObjects
|
||||
ruleReport.ListInputKinds = listMatchKinds(rule.Match)
|
||||
ruleReports = append(ruleReports, ruleReport)
|
||||
}
|
||||
controlReport.RuleReports = ruleReports
|
||||
controlReports = append(controlReports, controlReport)
|
||||
for i := range opap.Frameworks {
|
||||
frameworkReport, err := opap.processFramework(&opap.Frameworks[i])
|
||||
if err != nil {
|
||||
errs = fmt.Errorf("%v\n%s", errs, err.Error())
|
||||
}
|
||||
frameworkReport.ControlReports = controlReports
|
||||
frameworkReports = append(frameworkReports, frameworkReport)
|
||||
frameworkReports = append(frameworkReports, *frameworkReport)
|
||||
}
|
||||
|
||||
opaSessionObj.PostureReport.FrameworkReports = frameworkReports
|
||||
opaSessionObj.PostureReport.ReportGenerationTime = time.Now().UTC()
|
||||
opap.PostureReport.FrameworkReports = frameworkReports
|
||||
opap.PostureReport.ReportGenerationTime = time.Now().UTC()
|
||||
// glog.Infof(fmt.Sprintf("Done 'Process'. reportID: %s", opap.PostureReport.ReportID))
|
||||
cautils.StopSpinner()
|
||||
cautils.SuccessTextDisplay(fmt.Sprintf("Done scanning cluster %s", cautils.ClusterName))
|
||||
return errs
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) processFramework(framework *opapolicy.Framework) (*opapolicy.FrameworkReport, error) {
|
||||
var errs error
|
||||
|
||||
frameworkReport := opapolicy.FrameworkReport{}
|
||||
frameworkReport.Name = framework.Name
|
||||
controlReports := []opapolicy.ControlReport{}
|
||||
for i := range framework.Controls {
|
||||
controlReport, err := opap.processControl(&framework.Controls[i])
|
||||
if err != nil {
|
||||
errs = fmt.Errorf("%v\n%s", errs, err.Error())
|
||||
}
|
||||
controlReports = append(controlReports, *controlReport)
|
||||
}
|
||||
frameworkReport.ControlReports = controlReports
|
||||
return &frameworkReport, errs
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) processControl(control *opapolicy.Control) (*opapolicy.ControlReport, error) {
|
||||
var errs error
|
||||
|
||||
controlReport := opapolicy.ControlReport{}
|
||||
controlReport.PortalBase = control.PortalBase
|
||||
|
||||
controlReport.Name = control.Name
|
||||
controlReport.Description = control.Description
|
||||
controlReport.Remediation = control.Remediation
|
||||
|
||||
ruleReports := []opapolicy.RuleReport{}
|
||||
for i := range control.Rules {
|
||||
ruleReport, err := opap.processRule(&control.Rules[i])
|
||||
if err != nil {
|
||||
errs = fmt.Errorf("%v\n%s", errs, err.Error())
|
||||
}
|
||||
if ruleReport != nil {
|
||||
ruleReports = append(ruleReports, *ruleReport)
|
||||
}
|
||||
}
|
||||
controlReport.RuleReports = ruleReports
|
||||
return &controlReport, errs
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) processRule(rule *opapolicy.PolicyRule) (*opapolicy.RuleReport, error) {
|
||||
if ruleWithArmoOpaDependency(rule.Attributes) {
|
||||
return nil, nil
|
||||
}
|
||||
k8sObjects := getKubernetesObjects(opap.K8SResources, rule.Match)
|
||||
ruleReport, err := opap.runOPAOnSingleRule(rule, k8sObjects)
|
||||
if err != nil {
|
||||
ruleReport.RuleStatus.Status = "failure"
|
||||
ruleReport.RuleStatus.Message = err.Error()
|
||||
glog.Error(err)
|
||||
} else {
|
||||
ruleReport.RuleStatus.Status = "success"
|
||||
}
|
||||
ruleReport.ListInputResources = k8sObjects
|
||||
return &ruleReport, err
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) runOPAOnSingleRule(rule *opapolicy.PolicyRule, k8sObjects []map[string]interface{}) (opapolicy.RuleReport, error) {
|
||||
switch rule.RuleLanguage {
|
||||
case opapolicy.RegoLanguage, opapolicy.RegoLanguage2:
|
||||
@@ -147,18 +205,42 @@ func (opap *OPAProcessor) regoEval(inputObj []map[string]interface{}, compiledRe
|
||||
rego.Query("data.armo_builtins"), // get package name from rule
|
||||
rego.Compiler(compiledRego),
|
||||
rego.Input(inputObj),
|
||||
rego.Store(opap.regoK8sCredentials),
|
||||
rego.Store(RegoK8sCredentials),
|
||||
)
|
||||
|
||||
// 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, fmt.Errorf("in 'regoEval', failed to evaluate rule, reason: %s", err.Error())
|
||||
}
|
||||
results, err := opapolicy.ParseRegoResult(&resultSet)
|
||||
results, err := parseRegoResult(&resultSet)
|
||||
|
||||
// results, err := ParseRegoResult(&resultSet)
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) updateScore() {
|
||||
|
||||
// calculate score
|
||||
s := score.NewScore(k8sinterface.NewKubernetesApi(), ScoreConfigPath)
|
||||
s.Calculate(opap.PostureReport.FrameworkReports)
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) updateResults() {
|
||||
for f, frameworkReport := range opap.PostureReport.FrameworkReports {
|
||||
for c, controlReport := 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)
|
||||
|
||||
// adding exceptions to the rules
|
||||
ruleExceptions := exceptions.ListRuleExceptions(opap.Exceptions, frameworkReport.Name, controlReport.Name, ruleReport.Name)
|
||||
exceptions.AddExceptionsToRuleResponses(opap.PostureReport.FrameworkReports[f].ControlReports[c].RuleReports[r].RuleResponses, ruleExceptions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,21 @@
|
||||
package opaprocessor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/armosec/kubescape/cautils"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/k8sinterface"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/opapolicy"
|
||||
"github.com/armosec/kubescape/cautils/opapolicy/resources"
|
||||
|
||||
"github.com/open-policy-agent/opa/ast"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
)
|
||||
|
||||
func NewOPAProcessorMock() *OPAProcessor {
|
||||
c := make(chan *cautils.OPASessionObj)
|
||||
|
||||
deps := resources.NewRegoDependenciesDataMock()
|
||||
storage, err := deps.TOStorage()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &OPAProcessor{
|
||||
processedPolicy: &c,
|
||||
reportResults: &c,
|
||||
regoK8sCredentials: storage,
|
||||
}
|
||||
return &OPAProcessor{}
|
||||
}
|
||||
func TestProcessRulesHandler(t *testing.T) {
|
||||
func TestProcess(t *testing.T) {
|
||||
|
||||
// set k8s
|
||||
k8sResources := make(cautils.K8SResources)
|
||||
k8sResources["/v1/pods"] = k8sinterface.ConvertUnstructuredSliceToMap(k8sinterface.V1KubeSystemNamespaceMock().Items)
|
||||
@@ -47,149 +24,21 @@ func TestProcessRulesHandler(t *testing.T) {
|
||||
opaSessionObj := cautils.NewOPASessionObjMock()
|
||||
opaSessionObj.Frameworks = []opapolicy.Framework{*opapolicy.MockFrameworkA()}
|
||||
opaSessionObj.K8SResources = &k8sResources
|
||||
k8sinterface.K8SConfig = &restclient.Config{}
|
||||
|
||||
// run test
|
||||
processor := NewOPAProcessorMock()
|
||||
if err := processor.ProcessRulesHandler(opaSessionObj); err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
// bla, _ := json.Marshal(opaSessionObj.PostureReport)
|
||||
// t.Errorf("%v", string(bla))
|
||||
}
|
||||
|
||||
func TestRunRegoOnK8s(t *testing.T) {
|
||||
// set k8s
|
||||
k8sResources := make(cautils.K8SResources)
|
||||
// k8sResources["/v1/pods"] = k8sinterface.ConvertUnstructuredSliceToMap(k8sinterface.V1KubeSystemNamespaceMock().Items)
|
||||
k8sResources["/v1/pods"] = k8sinterface.V1KubeSystemNamespaceMock().Items
|
||||
|
||||
k8sinterface.K8SConfig = &restclient.Config{}
|
||||
|
||||
// run test
|
||||
processor := NewOPAProcessorMock()
|
||||
report, err := processor.runRegoOnK8s(opapolicy.MockRuleA(), []map[string]interface{}{k8sResources})
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
if len(report.RuleResponses) == 0 {
|
||||
t.Errorf("len(report.RuleResponses) == 0")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompromisedRegistries(t *testing.T) {
|
||||
// set k8s
|
||||
k8sResources := make(cautils.K8SResources)
|
||||
// k8sResources["/v1/pods"] = k8sinterface.ConvertUnstructuredSliceToMap(k8sinterface.V1KubeSystemNamespaceMock().Items)
|
||||
k8sResources["/v1/pods"] = k8sinterface.V1AllClusterWithCompromisedRegistriesMock().Items
|
||||
wd, _ := os.Getwd()
|
||||
baseDirName := "kubescape"
|
||||
idx := strings.Index(wd, baseDirName)
|
||||
wd = wd[0:idx]
|
||||
resources.RegoDependenciesPath = path.Join(wd, "/kubescape/vendor/asterix.cyberarmor.io/cyberarmor/capacketsgo/opapolicy/resources/rego/dependencies")
|
||||
k8sinterface.K8SConfig = &restclient.Config{}
|
||||
|
||||
opaProcessor := NewOPAProcessorMock()
|
||||
|
||||
// run test
|
||||
reportB, errB := opaProcessor.runRegoOnK8s(opapolicy.MockRuleUntrustedRegistries(), []map[string]interface{}{k8sResources})
|
||||
if errB != nil {
|
||||
t.Errorf("%v", errB)
|
||||
}
|
||||
if len(reportB.RuleResponses) == 0 {
|
||||
t.Errorf("len(report.RuleResponses) == 0")
|
||||
return
|
||||
}
|
||||
// bla, _ := json.Marshal(reportB.RuleResponses[0])
|
||||
// t.Errorf("%s", bla)
|
||||
}
|
||||
|
||||
// func TestForLior(t *testing.T) {
|
||||
// // set k8s
|
||||
// k8sResources := make(cautils.K8SResources)
|
||||
// // k8sResources["/v1/pods"] = k8sinterface.ConvertUnstructuredSliceToMap(k8sinterface.V1KubeSystemNamespaceMock().Items)
|
||||
// k8sResources["/v1/pods"] = k8sinterface.V1KubeSystemNamespaceMock().Items
|
||||
// resources.RegoDependenciesPath = "/home/david/go/src/kubescape/vendor/asterix.cyberarmor.io/cyberarmor/capacketsgo/opapolicy/resources/rego/dependencies"
|
||||
// opaProcessor := NewOPAProcessorMock()
|
||||
|
||||
// // set opaSessionObj
|
||||
// opaSessionObj := cautils.NewOPASessionObjMock()
|
||||
// opaSessionObj.K8SResources = &k8sResources
|
||||
|
||||
// opaSessionObj.Frameworks = []opapolicy.Framework{*opapolicy.MockFrameworkA()}
|
||||
// opaSessionObj.Frameworks[0].Controls[0].Rules[0] = *opapolicy.MockRuleB()
|
||||
|
||||
// // run test
|
||||
// reportB, errB := opaProcessor.runRegoOnK8s(opapolicy.MockRuleB(), opaSessionObj)
|
||||
// if errB != nil {
|
||||
// t.Errorf("%v", errB)
|
||||
// return
|
||||
// }
|
||||
// if len(reportB.RuleResponses) == 0 {
|
||||
// t.Errorf("len(report.RuleResponses) == 0")
|
||||
// return
|
||||
// }
|
||||
// bla, _ := json.Marshal(reportB.RuleResponses[0])
|
||||
// t.Errorf("%s", bla)
|
||||
// }
|
||||
|
||||
func TestNewRego(t *testing.T) {
|
||||
// TODO - remove before testing
|
||||
return
|
||||
|
||||
// k8sConfig := k8sinterface.GetK8sConfig()
|
||||
|
||||
// t.Errorf(fmt.Sprintf("%v", k8sConfig.String()))
|
||||
// t.Errorf(fmt.Sprintf("%v", k8sConfig.AuthProvider.Config))
|
||||
// return
|
||||
|
||||
ruleName := "some rule"
|
||||
rule := opapolicy.MockTemp()
|
||||
allResources := []schema.GroupVersionResource{
|
||||
{Group: "api-versions", Version: "", Resource: ""},
|
||||
}
|
||||
namespace := ""
|
||||
k8sinterface.K8SConfig = nil
|
||||
|
||||
// compile modules
|
||||
modules, err := getRuleDependencies()
|
||||
if err != nil {
|
||||
t.Errorf("err: %v", err)
|
||||
return
|
||||
}
|
||||
modules[ruleName] = rule
|
||||
compiled, err := ast.CompileModules(modules)
|
||||
if err != nil {
|
||||
t.Errorf("err: %v", err)
|
||||
return
|
||||
}
|
||||
opaProcessor := NewOPAProcessorMock()
|
||||
k8s := k8sinterface.NewKubernetesApi()
|
||||
|
||||
// set dynamic object
|
||||
var clientResource dynamic.ResourceInterface
|
||||
recourceList := []unstructured.Unstructured{}
|
||||
for i := range allResources {
|
||||
if namespace != "" {
|
||||
clientResource = k8s.DynamicClient.Resource(allResources[i]).Namespace(namespace)
|
||||
} else {
|
||||
clientResource = k8s.DynamicClient.Resource(allResources[i])
|
||||
opap := NewOPAProcessor(opaSessionObj)
|
||||
opap.Process()
|
||||
opap.updateResults()
|
||||
for _, f := range opap.PostureReport.FrameworkReports {
|
||||
for _, c := range f.ControlReports {
|
||||
for _, r := range c.RuleReports {
|
||||
for _, rr := range r.RuleResponses {
|
||||
// t.Errorf("AlertMessage: %v", rr.AlertMessage)
|
||||
if rr.Exception != nil {
|
||||
t.Errorf("Exception: %v", rr.Exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
l, err := clientResource.List(context.Background(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("err: %v", err)
|
||||
return
|
||||
}
|
||||
recourceList = append(recourceList, l.Items...)
|
||||
}
|
||||
inputObj := k8sinterface.ConvertUnstructuredSliceToMap(k8sinterface.FilterOutOwneredResources(recourceList))
|
||||
// inputObj := k8sinterface.ConvertUnstructuredSliceToMap(l.Items)
|
||||
result, err := opaProcessor.regoEval(inputObj, compiled)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
return
|
||||
}
|
||||
resb, _ := json.Marshal(result)
|
||||
t.Errorf("result: %s", resb)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
package opaprocessor
|
||||
|
||||
import (
|
||||
"github.com/armosec/kubescape/cautils"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
pkgcautils "github.com/armosec/kubescape/cautils/cautils"
|
||||
|
||||
"github.com/armosec/kubescape/cautils"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/k8sinterface"
|
||||
"github.com/armosec/kubescape/cautils/opapolicy"
|
||||
resources "github.com/armosec/kubescape/cautils/opapolicy/resources"
|
||||
"github.com/open-policy-agent/opa/rego"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
@@ -49,6 +54,73 @@ func getRuleDependencies() (map[string]string, error) {
|
||||
}
|
||||
return modules, nil
|
||||
}
|
||||
func parseRegoResult(regoResult *rego.ResultSet) ([]opapolicy.RuleResponse, error) {
|
||||
var errs error
|
||||
ruleResponses := []opapolicy.RuleResponse{}
|
||||
for _, result := range *regoResult {
|
||||
for desicionIdx := range result.Expressions {
|
||||
if resMap, ok := result.Expressions[desicionIdx].Value.(map[string]interface{}); ok {
|
||||
for objName := range resMap {
|
||||
jsonBytes, err := json.Marshal(resMap[objName])
|
||||
if err != nil {
|
||||
err = fmt.Errorf("in parseRegoResult, json.Marshal failed. name: %s, obj: %v, reason: %s", objName, resMap[objName], err)
|
||||
glog.Error(err)
|
||||
errs = fmt.Errorf("%s\n%s", errs, err)
|
||||
continue
|
||||
}
|
||||
desObj := make([]opapolicy.RuleResponse, 0)
|
||||
if err := json.Unmarshal(jsonBytes, &desObj); err != nil {
|
||||
err = fmt.Errorf("in parseRegoResult, json.Unmarshal failed. name: %s, obj: %v, reason: %s", objName, resMap[objName], err)
|
||||
glog.Error(err)
|
||||
errs = fmt.Errorf("%s\n%s", errs, err)
|
||||
continue
|
||||
}
|
||||
ruleResponses = append(ruleResponses, desObj...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ruleResponses, errs
|
||||
}
|
||||
|
||||
//editRuleResponses editing the responses -> removing duplications, clearing secret data, etc.
|
||||
func editRuleResponses(ruleResponses []opapolicy.RuleResponse) []opapolicy.RuleResponse {
|
||||
uniqueRuleResponses := map[string]bool{}
|
||||
lenRuleResponses := len(ruleResponses)
|
||||
for i := 0; i < lenRuleResponses; i++ {
|
||||
for j := range ruleResponses[i].AlertObject.K8SApiObjects {
|
||||
w := k8sinterface.NewWorkloadObj(ruleResponses[i].AlertObject.K8SApiObjects[j])
|
||||
if w == nil {
|
||||
continue
|
||||
}
|
||||
resourceID := fmt.Sprintf("%s/%s/%s/%s", w.GetApiVersion(), w.GetNamespace(), w.GetKind(), w.GetName())
|
||||
if found := uniqueRuleResponses[resourceID]; found {
|
||||
// resource found -> remove from slice
|
||||
ruleResponses = removeFromSlice(ruleResponses, i)
|
||||
lenRuleResponses -= 1
|
||||
break
|
||||
} else {
|
||||
cleanRuleResponses(w)
|
||||
ruleResponses[i].AlertObject.K8SApiObjects[j] = w.GetWorkload()
|
||||
uniqueRuleResponses[resourceID] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return ruleResponses
|
||||
}
|
||||
func cleanRuleResponses(workload k8sinterface.IWorkload) {
|
||||
if workload.GetKind() == "Secret" {
|
||||
workload.RemoveSecretData()
|
||||
}
|
||||
}
|
||||
|
||||
func removeFromSlice(ruleResponses []opapolicy.RuleResponse, i int) []opapolicy.RuleResponse {
|
||||
if i != len(ruleResponses)-1 {
|
||||
ruleResponses[i] = ruleResponses[len(ruleResponses)-1]
|
||||
}
|
||||
|
||||
return ruleResponses[:len(ruleResponses)-1]
|
||||
}
|
||||
|
||||
func ruleWithArmoOpaDependency(annotations map[string]interface{}) bool {
|
||||
if annotations == nil {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/armosec/kubescape/cautils"
|
||||
"github.com/armosec/kubescape/cautils/getter"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/armotypes"
|
||||
"github.com/armosec/kubescape/cautils/k8sinterface"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/opapolicy"
|
||||
@@ -16,6 +16,7 @@ type PolicyHandler struct {
|
||||
k8s *k8sinterface.KubernetesApi
|
||||
// we are listening on this chan in opaprocessor/processorhandler.go/ProcessRulesListenner func
|
||||
processPolicy *chan *cautils.OPASessionObj
|
||||
getters *cautils.Getters
|
||||
}
|
||||
|
||||
// CreatePolicyHandler Create ws-handler obj
|
||||
@@ -30,9 +31,10 @@ func (policyHandler *PolicyHandler) HandleNotificationRequest(notification *opap
|
||||
opaSessionObj := cautils.NewOPASessionObj(nil, nil)
|
||||
// validate notification
|
||||
// TODO
|
||||
policyHandler.getters = &scanInfo.Getters
|
||||
|
||||
// get policies
|
||||
frameworks, err := policyHandler.getPolicies(notification, scanInfo.PolicyGetter)
|
||||
frameworks, exceptions, err := policyHandler.getPolicies(notification)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -40,6 +42,7 @@ func (policyHandler *PolicyHandler) HandleNotificationRequest(notification *opap
|
||||
return fmt.Errorf("empty list of frameworks")
|
||||
}
|
||||
opaSessionObj.Frameworks = frameworks
|
||||
opaSessionObj.Exceptions = exceptions
|
||||
|
||||
k8sResources, err := policyHandler.getResources(notification, opaSessionObj, scanInfo)
|
||||
if err != nil {
|
||||
@@ -55,22 +58,22 @@ func (policyHandler *PolicyHandler) HandleNotificationRequest(notification *opap
|
||||
return nil
|
||||
}
|
||||
|
||||
func (policyHandler *PolicyHandler) getPolicies(notification *opapolicy.PolicyNotification, policyGetter getter.IPolicyGetter) ([]opapolicy.Framework, error) {
|
||||
func (policyHandler *PolicyHandler) getPolicies(notification *opapolicy.PolicyNotification) ([]opapolicy.Framework, []armotypes.PostureExceptionPolicy, error) {
|
||||
|
||||
cautils.ProgressTextDisplay("Downloading/Loading framework definitions")
|
||||
|
||||
frameworks, err := policyHandler.GetPoliciesFromBackend(notification, policyGetter)
|
||||
frameworks, exceptions, err := policyHandler.GetPoliciesFromBackend(notification)
|
||||
if err != nil {
|
||||
return frameworks, err
|
||||
return frameworks, exceptions, err
|
||||
}
|
||||
|
||||
if len(frameworks) == 0 {
|
||||
err := fmt.Errorf("could not download any policies, please check previous logs")
|
||||
return frameworks, err
|
||||
return frameworks, exceptions, err
|
||||
}
|
||||
cautils.SuccessTextDisplay("Downloaded/Loaded framework")
|
||||
|
||||
return frameworks, nil
|
||||
return frameworks, exceptions, nil
|
||||
}
|
||||
|
||||
func (policyHandler *PolicyHandler) getResources(notification *opapolicy.PolicyNotification, opaSessionObj *cautils.OPASessionObj, scanInfo *cautils.ScanInfo) (*cautils.K8SResources, error) {
|
||||
|
||||
@@ -3,25 +3,28 @@ package policyhandler
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/armosec/kubescape/cautils/getter"
|
||||
"github.com/armosec/kubescape/cautils/armotypes"
|
||||
"github.com/armosec/kubescape/cautils/opapolicy"
|
||||
)
|
||||
|
||||
func (policyHandler *PolicyHandler) GetPoliciesFromBackend(notification *opapolicy.PolicyNotification, getPolicies getter.IPolicyGetter) ([]opapolicy.Framework, error) {
|
||||
func (policyHandler *PolicyHandler) GetPoliciesFromBackend(notification *opapolicy.PolicyNotification) ([]opapolicy.Framework, []armotypes.PostureExceptionPolicy, error) {
|
||||
var errs error
|
||||
// d := getter.NewArmoAPI()
|
||||
frameworks := []opapolicy.Framework{}
|
||||
exceptionPolicies := []armotypes.PostureExceptionPolicy{}
|
||||
|
||||
// Get - cacli opa get
|
||||
for _, rule := range notification.Rules {
|
||||
switch rule.Kind {
|
||||
case opapolicy.KindFramework:
|
||||
// backend
|
||||
receivedFramework, err := getPolicies.GetFramework(rule.Name)
|
||||
receivedFramework, recExceptionPolicies, err := policyHandler.getFrameworkPolicies(rule.Name)
|
||||
if err != nil {
|
||||
errs = err
|
||||
errs = fmt.Errorf("%v\nKind: %v, Name: %s, error: %s", errs, rule.Kind, rule.Name, err.Error())
|
||||
}
|
||||
if receivedFramework != nil {
|
||||
frameworks = append(frameworks, *receivedFramework)
|
||||
if recExceptionPolicies != nil {
|
||||
exceptionPolicies = append(exceptionPolicies, recExceptionPolicies...)
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -29,5 +32,19 @@ func (policyHandler *PolicyHandler) GetPoliciesFromBackend(notification *opapoli
|
||||
errs = fmt.Errorf("%s", err.Error())
|
||||
}
|
||||
}
|
||||
return frameworks, errs
|
||||
return frameworks, exceptionPolicies, errs
|
||||
}
|
||||
|
||||
func (policyHandler *PolicyHandler) getFrameworkPolicies(policyName string) (*opapolicy.Framework, []armotypes.PostureExceptionPolicy, error) {
|
||||
receivedFramework, err := policyHandler.getters.PolicyGetter.GetFramework(policyName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
receivedException, err := policyHandler.getters.ExceptionsGetter.GetExceptions("", "", "")
|
||||
if err != nil {
|
||||
return receivedFramework, nil, err
|
||||
}
|
||||
|
||||
return receivedFramework, receivedException, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user