mirror of
https://github.com/kubescape/kubescape.git
synced 2026-04-15 06:58:11 +00:00
report v1 to v2
This commit is contained in:
+24
-12
@@ -4,25 +4,31 @@ import (
|
||||
"github.com/armosec/armoapi-go/armotypes"
|
||||
"github.com/armosec/k8s-interface/workloadinterface"
|
||||
"github.com/armosec/opa-utils/reporthandling"
|
||||
"github.com/armosec/opa-utils/reporthandling/results/v1/resourcesresults"
|
||||
reporthandlingv2 "github.com/armosec/opa-utils/reporthandling/v2"
|
||||
)
|
||||
|
||||
// K8SResources map[<api group>/<api version>/<resource>][]<resourceID>
|
||||
type K8SResources map[string][]string
|
||||
|
||||
type OPASessionObj struct {
|
||||
K8SResources *K8SResources // input k8s objects
|
||||
Frameworks []reporthandling.Framework // list of frameworks to scan
|
||||
AllResources map[string]workloadinterface.IMetadata // all scanned resources, map[<rtesource ID>]<resource>
|
||||
PostureReport *reporthandling.PostureReport // scan results
|
||||
Exceptions []armotypes.PostureExceptionPolicy // list of exceptions to apply on scan results
|
||||
RegoInputData RegoInputData // input passed to rgo for scanning. map[<control name>][<input arguments>]
|
||||
K8SResources *K8SResources // input k8s objects
|
||||
Frameworks []reporthandling.Framework // list of frameworks to scan
|
||||
AllResources map[string]workloadinterface.IMetadata // all scanned resources, map[<rtesource ID>]<resource>
|
||||
ResourcesResult map[string]resourcesresults.Result // resources scan results, map[<rtesource ID>]<resource result>
|
||||
PostureReport *reporthandling.PostureReport // scan results v1
|
||||
Report *reporthandlingv2.PostureReport // scan results v2
|
||||
Exceptions []armotypes.PostureExceptionPolicy // list of exceptions to apply on scan results
|
||||
RegoInputData RegoInputData // input passed to rgo for scanning. map[<control name>][<input arguments>]
|
||||
}
|
||||
|
||||
func NewOPASessionObj(frameworks []reporthandling.Framework, k8sResources *K8SResources) *OPASessionObj {
|
||||
return &OPASessionObj{
|
||||
Frameworks: frameworks,
|
||||
K8SResources: k8sResources,
|
||||
AllResources: make(map[string]workloadinterface.IMetadata),
|
||||
Report: &reporthandlingv2.PostureReport{},
|
||||
Frameworks: frameworks,
|
||||
K8SResources: k8sResources,
|
||||
AllResources: make(map[string]workloadinterface.IMetadata),
|
||||
ResourcesResult: make(map[string]resourcesresults.Result),
|
||||
PostureReport: &reporthandling.PostureReport{
|
||||
ClusterName: ClusterName,
|
||||
CustomerGUID: CustomerGUID,
|
||||
@@ -32,9 +38,10 @@ func NewOPASessionObj(frameworks []reporthandling.Framework, k8sResources *K8SRe
|
||||
|
||||
func NewOPASessionObjMock() *OPASessionObj {
|
||||
return &OPASessionObj{
|
||||
Frameworks: nil,
|
||||
K8SResources: nil,
|
||||
AllResources: make(map[string]workloadinterface.IMetadata),
|
||||
Frameworks: nil,
|
||||
K8SResources: nil,
|
||||
AllResources: make(map[string]workloadinterface.IMetadata),
|
||||
ResourcesResult: make(map[string]resourcesresults.Result),
|
||||
PostureReport: &reporthandling.PostureReport{
|
||||
ClusterName: "",
|
||||
CustomerGUID: "",
|
||||
@@ -60,3 +67,8 @@ type RegoInputData struct {
|
||||
// ClusterName string `json:"clusterName"`
|
||||
// K8sConfig RegoK8sConfig `json:"k8sconfig"`
|
||||
}
|
||||
|
||||
type Policies struct {
|
||||
Frameworks []string
|
||||
Controls map[string]reporthandling.Control // map[<control ID>]<control>
|
||||
}
|
||||
|
||||
@@ -1,26 +1,63 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
pkgcautils "github.com/armosec/utils-go/utils"
|
||||
|
||||
"github.com/open-policy-agent/opa/storage"
|
||||
"github.com/open-policy-agent/opa/storage/inmem"
|
||||
"github.com/open-policy-agent/opa/util"
|
||||
"github.com/armosec/opa-utils/reporthandling"
|
||||
)
|
||||
|
||||
func (data *RegoInputData) SetControlsInputs(controlsInputs map[string][]string) {
|
||||
data.PostureControlInputs = controlsInputs
|
||||
func NewPolicies() *Policies {
|
||||
return &Policies{
|
||||
Frameworks: make([]string, 0),
|
||||
Controls: make(map[string]reporthandling.Control),
|
||||
}
|
||||
}
|
||||
|
||||
func (data *RegoInputData) TOStorage() (storage.Store, error) {
|
||||
var jsonObj map[string]interface{}
|
||||
bytesData, err := json.Marshal(*data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (policies *Policies) Set(frameworks []reporthandling.Framework, version string) {
|
||||
for i := range frameworks {
|
||||
policies.Frameworks = append(policies.Frameworks, frameworks[i].Name)
|
||||
for j := range frameworks[i].Controls {
|
||||
compatibleRules := []reporthandling.PolicyRule{}
|
||||
for r := range frameworks[i].Controls[j].Rules {
|
||||
if !ruleWithArmoOpaDependency(frameworks[i].Controls[j].Rules[r].Attributes) && isRuleKubescapeVersionCompatible(frameworks[i].Controls[j].Rules[r].Attributes, version) {
|
||||
compatibleRules = append(compatibleRules, frameworks[i].Controls[j].Rules[r])
|
||||
}
|
||||
}
|
||||
frameworks[i].Controls[j].Rules = compatibleRules
|
||||
policies.Controls[frameworks[i].Controls[j].ControlID] = frameworks[i].Controls[j]
|
||||
}
|
||||
}
|
||||
// glog.Infof("RegoDependenciesData: %s", bytesData)
|
||||
if err := util.UnmarshalJSON(bytesData, &jsonObj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func ruleWithArmoOpaDependency(attributes map[string]interface{}) bool {
|
||||
if attributes == nil {
|
||||
return false
|
||||
}
|
||||
return inmem.NewFromObject(jsonObj), nil
|
||||
if s, ok := attributes["armoOpa"]; ok { // TODO - make global
|
||||
return pkgcautils.StringToBool(s.(string))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Checks that kubescape version is in range of use for this rule
|
||||
// In local build (BuildNumber = ""):
|
||||
// returns true only if rule doesn't have the "until" attribute
|
||||
func isRuleKubescapeVersionCompatible(attributes map[string]interface{}, version string) bool {
|
||||
if from, ok := attributes["useFromKubescapeVersion"]; ok && from != nil {
|
||||
if version != "" {
|
||||
if from.(string) > BuildNumber {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if until, ok := attributes["useUntilKubescapeVersion"]; ok && until != nil {
|
||||
if version != "" {
|
||||
if until.(string) <= BuildNumber {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import (
|
||||
"github.com/armosec/kubescape/cautils"
|
||||
"github.com/armosec/opa-utils/objectsenvelopes"
|
||||
"github.com/armosec/opa-utils/reporthandling"
|
||||
"github.com/armosec/opa-utils/score"
|
||||
"github.com/armosec/opa-utils/reporthandling/results/v1/resourcesresults"
|
||||
"github.com/open-policy-agent/opa/storage"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
@@ -58,41 +59,51 @@ func (opaHandler *OPAProcessorHandler) ProcessRulesListenner() {
|
||||
opaSessionObj := <-*opaHandler.processedPolicy
|
||||
opap := NewOPAProcessor(opaSessionObj, opaHandler.regoDependenciesData)
|
||||
|
||||
initializeSummaryDetails(&opap.Report.SummaryDetails, opap.Frameworks)
|
||||
|
||||
policies := ConvertFrameworksToPolicies(opap.Frameworks, cautils.BuildNumber)
|
||||
|
||||
// process
|
||||
if err := opap.Process(); err != nil {
|
||||
if err := opap.Process(policies); err != nil {
|
||||
// fmt.Println(err)
|
||||
}
|
||||
|
||||
// edit results
|
||||
opap.updateResults()
|
||||
|
||||
// update score
|
||||
scoreutil := score.NewScore(opaSessionObj.AllResources)
|
||||
scoreutil.Calculate(opaSessionObj.PostureReport.FrameworkReports)
|
||||
|
||||
// report
|
||||
*opaHandler.reportResults <- opaSessionObj
|
||||
}
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) Process() error {
|
||||
func (opap *OPAProcessor) Process(policies *cautils.Policies) error {
|
||||
// glog.Infof(fmt.Sprintf("Starting 'Process'. reportID: %s", opap.PostureReport.ReportID))
|
||||
cautils.ProgressTextDisplay(fmt.Sprintf("Scanning cluster %s", cautils.ClusterName))
|
||||
cautils.StartSpinner()
|
||||
frameworkReports := []reporthandling.FrameworkReport{}
|
||||
|
||||
var errs error
|
||||
for i := range opap.Frameworks {
|
||||
frameworkReport, err := opap.processFramework(&opap.Frameworks[i])
|
||||
for _, control := range policies.Controls {
|
||||
|
||||
resourcesAssociatedControl, err := opap.processControl(&control)
|
||||
if err != nil {
|
||||
appendError(&errs, err)
|
||||
}
|
||||
frameworkReports = append(frameworkReports, *frameworkReport)
|
||||
// update resources with latest results
|
||||
if len(resourcesAssociatedControl) != 0 {
|
||||
for resourceID, controlResult := range resourcesAssociatedControl {
|
||||
if _, ok := opap.ResourcesResult[resourceID]; !ok {
|
||||
opap.ResourcesResult[resourceID] = resourcesresults.Result{ResourceID: resourceID}
|
||||
}
|
||||
t := opap.ResourcesResult[resourceID]
|
||||
t.AssociatedControls = append(t.AssociatedControls, controlResult)
|
||||
opap.ResourcesResult[resourceID] = t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opap.PostureReport.FrameworkReports = frameworkReports
|
||||
opap.PostureReport.ReportID = uuid.NewV4().String()
|
||||
opap.PostureReport.ReportGenerationTime = time.Now().UTC()
|
||||
// glog.Infof(fmt.Sprintf("Done 'Process'. reportID: %s", opap.PostureReport.ReportID))
|
||||
opap.Report.ReportID = uuid.NewV4().String()
|
||||
opap.Report.ReportGenerationTime = time.Now().UTC()
|
||||
|
||||
cautils.StopSpinner()
|
||||
cautils.SuccessTextDisplay(fmt.Sprintf("Done scanning cluster %s", cautils.ClusterName))
|
||||
return errs
|
||||
@@ -108,62 +119,46 @@ func appendError(errs *error, err error) {
|
||||
*errs = fmt.Errorf("%v\n%s", *errs, err.Error())
|
||||
}
|
||||
}
|
||||
func (opap *OPAProcessor) processFramework(framework *reporthandling.Framework) (*reporthandling.FrameworkReport, error) {
|
||||
|
||||
func (opap *OPAProcessor) processControl(control *reporthandling.Control) (map[string]resourcesresults.ResourceAssociatedControl, error) {
|
||||
var errs error
|
||||
|
||||
frameworkReport := reporthandling.FrameworkReport{}
|
||||
frameworkReport.Name = framework.Name
|
||||
resourcesAssociatedControl := make(map[string]resourcesresults.ResourceAssociatedControl)
|
||||
|
||||
controlReports := []reporthandling.ControlReport{}
|
||||
for i := range framework.Controls {
|
||||
controlReport, err := opap.processControl(&framework.Controls[i])
|
||||
if err != nil {
|
||||
appendError(&errs, err)
|
||||
// errs = fmt.Errorf("%v\n%s", errs, err.Error())
|
||||
}
|
||||
if controlReport != nil {
|
||||
controlReports = append(controlReports, *controlReport)
|
||||
}
|
||||
}
|
||||
frameworkReport.ControlReports = controlReports
|
||||
return &frameworkReport, errs
|
||||
}
|
||||
controlResult := resourcesresults.ResourceAssociatedControl{}
|
||||
controlResult.SetID(control.ControlID)
|
||||
|
||||
func (opap *OPAProcessor) processControl(control *reporthandling.Control) (*reporthandling.ControlReport, error) {
|
||||
var errs error
|
||||
|
||||
controlReport := reporthandling.ControlReport{}
|
||||
controlReport.PortalBase = control.PortalBase
|
||||
controlReport.ControlID = control.ControlID
|
||||
controlReport.BaseScore = control.BaseScore
|
||||
|
||||
controlReport.Control_ID = control.Control_ID // TODO: delete when 'id' is deprecated
|
||||
|
||||
controlReport.Name = control.Name
|
||||
controlReport.Description = control.Description
|
||||
controlReport.Remediation = control.Remediation
|
||||
|
||||
ruleReports := []reporthandling.RuleReport{}
|
||||
// ruleResults := make(map[string][]resourcesresults.ResourceAssociatedRule)
|
||||
for i := range control.Rules {
|
||||
ruleReport, err := opap.processRule(&control.Rules[i])
|
||||
resourceAssociatedRule, err := opap.processRule(&control.Rules[i])
|
||||
if err != nil {
|
||||
appendError(&errs, err)
|
||||
}
|
||||
if ruleReport != nil {
|
||||
ruleReports = append(ruleReports, *ruleReport)
|
||||
|
||||
// append failed rules to controls
|
||||
if len(resourceAssociatedRule) != 0 {
|
||||
for resourceID, ruleResponse := range resourceAssociatedRule {
|
||||
if _, ok := resourcesAssociatedControl[resourceID]; ok {
|
||||
controlResult.ResourceAssociatedRules = resourcesAssociatedControl[resourceID].ResourceAssociatedRules
|
||||
}
|
||||
if ruleResponse != nil {
|
||||
controlResult.ResourceAssociatedRules = append(controlResult.ResourceAssociatedRules, *ruleResponse)
|
||||
}
|
||||
resourcesAssociatedControl[resourceID] = controlResult
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(ruleReports) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
controlReport.RuleReports = ruleReports
|
||||
return &controlReport, errs
|
||||
|
||||
return resourcesAssociatedControl, errs
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) processRule(rule *reporthandling.PolicyRule) (*reporthandling.RuleReport, error) {
|
||||
if ruleWithArmoOpaDependency(rule.Attributes) || !isRuleKubescapeVersionCompatible(rule) {
|
||||
return nil, nil
|
||||
}
|
||||
func (opap *OPAProcessor) processRule(rule *reporthandling.PolicyRule) (map[string]*resourcesresults.ResourceAssociatedRule, error) {
|
||||
|
||||
postureControlInputs := opap.regoDependenciesData.GetFilteredPostureControlInputs(rule.ConfigInputs) // get store
|
||||
|
||||
ruleResult := resourcesresults.ResourceAssociatedRule{}
|
||||
ruleResult.SetName(rule.Name)
|
||||
ruleResult.ControlConfigurations = postureControlInputs
|
||||
|
||||
inputResources, err := reporthandling.RegoResourcesAggregator(rule, getAllSupportedObjects(opap.K8SResources, opap.AllResources, rule))
|
||||
if err != nil {
|
||||
@@ -172,98 +167,80 @@ func (opap *OPAProcessor) processRule(rule *reporthandling.PolicyRule) (*reporth
|
||||
|
||||
inputRawResources := workloadinterface.ListMetaToMap(inputResources)
|
||||
|
||||
ruleReport, err := opap.runOPAOnSingleRule(rule, inputRawResources, ruleData)
|
||||
if err != nil {
|
||||
// ruleReport.RuleStatus.Status = reporthandling.StatusFailed
|
||||
ruleReport.RuleStatus.Status = "failure"
|
||||
ruleReport.RuleStatus.Message = err.Error()
|
||||
glog.Error(err)
|
||||
} else {
|
||||
ruleReport.RuleStatus.Status = reporthandling.StatusPassed
|
||||
}
|
||||
|
||||
resources := map[string]*resourcesresults.ResourceAssociatedRule{}
|
||||
// the failed resources are a subgroup of the enumeratedData, so we store the enumeratedData like it was the input data
|
||||
enumeratedData, err := opap.enumerateData(rule, inputRawResources)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inputResources = objectsenvelopes.ListMapToMeta(enumeratedData)
|
||||
ruleReport.ListInputKinds = workloadinterface.ListMetaIDs(inputResources)
|
||||
|
||||
for i := range inputResources {
|
||||
opap.AllResources[inputResources[i].GetID()] = inputResources[i]
|
||||
resources[inputResources[i].GetID()] = nil
|
||||
}
|
||||
|
||||
failedResources := objectsenvelopes.ListMapToMeta(ruleReport.GetFailedResources())
|
||||
for i := range failedResources {
|
||||
if r, ok := opap.AllResources[failedResources[i].GetID()]; !ok {
|
||||
opap.AllResources[failedResources[i].GetID()] = r
|
||||
}
|
||||
}
|
||||
warningResources := objectsenvelopes.ListMapToMeta(ruleReport.GetWarnignResources())
|
||||
for i := range warningResources {
|
||||
if r, ok := opap.AllResources[warningResources[i].GetID()]; !ok {
|
||||
opap.AllResources[warningResources[i].GetID()] = r
|
||||
ruleResponses, err := opap.runOPAOnSingleRule(rule, inputRawResources, ruleData, postureControlInputs)
|
||||
if err != nil {
|
||||
// TODO - Handle error
|
||||
glog.Error(err)
|
||||
} else {
|
||||
// ruleResponse to ruleResult
|
||||
for i := range ruleResponses {
|
||||
ruleResult.FailedPaths = ruleResponses[i].FailedPaths
|
||||
failedResources := objectsenvelopes.ListMapToMeta(ruleResponses[i].GetFailedResources())
|
||||
for j := range failedResources {
|
||||
resources[failedResources[j].GetID()] = &ruleResult
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove all data from responses, leave only the metadata
|
||||
keepFields := []string{"kind", "apiVersion", "metadata"}
|
||||
keepMetadataFields := []string{"name", "namespace", "labels"}
|
||||
ruleReport.RemoveData(keepFields, keepMetadataFields)
|
||||
|
||||
return &ruleReport, err
|
||||
return resources, err
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) runOPAOnSingleRule(rule *reporthandling.PolicyRule, k8sObjects []map[string]interface{}, getRuleData func(*reporthandling.PolicyRule) string) (reporthandling.RuleReport, error) {
|
||||
func (opap *OPAProcessor) runOPAOnSingleRule(rule *reporthandling.PolicyRule, k8sObjects []map[string]interface{}, getRuleData func(*reporthandling.PolicyRule) string, postureControlInputs map[string][]string) ([]reporthandling.RuleResponse, error) {
|
||||
switch rule.RuleLanguage {
|
||||
case reporthandling.RegoLanguage, reporthandling.RegoLanguage2:
|
||||
return opap.runRegoOnK8s(rule, k8sObjects, getRuleData)
|
||||
return opap.runRegoOnK8s(rule, k8sObjects, getRuleData, postureControlInputs)
|
||||
default:
|
||||
return reporthandling.RuleReport{}, fmt.Errorf("rule: '%s', language '%v' not supported", rule.Name, rule.RuleLanguage)
|
||||
return nil, fmt.Errorf("rule: '%s', language '%v' not supported", rule.Name, rule.RuleLanguage)
|
||||
}
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) runRegoOnK8s(rule *reporthandling.PolicyRule, k8sObjects []map[string]interface{}, getRuleData func(*reporthandling.PolicyRule) string) (reporthandling.RuleReport, error) {
|
||||
func (opap *OPAProcessor) runRegoOnK8s(rule *reporthandling.PolicyRule, k8sObjects []map[string]interface{}, getRuleData func(*reporthandling.PolicyRule) string, postureControlInputs map[string][]string) ([]reporthandling.RuleResponse, error) {
|
||||
var errs error
|
||||
ruleReport := reporthandling.RuleReport{
|
||||
Name: rule.Name,
|
||||
}
|
||||
|
||||
// compile modules
|
||||
modules, err := getRuleDependencies()
|
||||
if err != nil {
|
||||
return ruleReport, fmt.Errorf("rule: '%s', %s", rule.Name, err.Error())
|
||||
return nil, fmt.Errorf("rule: '%s', %s", rule.Name, err.Error())
|
||||
}
|
||||
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())
|
||||
return nil, fmt.Errorf("in 'runRegoOnSingleRule', failed to compile rule, name: %s, reason: %s", rule.Name, err.Error())
|
||||
}
|
||||
|
||||
store, err := resources.TOStorage(postureControlInputs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Eval
|
||||
results, err := opap.regoEval(k8sObjects, compiled)
|
||||
results, err := opap.regoEval(k8sObjects, compiled, &store)
|
||||
if err != nil {
|
||||
errs = fmt.Errorf("rule: '%s', %s", rule.Name, err.Error())
|
||||
}
|
||||
|
||||
if results != nil {
|
||||
ruleReport.RuleResponses = append(ruleReport.RuleResponses, results...)
|
||||
}
|
||||
return ruleReport, errs
|
||||
return results, errs
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) regoEval(inputObj []map[string]interface{}, compiledRego *ast.Compiler) ([]reporthandling.RuleResponse, error) {
|
||||
store, err := opap.regoDependenciesData.TOStorage() // get store
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (opap *OPAProcessor) regoEval(inputObj []map[string]interface{}, compiledRego *ast.Compiler, store *storage.Store) ([]reporthandling.RuleResponse, error) {
|
||||
// opap.regoDependenciesData.PostureControlInputs
|
||||
|
||||
rego := rego.New(
|
||||
rego.Query("data.armo_builtins"), // get package name from rule
|
||||
rego.Compiler(compiledRego),
|
||||
rego.Input(inputObj),
|
||||
rego.Store(store),
|
||||
rego.Store(*store),
|
||||
)
|
||||
|
||||
// Run evaluation
|
||||
@@ -284,9 +261,15 @@ func (opap *OPAProcessor) enumerateData(rule *reporthandling.PolicyRule, k8sObje
|
||||
if ruleEnumeratorData(rule) == "" {
|
||||
return k8sObjects, nil
|
||||
}
|
||||
ruleReport, err := opap.runOPAOnSingleRule(rule, k8sObjects, ruleEnumeratorData)
|
||||
postureControlInputs := opap.regoDependenciesData.GetFilteredPostureControlInputs(rule.ConfigInputs)
|
||||
|
||||
ruleResponse, err := opap.runOPAOnSingleRule(rule, k8sObjects, ruleEnumeratorData, postureControlInputs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ruleReport.GetFailedResources(), nil
|
||||
failedResources := []map[string]interface{}{}
|
||||
for _, ruleResponse := range ruleResponse {
|
||||
failedResources = append(failedResources, ruleResponse.GetFailedResources()...)
|
||||
}
|
||||
return failedResources, nil
|
||||
}
|
||||
|
||||
@@ -30,11 +30,13 @@ func TestProcess(t *testing.T) {
|
||||
// set opaSessionObj
|
||||
opaSessionObj := cautils.NewOPASessionObjMock()
|
||||
opaSessionObj.Frameworks = []reporthandling.Framework{*reporthandling.MockFrameworkA()}
|
||||
policies := ConvertFrameworksToPolicies(opaSessionObj.Frameworks, "")
|
||||
|
||||
opaSessionObj.K8SResources = &k8sResources
|
||||
opaSessionObj.AllResources = allResources
|
||||
|
||||
opap := NewOPAProcessor(opaSessionObj, resources.NewRegoDependenciesDataMock())
|
||||
opap.Process()
|
||||
opap.Process(policies)
|
||||
opap.updateResults()
|
||||
for _, f := range opap.PostureReport.FrameworkReports {
|
||||
for _, c := range f.ControlReports {
|
||||
|
||||
@@ -7,29 +7,53 @@ 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"
|
||||
)
|
||||
|
||||
// updateResults update the results objects and report objects. This is a critical function - DO NOT CHANGE
|
||||
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 exceptions
|
||||
for i := range opap.ResourcesResult {
|
||||
|
||||
// set counters
|
||||
reporthandling.SetUniqueResourcesCounter(&opap.PostureReport.FrameworkReports[f])
|
||||
t := opap.ResourcesResult[i]
|
||||
|
||||
// set default score
|
||||
// reporthandling.SetDefaultScore(&opap.PostureReport.FrameworkReports[f])
|
||||
// first set exceptions
|
||||
if resource, ok := opap.AllResources[i]; ok {
|
||||
t.SetExceptions(resource, opap.Exceptions, cautils.ClusterName)
|
||||
}
|
||||
|
||||
// summarize the resources
|
||||
opap.Report.AppendResourceResultToSummary(&t)
|
||||
|
||||
// Add score
|
||||
// TODO
|
||||
|
||||
// save changes
|
||||
opap.ResourcesResult[i] = t
|
||||
}
|
||||
|
||||
// set result summary
|
||||
opap.Report.SummaryDetails.InitResourcesSummary()
|
||||
|
||||
// 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 getAllSupportedObjects(k8sResources *cautils.K8SResources, allResources map[string]workloadinterface.IMetadata, rule *reporthandling.PolicyRule) []workloadinterface.IMetadata {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package opaprocessor
|
||||
|
||||
import (
|
||||
"github.com/armosec/kubescape/cautils"
|
||||
"github.com/armosec/opa-utils/reporthandling"
|
||||
"github.com/armosec/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
)
|
||||
|
||||
// ConvertFrameworksToPolicies convert list of frameworks to list of policies
|
||||
func ConvertFrameworksToPolicies(frameworks []reporthandling.Framework, version string) *cautils.Policies {
|
||||
policies := cautils.NewPolicies()
|
||||
policies.Set(frameworks, version)
|
||||
return policies
|
||||
}
|
||||
|
||||
// initializeReport initialize the summary details for the report object
|
||||
func initializeSummaryDetails(summaryDetails *reportsummary.SummaryDetails, frameworks []reporthandling.Framework) {
|
||||
|
||||
for i := range frameworks {
|
||||
controls := map[string]reportsummary.ControlSummary{}
|
||||
for j := range frameworks[i].Controls {
|
||||
id := frameworks[i].Controls[j].ControlID
|
||||
c := reportsummary.ControlSummary{
|
||||
Name: frameworks[i].Controls[j].Name,
|
||||
}
|
||||
controls[frameworks[i].Controls[j].ControlID] = c
|
||||
summaryDetails.Controls[id] = c
|
||||
}
|
||||
summaryDetails.Frameworks = append(summaryDetails.Frameworks, reportsummary.FrameworkSummary{
|
||||
Name: frameworks[i].Name,
|
||||
Controls: controls,
|
||||
})
|
||||
}
|
||||
|
||||
// opap.Report.GenerateSummary()
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/armosec/kubescape/resultshandling/printer"
|
||||
"github.com/armosec/kubescape/resultshandling/reporter"
|
||||
"github.com/armosec/opa-utils/reporthandling"
|
||||
v1 "github.com/armosec/opa-utils/reporthandling/helpers/v1"
|
||||
"github.com/armosec/opa-utils/score"
|
||||
)
|
||||
|
||||
type ResultsHandler struct {
|
||||
@@ -27,6 +29,8 @@ func (resultsHandler *ResultsHandler) HandleResults(scanInfo *cautils.ScanInfo)
|
||||
|
||||
opaSessionObj := <-*resultsHandler.opaSessionObj
|
||||
|
||||
resultsHandler.reportV2ToV1(opaSessionObj)
|
||||
|
||||
resultsHandler.printerObj.ActionPrint(opaSessionObj)
|
||||
|
||||
if err := resultsHandler.reporterObj.ActionSendReport(opaSessionObj); err != nil {
|
||||
@@ -55,3 +59,94 @@ func CalculatePostureScore(postureReport *reporthandling.PostureReport) float32
|
||||
|
||||
return (float32(len(allResources)) - float32(len(failedResources))) / float32(len(allResources))
|
||||
}
|
||||
|
||||
func (resultsHandler *ResultsHandler) reportV2ToV1(opaSessionObj *cautils.OPASessionObj) {
|
||||
opaSessionObj.PostureReport.ReportID = opaSessionObj.Report.ReportID
|
||||
opaSessionObj.PostureReport.CustomerGUID = opaSessionObj.Report.CustomerGUID
|
||||
opaSessionObj.PostureReport.ClusterCloudProvider = opaSessionObj.Report.ClusterCloudProvider
|
||||
opaSessionObj.PostureReport.ClusterName = opaSessionObj.Report.ClusterName
|
||||
|
||||
frameworks := []reporthandling.FrameworkReport{}
|
||||
fwv1 := reporthandling.FrameworkReport{}
|
||||
for _, fwv2 := range opaSessionObj.Report.SummaryDetails.Frameworks {
|
||||
fwv1.Name = fwv2.GetName()
|
||||
fwv1.Score = fwv2.GetScore()
|
||||
fwv1.WarningResources = fwv2.NumberOf().Excluded()
|
||||
fwv1.FailedResources = fwv2.NumberOf().Failed()
|
||||
fwv1.TotalResources = fwv2.NumberOf().All()
|
||||
|
||||
crv1 := reporthandling.ControlReport{}
|
||||
for _, crv2 := range fwv2.Controls {
|
||||
crv1.ControlID = crv2.GetID()
|
||||
crv1.Name = crv2.GetName()
|
||||
crv1.Score = crv2.GetScore()
|
||||
crv1.WarningResources = crv2.NumberOf().Excluded()
|
||||
crv1.FailedResources = crv2.NumberOf().Failed()
|
||||
crv1.TotalResources = crv2.NumberOf().All()
|
||||
|
||||
// TODO - add fields
|
||||
// crv1.Description
|
||||
// crv1.GUID
|
||||
// crv1.Remediation
|
||||
|
||||
rulesv1 := map[string]reporthandling.RuleReport{} // ruleName: rules
|
||||
for _, resourceID := range crv2.List().All() {
|
||||
if resource, ok := opaSessionObj.ResourcesResult[resourceID]; ok {
|
||||
for _, rulev2 := range resource.ListRules() {
|
||||
if _, ok := rulesv1[rulev2.GetName()]; !ok {
|
||||
rulesv1[rulev2.GetName()] = reporthandling.RuleReport{}
|
||||
}
|
||||
rulev1 := reporthandling.RuleReport{}
|
||||
rulev1.Name = rulev2.GetName()
|
||||
// rulev1.Remediation
|
||||
rulev1.ResourceUniqueCounter.TotalResources++
|
||||
if rulev2.GetStatus(&v1.Filters{FrameworkNames: []string{fwv2.GetName()}}).IsFailed() {
|
||||
rulev1.ResourceUniqueCounter.FailedResources++
|
||||
} else if rulev2.GetStatus(&v1.Filters{FrameworkNames: []string{fwv2.GetName()}}).IsExcluded() {
|
||||
rulev1.ResourceUniqueCounter.WarningResources++
|
||||
}
|
||||
ruleResponse := reporthandling.RuleResponse{}
|
||||
ruleResponse.Rulename = rulev2.GetName()
|
||||
ruleResponse.FailedPaths = rulev2.FailedPaths
|
||||
ruleResponse.RuleStatus = string(rulev2.GetStatus(&v1.Filters{FrameworkNames: []string{fwv2.GetName()}}).Status())
|
||||
if len(rulev2.Exception) > 0 {
|
||||
ruleResponse.Exception = &rulev2.Exception[0]
|
||||
}
|
||||
|
||||
if fullRessource, ok := opaSessionObj.AllResources[resourceID]; ok {
|
||||
ruleResponse.AlertObject.K8SApiObjects = append(ruleResponse.AlertObject.K8SApiObjects, fullRessource.GetObject())
|
||||
}
|
||||
rulev1.RuleResponses = append(rulev1.RuleResponses, ruleResponse)
|
||||
rulev1.ListInputKinds = append(rulev1.ListInputKinds, resourceID)
|
||||
crv1.RuleReports = append(crv1.RuleReports, rulev1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rulev1.ListInputKinds
|
||||
|
||||
}
|
||||
fwv1.ControlReports = append(fwv1.ControlReports, crv1)
|
||||
|
||||
frameworks = append(frameworks, fwv1)
|
||||
|
||||
}
|
||||
|
||||
for f := range frameworks {
|
||||
// // 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(&frameworks[f])
|
||||
}
|
||||
|
||||
// update score
|
||||
scoreutil := score.NewScore(opaSessionObj.AllResources)
|
||||
scoreutil.Calculate(frameworks)
|
||||
|
||||
opaSessionObj.PostureReport.FrameworkReports = frameworks
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user