Skip to content

Commit

Permalink
fix: update CIS status with errors decoding scan report (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
erikgb authored Jan 18, 2023
1 parent 93c183f commit 27e5c51
Show file tree
Hide file tree
Showing 5 changed files with 59,423 additions and 2 deletions.
1 change: 1 addition & 0 deletions api/stas/v1alpha1/containerimagescan_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

const (
ReasonVulnerabilityOverflow = "VulnerabilityOverflow"
ReasonScanReportDecodeError = "ScanReportDecodeError"
WorkloadAnnotationKeyIgnoreUnfixed = "image-scanner.statnett.no/ignore-unfixed"
)

Expand Down
18 changes: 16 additions & 2 deletions internal/controller/stas/scan_job_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,25 @@ func (r *ScanJobReconciler) reconcileCompleteJob(ctx context.Context, jobName st
var (
cleanCis = cis.DeepCopy()
vulnerabilities []stasv1alpha1.Vulnerability
now = metav1.Now()
)

err := json.NewDecoderCaseSensitivePreserveInts(log).Decode(&vulnerabilities)
if err != nil {
cis = cleanCis.DeepCopy()

condition := metav1.Condition{
Type: string(kstatus.ConditionStalled),
Status: metav1.ConditionTrue,
Reason: stasv1alpha1.ReasonScanReportDecodeError,
Message: fmt.Sprintf("error decoding scan report JSON from job '%s': %s", jobName, err),
}
meta.SetStatusCondition(&cis.Status.Conditions, condition)
meta.RemoveStatusCondition(&cis.Status.Conditions, string(kstatus.ConditionReconciling))
cis.Status.LastScanTime = &now
cis.Status.LastScanJobName = jobName
err = r.Status().Patch(ctx, cis, client.MergeFrom(cleanCis))

return err
}

Expand All @@ -80,7 +95,6 @@ func (r *ScanJobReconciler) reconcileCompleteJob(ctx context.Context, jobName st
cis.Status.VulnerabilitySummary = vulnerabilitySummary(vulnerabilities, minSeverity)
// Clear any conditions since we now have a successful scan report
cis.Status.Conditions = nil
now := metav1.Now()
cis.Status.LastScanTime = &now
cis.Status.LastScanJobName = jobName
cis.Status.LastSuccessfulScanTime = &now
Expand All @@ -93,7 +107,7 @@ func (r *ScanJobReconciler) reconcileCompleteJob(ctx context.Context, jobName st
Type: string(kstatus.ConditionStalled),
Status: metav1.ConditionTrue,
Reason: stasv1alpha1.ReasonVulnerabilityOverflow,
Message: "Number of detected vulnerabilities is too high to fit in API",
Message: fmt.Sprintf("vulnerability report is too large to fit in API: %s", err),
}
meta.SetStatusCondition(&cis.Status.Conditions, condition)
meta.RemoveStatusCondition(&cis.Status.Conditions, string(kstatus.ConditionReconciling))
Expand Down
33 changes: 33 additions & 0 deletions internal/controller/stas/scan_job_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,39 @@ var _ = Describe("Scan Job controller", func() {
Expect(condition.Message).To(Not(BeEmpty()))
})
})

Context("but scan report is invalid JSON", func() {
It("should report stalled condition", func() {
// Create CIS
cis := &stasv1alpha1.ContainerImageScan{}
Expect(yaml.FromFile(path.Join("testdata", "scan-job-invalid-json", "cis.yaml"), cis)).To(Succeed())
Expect(k8sClient.Create(ctx, cis))

// Wait for CIS to get reconciled
Eventually(komega.Object(cis)).Should(HaveField("Status.ObservedGeneration", Not(BeZero())))
// Sanity check for conditions set
Expect(cis.Status.Conditions).To(Not(BeEmpty()))

// Simulate scan job complete
scanJob := getContainerImageScanJob(cis)
createScanJobPodWithLogs(scanJob, path.Join("testdata", "scan-job-invalid-json", "scan-job-pod.log.invalid.json"))
Eventually(komega.UpdateStatus(scanJob, func() {
scanJob.Status.Succeeded = 1
})).Should(Succeed())

// Wait for Job to get reconciled
Eventually(komega.Object(cis), timeout, interval).Should(HaveField("Status.LastScanTime", Not(BeZero())))
Expect(cis.Status.LastSuccessfulScanTime).To(BeZero())
Expect(cis.Status.LastScanJobName).To(Equal(scanJob.Name))
// Check conditions
Expect(cis.Status.Conditions).To(HaveLen(1))
condition := cis.Status.Conditions[0]
Expect(condition.Type).To(Equal("Stalled"))
Expect(condition.Status).To(Equal(metav1.ConditionTrue))
Expect(condition.Reason).To(Equal("ScanReportDecodeError"))
Expect(condition.Message).To(Not(BeEmpty()))
})
})
})

Context("When scan job is failed", func() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
apiVersion: stas.statnett.no/v1alpha1
kind: ContainerImageScan
metadata:
name: invalid-scan-json-a309a
namespace: default
spec:
digest: 'sha256:56ef615b2e26c3b9a10dc2824238fb8b8a154ec7db4907ec6ee357ed7bb350b7'
name: docker.io/user/image
Loading

0 comments on commit 27e5c51

Please sign in to comment.