Skip to content

Commit 1795ed2

Browse files
malexmaveJ12934
authored andcommitted
WIP: Support cluster-wide resources in operator
Signed-off-by: Max Maass <max.maass@iteratec.com>
1 parent 87e3c74 commit 1795ed2

File tree

2 files changed

+87
-45
lines changed

2 files changed

+87
-45
lines changed

operator/controllers/execution/scans/parse_reconciler.go

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,41 @@ func (r *ScanReconciler) startParser(scan *executionv1.Scan) error {
3737

3838
parseType := scan.Status.RawResultType
3939

40-
// get the scan template for the scan
41-
var parseDefinition executionv1.ParseDefinition
42-
if err := r.Get(ctx, types.NamespacedName{Name: parseType, Namespace: scan.Namespace}, &parseDefinition); err != nil {
43-
log.V(7).Info("Unable to fetch ParseDefinition")
40+
// get the parse definition matching the parseType of the scan result
41+
var parseDefinitionSpec executionv1.ParseDefinitionSpec
42+
if scan.Spec.ResourceMode == executionv1.NamespaceLocal {
43+
var parseDefinition executionv1.ParseDefinition
44+
if err := r.Get(ctx, types.NamespacedName{Name: parseType, Namespace: scan.Namespace}, &parseDefinition); err != nil {
45+
log.V(7).Info("Unable to fetch ParseDefinition")
4446

45-
scan.Status.State = "Errored"
46-
scan.Status.ErrorDescription = fmt.Sprintf("No ParseDefinition for ResultType '%s' found in Scans Namespace.", parseType)
47-
if err := r.Status().Update(ctx, scan); err != nil {
48-
r.Log.Error(err, "unable to update Scan status")
49-
return err
47+
scan.Status.State = "Errored"
48+
scan.Status.ErrorDescription = fmt.Sprintf("No ParseDefinition for ResultType '%s' found in Scans Namespace.", parseType)
49+
if err := r.Status().Update(ctx, scan); err != nil {
50+
r.Log.Error(err, "unable to update Scan status")
51+
return err
52+
}
53+
54+
return fmt.Errorf("No ParseDefinition of type '%s' found", parseType)
5055
}
56+
log.Info("Matching ParseDefinition Found", "ParseDefinition", parseType)
57+
parseDefinitionSpec = parseDefinition.Spec
58+
} else if scan.Spec.ResourceMode == executionv1.ClusterWide {
59+
var clusterParseDefinition executionv1.ClusterParseDefinition
60+
if err := r.Get(ctx, types.NamespacedName{Name: parseType}, &clusterParseDefinition); err != nil {
61+
log.V(7).Info("Unable to fetch ClusterParseDefinition")
62+
63+
scan.Status.State = "Errored"
64+
scan.Status.ErrorDescription = fmt.Sprintf("No ClusterParseDefinition for ResultType '%s' found.", parseType)
65+
if err := r.Status().Update(ctx, scan); err != nil {
66+
r.Log.Error(err, "unable to update Scan status")
67+
return err
68+
}
5169

52-
return fmt.Errorf("No ParseDefinition of type '%s' found", parseType)
70+
return fmt.Errorf("No ClusterParseDefinition of type '%s' found", parseType)
71+
}
72+
log.Info("Matching ClusterParseDefinition Found", "ClusterParseDefinition", parseType)
73+
parseDefinitionSpec = clusterParseDefinition.Spec
5374
}
54-
log.Info("Matching ParseDefinition Found", "ParseDefinition", parseType)
5575

5676
urlExpirationDuration, err := util.GetUrlExpirationDuration(util.ParserController)
5777
if err != nil {
@@ -108,8 +128,8 @@ func (r *ScanReconciler) startParser(scan *executionv1.Scan) error {
108128
corev1.ResourceMemory: resource.MustParse("200Mi"),
109129
},
110130
}
111-
if len(parseDefinition.Spec.Resources.Requests) != 0 || len(parseDefinition.Spec.Resources.Limits) != 0 {
112-
resources = parseDefinition.Spec.Resources
131+
if len(parseDefinitionSpec.Resources.Requests) != 0 || len(parseDefinitionSpec.Resources.Limits) != 0 {
132+
resources = parseDefinitionSpec.Resources
113133
}
114134

115135
job := &batch.Job{
@@ -120,7 +140,7 @@ func (r *ScanReconciler) startParser(scan *executionv1.Scan) error {
120140
Labels: labels,
121141
},
122142
Spec: batch.JobSpec{
123-
TTLSecondsAfterFinished: parseDefinition.Spec.TTLSecondsAfterFinished,
143+
TTLSecondsAfterFinished: parseDefinitionSpec.TTLSecondsAfterFinished,
124144
BackoffLimit: &backOffLimit,
125145
Template: corev1.PodTemplateSpec{
126146
ObjectMeta: metav1.ObjectMeta{
@@ -135,11 +155,11 @@ func (r *ScanReconciler) startParser(scan *executionv1.Scan) error {
135155
Spec: corev1.PodSpec{
136156
RestartPolicy: corev1.RestartPolicyNever,
137157
ServiceAccountName: "parser",
138-
ImagePullSecrets: parseDefinition.Spec.ImagePullSecrets,
158+
ImagePullSecrets: parseDefinitionSpec.ImagePullSecrets,
139159
Containers: []corev1.Container{
140160
{
141161
Name: "parser",
142-
Image: parseDefinition.Spec.Image,
162+
Image: parseDefinitionSpec.Image,
143163
Env: []corev1.EnvVar{
144164
{
145165
Name: "NAMESPACE",
@@ -158,7 +178,7 @@ func (r *ScanReconciler) startParser(scan *executionv1.Scan) error {
158178
rawResultDownloadURL,
159179
findingsUploadURL,
160180
},
161-
ImagePullPolicy: parseDefinition.Spec.ImagePullPolicy,
181+
ImagePullPolicy: parseDefinitionSpec.ImagePullPolicy,
162182
Resources: resources,
163183
SecurityContext: &corev1.SecurityContext{
164184
RunAsNonRoot: &truePointer,
@@ -180,31 +200,31 @@ func (r *ScanReconciler) startParser(scan *executionv1.Scan) error {
180200
// Merge Env from ParserTemplate
181201
job.Spec.Template.Spec.Containers[0].Env = append(
182202
job.Spec.Template.Spec.Containers[0].Env,
183-
parseDefinition.Spec.Env...,
203+
parseDefinitionSpec.Env...,
184204
)
185205
// Merge VolumeMounts from ParserTemplate
186206
job.Spec.Template.Spec.Containers[0].VolumeMounts = append(
187207
job.Spec.Template.Spec.Containers[0].VolumeMounts,
188-
parseDefinition.Spec.VolumeMounts...,
208+
parseDefinitionSpec.VolumeMounts...,
189209
)
190210
// Merge Volumes from ParserTemplate
191211
job.Spec.Template.Spec.Volumes = append(
192212
job.Spec.Template.Spec.Volumes,
193-
parseDefinition.Spec.Volumes...,
213+
parseDefinitionSpec.Volumes...,
194214
)
195215

196216
// Set affinity based on scan, if defined, or parseDefinition if not overridden by scan
197217
if scan.Spec.Affinity != nil {
198218
job.Spec.Template.Spec.Affinity = scan.Spec.Affinity
199219
} else {
200-
job.Spec.Template.Spec.Affinity = parseDefinition.Spec.Affinity
220+
job.Spec.Template.Spec.Affinity = parseDefinitionSpec.Affinity
201221
}
202222

203223
// Set tolerations, either from parseDefinition or from scan
204224
if scan.Spec.Tolerations != nil {
205225
job.Spec.Template.Spec.Tolerations = scan.Spec.Tolerations
206226
} else {
207-
job.Spec.Template.Spec.Tolerations = parseDefinition.Spec.Tolerations
227+
job.Spec.Template.Spec.Tolerations = parseDefinitionSpec.Tolerations
208228
}
209229

210230
r.Log.V(8).Info("Configuring customCACerts for Parser")

operator/controllers/execution/scans/scan_reconciler.go

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,43 @@ func (r *ScanReconciler) startScan(scan *executionv1.Scan) error {
4949
}
5050

5151
// get the ScanType for the scan
52-
var scanType executionv1.ScanType
53-
if err := r.Get(ctx, types.NamespacedName{Name: scan.Spec.ScanType, Namespace: scan.Namespace}, &scanType); err != nil {
54-
log.V(7).Info("Unable to fetch ScanType")
52+
var scanTypeSpec executionv1.ScanTypeSpec
53+
if scan.Spec.ResourceMode == executionv1.NamespaceLocal {
54+
var scanType executionv1.ScanType
55+
if err := r.Get(ctx, types.NamespacedName{Name: scan.Spec.ScanType, Namespace: scan.Namespace}, &scanType); err != nil {
5556

56-
scan.Status.State = "Errored"
57-
scan.Status.ErrorDescription = fmt.Sprintf("Configured ScanType '%s' not found in '%s' namespace. You'll likely need to deploy the ScanType.", scan.Spec.ScanType, scan.Namespace)
58-
if err := r.Status().Update(ctx, scan); err != nil {
59-
r.Log.Error(err, "unable to update Scan status")
60-
return err
61-
}
57+
log.V(7).Info("Unable to fetch ScanType")
6258

63-
return fmt.Errorf("No ScanType of type '%s' found", scan.Spec.ScanType)
59+
scan.Status.State = "Errored"
60+
scan.Status.ErrorDescription = fmt.Sprintf("Configured ScanType '%s' not found in '%s' namespace. You'll likely need to deploy the ScanType.", scan.Spec.ScanType, scan.Namespace)
61+
if err := r.Status().Update(ctx, scan); err != nil {
62+
r.Log.Error(err, "unable to update Scan status")
63+
return err
64+
}
65+
66+
return fmt.Errorf("No ScanType of type '%s' found", scan.Spec.ScanType)
67+
}
68+
log.Info("Matching ScanType Found", "ScanType", scanType.Name)
69+
scanTypeSpec = scanType.Spec
70+
} else if scan.Spec.ResourceMode == executionv1.ClusterWide {
71+
var clusterScanType executionv1.ClusterScanType
72+
73+
if err := r.Get(ctx, types.NamespacedName{Name: scan.Spec.ScanType}, &clusterScanType); err != nil {
74+
r.Log.Error(err, "Failing around")
75+
log.V(7).Info("Unable to fetch ClusterScanType")
76+
77+
scan.Status.State = "Errored"
78+
scan.Status.ErrorDescription = fmt.Sprintf("Configured ClusterScanType '%s' not found in global ClusterScanTypes. You'll likely need to deploy the ScanType.", scan.Spec.ScanType)
79+
if err := r.Status().Update(ctx, scan); err != nil {
80+
r.Log.Error(err, "unable to update Scan status")
81+
return err
82+
}
83+
84+
return fmt.Errorf("No ClusterScanType of type '%s' found", scan.Spec.ScanType)
85+
}
86+
log.Info("Matching ClusterScanType Found", "ClusterScanType", clusterScanType.Name)
87+
scanTypeSpec = clusterScanType.Spec
6488
}
65-
log.Info("Matching ScanType Found", "ScanType", scanType.Name)
6689

6790
rules := []rbacv1.PolicyRule{
6891
{
@@ -78,9 +101,9 @@ func (r *ScanReconciler) startScan(scan *executionv1.Scan) error {
78101
rules,
79102
)
80103

81-
job, err := r.constructJobForScan(scan, &scanType)
104+
job, err := r.constructJobForScan(scan, &scanTypeSpec)
82105
if err != nil {
83-
log.Error(err, "unable to create job object ScanType")
106+
log.Error(err, "unable to create job object from ScanType / ClusterScanType")
84107
return err
85108
}
86109

@@ -92,8 +115,8 @@ func (r *ScanReconciler) startScan(scan *executionv1.Scan) error {
92115
}
93116

94117
scan.Status.State = "Scanning"
95-
scan.Status.RawResultType = scanType.Spec.ExtractResults.Type
96-
scan.Status.RawResultFile = filepath.Base(scanType.Spec.ExtractResults.Location)
118+
scan.Status.RawResultType = scanTypeSpec.ExtractResults.Type
119+
scan.Status.RawResultFile = filepath.Base(scanTypeSpec.ExtractResults.Location)
97120

98121
urlExpirationDuration, err := util.GetUrlExpirationDuration(util.ScanController)
99122
if err != nil {
@@ -166,21 +189,20 @@ func (r *ScanReconciler) checkIfScanIsCompleted(scan *executionv1.Scan) error {
166189
return nil
167190
}
168191

169-
func (r *ScanReconciler) constructJobForScan(scan *executionv1.Scan, scanType *executionv1.ScanType) (*batch.Job, error) {
170-
filename := filepath.Base(scanType.Spec.ExtractResults.Location)
192+
func (r *ScanReconciler) constructJobForScan(scan *executionv1.Scan, scanTypeSpec *executionv1.ScanTypeSpec) (*batch.Job, error) {
193+
filename := filepath.Base(scanTypeSpec.ExtractResults.Location)
171194
urlExpirationDuration, err := util.GetUrlExpirationDuration(util.ScanController)
172195
if err != nil {
173196
r.Log.Error(err, "Failed to parse scan url expiration")
174197
panic(err)
175198
}
176-
177199
resultUploadURL, err := r.PresignedPutURL(*scan, filename, urlExpirationDuration)
178200
if err != nil {
179201
r.Log.Error(err, "Could not get presigned url from s3 or compatible storage provider")
180202
return nil, err
181203
}
182204

183-
if len(scanType.Spec.JobTemplate.Spec.Template.Spec.Containers) < 1 {
205+
if len(scanTypeSpec.JobTemplate.Spec.Template.Spec.Containers) < 1 {
184206
return nil, errors.New("ScanType must at least contain one container in which the scanner is running")
185207
}
186208

@@ -195,7 +217,7 @@ func (r *ScanReconciler) constructJobForScan(scan *executionv1.Scan, scanType *e
195217
GenerateName: util.TruncateName(fmt.Sprintf("scan-%s", scan.Name)),
196218
Namespace: scan.Namespace,
197219
},
198-
Spec: *scanType.Spec.JobTemplate.Spec.DeepCopy(),
220+
Spec: *scanTypeSpec.JobTemplate.Spec.DeepCopy(),
199221
}
200222

201223
//add recommend kubernetes "managed by" label, to tell the SCB container autodiscovery to ignore the scan pod
@@ -206,7 +228,7 @@ func (r *ScanReconciler) constructJobForScan(scan *executionv1.Scan, scanType *e
206228
podLabels["app.kubernetes.io/managed-by"] = "securecodebox"
207229
job.Spec.Template.Labels = podLabels
208230

209-
podAnnotations := scanType.Spec.JobTemplate.DeepCopy().Annotations
231+
podAnnotations := scanTypeSpec.JobTemplate.DeepCopy().Annotations
210232
if podAnnotations == nil {
211233
podAnnotations = make(map[string]string)
212234
}
@@ -273,7 +295,7 @@ func (r *ScanReconciler) constructJobForScan(scan *executionv1.Scan, scanType *e
273295
"--container",
274296
job.Spec.Template.Spec.Containers[0].Name,
275297
"--file",
276-
scanType.Spec.ExtractResults.Location,
298+
scanTypeSpec.ExtractResults.Location,
277299
"--url",
278300
resultUploadURL,
279301
},
@@ -345,7 +367,7 @@ func (r *ScanReconciler) constructJobForScan(scan *executionv1.Scan, scanType *e
345367
}
346368

347369
command := append(
348-
scanType.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Command,
370+
scanTypeSpec.JobTemplate.Spec.Template.Spec.Containers[0].Command,
349371
scan.Spec.Parameters...,
350372
)
351373

0 commit comments

Comments
 (0)