From 8908a0e5a73a0a9925347daf064fa389b3a173aa Mon Sep 17 00:00:00 2001 From: Amit Schendel Date: Tue, 9 Jul 2024 11:11:57 +0300 Subject: [PATCH 1/7] Adding unauthenticated service control Signed-off-by: Amit Schendel --- controls/C-0274-unauthenticatedservice.json | 27 ++++++ frameworks/security.json | 6 ++ rules/unauthenticated-service/raw.rego | 50 +++++++++++ .../rule.metadata.json | 61 ++++++++++++++ .../test/service/expected.json | 83 +++++++++++++++++++ .../test/service/input/operator.yaml | 18 ++++ .../test/service/input/pod.yaml | 17 ++++ .../test/service/input/service.yaml | 12 +++ 8 files changed, 274 insertions(+) create mode 100644 controls/C-0274-unauthenticatedservice.json create mode 100644 rules/unauthenticated-service/raw.rego create mode 100644 rules/unauthenticated-service/rule.metadata.json create mode 100644 rules/unauthenticated-service/test/service/expected.json create mode 100644 rules/unauthenticated-service/test/service/input/operator.yaml create mode 100644 rules/unauthenticated-service/test/service/input/pod.yaml create mode 100644 rules/unauthenticated-service/test/service/input/service.yaml diff --git a/controls/C-0274-unauthenticatedservice.json b/controls/C-0274-unauthenticatedservice.json new file mode 100644 index 00000000..4fe73726 --- /dev/null +++ b/controls/C-0274-unauthenticatedservice.json @@ -0,0 +1,27 @@ +{ + "controlID": "C-0274", + "name": "Verify Authenticated Service", + "description": "Verifies if the service is authenticated", + "long_description": "Verifies that in order to access the service, the user must be authenticated.", + "remediation": "Configure the service to require authentication.", + "manual_test": "", + "attributes": { + "controlTypeTags": [ + "security" + ] + }, + "rulesNames": [ + "unauthenticated-service" + ], + "baseScore": 7, + "impact_statement": "", + "default_value": "", + "category": { + "name": "Network" + }, + "scanningScope": { + "matches": [ + "cluster" + ] + } +} \ No newline at end of file diff --git a/frameworks/security.json b/frameworks/security.json index 0b1651f6..2bdf8449 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -223,6 +223,12 @@ "patch": { "name": "Exposure to internet via Gateway API" } + }, + { + "controlID": "C-0274", + "patch": { + "name": "Verify Authenticated Service" + } } ] } \ No newline at end of file diff --git a/rules/unauthenticated-service/raw.rego b/rules/unauthenticated-service/raw.rego new file mode 100644 index 00000000..9638b898 --- /dev/null +++ b/rules/unauthenticated-service/raw.rego @@ -0,0 +1,50 @@ +package armo_builtins + +import future.keywords.contains +import future.keywords.if + +deny contains msga if { + service := input[_] + service.kind == "Service" + + wl := input[_] + spec_template_spec_patterns := {"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Pod", "Job", "CronJob"} + spec_template_spec_patterns[wl.kind] + wl_connected_to_service(wl, service) + + service_scan_result := input[_] + service_scan_result.kind == "ServiceScanResult" + service_name := service.metadata.name + has_unauthenticated_service(service_name, service.metadata.namespace, service_scan_result) + + # Path to the workload spec. + path := "spec" + + msga := { + "alertMessage": sprintf("Unauthenticated service %v exposes %v", [service_name, wl.metadata.name]), + "alertScore": 7, + "fixPaths": [], + "reviewPaths": [path], + "failedPaths": [path], + "packagename": "armo_builtins", + "alertObject": {"k8sApiObjects": [wl]}, + "relatedObjects": [ + {"object": service}, + {"object": service_scan_result}, + ], + } +} + +has_unauthenticated_service(service_name, namespace, service_scan_result) if { + service_scan_result.metadata.name == service_name + service_scan_result.metadata.namespace == namespace + service_scan_result.spec.ports[_].authenticated == false +} + +wl_connected_to_service(wl, svc) if { + count({x | svc.spec.selector[x] == wl.metadata.labels[x]}) == count(svc.spec.selector) +} + +wl_connected_to_service(wl, svc) if { + wl.spec.selector.matchLabels == svc.spec.selector +} diff --git a/rules/unauthenticated-service/rule.metadata.json b/rules/unauthenticated-service/rule.metadata.json new file mode 100644 index 00000000..054326f7 --- /dev/null +++ b/rules/unauthenticated-service/rule.metadata.json @@ -0,0 +1,61 @@ +{ + "name": "unauthenticated-service", + "ruleLanguage": "Rego", + "match": [ + { + "apiGroups": [ + "" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Pod", + "Service" + ] + }, + { + "apiGroups": [ + "apps" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "Deployment", + "ReplicaSet", + "DaemonSet", + "StatefulSet" + ] + }, + { + "apiGroups": [ + "batch" + ], + "apiVersions": [ + "*" + ], + "resources": [ + "Job", + "CronJob" + ] + }, + { + "apiGroups": [ + "apiextensions.k8s.io/v1" + ], + "apiVersions": [ + "CustomResourceDefinition" + ], + "resources": [ + "ServiceScanResult" + ] + } + ], + "dynamicMatch": [ + ], + "ruleDependencies": [], + "description": "Verifies that the service is authenticated", + "remediation": "Add authentication to the service", + "ruleQuery": "armo_builtins" +} \ No newline at end of file diff --git a/rules/unauthenticated-service/test/service/expected.json b/rules/unauthenticated-service/test/service/expected.json new file mode 100644 index 00000000..2ae4b64f --- /dev/null +++ b/rules/unauthenticated-service/test/service/expected.json @@ -0,0 +1,83 @@ +{ + "alertMessage": "Unauthenticated service operator exposes operator", + "alertObject": { + "k8sApiObjects": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "operator", + "labels": { + "app": "operator" + } + } + } + ] + }, + "alertScore": 7, + "deletePaths": null, + "failedPaths": ["spec"], + "fixPaths": [], + "packagename": "armo_builtins", + "relatedObjects": [ + { + "deletePaths": null, + "failedPaths": null, + "fixPaths": null, + "object": { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "operator", + "namespace": "kubescape" + }, + "spec": { + "ports": [ + { + "port": 4002, + "protocol": "TCP", + "targetPort": 8080 + } + ], + "selector": { + "app": "operator" + } + } + }, + "reviewPaths": null + }, + { + "deletePaths": null, + "failedPaths": null, + "fixPaths": null, + "object": { + "apiVersion": "kubescape.io/v1", + "kind": "ServiceScanResult", + "metadata": { + "creationTimestamp": "2024-07-03T04:40:17Z", + "generation": 4, + "name": "operator", + "namespace": "kubescape", + "resourceVersion": "2772", + "uid": "24dc622d-ee78-40c2-8654-2a5604715f95" + }, + "spec": { + "clusterIP": "10.103.207.220", + "ports": [ + { + "applicationLayer": "", + "authenticated": false, + "port": 4002, + "presentationLayer": "http", + "protocol": "TCP", + "sessionLayer": "tcp" + } + ] + } + }, + "reviewPaths": null + } + ], + "reviewPaths": ["spec"], + "ruleStatus": "" +} \ No newline at end of file diff --git a/rules/unauthenticated-service/test/service/input/operator.yaml b/rules/unauthenticated-service/test/service/input/operator.yaml new file mode 100644 index 00000000..2905008e --- /dev/null +++ b/rules/unauthenticated-service/test/service/input/operator.yaml @@ -0,0 +1,18 @@ +apiVersion: kubescape.io/v1 +kind: ServiceScanResult +metadata: + creationTimestamp: "2024-07-03T04:40:17Z" + generation: 4 + name: operator + namespace: kubescape + resourceVersion: "2772" + uid: 24dc622d-ee78-40c2-8654-2a5604715f95 +spec: + clusterIP: 10.103.207.220 + ports: + - applicationLayer: "" + authenticated: false + port: 4002 + presentationLayer: http + protocol: TCP + sessionLayer: tcp diff --git a/rules/unauthenticated-service/test/service/input/pod.yaml b/rules/unauthenticated-service/test/service/input/pod.yaml new file mode 100644 index 00000000..f91f8973 --- /dev/null +++ b/rules/unauthenticated-service/test/service/input/pod.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: operator + namespace: kubescape + labels: + app: operator +spec: + containers: + - name: operator-container + image: your-operator-image:latest + ports: + - containerPort: 8080 + resources: + limits: + cpu: "1" + memory: "1Gi" \ No newline at end of file diff --git a/rules/unauthenticated-service/test/service/input/service.yaml b/rules/unauthenticated-service/test/service/input/service.yaml new file mode 100644 index 00000000..9d2ae271 --- /dev/null +++ b/rules/unauthenticated-service/test/service/input/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: operator + namespace: kubescape +spec: + selector: + app: operator + ports: + - protocol: TCP + port: 4002 + targetPort: 8080 \ No newline at end of file From 96cc0fbe9594f2dce8fffd412727c050bf3a1a74 Mon Sep 17 00:00:00 2001 From: Amit Schendel Date: Wed, 10 Jul 2024 10:28:06 +0300 Subject: [PATCH 2/7] Adding yamls that doesn't fail in the test Signed-off-by: Amit Schendel --- .../test/service/expected.json | 5 +++-- .../test/service/input/operator2.yaml | 18 ++++++++++++++++++ .../test/service/input/pod2.yaml | 17 +++++++++++++++++ .../test/service/input/service2.yaml | 12 ++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 rules/unauthenticated-service/test/service/input/operator2.yaml create mode 100644 rules/unauthenticated-service/test/service/input/pod2.yaml create mode 100644 rules/unauthenticated-service/test/service/input/service2.yaml diff --git a/rules/unauthenticated-service/test/service/expected.json b/rules/unauthenticated-service/test/service/expected.json index 2ae4b64f..033ae1ea 100644 --- a/rules/unauthenticated-service/test/service/expected.json +++ b/rules/unauthenticated-service/test/service/expected.json @@ -1,4 +1,4 @@ -{ +[{ "alertMessage": "Unauthenticated service operator exposes operator", "alertObject": { "k8sApiObjects": [ @@ -80,4 +80,5 @@ ], "reviewPaths": ["spec"], "ruleStatus": "" -} \ No newline at end of file +} +] \ No newline at end of file diff --git a/rules/unauthenticated-service/test/service/input/operator2.yaml b/rules/unauthenticated-service/test/service/input/operator2.yaml new file mode 100644 index 00000000..96a49561 --- /dev/null +++ b/rules/unauthenticated-service/test/service/input/operator2.yaml @@ -0,0 +1,18 @@ +apiVersion: kubescape.io/v1 +kind: ServiceScanResult +metadata: + creationTimestamp: "2024-07-03T04:40:17Z" + generation: 4 + name: operator2 + namespace: kubescape + resourceVersion: "2772" + uid: 24dc622d-ee78-40c2-8654-2a5604715f95 +spec: + clusterIP: 10.103.207.220 + ports: + - applicationLayer: "" + authenticated: true + port: 4002 + presentationLayer: http + protocol: TCP + sessionLayer: tcp diff --git a/rules/unauthenticated-service/test/service/input/pod2.yaml b/rules/unauthenticated-service/test/service/input/pod2.yaml new file mode 100644 index 00000000..160f5645 --- /dev/null +++ b/rules/unauthenticated-service/test/service/input/pod2.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: operator2 + namespace: kubescape + labels: + app: operator2 +spec: + containers: + - name: operator-container + image: your-operator-image:latest + ports: + - containerPort: 8080 + resources: + limits: + cpu: "1" + memory: "1Gi" \ No newline at end of file diff --git a/rules/unauthenticated-service/test/service/input/service2.yaml b/rules/unauthenticated-service/test/service/input/service2.yaml new file mode 100644 index 00000000..bcec6292 --- /dev/null +++ b/rules/unauthenticated-service/test/service/input/service2.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: operator2 + namespace: kubescape +spec: + selector: + app: operator2 + ports: + - protocol: TCP + port: 4002 + targetPort: 8080 \ No newline at end of file From 81e9cffc028d3814fc8984e5d5c7d594af56118d Mon Sep 17 00:00:00 2001 From: Amit Schendel Date: Thu, 11 Jul 2024 11:38:23 +0300 Subject: [PATCH 3/7] Adding attack track Signed-off-by: Amit Schendel --- controls/C-0274-unauthenticatedservice.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/controls/C-0274-unauthenticatedservice.json b/controls/C-0274-unauthenticatedservice.json index 4fe73726..37c3802d 100644 --- a/controls/C-0274-unauthenticatedservice.json +++ b/controls/C-0274-unauthenticatedservice.json @@ -8,6 +8,14 @@ "attributes": { "controlTypeTags": [ "security" + ], + "attackTracks": [ + { + "attackTrack": "workload-external-track", + "categories": [ + "Data Collection" + ] + } ] }, "rulesNames": [ From 759dc32c97bbf44bf98c46cbdbb02346ea9cfcc6 Mon Sep 17 00:00:00 2001 From: Amit Schendel Date: Sun, 14 Jul 2024 11:41:58 +0300 Subject: [PATCH 4/7] Moving name to be in the top of the json Signed-off-by: Amit Schendel --- controls/C-0274-unauthenticatedservice.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controls/C-0274-unauthenticatedservice.json b/controls/C-0274-unauthenticatedservice.json index 4fe73726..c249ef69 100644 --- a/controls/C-0274-unauthenticatedservice.json +++ b/controls/C-0274-unauthenticatedservice.json @@ -1,6 +1,6 @@ { - "controlID": "C-0274", "name": "Verify Authenticated Service", + "controlID": "C-0274", "description": "Verifies if the service is authenticated", "long_description": "Verifies that in order to access the service, the user must be authenticated.", "remediation": "Configure the service to require authentication.", From 1917ab8f6b53536df574adea3701a32b7814cf19 Mon Sep 17 00:00:00 2001 From: Amit Schendel Date: Mon, 15 Jul 2024 14:34:10 +0300 Subject: [PATCH 5/7] Fixing the metadata Signed-off-by: Amit Schendel --- rules/unauthenticated-service/rule.metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/unauthenticated-service/rule.metadata.json b/rules/unauthenticated-service/rule.metadata.json index 054326f7..74686b71 100644 --- a/rules/unauthenticated-service/rule.metadata.json +++ b/rules/unauthenticated-service/rule.metadata.json @@ -42,10 +42,10 @@ }, { "apiGroups": [ - "apiextensions.k8s.io/v1" + "kubescape.io" ], "apiVersions": [ - "CustomResourceDefinition" + "v1" ], "resources": [ "ServiceScanResult" From 4f49212272d3ce72fc8828b146c76b79fdca3bc8 Mon Sep 17 00:00:00 2001 From: Amit Schendel Date: Tue, 16 Jul 2024 15:59:02 +0300 Subject: [PATCH 6/7] Adding fixed rego rule Signed-off-by: Amit Schendel --- controls/C-0274-unauthenticatedservice.json | 2 +- .../rule.metadata.json | 2 +- .../{service => fail_service}/expected.json | 0 .../input/operator.yaml | 0 .../input/operator2.yaml | 0 .../{service => fail_service}/input/pod.yaml | 0 .../{service => fail_service}/input/pod2.yaml | 0 .../input/service.yaml | 0 .../input/service2.yaml | 0 .../test/pass/expected.json | 1 + .../test/pass/input/deploy.yaml | 78 +++++++++++++++++++ .../test/pass/input/service.yaml | 31 ++++++++ .../test/pass/input/service_result.yaml | 21 +++++ 13 files changed, 133 insertions(+), 2 deletions(-) rename rules/unauthenticated-service/test/{service => fail_service}/expected.json (100%) rename rules/unauthenticated-service/test/{service => fail_service}/input/operator.yaml (100%) rename rules/unauthenticated-service/test/{service => fail_service}/input/operator2.yaml (100%) rename rules/unauthenticated-service/test/{service => fail_service}/input/pod.yaml (100%) rename rules/unauthenticated-service/test/{service => fail_service}/input/pod2.yaml (100%) rename rules/unauthenticated-service/test/{service => fail_service}/input/service.yaml (100%) rename rules/unauthenticated-service/test/{service => fail_service}/input/service2.yaml (100%) create mode 100644 rules/unauthenticated-service/test/pass/expected.json create mode 100644 rules/unauthenticated-service/test/pass/input/deploy.yaml create mode 100644 rules/unauthenticated-service/test/pass/input/service.yaml create mode 100644 rules/unauthenticated-service/test/pass/input/service_result.yaml diff --git a/controls/C-0274-unauthenticatedservice.json b/controls/C-0274-unauthenticatedservice.json index 75e1ba43..17d4e11b 100644 --- a/controls/C-0274-unauthenticatedservice.json +++ b/controls/C-0274-unauthenticatedservice.json @@ -29,7 +29,7 @@ }, "scanningScope": { "matches": [ - "cluster" + "cluster" ] } } \ No newline at end of file diff --git a/rules/unauthenticated-service/rule.metadata.json b/rules/unauthenticated-service/rule.metadata.json index 74686b71..3ce6e83d 100644 --- a/rules/unauthenticated-service/rule.metadata.json +++ b/rules/unauthenticated-service/rule.metadata.json @@ -48,7 +48,7 @@ "v1" ], "resources": [ - "ServiceScanResult" + "servicesscanresults" ] } ], diff --git a/rules/unauthenticated-service/test/service/expected.json b/rules/unauthenticated-service/test/fail_service/expected.json similarity index 100% rename from rules/unauthenticated-service/test/service/expected.json rename to rules/unauthenticated-service/test/fail_service/expected.json diff --git a/rules/unauthenticated-service/test/service/input/operator.yaml b/rules/unauthenticated-service/test/fail_service/input/operator.yaml similarity index 100% rename from rules/unauthenticated-service/test/service/input/operator.yaml rename to rules/unauthenticated-service/test/fail_service/input/operator.yaml diff --git a/rules/unauthenticated-service/test/service/input/operator2.yaml b/rules/unauthenticated-service/test/fail_service/input/operator2.yaml similarity index 100% rename from rules/unauthenticated-service/test/service/input/operator2.yaml rename to rules/unauthenticated-service/test/fail_service/input/operator2.yaml diff --git a/rules/unauthenticated-service/test/service/input/pod.yaml b/rules/unauthenticated-service/test/fail_service/input/pod.yaml similarity index 100% rename from rules/unauthenticated-service/test/service/input/pod.yaml rename to rules/unauthenticated-service/test/fail_service/input/pod.yaml diff --git a/rules/unauthenticated-service/test/service/input/pod2.yaml b/rules/unauthenticated-service/test/fail_service/input/pod2.yaml similarity index 100% rename from rules/unauthenticated-service/test/service/input/pod2.yaml rename to rules/unauthenticated-service/test/fail_service/input/pod2.yaml diff --git a/rules/unauthenticated-service/test/service/input/service.yaml b/rules/unauthenticated-service/test/fail_service/input/service.yaml similarity index 100% rename from rules/unauthenticated-service/test/service/input/service.yaml rename to rules/unauthenticated-service/test/fail_service/input/service.yaml diff --git a/rules/unauthenticated-service/test/service/input/service2.yaml b/rules/unauthenticated-service/test/fail_service/input/service2.yaml similarity index 100% rename from rules/unauthenticated-service/test/service/input/service2.yaml rename to rules/unauthenticated-service/test/fail_service/input/service2.yaml diff --git a/rules/unauthenticated-service/test/pass/expected.json b/rules/unauthenticated-service/test/pass/expected.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/rules/unauthenticated-service/test/pass/expected.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rules/unauthenticated-service/test/pass/input/deploy.yaml b/rules/unauthenticated-service/test/pass/input/deploy.yaml new file mode 100644 index 00000000..608beba2 --- /dev/null +++ b/rules/unauthenticated-service/test/pass/input/deploy.yaml @@ -0,0 +1,78 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + deployment.kubernetes.io/revision: "1" + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"operator-deployment","namespace":"new-namespace"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"operator"}},"template":{"metadata":{"labels":{"app":"operator"}},"spec":{"containers":[{"args":["-c","nc -lnvp 8080"[],"command":["/bin/sh"],"image":"alpine:3.18.2","name":"operator-container","ports":[{"containerPort":8080}],"volumeMounts":[{"mountPath":"/etc/config","name":"config-volume"}]}],"volumes":[{"configMap":{"name":"operator-configmap"},"name":"config-volume"}]}}}} + creationTimestamp: "2024-07-15T11:38:56Z" + generation: 1 + name: operator-deployment + namespace: new-namespace + resourceVersion: "1118651" + uid: d613b9a8-7ed8-4e0c-b80d-b14023b8d346 +spec: + progressDeadlineSeconds: 600 + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + app: operator + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + creationTimestamp: null + labels: + app: operator + spec: + containers: + - args: + - -c + - nc -lnvp 8080 + command: + - /bin/sh + image: alpine:3.18.2 + imagePullPolicy: IfNotPresent + name: operator-container + ports: + - containerPort: 8080 + protocol: TCP + resources: {} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /etc/config + name: config-volume + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - configMap: + defaultMode: 420 + name: operator-configmap + name: config-volume +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: "2024-07-15T11:39:01Z" + lastUpdateTime: "2024-07-15T11:39:01Z" + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: "True" + type: Available + - lastTransitionTime: "2024-07-15T11:38:56Z" + lastUpdateTime: "2024-07-15T11:39:01Z" + message: ReplicaSet "operator-deployment-748b6d7d54" has successfully progressed. + reason: NewReplicaSetAvailable + status: "True" + type: Progressing + observedGeneration: 1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 \ No newline at end of file diff --git a/rules/unauthenticated-service/test/pass/input/service.yaml b/rules/unauthenticated-service/test/pass/input/service.yaml new file mode 100644 index 00000000..de9e1b93 --- /dev/null +++ b/rules/unauthenticated-service/test/pass/input/service.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"operator","namespace":"new-namespace"},"spec":{"ports":[{"port":4002,"protocol":"TCP","targetPort":8080}],"selector":{"app":"operator"},"type":"NodePort"}} + creationTimestamp: "2024-07-15T11:38:56Z" + name: operator + namespace: new-namespace + resourceVersion: "1118630" + uid: 9cb0d9b9-c4d7-4b48-b456-71229bdc7216 +spec: + clusterIP: 10.105.77.60 + clusterIPs: + - 10.105.77.60 + externalTrafficPolicy: Cluster + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - nodePort: 31624 + port: 4002 + protocol: TCP + targetPort: 8080 + selector: + app: operator + sessionAffinity: None + type: NodePort +status: + loadBalancer: {} \ No newline at end of file diff --git a/rules/unauthenticated-service/test/pass/input/service_result.yaml b/rules/unauthenticated-service/test/pass/input/service_result.yaml new file mode 100644 index 00000000..b46f4179 --- /dev/null +++ b/rules/unauthenticated-service/test/pass/input/service_result.yaml @@ -0,0 +1,21 @@ +apiVersion: kubescape.io/v1 +kind: ServiceScanResult +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"kubescape.io/v1","kind":"ServiceScanResult","metadata":{"annotations":{},"name":"operator","namespace":"new-namespace"},"spec":{"clusterIP":"10.103.207.220","ports":[{"applicationLayer":"","authenticated":false,"port":4002,"presentationLayer":"http","protocol":"TCP","sessionLayer":"tcp"}]}} + creationTimestamp: "2024-07-15T11:39:46Z" + generation: 1 + name: operator + namespace: new-namespace + resourceVersion: "1118691" + uid: cd049412-c329-48ce-82b8-dfa56d6e85fd +spec: + clusterIP: 10.103.207.220 + ports: + - applicationLayer: "" + authenticated: true + port: 4002 + presentationLayer: http + protocol: TCP + sessionLayer: tcp \ No newline at end of file From 3f59097a5e2027f064408f4fbf1ba96b78e2afa1 Mon Sep 17 00:00:00 2001 From: Amit Schendel Date: Tue, 16 Jul 2024 17:50:47 +0300 Subject: [PATCH 7/7] Fixing reviews and tests Signed-off-by: Amit Schendel --- rules/unauthenticated-service/raw.rego | 7 +-- .../test/fail_service/expected.json | 52 +++++++++++++++---- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/rules/unauthenticated-service/raw.rego b/rules/unauthenticated-service/raw.rego index 9638b898..950b484e 100644 --- a/rules/unauthenticated-service/raw.rego +++ b/rules/unauthenticated-service/raw.rego @@ -17,7 +17,7 @@ deny contains msga if { service_name := service.metadata.name has_unauthenticated_service(service_name, service.metadata.namespace, service_scan_result) - # Path to the workload spec. + # Path to the service object path := "spec" msga := { @@ -25,10 +25,11 @@ deny contains msga if { "alertScore": 7, "fixPaths": [], "reviewPaths": [path], - "failedPaths": [path], + "failedPaths": [], "packagename": "armo_builtins", - "alertObject": {"k8sApiObjects": [wl]}, + "alertObject": {"k8sApiObjects": [service]}, "relatedObjects": [ + {"object": wl}, {"object": service}, {"object": service_scan_result}, ], diff --git a/rules/unauthenticated-service/test/fail_service/expected.json b/rules/unauthenticated-service/test/fail_service/expected.json index 033ae1ea..bd3170cf 100644 --- a/rules/unauthenticated-service/test/fail_service/expected.json +++ b/rules/unauthenticated-service/test/fail_service/expected.json @@ -1,25 +1,59 @@ -[{ +[ + { "alertMessage": "Unauthenticated service operator exposes operator", "alertObject": { "k8sApiObjects": [ { "apiVersion": "v1", - "kind": "Pod", + "kind": "Service", "metadata": { - "name": "operator", - "labels": { - "app": "operator" - } + "name": "operator" } } ] }, "alertScore": 7, "deletePaths": null, - "failedPaths": ["spec"], + "failedPaths": [], "fixPaths": [], "packagename": "armo_builtins", "relatedObjects": [ + { + "deletePaths": null, + "failedPaths": null, + "fixPaths": null, + "object": { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "labels": { + "app": "operator" + }, + "name": "operator", + "namespace": "kubescape" + }, + "spec": { + "containers": [ + { + "image": "your-operator-image:latest", + "name": "operator-container", + "ports": [ + { + "containerPort": 8080 + } + ], + "resources": { + "limits": { + "cpu": "1", + "memory": "1Gi" + } + } + } + ] + } + }, + "reviewPaths": null + }, { "deletePaths": null, "failedPaths": null, @@ -80,5 +114,5 @@ ], "reviewPaths": ["spec"], "ruleStatus": "" -} -] \ No newline at end of file + } +]