Skip to content

Commit

Permalink
add trivy_exposedsecrets_info metric with discovered secrets details (#…
Browse files Browse the repository at this point in the history
…1000)

* add trivy_exposedsecrets_info metric with discovered secrets details

* run make manifests

* cosmetics

* formatting

* handle duplicate secrets per target

* change config param default env value to false (same for MetricsVulnerabilityId)
  • Loading branch information
dkulchinsky authored Feb 24, 2023
1 parent cdfedbc commit e100287
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 45 deletions.
1 change: 1 addition & 0 deletions deploy/helm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ You can configure Trivy-Operator to control it's behavior and adapt it to your n
| `OPERATOR_LEADER_ELECTION_ENABLED` | `false` | The flag to enable operator replica leader election |
| `OPERATOR_LEADER_ELECTION_ID` | `trivy-operator-lock` | The name of the resource lock for leader election |
| `OPERATOR_EXPOSED_SECRET_SCANNER_ENABLED` | `true` | The flag to enable exposed secret scanner |
| `OPERATOR_METRICS_EXPOSED_SECRET_INFO_ENABLED` | `false` | the flag to enable metrics about exposed secrets |
| `OPERATOR_WEBHOOK_BROADCAST_URL` | `""` | The flag to enable operator reports to be sent to a webhook endpoint. "" means that this feature is disabled |
| `OPERATOR_BUILT_IN_TRIVY_SERVER` | `false` | The flag enable the usage of built-in trivy server in cluster ,its also overwrite the following trivy params with built-in values trivy.mode = ClientServer and serverURL = <http://[server> Service Name].[trivy Operator Namespace]:4975 |
| `TRIVY_SERVER_HEALTH_CHECK_CACHE_EXPIRATION` | `10h` | The flag to set the interval for trivy server health cache before it invalidate |
Expand Down
2 changes: 2 additions & 0 deletions deploy/helm/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ spec:
value: {{ .Values.operator.configAuditScannerScanOnlyCurrentRevisions | quote }}
- name: OPERATOR_EXPOSED_SECRET_SCANNER_ENABLED
value: {{ .Values.operator.exposedSecretScannerEnabled | quote }}
- name: OPERATOR_METRICS_EXPOSED_SECRET_INFO_ENABLED
value: {{ .Values.operator.metricsExposedSecretInfo | quote }}
- name: OPERATOR_WEBHOOK_BROADCAST_URL
value: {{ .Values.operator.webhookBroadcastURL | quote }}
- name: OPERATOR_WEBHOOK_BROADCAST_TIMEOUT
Expand Down
4 changes: 4 additions & 0 deletions deploy/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ operator:
# exposedSecretScannerEnabled the flag to enable exposed secret scanner
exposedSecretScannerEnabled: true

# MetricsExposedSecretInfo the flag to enable metrics about exposed secrets
# be aware of metrics cardinality is significantly increased with this feature enabled.
metricsExposedSecretInfo: false

# webhookBroadcastURL the flag to set reports should be sent to a webhook endpoint. "" means that the webhookBroadcastURL feature is disabled
webhookBroadcastURL: ""

Expand Down
2 changes: 2 additions & 0 deletions deploy/static/trivy-operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1920,6 +1920,8 @@ spec:
value: "true"
- name: OPERATOR_EXPOSED_SECRET_SCANNER_ENABLED
value: "true"
- name: OPERATOR_METRICS_EXPOSED_SECRET_INFO_ENABLED
value: "false"
- name: OPERATOR_WEBHOOK_BROADCAST_URL
value: ""
- name: OPERATOR_WEBHOOK_BROADCAST_TIMEOUT
Expand Down
10 changes: 10 additions & 0 deletions docs/tutorials/integrations/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ trivy_image_exposedsecrets{
} 1
```

### ExposedsSecretsInfo

Exposes details about secrets that were discovered in images, enable by setting the EnvVar: `OPERATOR_METRICS_EXPOSED_SECRET_INFO_ENABLED" envDefault:"false"` . For example:

```shell
trivy_exposedsecrets_info{
container_name="trivy",image_digest="",image_registry="index.docker.io",image_repository="josedonizetti/trivy",image_tag="secrettest",name="pod-tt-reg-test",namespace="default",resource_kind="Pod",resource_name="tt-reg-test",secret_category="AWS",secret_rule_id="aws-access-key-id",secret_target="/etc/apt/s3auth.conf",secret_title="AWS Access Key ID",severity="Critical"
} 1
```

### InfraAssessments

A report summary series exposes the count of checks of each status reported in a given `InfraAssessmentsReport`. For example:
Expand Down
107 changes: 93 additions & 14 deletions pkg/metrics/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"strconv"

"github.com/aquasecurity/trivy-operator/pkg/kube"
"github.com/aquasecurity/trivy-operator/pkg/trivyoperator"
"github.com/go-logr/logr"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -40,6 +41,11 @@ const (
title = "title"
description = "description"
status = "status"
//exposed secret
secret_category = "secret_category"
secret_rule_id = "secret_rule_id"
secret_target = "secret_target"
secret_title = "secret_title"
)

type metricDescriptors struct {
Expand All @@ -52,19 +58,21 @@ type metricDescriptors struct {
complianceStatuses map[string]func(vs v1alpha1.ComplianceSummary) int

// Labels
imageVulnLabels []string
vulnIdLabels []string
exposedSecretLabels []string
configAuditLabels []string
rbacAssessmentLabels []string
infraAssessmentLabels []string
complianceLabels []string
imageVulnLabels []string
vulnIdLabels []string
exposedSecretLabels []string
exposedSecretInfoLabels []string
configAuditLabels []string
rbacAssessmentLabels []string
infraAssessmentLabels []string
complianceLabels []string

// Descriptors
imageVulnDesc *prometheus.Desc
vulnIdDesc *prometheus.Desc
configAuditDesc *prometheus.Desc
exposedSecretDesc *prometheus.Desc
exposedSecretInfoDesc *prometheus.Desc
rbacAssessmentDesc *prometheus.Desc
clusterRbacAssessmentDesc *prometheus.Desc
infraAssessmentDesc *prometheus.Desc
Expand Down Expand Up @@ -240,6 +248,23 @@ func buildMetricDescriptors(config trivyoperator.ConfigData) metricDescriptors {
severity,
}
exposedSecretLabels = append(exposedSecretLabels, dynamicLabels...)
exposedSecretInfoLabels := []string{
namespace,
name,
resource_kind,
resource_name,
container_name,
image_registry,
image_repository,
image_tag,
image_digest,
secret_category,
secret_rule_id,
secret_target,
secret_title,
severity,
}
exposedSecretInfoLabels = append(exposedSecretInfoLabels, dynamicLabels...)
configAuditLabels := []string{
namespace,
name,
Expand Down Expand Up @@ -289,6 +314,12 @@ func buildMetricDescriptors(config trivyoperator.ConfigData) metricDescriptors {
exposedSecretLabels,
nil,
)
exposedSecretInfoDesc := prometheus.NewDesc(
prometheus.BuildFQName("trivy", "exposedsecrets", "info"),
"Number of container image exposed secrets group by secret rule id",
exposedSecretInfoLabels,
nil,
)
configAuditDesc := prometheus.NewDesc(
prometheus.BuildFQName("trivy", "resource", "configaudits"),
"Number of failing resource configuration auditing checks",
Expand Down Expand Up @@ -327,18 +358,20 @@ func buildMetricDescriptors(config trivyoperator.ConfigData) metricDescriptors {
infraAssessmentSeverities: infraAssessmentSeverities,
complianceStatuses: complainceStatuses,

imageVulnLabels: imageVulnLabels,
vulnIdLabels: vulnIdLabels,
exposedSecretLabels: exposedSecretLabels,
configAuditLabels: configAuditLabels,
rbacAssessmentLabels: rbacAssessmentLabels,
infraAssessmentLabels: infraAssessmentLabels,
complianceLabels: clusterComplianceLabels,
imageVulnLabels: imageVulnLabels,
vulnIdLabels: vulnIdLabels,
exposedSecretLabels: exposedSecretLabels,
exposedSecretInfoLabels: exposedSecretInfoLabels,
configAuditLabels: configAuditLabels,
rbacAssessmentLabels: rbacAssessmentLabels,
infraAssessmentLabels: infraAssessmentLabels,
complianceLabels: clusterComplianceLabels,

imageVulnDesc: imageVulnDesc,
vulnIdDesc: vulnIdDesc,
configAuditDesc: configAuditDesc,
exposedSecretDesc: exposedSecretDesc,
exposedSecretInfoDesc: exposedSecretInfoDesc,
rbacAssessmentDesc: rbacAssessmentDesc,
clusterRbacAssessmentDesc: clusterRbacAssessmentDesc,
infraAssessmentDesc: infraAssessmentDesc,
Expand Down Expand Up @@ -371,6 +404,9 @@ func (c ResourcesMetricsCollector) Collect(metrics chan<- prometheus.Metric) {
c.collectVulnerabilityIdReports(ctx, metrics, targetNamespaces)
}
c.collectExposedSecretsReports(ctx, metrics, targetNamespaces)
if c.Config.MetricsExposedSecretInfo {
c.collectExposedSecretsInfoReports(ctx, metrics, targetNamespaces)
}
c.collectConfigAuditReports(ctx, metrics, targetNamespaces)
c.collectRbacAssessmentReports(ctx, metrics, targetNamespaces)
c.collectInfraAssessmentReports(ctx, metrics, targetNamespaces)
Expand Down Expand Up @@ -485,6 +521,48 @@ func (c ResourcesMetricsCollector) collectExposedSecretsReports(ctx context.Cont
}
}

func (c ResourcesMetricsCollector) collectExposedSecretsInfoReports(ctx context.Context, metrics chan<- prometheus.Metric, targetNamespaces []string) {
reports := &v1alpha1.ExposedSecretReportList{}
labelValues := make([]string, len(c.exposedSecretInfoLabels))
for _, n := range targetNamespaces {
if err := c.List(ctx, reports, client.InNamespace(n)); err != nil {
c.Logger.Error(err, "failed to list exposedsecretreports from API", "namespace", n)
continue
}
for _, r := range reports.Items {
if c.Config.MetricsExposedSecretInfo {
labelValues[0] = r.Namespace
labelValues[1] = r.Name
labelValues[2] = r.Labels[trivyoperator.LabelResourceKind]
labelValues[3] = r.Labels[trivyoperator.LabelResourceName]
labelValues[4] = r.Labels[trivyoperator.LabelContainerName]
labelValues[5] = r.Report.Registry.Server
labelValues[6] = r.Report.Artifact.Repository
labelValues[7] = r.Report.Artifact.Tag
labelValues[8] = r.Report.Artifact.Digest
for i, label := range c.GetReportResourceLabels() {
labelValues[i+14] = r.Labels[label]
}
var secretList = make(map[string]bool)
for _, secret := range r.Report.Secrets {
secretHash := kube.ComputeHash(secret.Category + secret.RuleID + secret.Target + secret.Title + NewSeverityLabel(secret.Severity).Label)
if secretList[secretHash] {
continue
}
secretList[secretHash] = true
labelValues[9] = secret.Category
labelValues[10] = secret.RuleID
labelValues[11] = secret.Target
labelValues[12] = secret.Title
labelValues[13] = NewSeverityLabel(secret.Severity).Label

metrics <- prometheus.MustNewConstMetric(c.exposedSecretInfoDesc, prometheus.GaugeValue, float64(1), labelValues...)
}
}
}
}
}

func (c *ResourcesMetricsCollector) collectConfigAuditReports(ctx context.Context, metrics chan<- prometheus.Metric, targetNamespaces []string) {
reports := &v1alpha1.ConfigAuditReportList{}
labelValues := make([]string, len(c.configAuditLabels))
Expand Down Expand Up @@ -616,6 +694,7 @@ func (c ResourcesMetricsCollector) Describe(descs chan<- *prometheus.Desc) {
descs <- c.vulnIdDesc
descs <- c.configAuditDesc
descs <- c.exposedSecretDesc
descs <- c.exposedSecretInfoDesc
descs <- c.rbacAssessmentDesc
descs <- c.infraAssessmentDesc
descs <- c.clusterRbacAssessmentDesc
Expand Down
Loading

0 comments on commit e100287

Please sign in to comment.