mirror of
https://github.com/kubescape/kubescape.git
synced 2026-02-14 18:09:55 +00:00
junit format
This commit is contained in:
@@ -17,16 +17,22 @@ RUN pip3 install --no-cache --upgrade pip setuptools
|
||||
|
||||
WORKDIR /work
|
||||
ADD . .
|
||||
WORKDIR /work/httphandler
|
||||
|
||||
# build kubescape server
|
||||
WORKDIR /work/httphandler
|
||||
RUN python build.py
|
||||
RUN ls -ltr build/ubuntu-latest
|
||||
|
||||
# build kubescape cmd
|
||||
WORKDIR /work/cmd
|
||||
RUN python build.py
|
||||
|
||||
RUN ls -ltr build/ubuntu-latest
|
||||
RUN /work/build/ubuntu-latest/kubescape download artifacts -o /work/artifacts
|
||||
|
||||
FROM alpine
|
||||
COPY --from=builder /work/httphandler/build/ubuntu-latest/kubescape /usr/bin/kubescape
|
||||
|
||||
# # Download the frameworks. Use the "--use-default" flag when running kubescape
|
||||
# RUN kubescape download framework nsa && kubescape download framework mitre
|
||||
RUN mkdir $HOME/.kubescape && chmod 777 -R $HOME/.kubescape
|
||||
COPY --from=builder /work/artifacts/ $HOME/.kubescape
|
||||
|
||||
ENTRYPOINT ["kubescape"]
|
||||
|
||||
@@ -133,15 +133,6 @@ func (scanInfo *ScanInfo) setUseArtifactsFrom() {
|
||||
scanInfo.UseExceptions = filepath.Join(scanInfo.UseArtifactsFrom, localExceptionsFilename)
|
||||
}
|
||||
|
||||
func (scanInfo *ScanInfo) setUseExceptions() {
|
||||
if scanInfo.UseExceptions != "" {
|
||||
// load exceptions from file
|
||||
scanInfo.ExceptionsGetter = getter.NewLoadPolicy([]string{scanInfo.UseExceptions})
|
||||
} else {
|
||||
scanInfo.ExceptionsGetter = getter.GetArmoAPIConnector()
|
||||
}
|
||||
}
|
||||
|
||||
func (scanInfo *ScanInfo) setUseFrom() {
|
||||
if scanInfo.UseDefault {
|
||||
for _, policy := range scanInfo.PolicyIdentifier {
|
||||
|
||||
@@ -2,6 +2,7 @@ package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -30,6 +31,9 @@ func DownloadSupportCommands() []string {
|
||||
|
||||
func (ks *Kubescape) Download(downloadInfo *metav1.DownloadInfo) error {
|
||||
setPathandFilename(downloadInfo)
|
||||
if err := os.MkdirAll(downloadInfo.Path, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := downloadArtifact(downloadInfo, downloadFunc); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -86,6 +90,9 @@ func downloadConfigInputs(downloadInfo *metav1.DownloadInfo) error {
|
||||
if downloadInfo.FileName == "" {
|
||||
downloadInfo.FileName = fmt.Sprintf("%s.json", downloadInfo.Target)
|
||||
}
|
||||
if controlInputs == nil {
|
||||
return fmt.Errorf("failed to download controlInputs - received an empty objects")
|
||||
}
|
||||
// save in file
|
||||
err = getter.SaveInFile(controlInputs, filepath.Join(downloadInfo.Path, downloadInfo.FileName))
|
||||
if err != nil {
|
||||
@@ -148,6 +155,9 @@ func downloadFramework(downloadInfo *metav1.DownloadInfo) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if framework == nil {
|
||||
return fmt.Errorf("failed to download framework - received an empty objects")
|
||||
}
|
||||
downloadTo := filepath.Join(downloadInfo.Path, downloadInfo.FileName)
|
||||
err = getter.SaveInFile(framework, downloadTo)
|
||||
if err != nil {
|
||||
@@ -175,6 +185,9 @@ func downloadControl(downloadInfo *metav1.DownloadInfo) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if controls == nil {
|
||||
return fmt.Errorf("failed to download control - received an empty objects")
|
||||
}
|
||||
downloadTo := filepath.Join(downloadInfo.Path, downloadInfo.FileName)
|
||||
err = getter.SaveInFile(controls, downloadTo)
|
||||
if err != nil {
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.17
|
||||
require (
|
||||
github.com/armosec/armoapi-go v0.0.58
|
||||
github.com/armosec/k8s-interface v0.0.68
|
||||
github.com/armosec/opa-utils v0.0.116
|
||||
github.com/armosec/opa-utils v0.0.118
|
||||
github.com/armosec/rbac-utils v0.0.14
|
||||
github.com/armosec/utils-go v0.0.3
|
||||
github.com/armosec/utils-k8s-go v0.0.3
|
||||
|
||||
@@ -109,8 +109,8 @@ github.com/armosec/k8s-interface v0.0.66/go.mod h1:vwprS8qn/iowd5yf0JHpqDsLA5I8W
|
||||
github.com/armosec/k8s-interface v0.0.68 h1:6CtSakISiI47YHkxh+Va9FzZQIBkWa6g9sbiNxq1Zkk=
|
||||
github.com/armosec/k8s-interface v0.0.68/go.mod h1:PeWn41C2uenZi+xfZdyFF/zG5wXACA00htQyknDUWDE=
|
||||
github.com/armosec/opa-utils v0.0.64/go.mod h1:6tQP8UDq2EvEfSqh8vrUdr/9QVSCG4sJfju1SXQOn4c=
|
||||
github.com/armosec/opa-utils v0.0.116 h1:3oWuhcpI+MJD/CktEStU1BA0feGNwsCbQrI3ifVfzMs=
|
||||
github.com/armosec/opa-utils v0.0.116/go.mod h1:gap+EaLG5rnyqvIRGxtdNDC9y7VvoGNm90zK8Ls7avQ=
|
||||
github.com/armosec/opa-utils v0.0.118 h1:ZX1crwVQmo+sDv+jmTNLbDYfApUBzlgPhD8QI2GCJX0=
|
||||
github.com/armosec/opa-utils v0.0.118/go.mod h1:gap+EaLG5rnyqvIRGxtdNDC9y7VvoGNm90zK8Ls7avQ=
|
||||
github.com/armosec/rbac-utils v0.0.1/go.mod h1:pQ8CBiij8kSKV7aeZm9FMvtZN28VgA7LZcYyTWimq40=
|
||||
github.com/armosec/rbac-utils v0.0.14 h1:CKYKcgqJEXWF2Hen/B1pVGtS3nDAG1wp9dDv6oNtq90=
|
||||
github.com/armosec/rbac-utils v0.0.14/go.mod h1:Ex/IdGWhGv9HZq6Hs8N/ApzCKSIvpNe/ETqDfnuyah0=
|
||||
|
||||
@@ -112,10 +112,10 @@ func TestProcessResourcesResult(t *testing.T) {
|
||||
assert.Equal(t, 0, len(summaryDetails.ListResourcesIDs().Passed()))
|
||||
|
||||
// test control listing
|
||||
assert.Equal(t, len(res.ListControlsIDs(nil).All()), len(summaryDetails.ListControls().All()))
|
||||
assert.Equal(t, len(res.ListControlsIDs(nil).Passed()), len(summaryDetails.ListControls().Passed()))
|
||||
assert.Equal(t, len(res.ListControlsIDs(nil).Failed()), len(summaryDetails.ListControls().Failed()))
|
||||
assert.Equal(t, len(res.ListControlsIDs(nil).Excluded()), len(summaryDetails.ListControls().Excluded()))
|
||||
assert.Equal(t, len(res.ListControlsIDs(nil).All()), summaryDetails.NumberOfControls().All())
|
||||
assert.Equal(t, len(res.ListControlsIDs(nil).Passed()), summaryDetails.NumberOfControls().Passed())
|
||||
assert.Equal(t, len(res.ListControlsIDs(nil).Failed()), summaryDetails.NumberOfControls().Failed())
|
||||
assert.Equal(t, len(res.ListControlsIDs(nil).Excluded()), summaryDetails.NumberOfControls().Excluded())
|
||||
assert.True(t, summaryDetails.GetStatus().IsFailed())
|
||||
|
||||
opaSessionObj.Exceptions = []armotypes.PostureExceptionPolicy{*mocks.MockExceptionAllKinds(&armotypes.PosturePolicy{FrameworkName: frameworks[0].Name})}
|
||||
|
||||
@@ -128,7 +128,7 @@ func listTestsSuite(results *cautils.OPASessionObj) []JUnitTestSuite {
|
||||
var testSuites []JUnitTestSuite
|
||||
|
||||
// control scan
|
||||
if len(results.Report.SummaryDetails.ListFrameworks().All()) == 0 {
|
||||
if len(results.Report.SummaryDetails.ListFrameworks()) == 0 {
|
||||
testSuite := JUnitTestSuite{}
|
||||
testSuite.Failures = results.Report.SummaryDetails.NumberOfControls().Failed()
|
||||
testSuite.Timestamp = results.Report.ReportGenerationTime.String()
|
||||
@@ -147,7 +147,7 @@ func listTestsSuite(results *cautils.OPASessionObj) []JUnitTestSuite {
|
||||
testSuite.ID = i
|
||||
testSuite.Name = f.Name
|
||||
testSuite.Properties = properties(f.Score)
|
||||
testSuite.TestCases = testsCases(results, f.ListControls(), f.GetName())
|
||||
testSuite.TestCases = testsCases(results, f.GetControls(), f.GetName())
|
||||
testSuites = append(testSuites, testSuite)
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ func testsCases(results *cautils.OPASessionObj, controls reportsummary.IControls
|
||||
testCaseFailure := JUnitFailure{}
|
||||
testCaseFailure.Type = "Control"
|
||||
// testCaseFailure.Contents =
|
||||
testCaseFailure.Message = fmt.Sprintf("Remediation: %s\nMore details: %s\n\n%s", control.GetRemediation(), getControlURL(control.GetID()), strings.Join(resourcesStr, "\n"))
|
||||
testCaseFailure.Message = fmt.Sprintf("Remediation: %s\nMore details: %s\n\n%s", control.GetRemediation(), getControlLink(control.GetID()), strings.Join(resourcesStr, "\n"))
|
||||
|
||||
testCase.Failure = &testCaseFailure
|
||||
} else if control.GetStatus().IsSkipped() {
|
||||
|
||||
@@ -60,7 +60,7 @@ func (pdfPrinter *PdfPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj)
|
||||
|
||||
m := pdf.NewMaroto(consts.Portrait, consts.A4)
|
||||
pdfPrinter.printHeader(m)
|
||||
pdfPrinter.printFramework(m, opaSessionObj.Report.SummaryDetails.ListFrameworks().All())
|
||||
pdfPrinter.printFramework(m, opaSessionObj.Report.SummaryDetails.ListFrameworks())
|
||||
pdfPrinter.printTable(m, &opaSessionObj.Report.SummaryDetails)
|
||||
pdfPrinter.printFinalResult(m, &opaSessionObj.Report.SummaryDetails)
|
||||
|
||||
@@ -115,7 +115,7 @@ func (pdfPrinter *PdfPrinter) printHeader(m pdf.Maroto) {
|
||||
}
|
||||
|
||||
// Print pdf frameworks after pdf header.
|
||||
func (pdfPrinter *PdfPrinter) printFramework(m pdf.Maroto, frameworks []reportsummary.IPolicies) {
|
||||
func (pdfPrinter *PdfPrinter) printFramework(m pdf.Maroto, frameworks []reportsummary.IFrameworkSummary) {
|
||||
m.Row(10, func() {
|
||||
m.Text(frameworksScoresToString(frameworks), props.Text{
|
||||
Align: consts.Center,
|
||||
|
||||
@@ -75,7 +75,7 @@ func (prettyPrinter *PrettyPrinter) printSummary(controlName string, controlSumm
|
||||
|
||||
}
|
||||
func (prettyPrinter *PrettyPrinter) printTitle(controlSummary reportsummary.IControlSummary) {
|
||||
cautils.InfoDisplay(prettyPrinter.writer, "[control: %s - %s] ", controlSummary.GetName(), getControlURL(controlSummary.GetID()))
|
||||
cautils.InfoDisplay(prettyPrinter.writer, "[control: %s - %s] ", controlSummary.GetName(), getControlLink(controlSummary.GetID()))
|
||||
switch controlSummary.GetStatus().Status() {
|
||||
case apis.StatusSkipped:
|
||||
cautils.InfoDisplay(prettyPrinter.writer, "skipped %v\n", emoji.ConfusedFace)
|
||||
@@ -188,10 +188,10 @@ func (prettyPrinter *PrettyPrinter) printSummaryTable(summaryDetails *reportsumm
|
||||
summaryTable.Render()
|
||||
|
||||
// For control scan framework will be nil
|
||||
cautils.InfoTextDisplay(prettyPrinter.writer, frameworksScoresToString(summaryDetails.ListFrameworks().All()))
|
||||
cautils.InfoTextDisplay(prettyPrinter.writer, frameworksScoresToString(summaryDetails.ListFrameworks()))
|
||||
}
|
||||
|
||||
func frameworksScoresToString(frameworks []reportsummary.IPolicies) string {
|
||||
func frameworksScoresToString(frameworks []reportsummary.IFrameworkSummary) string {
|
||||
if len(frameworks) == 1 {
|
||||
if frameworks[0].GetName() != "" {
|
||||
return fmt.Sprintf("FRAMEWORK %s\n", frameworks[0].GetName())
|
||||
@@ -217,6 +217,6 @@ func frameworksScoresToString(frameworks []reportsummary.IPolicies) string {
|
||||
// sort.Strings(controlNames)
|
||||
// return controlNames
|
||||
// }
|
||||
func getControlURL(controlID string) string {
|
||||
func getControlLink(controlID string) string {
|
||||
return fmt.Sprintf("https://hub.armo.cloud/docs/%s", strings.ToLower(controlID))
|
||||
}
|
||||
|
||||
55
core/pkg/resultshandling/printer/v2/prometheus.go
Normal file
55
core/pkg/resultshandling/printer/v2/prometheus.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/armosec/k8s-interface/workloadinterface"
|
||||
"github.com/armosec/kubescape/core/cautils"
|
||||
"github.com/armosec/kubescape/core/cautils/logger"
|
||||
"github.com/armosec/kubescape/core/cautils/logger/helpers"
|
||||
"github.com/armosec/kubescape/core/pkg/resultshandling/printer"
|
||||
"github.com/armosec/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
"github.com/armosec/opa-utils/reporthandling/results/v1/resourcesresults"
|
||||
)
|
||||
|
||||
type PrometheusPrinter struct {
|
||||
writer *os.File
|
||||
verboseMode bool
|
||||
}
|
||||
|
||||
func NewPrometheusPrinter(verboseMode bool) *PrometheusPrinter {
|
||||
return &PrometheusPrinter{
|
||||
verboseMode: verboseMode,
|
||||
}
|
||||
}
|
||||
|
||||
func (prometheusPrinter *PrometheusPrinter) SetWriter(outputFile string) {
|
||||
prometheusPrinter.writer = printer.GetWriter(outputFile)
|
||||
}
|
||||
|
||||
func (prometheusPrinter *PrometheusPrinter) Score(score float32) {
|
||||
fmt.Printf("\n# Overall risk-score (0- Excellent, 100- All failed)\nkubescape_score %d\n", int(score))
|
||||
}
|
||||
|
||||
func (printer *PrometheusPrinter) generatePrometheusFormat(
|
||||
resources map[string]workloadinterface.IMetadata,
|
||||
results map[string]resourcesresults.Result,
|
||||
summaryDetails *reportsummary.SummaryDetails) *Metrics {
|
||||
|
||||
m := &Metrics{}
|
||||
m.setRiskScores(summaryDetails)
|
||||
m.setResourcesCounters(resources, results)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (printer *PrometheusPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) {
|
||||
|
||||
metrics := printer.generatePrometheusFormat(opaSessionObj.AllResources, opaSessionObj.ResourcesResult, &opaSessionObj.Report.SummaryDetails)
|
||||
|
||||
logOUtputFile(printer.writer.Name())
|
||||
if _, err := printer.writer.Write([]byte(metrics.String())); err != nil {
|
||||
logger.L().Error("failed to write results", helpers.Error(err))
|
||||
}
|
||||
}
|
||||
248
core/pkg/resultshandling/printer/v2/prometheusutils.go
Normal file
248
core/pkg/resultshandling/printer/v2/prometheusutils.go
Normal file
@@ -0,0 +1,248 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/armosec/k8s-interface/workloadinterface"
|
||||
"github.com/armosec/opa-utils/reporthandling/apis"
|
||||
"github.com/armosec/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
"github.com/armosec/opa-utils/reporthandling/results/v1/resourcesresults"
|
||||
)
|
||||
|
||||
type metricsName string
|
||||
|
||||
const (
|
||||
metricsFrameworkScore metricsName = "kubescape_risk_score_framework"
|
||||
metricsControlScore metricsName = "kubescape_risk_score_control"
|
||||
metricsScore metricsName = "kubescape_risk_score"
|
||||
metricsresourceFailed metricsName = "kubescape_resource_controls_number_of_failed"
|
||||
metricsresourcePassed metricsName = "kubescape_resource_controls_number_of_passed"
|
||||
metricsresourceExcluded metricsName = "kubescape_resource_controls_number_of_exclude"
|
||||
)
|
||||
|
||||
func (mrs *mRiskScore) string() string {
|
||||
r := fmt.Sprintf("resourcesCountPassed: \"%d\"", mrs.resourcesCountPassed) + ", "
|
||||
r += fmt.Sprintf("resourcesCountFailed: \"%d\"", mrs.resourcesCountFailed) + ", "
|
||||
r += fmt.Sprintf("resourcesCountExcluded: \"%d\"", mrs.resourcesCountExcluded) + ", "
|
||||
r += fmt.Sprintf("controlsCountPassed: \"%d\"", mrs.controlsCountPassed) + ", "
|
||||
r += fmt.Sprintf("controlsCountExcluded: \"%d\"", mrs.controlsCountExcluded) + ", "
|
||||
r += fmt.Sprintf("controlsCountSkipped: \"%d\"", mrs.controlsCountSkipped) + ", "
|
||||
r += fmt.Sprintf("controlsCountFailed: \"%d\"", mrs.controlsCountFailed)
|
||||
return r
|
||||
}
|
||||
func (mrs *mRiskScore) value() int {
|
||||
return mrs.riskScore
|
||||
}
|
||||
|
||||
func (mcrs *mControlRiskScore) string() string {
|
||||
r := fmt.Sprintf("controlName: \"%s\"", mcrs.controlName) + ", "
|
||||
r += fmt.Sprintf("controlID: \"%s\"", mcrs.controlID) + ", "
|
||||
r += fmt.Sprintf("link: \"%s\"", mcrs.link) + ", "
|
||||
r += fmt.Sprintf("severity: \"%s\"", mcrs.severity) + ", "
|
||||
r += fmt.Sprintf("remediation: \"%s\"", mcrs.remediation) + ", "
|
||||
r += fmt.Sprintf("resourcesCountPassed: \"%d\"", mcrs.resourcesCountPassed) + ", "
|
||||
r += fmt.Sprintf("resourcesCountFailed: \"%d\"", mcrs.resourcesCountFailed) + ", "
|
||||
r += fmt.Sprintf("resourcesCountExcluded: \"%d\"", mcrs.resourcesCountExcluded)
|
||||
return r
|
||||
}
|
||||
func (mcrs *mControlRiskScore) value() int {
|
||||
return mcrs.riskScore
|
||||
}
|
||||
|
||||
func (mfrs *mFrameworkRiskScore) string() string {
|
||||
r := fmt.Sprintf("frameworkName: \"%s\"", mfrs.frameworkName) + ", "
|
||||
r += fmt.Sprintf("resourcesCountPassed: \"%d\"", mfrs.resourcesCountPassed) + ", "
|
||||
r += fmt.Sprintf("resourcesCountFailed: \"%d\"", mfrs.resourcesCountFailed) + ", "
|
||||
r += fmt.Sprintf("resourcesCountExcluded: \"%d\"", mfrs.resourcesCountExcluded) + ", "
|
||||
r += fmt.Sprintf("controlsCountPassed: \"%d\"", mfrs.controlsCountPassed) + ", "
|
||||
r += fmt.Sprintf("controlsCountExcluded: \"%d\"", mfrs.controlsCountExcluded) + ", "
|
||||
r += fmt.Sprintf("controlsCountSkipped: \"%d\"", mfrs.controlsCountSkipped) + ", "
|
||||
r += fmt.Sprintf("controlsCountFailed: \"%d\"", mfrs.controlsCountFailed)
|
||||
return r
|
||||
}
|
||||
func (mfrs *mFrameworkRiskScore) value() int {
|
||||
return mfrs.riskScore
|
||||
}
|
||||
func (mrc *mResourceControls) string() string {
|
||||
r := fmt.Sprintf("name: \"%s\"", mrc.name) + ", "
|
||||
r += fmt.Sprintf("controlID: \"%s\"", mrc.namespace) + ", "
|
||||
r += fmt.Sprintf("link: \"%s\"", mrc.apiVersion) + ", "
|
||||
r += fmt.Sprintf("severity: \"%s\"", mrc.kind)
|
||||
return r
|
||||
}
|
||||
func (mrc *mResourceControls) value() int {
|
||||
return mrc.controls
|
||||
}
|
||||
func toRowInMetrics(name metricsName, row string, value int) string {
|
||||
return fmt.Sprintf("%s{%s} %d\n", name, row, value)
|
||||
|
||||
}
|
||||
func (m *Metrics) String() string {
|
||||
|
||||
r := toRowInMetrics(metricsScore, m.rs.string(), m.rs.value())
|
||||
for i := range m.listControls {
|
||||
r += toRowInMetrics(metricsScore, m.listControls[i].string(), m.listControls[i].value())
|
||||
}
|
||||
for i := range m.listFrameworks {
|
||||
r += toRowInMetrics(metricsScore, m.listFrameworks[i].string(), m.listFrameworks[i].value())
|
||||
}
|
||||
for i := range m.listResourcesControlsExcluded {
|
||||
r += toRowInMetrics(metricsScore, m.listResourcesControlsExcluded[i].string(), m.listResourcesControlsExcluded[i].value())
|
||||
}
|
||||
for i := range m.listResourcesControlsFiled {
|
||||
r += toRowInMetrics(metricsScore, m.listResourcesControlsFiled[i].string(), m.listResourcesControlsFiled[i].value())
|
||||
}
|
||||
for i := range m.listResourcesControlsPassed {
|
||||
r += toRowInMetrics(metricsScore, m.listResourcesControlsPassed[i].string(), m.listResourcesControlsPassed[i].value())
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
type mRiskScore struct {
|
||||
resourcesCountPassed int
|
||||
resourcesCountFailed int
|
||||
resourcesCountExcluded int
|
||||
controlsCountPassed int
|
||||
controlsCountFailed int
|
||||
controlsCountExcluded int
|
||||
controlsCountSkipped int
|
||||
riskScore int // metric
|
||||
}
|
||||
|
||||
type mControlRiskScore struct {
|
||||
controlName string
|
||||
controlID string
|
||||
link string
|
||||
severity string
|
||||
remediation string
|
||||
resourcesCountPassed int
|
||||
resourcesCountFailed int
|
||||
resourcesCountExcluded int
|
||||
riskScore int // metric
|
||||
}
|
||||
|
||||
type mFrameworkRiskScore struct {
|
||||
frameworkName string
|
||||
resourcesCountPassed int
|
||||
resourcesCountFailed int
|
||||
resourcesCountExcluded int
|
||||
controlsCountPassed int
|
||||
controlsCountFailed int
|
||||
controlsCountExcluded int
|
||||
controlsCountSkipped int
|
||||
riskScore int // metric
|
||||
}
|
||||
|
||||
type mResourceControls struct {
|
||||
name string
|
||||
namespace string
|
||||
apiVersion string
|
||||
kind string
|
||||
controls int // metric
|
||||
}
|
||||
type Metrics struct {
|
||||
rs mRiskScore
|
||||
listFrameworks []mFrameworkRiskScore
|
||||
listControls []mControlRiskScore
|
||||
listResourcesControlsFiled []mResourceControls
|
||||
listResourcesControlsPassed []mResourceControls
|
||||
listResourcesControlsExcluded []mResourceControls
|
||||
}
|
||||
|
||||
func (mrs *mRiskScore) set(resources reportsummary.ICounters, controls reportsummary.ICounters) {
|
||||
mrs.resourcesCountExcluded = resources.Excluded()
|
||||
mrs.resourcesCountFailed = resources.Failed()
|
||||
mrs.resourcesCountPassed = resources.Passed()
|
||||
mrs.controlsCountExcluded = controls.Excluded()
|
||||
mrs.controlsCountFailed = controls.Failed()
|
||||
mrs.controlsCountPassed = controls.Passed()
|
||||
mrs.controlsCountSkipped = controls.Skipped()
|
||||
}
|
||||
|
||||
func (mfrs *mFrameworkRiskScore) set(resources reportsummary.ICounters, controls reportsummary.ICounters) {
|
||||
mfrs.resourcesCountExcluded = resources.Excluded()
|
||||
mfrs.resourcesCountFailed = resources.Failed()
|
||||
mfrs.resourcesCountPassed = resources.Passed()
|
||||
mfrs.controlsCountExcluded = controls.Excluded()
|
||||
mfrs.controlsCountFailed = controls.Failed()
|
||||
mfrs.controlsCountPassed = controls.Passed()
|
||||
mfrs.controlsCountSkipped = controls.Skipped()
|
||||
}
|
||||
|
||||
func (mcrs *mControlRiskScore) set(resources reportsummary.ICounters) {
|
||||
mcrs.resourcesCountExcluded = resources.Excluded()
|
||||
mcrs.resourcesCountFailed = resources.Failed()
|
||||
mcrs.resourcesCountPassed = resources.Passed()
|
||||
}
|
||||
func (m *Metrics) setRiskScores(summaryDetails *reportsummary.SummaryDetails) {
|
||||
m.rs.set(summaryDetails.NumberOfResources(), summaryDetails.NumberOfControls())
|
||||
m.rs.riskScore = int(summaryDetails.GetScore())
|
||||
|
||||
for _, fw := range summaryDetails.ListFrameworks() {
|
||||
mfrs := mFrameworkRiskScore{
|
||||
frameworkName: fw.GetName(),
|
||||
riskScore: int(fw.GetScore()),
|
||||
}
|
||||
mfrs.set(fw.NumberOfResources(), fw.NumberOfControls())
|
||||
m.listFrameworks = append(m.listFrameworks, mfrs)
|
||||
}
|
||||
|
||||
for _, control := range summaryDetails.ListControls() {
|
||||
mcrs := mControlRiskScore{
|
||||
controlName: control.GetName(),
|
||||
controlID: control.GetID(),
|
||||
riskScore: int(control.GetScore()),
|
||||
link: getControlLink(control.GetID()),
|
||||
severity: apis.ControlSeverityToString(control.GetScoreFactor()),
|
||||
remediation: control.GetRemediation(),
|
||||
}
|
||||
mcrs.set(control.NumberOfResources())
|
||||
m.listControls = append(m.listControls, mcrs)
|
||||
}
|
||||
}
|
||||
|
||||
// return -> (passed, exceluded, failed)
|
||||
func resourceControlStatusCounters(result *resourcesresults.Result) (int, int, int) {
|
||||
failed := 0
|
||||
excluded := 0
|
||||
passed := 0
|
||||
for i := range result.ListControls() {
|
||||
switch result.ListControls()[i].GetStatus(nil).Status() {
|
||||
case apis.StatusExcluded:
|
||||
excluded++
|
||||
case apis.StatusFailed:
|
||||
failed++
|
||||
case apis.StatusPassed:
|
||||
passed++
|
||||
}
|
||||
}
|
||||
return passed, excluded, failed
|
||||
}
|
||||
func (m *Metrics) setResourcesCounters(
|
||||
resources map[string]workloadinterface.IMetadata,
|
||||
results map[string]resourcesresults.Result) {
|
||||
|
||||
for resourceID, result := range results {
|
||||
r, ok := resources[resourceID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
passed, excluded, failed := resourceControlStatusCounters(&result)
|
||||
|
||||
mrc := mResourceControls{}
|
||||
mrc.apiVersion = r.GetApiVersion()
|
||||
mrc.namespace = r.GetNamespace()
|
||||
mrc.kind = r.GetKind()
|
||||
mrc.name = r.GetName()
|
||||
|
||||
// append
|
||||
mrc.controls = passed
|
||||
m.listResourcesControlsPassed = append(m.listResourcesControlsPassed, mrc)
|
||||
|
||||
mrc.controls = failed
|
||||
m.listResourcesControlsFiled = append(m.listResourcesControlsFiled, mrc)
|
||||
|
||||
mrc.controls = excluded
|
||||
m.listResourcesControlsExcluded = append(m.listResourcesControlsExcluded, mrc)
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,8 @@
|
||||
```bash
|
||||
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
|
||||
helm repo update
|
||||
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --set prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues=false,prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false
|
||||
kubectl create namescape prometheus
|
||||
helm install -n prometheus kube-prometheus-stack prometheus-community/kube-prometheus-stack --set prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues=false,prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false
|
||||
```
|
||||
3. Deploy pod monitor
|
||||
```bash
|
||||
|
||||
@@ -11,5 +11,6 @@ spec:
|
||||
app: kubescape
|
||||
podMetricsEndpoints:
|
||||
- port: http
|
||||
# path: v1
|
||||
interval: 120s
|
||||
scrapeTimeout: 120s
|
||||
scrapeTimeout: 100s
|
||||
|
||||
@@ -6,17 +6,21 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/armosec/kubescape/core/cautils"
|
||||
"github.com/armosec/kubescape/core/cautils/getter"
|
||||
"github.com/armosec/kubescape/core/cautils/logger"
|
||||
"github.com/armosec/kubescape/core/cautils/logger/helpers"
|
||||
"github.com/armosec/kubescape/core/core"
|
||||
pkgcautils "github.com/armosec/utils-go/utils"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Metrics http listener for prometheus support
|
||||
func (handler *HTTPHandler) Metrics(w http.ResponseWriter, r *http.Request) {
|
||||
if handler.state.isBusy() { // if already scanning the cluster
|
||||
w.Write([]byte(fmt.Sprintf("scan '%s' in action", handler.state.getID())))
|
||||
message := fmt.Sprintf("scan '%s' in action", handler.state.getID())
|
||||
logger.L().Info("server is busy", helpers.String("message", message), helpers.Time())
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
w.Write([]byte(message))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -29,14 +33,13 @@ func (handler *HTTPHandler) Metrics(w http.ResponseWriter, r *http.Request) {
|
||||
logger.L().Info(handler.state.getID(), helpers.String("action", "triggering scan"), helpers.Time())
|
||||
ks := core.NewKubescape()
|
||||
results, err := ks.Scan(getPrometheusDefaultScanCommand(handler.state.getID(), resultsFile))
|
||||
results.HandleResults()
|
||||
logger.L().Info(handler.state.getID(), helpers.String("action", "done scanning"), helpers.Time())
|
||||
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(fmt.Sprintf("failed to complete scan. reason: %s", err.Error())))
|
||||
return
|
||||
}
|
||||
results.HandleResults()
|
||||
logger.L().Info(handler.state.getID(), helpers.String("action", "done scanning"), helpers.Time())
|
||||
|
||||
f, err := os.ReadFile(resultsFile)
|
||||
// res, err := results.ToJson()
|
||||
@@ -45,6 +48,7 @@ func (handler *HTTPHandler) Metrics(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(fmt.Sprintf("failed read results from file. reason: %s", err.Error())))
|
||||
return
|
||||
}
|
||||
os.Remove(resultsFile)
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(f)
|
||||
@@ -60,5 +64,15 @@ func getPrometheusDefaultScanCommand(scanID, resultsFile string) *cautils.ScanIn
|
||||
scanInfo.Format = "prometheus" // results format
|
||||
scanInfo.Output = resultsFile // results output
|
||||
scanInfo.Local = true // Do not publish results to Kubescape SaaS
|
||||
if !downloadArtifactsEveryScan() {
|
||||
scanInfo.UseArtifactsFrom = getter.DefaultLocalStore // Load files from cache (this will prevent kubescape fom downloading the artifacts every time)
|
||||
}
|
||||
scanInfo.Init()
|
||||
return &scanInfo
|
||||
}
|
||||
func downloadArtifactsEveryScan() bool {
|
||||
if d, ok := os.LookupEnv("KS_DOWNLOAD_ARTIFACTS"); ok {
|
||||
return pkgcautils.StringToBool(d)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/armosec/kubescape/core/cautils"
|
||||
"github.com/armosec/kubescape/core/cautils/logger"
|
||||
"github.com/armosec/kubescape/core/cautils/logger/helpers"
|
||||
handlerequestsv1 "github.com/armosec/kubescape/httphandler/handlerequests/v1"
|
||||
@@ -47,7 +48,7 @@ func SetupHTTPListener() error {
|
||||
|
||||
server.Handler = rtr
|
||||
|
||||
logger.L().Info("Started Kubescape server", helpers.String("port", getPort()))
|
||||
logger.L().Info("Started Kubescape server", helpers.String("port", getPort()), helpers.String("version", cautils.BuildNumber))
|
||||
server.ListenAndServe()
|
||||
if keyPair != nil {
|
||||
return server.ListenAndServeTLS("", "")
|
||||
|
||||
Reference in New Issue
Block a user