Skip to content

Commit 20309ac

Browse files
authored
Merge pull request #58 from prachidamle/custom_benchmarks
Custom benchmark for CIS scans
2 parents 955b927 + bc5b5cd commit 20309ac

File tree

4 files changed

+89
-28
lines changed

4 files changed

+89
-28
lines changed

pkg/securityscan/core/configmap.go

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1010
k8Yaml "k8s.io/apimachinery/pkg/util/yaml"
1111

12+
wcorev1 "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
1213
"github.com/rancher/wrangler/pkg/name"
1314

1415
cisoperatorapiv1 "github.com/rancher/cis-operator/pkg/apis/cis.cattle.io/v1"
@@ -18,12 +19,14 @@ type OverrideSkipInfoData struct {
1819
Skip map[string][]string `json:"skip"`
1920
}
2021

21-
var (
22-
CurrentBenchmarkKey = "current"
23-
ConfigFileName = "config.json"
22+
const (
23+
CurrentBenchmarkKey = "current"
24+
ConfigFileName = "config.json"
25+
customBenchmarkBaseDir = "/etc/kbs/custombenchmark/cfg"
2426
)
2527

26-
func NewConfigMaps(clusterscan *cisoperatorapiv1.ClusterScan, clusterscanprofile *cisoperatorapiv1.ClusterScanProfile, controllerName string, imageConfig *cisoperatorapiv1.ScanImageConfig) (configmaps []*corev1.ConfigMap, err error) {
28+
func NewConfigMaps(clusterscan *cisoperatorapiv1.ClusterScan, clusterscanprofile *cisoperatorapiv1.ClusterScanProfile, clusterscanbenchmark *cisoperatorapiv1.ClusterScanBenchmark, controllerName string, imageConfig *cisoperatorapiv1.ScanImageConfig, configmapsClient wcorev1.ConfigMapController) (cmMap map[string]*corev1.ConfigMap, err error) {
29+
cmMap = make(map[string]*corev1.ConfigMap)
2730

2831
configdata := map[string]interface{}{
2932
"namespace": cisoperatorapiv1.ClusterScanNS,
@@ -36,35 +39,53 @@ func NewConfigMaps(clusterscan *cisoperatorapiv1.ClusterScan, clusterscanprofile
3639
}
3740
configcm, err := generateConfigMap(clusterscan, "cisscanConfig.template", "./pkg/securityscan/core/templates/cisscanConfig.template", configdata)
3841
if err != nil {
39-
return configmaps, err
42+
return cmMap, err
4043
}
44+
cmMap["configcm"] = configcm
45+
46+
var isCustomBenchmark bool
47+
customBenchmarkConfigMapData := make(map[string]string)
48+
if clusterscanbenchmark.Spec.CustomBenchmarkConfigMapName != "" {
49+
isCustomBenchmark = true
50+
customcm, err := getCustomBenchmarkConfigMap(clusterscanbenchmark, configmapsClient)
51+
if err != nil {
52+
return cmMap, err
53+
}
54+
customBenchmarkConfigMapData = customcm.Data
55+
}
56+
4157
plugindata := map[string]interface{}{
42-
"namespace": cisoperatorapiv1.ClusterScanNS,
43-
"name": name.SafeConcatName(cisoperatorapiv1.ClusterScanPluginsConfigMap, clusterscan.Name),
44-
"runName": name.SafeConcatName("security-scan-runner", clusterscan.Name),
45-
"appName": "rancher-cis-benchmark",
46-
"serviceaccount": cisoperatorapiv1.ClusterScanSA,
47-
"securityScanImage": imageConfig.SecurityScanImage + ":" + imageConfig.SecurityScanImageTag,
48-
"benchmarkVersion": clusterscanprofile.Spec.BenchmarkVersion,
58+
"namespace": cisoperatorapiv1.ClusterScanNS,
59+
"name": name.SafeConcatName(cisoperatorapiv1.ClusterScanPluginsConfigMap, clusterscan.Name),
60+
"runName": name.SafeConcatName("security-scan-runner", clusterscan.Name),
61+
"appName": "rancher-cis-benchmark",
62+
"serviceaccount": cisoperatorapiv1.ClusterScanSA,
63+
"securityScanImage": imageConfig.SecurityScanImage + ":" + imageConfig.SecurityScanImageTag,
64+
"benchmarkVersion": clusterscanprofile.Spec.BenchmarkVersion,
65+
"isCustomBenchmark": isCustomBenchmark,
66+
"configDir": customBenchmarkBaseDir,
67+
"customBenchmarkConfigMapName": clusterscanbenchmark.Spec.CustomBenchmarkConfigMapName,
68+
"customBenchmarkConfigMapData": customBenchmarkConfigMapData,
4969
}
5070
plugincm, err := generateConfigMap(clusterscan, "pluginConfig.template", "./pkg/securityscan/core/templates/pluginConfig.template", plugindata)
5171
if err != nil {
52-
return configmaps, err
72+
return cmMap, err
5373
}
74+
cmMap["plugincm"] = plugincm
5475

5576
var skipConfigcm *corev1.ConfigMap
5677
if clusterscanprofile.Spec.SkipTests != nil && len(clusterscanprofile.Spec.SkipTests) > 0 {
5778
//create user skip config map as well
5879
// create the cm
5980
skipDataBytes, err := getOverrideSkipInfoData(clusterscanprofile.Spec.SkipTests)
6081
if err != nil {
61-
return configmaps, err
82+
return cmMap, err
6283
}
6384
skipConfigcm = getConfigMapObject(getOverrideConfigMapName(clusterscan), string(skipDataBytes))
85+
cmMap["skipConfigcm"] = skipConfigcm
6486
}
6587

66-
configmaps = append(configmaps, configcm, plugincm, skipConfigcm)
67-
return configmaps, nil
88+
return cmMap, nil
6889
}
6990

7091
func generateConfigMap(clusterscan *cisoperatorapiv1.ClusterScan, templateName string, templateFile string, data map[string]interface{}) (*corev1.ConfigMap, error) {
@@ -120,3 +141,10 @@ func getConfigMapObject(cmName, data string) *corev1.ConfigMap {
120141
},
121142
}
122143
}
144+
145+
func getCustomBenchmarkConfigMap(benchmark *cisoperatorapiv1.ClusterScanBenchmark, configmapsClient wcorev1.ConfigMapController) (*corev1.ConfigMap, error) {
146+
if benchmark.Spec.CustomBenchmarkConfigMapName == "" {
147+
return nil, nil
148+
}
149+
return configmapsClient.Get(benchmark.Spec.CustomBenchmarkConfigMapNameSpace, benchmark.Spec.CustomBenchmarkConfigMapName, metav1.GetOptions{})
150+
}

pkg/securityscan/core/templates/pluginConfig.template

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ data:
1414
hostIPC: true
1515
hostNetwork: true
1616
hostPID: true
17-
serviceAccountName: {{.serviceaccount}}
17+
serviceAccountName: {{ .serviceaccount }}
1818
tolerations:
1919
- effect: NoSchedule
2020
key: node-role.kubernetes.io/controlplane
@@ -38,18 +38,34 @@ data:
3838
- hostPath:
3939
path: /etc/cni/net.d
4040
name: rke2-cni
41+
{{- if .isCustomBenchmark }}
42+
- configMap:
43+
defaultMode: 420
44+
items:
45+
{{- range $key, $value := .customBenchmarkConfigMapData }}
46+
{{- if eq $key "config.yaml"}}
47+
- key: {{ $key }}
48+
path: {{ $key }}
49+
{{- else}}
50+
- key: {{ $key }}
51+
path: {{ $.benchmarkVersion }}/{{ $key }}
52+
{{- end }}
53+
{{- end }}
54+
name: {{ .customBenchmarkConfigMapName }}
55+
name: custom-benchmark-volume
56+
{{- end }}
4157
sonobuoy-config:
4258
driver: DaemonSet
4359
plugin-name: rancher-kube-bench
4460
result-type: rancher-kube-bench
4561
result-format: raw
4662
spec:
4763
name: rancher-kube-bench
48-
image: {{.securityScanImage}}
64+
image: {{ .securityScanImage }}
4965
command: ["/bin/bash", "-c", "run_sonobuoy_plugin.sh && sleep 3600"]
5066
env:
5167
- name: SONOBUOY_NS
52-
value: {{.namespace}}
68+
value: {{ .namespace }}
5369
- name: NODE_NAME
5470
valueFrom:
5571
fieldRef:
@@ -59,7 +75,11 @@ data:
5975
- name: CHROOT_DIR
6076
value: /node
6177
- name: OVERRIDE_BENCHMARK_VERSION
62-
value: {{.benchmarkVersion}}
78+
value: {{ .benchmarkVersion }}
79+
{{- if .isCustomBenchmark }}
80+
- name: CONFIG_DIR
81+
value: {{ .configDir }}
82+
{{- end }}
6383
imagePullPolicy: Always
6484
securityContext:
6585
privileged: true
@@ -82,3 +102,7 @@ data:
82102
- mountPath: /etc/cni/net.d
83103
name: rke2-cni
84104
readOnly: true
105+
{{- if .isCustomBenchmark }}
106+
- mountPath: /etc/kbs/custombenchmark/cfg
107+
name: custom-benchmark-volume
108+
{{- end }}

pkg/securityscan/jobHandler.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,11 @@ func (c *Controller) handleJobs(ctx context.Context) error {
6060
// if the scan has completed then delete the job
6161
if v1.ClusterScanConditionComplete.IsTrue(scan) {
6262
c.ensureCleanup(scan)
63-
v1.ClusterScanConditionAlerted.Unknown(scan)
63+
if !v1.ClusterScanConditionFailed.IsTrue(scan) {
64+
logrus.Infof("Marking ClusterScanConditionAlerted for scan: %v", scanName)
65+
v1.ClusterScanConditionAlerted.Unknown(scan)
66+
}
6467
scan.Status.ObservedGeneration = scan.Generation
65-
logrus.Infof("Marking ClusterScanConditionAlerted for scan: %v", scanName)
6668
c.setClusterScanStatusDisplay(scan)
6769

6870
if scan.Spec.ScheduledScanConfig != nil && scan.Spec.ScheduledScanConfig.CronSchedule != "" {

pkg/securityscan/scanHandler.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,22 +99,25 @@ func (c *Controller) handleClusterScans(ctx context.Context) error {
9999
}
100100
//launch new on demand scan
101101
c.mu.Lock()
102+
defer c.mu.Unlock()
102103
logrus.Infof("Launching a new on demand Job for scan %v to run cis using profile %v", obj.Name, profile.Name)
103-
configmaps, err := ciscore.NewConfigMaps(obj, profile, c.Name, c.ImageConfig)
104+
benchmark, err := c.getClusterScanBenchmark(profile)
105+
if err != nil {
106+
v1.ClusterScanConditionReconciling.True(obj)
107+
return objects, obj.Status, fmt.Errorf("Error when getting Benchmark: %v", err)
108+
}
109+
cmMap, err := ciscore.NewConfigMaps(obj, profile, benchmark, c.Name, c.ImageConfig, configmaps)
104110
if err != nil {
105111
v1.ClusterScanConditionReconciling.True(obj)
106-
c.mu.Unlock()
107112
return objects, obj.Status, fmt.Errorf("Error when creating ConfigMaps: %v", err)
108113

109114
}
110115
service, err := ciscore.NewService(obj, profile, c.Name)
111116
if err != nil {
112117
v1.ClusterScanConditionReconciling.True(obj)
113-
c.mu.Unlock()
114118
return objects, obj.Status, fmt.Errorf("Error when creating Service: %v", err)
115119
}
116-
117-
objects = append(objects, cisjob.New(obj, profile, c.Name, c.ImageConfig), configmaps[0], configmaps[1], configmaps[2], service)
120+
objects = append(objects, cisjob.New(obj, profile, c.Name, c.ImageConfig), cmMap["configcm"], cmMap["plugincm"], cmMap["skipConfigcm"], service)
118121

119122
if v1.ClusterScanConditionFailed.IsTrue(obj) {
120123
//clear the earlier failed status
@@ -126,7 +129,6 @@ func (c *Controller) handleClusterScans(ctx context.Context) error {
126129
v1.ClusterScanConditionRunCompleted.Unknown(obj)
127130
v1.ClusterScanConditionRunCompleted.Message(obj, "Creating Job to run the CIS scan")
128131
c.setClusterScanStatusDisplay(obj)
129-
c.mu.Unlock()
130132
return objects, obj.Status, nil
131133
}
132134
return objects, obj.Status, nil
@@ -163,6 +165,11 @@ func (c *Controller) getClusterScanProfile(scan *v1.ClusterScan) (*v1.ClusterSca
163165
return profile, nil
164166
}
165167

168+
func (c *Controller) getClusterScanBenchmark(profile *v1.ClusterScanProfile) (*v1.ClusterScanBenchmark, error) {
169+
clusterscanbmks := c.cisFactory.Cis().V1().ClusterScanBenchmark()
170+
return clusterscanbmks.Get(profile.Spec.BenchmarkVersion, metav1.GetOptions{})
171+
}
172+
166173
func (c *Controller) getDefaultClusterScanProfile(clusterprovider string) (string, error) {
167174
var err error
168175
configmaps := c.coreFactory.Core().V1().ConfigMap()

0 commit comments

Comments
 (0)