mirror of
https://github.com/kubescape/kubescape.git
synced 2026-04-15 06:58:11 +00:00
Merge remote-tracking branch 'prometheus/feature/prometheus'
This commit is contained in:
@@ -69,19 +69,19 @@ Set-ExecutionPolicy RemoteSigned -scope CurrentUser
|
||||
|
||||
## Flags
|
||||
|
||||
| flag | default | description | options |
|
||||
| --- | --- | --- | --- |
|
||||
| `-e`/`--exclude-namespaces` | Scan all namespaces | Namespaces to exclude from scanning. Recommended to exclude `kube-system` and `kube-public` namespaces |
|
||||
| `-s`/`--silent` | Display progress messages | Silent progress messages |
|
||||
| `-t`/`--fail-threshold` | `0` (do not fail) | fail command (return exit code 1) if result bellow threshold| `0` -> `100` |
|
||||
| `-f`/`--format` | `pretty-printer` | Output format | `pretty-printer`/`json`/`junit` |
|
||||
| `-o`/`--output` | print to stdout | Save scan result in file |
|
||||
| `--use-from` | | Load local framework object from specified path. If not used will download latest |
|
||||
| `--use-default` | `false` | Load local framework object from default path. If not used will download latest | `true`/`false` |
|
||||
| `--exceptions` | | Path to an [exceptions obj](examples/exceptions.json). If not set will download exceptions from Armo management portal |
|
||||
| `--submit` | `false` | If set, Kubescape will send the scan results to Armo management portal where you can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more. By default the results are not sent | `true`/`false`|
|
||||
| `--keep-local` | `false` | Kubescape will not send scan results to Armo management portal. Use this flag if you ran with the `--submit` flag in the past and you do not want to submit your current scan results | `true`/`false`|
|
||||
| `--account` | | Armo portal account ID. Default will load account ID from configMap or config file | |
|
||||
| flag | default | description | options |
|
||||
|-----------------------------|---------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------|
|
||||
| `-e`/`--exclude-namespaces` | Scan all namespaces | Namespaces to exclude from scanning. Recommended to exclude `kube-system` and `kube-public` namespaces | |
|
||||
| `-s`/`--silent` | Display progress messages | Silent progress messages | |
|
||||
| `-t`/`--fail-threshold` | `0` (do not fail) | fail command (return exit code 1) if result bellow threshold | `0` -> `100` |
|
||||
| `-f`/`--format` | `pretty-printer` | Output format | `pretty-printer`/`json`/`junit`/`prometheus` |
|
||||
| `-o`/`--output` | print to stdout | Save scan result in file | |
|
||||
| `--use-from` | | Load local framework object from specified path. If not used will download latest | |
|
||||
| `--use-default` | `false` | Load local framework object from default path. If not used will download latest | `true`/`false` |
|
||||
| `--exceptions` | | Path to an [exceptions obj](examples/exceptions.json). If not set will download exceptions from Armo management portal | |
|
||||
| `--submit` | `false` | If set, Kubescape will send the scan results to Armo management portal where you can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more. By default the results are not sent | `true`/`false` |
|
||||
| `--keep-local` | `false` | Kubescape will not send scan results to Armo management portal. Use this flag if you ran with the `--submit` flag in the past and you do not want to submit your current scan results | `true`/`false` |
|
||||
| `--account` | | Armo portal account ID. Default will load account ID from configMap or config file | |
|
||||
|
||||
## Usage & Examples
|
||||
|
||||
@@ -125,6 +125,11 @@ kubescape scan framework nsa --exclude-namespaces kube-system,kube-public --form
|
||||
kubescape scan framework nsa --exclude-namespaces kube-system,kube-public --format junit --output results.xml
|
||||
```
|
||||
|
||||
* Output in `prometheus` metrics format
|
||||
```
|
||||
kubescape scan framework nsa --exclude-namespaces kube-system,kube-public --format prometheus
|
||||
```
|
||||
|
||||
* Scan with exceptions, objects with exceptions will be presented as `exclude` and not `fail`
|
||||
```
|
||||
kubescape scan framework nsa --exceptions examples/exceptions.json
|
||||
|
||||
@@ -11,7 +11,8 @@ const EmptyPercentage = "NaN"
|
||||
const (
|
||||
PrettyFormat string = "pretty-printer"
|
||||
JsonFormat string = "json"
|
||||
JunitResultPrinter string = "junit"
|
||||
JunitResultFormat string = "junit"
|
||||
PrometheusFormat string = "prometheus"
|
||||
)
|
||||
|
||||
type IPrinter interface {
|
||||
@@ -24,8 +25,10 @@ func GetPrinter(printFormat string) IPrinter {
|
||||
switch printFormat {
|
||||
case JsonFormat:
|
||||
return NewJsonPrinter()
|
||||
case JunitResultPrinter:
|
||||
case JunitResultFormat:
|
||||
return NewJunitPrinter()
|
||||
case PrometheusFormat:
|
||||
return NewPrometheusPrinter()
|
||||
default:
|
||||
return NewPrettyPrinter()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package printer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/armosec/kubescape/cautils"
|
||||
"github.com/armosec/opa-utils/reporthandling"
|
||||
)
|
||||
|
||||
type PrometheusPrinter struct {
|
||||
writer *os.File
|
||||
}
|
||||
|
||||
func NewPrometheusPrinter() *PrometheusPrinter {
|
||||
return &PrometheusPrinter{}
|
||||
}
|
||||
|
||||
func (prometheusPrinter *PrometheusPrinter) SetWriter(outputFile string) {
|
||||
prometheusPrinter.writer = getWriter(outputFile)
|
||||
}
|
||||
|
||||
func (prometheusPrinter *PrometheusPrinter) Score(score float32) {
|
||||
fmt.Printf("\n# Overall score out of 100\nkubescape_score %f\n", score*100)
|
||||
}
|
||||
|
||||
func (printer *PrometheusPrinter) printDetails(details []reporthandling.RuleResponse, frameworkName string, controlName string) error {
|
||||
objs := make(map[string]map[string]map[string]int)
|
||||
for _, ruleResponses := range details {
|
||||
for _, k8sObj := range ruleResponses.AlertObject.K8SApiObjects {
|
||||
kind, ok := k8sObj[`kind`].(string)
|
||||
if (!ok) {
|
||||
return errors.New("Found object with non string kind")
|
||||
}
|
||||
apiVersion,ok := k8sObj[`apiVersion`].(string)
|
||||
if (!ok) {
|
||||
return errors.New("Found object with non string apiVersion")
|
||||
}
|
||||
gvk := fmt.Sprintf("%s/%s",apiVersion,kind)
|
||||
metadata,ok := k8sObj[`metadata`].(map[string]interface{})
|
||||
if (!ok) {
|
||||
return errors.New("Found object with non convertable metadata")
|
||||
}
|
||||
name,ok := metadata[`name`].(string)
|
||||
if (!ok) {
|
||||
return errors.New("Found metadata with non string name")
|
||||
}
|
||||
namespace,ok := metadata[`namespace`].(string)
|
||||
if (!ok) {
|
||||
namespace = ""
|
||||
}
|
||||
if (objs[gvk] == nil) {
|
||||
objs[gvk] = make(map[string]map[string]int)
|
||||
}
|
||||
if (objs[gvk][namespace] == nil) {
|
||||
objs[gvk][namespace] = make(map[string]int)
|
||||
}
|
||||
objs[gvk][namespace][name]++
|
||||
}
|
||||
}
|
||||
for gvk, namespaces := range objs {
|
||||
for namespace, names := range namespaces {
|
||||
for name, value := range names {
|
||||
fmt.Fprintf(printer.writer, "# Failed object from %s control %s\n", frameworkName, controlName)
|
||||
if namespace != "" {
|
||||
fmt.Fprintf(printer.writer, "kubescape_object_failed_count{framework=\"%s\",control=\"%s\",namespace=\"%s\",name=\"%s\",groupVersionKind=\"%s\"} %d\n", frameworkName, controlName, namespace, name, gvk, value)
|
||||
} else {
|
||||
fmt.Fprintf(printer.writer, "kubescape_object_failed_count{framework=\"%s\",control=\"%s\",name=\"%s\",groupVersionKind=\"%s\"} %d\n", frameworkName, controlName, name, gvk, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (printer *PrometheusPrinter) printReports(frameworks []reporthandling.FrameworkReport) error {
|
||||
for _, framework := range frameworks {
|
||||
for _, controlReports := range framework.ControlReports {
|
||||
if len(controlReports.RuleReports[0].RuleResponses) > 0 {
|
||||
fmt.Fprintf(printer.writer, "# Number of resources found as part of %s control %s\nkubescape_resources_found_count{framework=\"%s\",control=\"%s\"} %d\n", framework.Name, controlReports.Name, framework.Name, controlReports.Name, controlReports.GetNumberOfResources())
|
||||
fmt.Fprintf(printer.writer, "# Number of resources excluded as part of %s control %s\nkubescape_resources_excluded_count{framework=\"%s\",control=\"%s\"} %d\n", framework.Name, controlReports.Name, framework.Name, controlReports.Name, controlReports.GetNumberOfWarningResources())
|
||||
fmt.Fprintf(printer.writer, "# Number of resources failed as part of %s control %s\nkubescape_resources_failed_count{framework=\"%s\",control=\"%s\"} %d\n", framework.Name, controlReports.Name, framework.Name, controlReports.Name, controlReports.GetNumberOfFailedResources())
|
||||
err := printer.printDetails(controlReports.RuleReports[0].RuleResponses, framework.Name, controlReports.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (printer *PrometheusPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) {
|
||||
err := printer.printReports(opaSessionObj.PostureReport.FrameworkReports)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user