diff --git a/rules/resources-cpu-limit-and-request/raw.rego b/rules/resources-cpu-limit-and-request/raw.rego index 317be212e..07f136ec4 100644 --- a/rules/resources-cpu-limit-and-request/raw.rego +++ b/rules/resources-cpu-limit-and-request/raw.rego @@ -1,14 +1,14 @@ package armo_builtins -# Fails if pod does not have container with CPU-limit or request +# ==================================== CPU requests ============================================= +# Fails if pod does not have container with CPU request deny[msga] { pod := input[_] pod.kind == "Pod" container := pod.spec.containers[i] - not request_or_limit_cpu(container) + not container.resources.requests.cpu - fixPaths := [{"path": sprintf("spec.containers[%v].resources.limits.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}, - {"path": sprintf("spec.containers[%v].resources.requests.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}] + fixPaths := [{"path": sprintf("spec.containers[%v].resources.requests.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}] msga := { "alertMessage": sprintf("Container: %v does not have CPU-limit or request", [ container.name]), @@ -22,16 +22,15 @@ deny[msga] { } } -# Fails if workload does not have container with CPU-limit or request +# Fails if workload does not have container with CPU requests deny[msga] { wl := input[_] spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} spec_template_spec_patterns[wl.kind] container := wl.spec.template.spec.containers[i] - not request_or_limit_cpu(container) + not container.resources.requests.cpu - fixPaths := [{"path": sprintf("spec.template.spec.containers[%v].resources.limits.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}, - {"path": sprintf("spec.template.spec.containers[%v].resources.requests.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}] + fixPaths := [{"path": sprintf("spec.template.spec.containers[%v].resources.requests.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}] msga := { "alertMessage": sprintf("Container: %v in %v: %v does not have CPU-limit or request", [ container.name, wl.kind, wl.metadata.name]), @@ -45,15 +44,14 @@ deny[msga] { } } -# Fails if cronjob does not have container with CPU-limit or request +# Fails if cronjob does not have container with CPU requests deny[msga] { wl := input[_] wl.kind == "CronJob" container = wl.spec.jobTemplate.spec.template.spec.containers[i] - not request_or_limit_cpu(container) + not container.resources.requests.cpu - fixPaths := [{"path": sprintf("spec.jobTemplate.spec.template.spec.containers[%v].resources.limits.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}, - {"path": sprintf("spec.jobTemplate.spec.template.spec.containers[%v].resources.requests.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}] + fixPaths := [{"path": sprintf("spec.jobTemplate.spec.template.spec.containers[%v].resources.requests.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}] msga := { "alertMessage": sprintf("Container: %v in %v: %v does not have CPU-limit or request", [ container.name, wl.kind, wl.metadata.name]), @@ -67,6 +65,70 @@ deny[msga] { } } +# ==================================== CPU limits ============================================= +# Fails if pod does not have container with CPU-limits +deny[msga] { + pod := input[_] + pod.kind == "Pod" + container := pod.spec.containers[i] + not container.resources.limits.cpu + + fixPaths := [{"path": sprintf("spec.containers[%v].resources.limits.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}] + + msga := { + "alertMessage": sprintf("Container: %v does not have CPU-limit or request", [ container.name]), + "packagename": "armo_builtins", + "alertScore": 7, + "failedPaths": [], + "fixPaths": fixPaths, + "alertObject": { + "k8sApiObjects": [pod] + } + } +} + +# Fails if workload does not have container with CPU-limits +deny[msga] { + wl := input[_] + spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} + spec_template_spec_patterns[wl.kind] + container := wl.spec.template.spec.containers[i] + not container.resources.limits.cpu + + fixPaths := [{"path": sprintf("spec.template.spec.containers[%v].resources.limits.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}] + + msga := { + "alertMessage": sprintf("Container: %v in %v: %v does not have CPU-limit or request", [ container.name, wl.kind, wl.metadata.name]), + "packagename": "armo_builtins", + "alertScore": 7, + "failedPaths": [], + "fixPaths": fixPaths, + "alertObject": { + "k8sApiObjects": [wl] + } + } +} + +# Fails if cronjob does not have container with CPU-limits +deny[msga] { + wl := input[_] + wl.kind == "CronJob" + container = wl.spec.jobTemplate.spec.template.spec.containers[i] + not container.resources.limits.cpu + + fixPaths := [{"path": sprintf("spec.jobTemplate.spec.template.spec.containers[%v].resources.limits.cpu", [format_int(i, 10)]), "value": "YOUR_VALUE"}] + + msga := { + "alertMessage": sprintf("Container: %v in %v: %v does not have CPU-limit or request", [ container.name, wl.kind, wl.metadata.name]), + "packagename": "armo_builtins", + "alertScore": 7, + "failedPaths": [], + "fixPaths": fixPaths, + "alertObject": { + "k8sApiObjects": [wl] + } + } +} diff --git a/rules/resources-cpu-limit-and-request/test/cronjob/expected.json b/rules/resources-cpu-limit-and-request/test/cronjob/expected.json index 28b1ab3ba..e03f943e8 100644 --- a/rules/resources-cpu-limit-and-request/test/cronjob/expected.json +++ b/rules/resources-cpu-limit-and-request/test/cronjob/expected.json @@ -2,8 +2,36 @@ { "alertMessage": "Container: hello in CronJob: hello does not have CPU-limit or request", "failedPaths": [], - "fixPaths" : [{"path": "spec.jobTemplate.spec.template.spec.containers[0].resources.limits.cpu", "value": "YOUR_VALUE"}, - {"path": "spec.jobTemplate.spec.template.spec.containers[0].resources.requests.cpu", "value": "YOUR_VALUE"}], + "fixPaths": [ + { + "path": "spec.jobTemplate.spec.template.spec.containers[0].resources.limits.cpu", + "value": "YOUR_VALUE" + } + ], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 7, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "batch/v1beta1", + "kind": "CronJob", + "metadata": { + "name": "hello" + } + } + ] + } + }, + { + "alertMessage": "Container: hello in CronJob: hello does not have CPU-limit or request", + "failedPaths": [], + "fixPaths": [ + { + "path": "spec.jobTemplate.spec.template.spec.containers[0].resources.requests.cpu", + "value": "YOUR_VALUE" + } + ], "ruleStatus": "", "packagename": "armo_builtins", "alertScore": 7, diff --git a/rules/resources-cpu-limit-and-request/test/pod-only-limits/expected.json b/rules/resources-cpu-limit-and-request/test/pod-only-limits/expected.json new file mode 100644 index 000000000..a19179dff --- /dev/null +++ b/rules/resources-cpu-limit-and-request/test/pod-only-limits/expected.json @@ -0,0 +1,22 @@ +[ + { + "alertMessage": "Container: log-aggregator does not have CPU-limit or request", + "failedPaths": [], + "fixPaths" : [{"path":"spec.containers[1].resources.limits.cpu", "value": "YOUR_VALUE"}], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 7, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "frontend" + } + } + ] + } + } +] + diff --git a/rules/resources-cpu-limit-and-request/test/pod-only-limits/input/pod.yaml b/rules/resources-cpu-limit-and-request/test/pod-only-limits/input/pod.yaml new file mode 100644 index 000000000..d1207f1bb --- /dev/null +++ b/rules/resources-cpu-limit-and-request/test/pod-only-limits/input/pod.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: frontend +spec: + containers: + - name: app + image: images.my-company.example/app:v4 + resources: + requests: + memory: "64Mi" + cpu: "250m" + limits: + memory: "128Mi" + cpu: "500m" + - name: log-aggregator + image: images.my-company.example/log-aggregator:v6 + resources: + requests: + memory: "64Mi" + cpu: "250m" + limits: + memory: "128Mi" diff --git a/rules/resources-cpu-limit-and-request/test/pod-only-requests/expected.json b/rules/resources-cpu-limit-and-request/test/pod-only-requests/expected.json new file mode 100644 index 000000000..8a0bba75c --- /dev/null +++ b/rules/resources-cpu-limit-and-request/test/pod-only-requests/expected.json @@ -0,0 +1,21 @@ +[ + { + "alertMessage": "Container: log-aggregator does not have CPU-limit or request", + "failedPaths": [], + "fixPaths" : [{"path": "spec.containers[1].resources.requests.cpu", "value": "YOUR_VALUE"}], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 7, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "frontend" + } + } + ] + } + } +] \ No newline at end of file diff --git a/rules/resources-cpu-limit-and-request/test/pod-only-requests/input/pod.yaml b/rules/resources-cpu-limit-and-request/test/pod-only-requests/input/pod.yaml new file mode 100644 index 000000000..0495de5d3 --- /dev/null +++ b/rules/resources-cpu-limit-and-request/test/pod-only-requests/input/pod.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: frontend +spec: + containers: + - name: app + image: images.my-company.example/app:v4 + resources: + requests: + memory: "64Mi" + cpu: "250m" + limits: + memory: "128Mi" + cpu: "500m" + - name: log-aggregator + image: images.my-company.example/log-aggregator:v6 + resources: + requests: + memory: "64Mi" + limits: + memory: "128Mi" + cpu: "500m" diff --git a/rules/resources-cpu-limit-and-request/test/pod/expected.json b/rules/resources-cpu-limit-and-request/test/pod/expected.json index 24a8f72bb..08f0190f9 100644 --- a/rules/resources-cpu-limit-and-request/test/pod/expected.json +++ b/rules/resources-cpu-limit-and-request/test/pod/expected.json @@ -2,8 +2,36 @@ { "alertMessage": "Container: log-aggregator does not have CPU-limit or request", "failedPaths": [], - "fixPaths" : [{"path":"spec.containers[1].resources.limits.cpu", "value": "YOUR_VALUE"}, - {"path": "spec.containers[1].resources.requests.cpu", "value": "YOUR_VALUE"}], + "fixPaths": [ + { + "path": "spec.containers[1].resources.limits.cpu", + "value": "YOUR_VALUE" + } + ], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 7, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "frontend" + } + } + ] + } + }, + { + "alertMessage": "Container: log-aggregator does not have CPU-limit or request", + "failedPaths": [], + "fixPaths": [ + { + "path": "spec.containers[1].resources.requests.cpu", + "value": "YOUR_VALUE" + } + ], "ruleStatus": "", "packagename": "armo_builtins", "alertScore": 7, diff --git a/rules/resources-cpu-limit-and-request/test/workload/expected.json b/rules/resources-cpu-limit-and-request/test/workload/expected.json index aa8d65acf..0d4c0c19e 100644 --- a/rules/resources-cpu-limit-and-request/test/workload/expected.json +++ b/rules/resources-cpu-limit-and-request/test/workload/expected.json @@ -1,26 +1,56 @@ -[{ - "alertMessage": "Container: app in Deployment: test does not have CPU-limit or request", - "failedPaths": [], - "fixPaths": [{ - "path": "spec.template.spec.containers[0].resources.limits.cpu", - "value": "YOUR_VALUE" - }, { - "path": "spec.template.spec.containers[0].resources.requests.cpu", - "value": "YOUR_VALUE" - }], - "ruleStatus": "", - "packagename": "armo_builtins", - "alertScore": 7, - "alertObject": { - "k8sApiObjects": [{ - "apiVersion": "apps/v1", - "kind": "Deployment", - "metadata": { - "labels": { - "purpose": "demonstrate-command" - }, - "name": "test" +[ + { + "alertMessage": "Container: app in Deployment: test does not have CPU-limit or request", + "failedPaths": [], + "fixPaths": [ + { + "path": "spec.template.spec.containers[0].resources.limits.cpu", + "value": "YOUR_VALUE" } - }] + ], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 7, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "purpose": "demonstrate-command" + }, + "name": "test" + } + } + ] + } + }, + { + "alertMessage": "Container: app in Deployment: test does not have CPU-limit or request", + "failedPaths": [], + "fixPaths": [ + { + "path": "spec.template.spec.containers[0].resources.requests.cpu", + "value": "YOUR_VALUE" + } + ], + "ruleStatus": "", + "packagename": "armo_builtins", + "alertScore": 7, + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "purpose": "demonstrate-command" + }, + "name": "test" + } + } + ] + } } -}] \ No newline at end of file +] \ No newline at end of file