Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding unauthenticated service control #628

Merged
merged 8 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions controls/C-0274-unauthenticatedservice.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"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.",
"manual_test": "",
"attributes": {
"controlTypeTags": [
"security"
],
"attackTracks": [
{
"attackTrack": "workload-external-track",
"categories": [
"Data Collection"
]
}
]
},
"rulesNames": [
"unauthenticated-service"
],
"baseScore": 7,
"impact_statement": "",
"default_value": "",
"category": {
"name": "Network"
},
"scanningScope": {
"matches": [
"cluster"
]
}
}
6 changes: 6 additions & 0 deletions frameworks/security.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,12 @@
"patch": {
"name": "Exposure to internet via Gateway API"
}
},
{
"controlID": "C-0274",
"patch": {
"name": "Verify Authenticated Service"
}
}
]
}
51 changes: 51 additions & 0 deletions rules/unauthenticated-service/raw.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
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 service object
path := "spec"
kooomix marked this conversation as resolved.
Show resolved Hide resolved

msga := {
"alertMessage": sprintf("Unauthenticated service %v exposes %v", [service_name, wl.metadata.name]),
"alertScore": 7,
"fixPaths": [],
"reviewPaths": [path],
"failedPaths": [],
"packagename": "armo_builtins",
"alertObject": {"k8sApiObjects": [service]},
"relatedObjects": [
{"object": wl},
{"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
}
61 changes: 61 additions & 0 deletions rules/unauthenticated-service/rule.metadata.json
Original file line number Diff line number Diff line change
@@ -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": [
"kubescape.io"
],
"apiVersions": [
"v1"
],
"resources": [
"servicesscanresults"
]
}
],
"dynamicMatch": [
],
"ruleDependencies": [],
"description": "Verifies that the service is authenticated",
"remediation": "Add authentication to the service",
"ruleQuery": "armo_builtins"
}
118 changes: 118 additions & 0 deletions rules/unauthenticated-service/test/fail_service/expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
[
{
"alertMessage": "Unauthenticated service operator exposes operator",
"alertObject": {
"k8sApiObjects": [
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "operator"
}
}
]
},
"alertScore": 7,
"deletePaths": null,
"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,
"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": ""
}
]
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
17 changes: 17 additions & 0 deletions rules/unauthenticated-service/test/fail_service/input/pod.yaml
Original file line number Diff line number Diff line change
@@ -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"
17 changes: 17 additions & 0 deletions rules/unauthenticated-service/test/fail_service/input/pod2.yaml
Original file line number Diff line number Diff line change
@@ -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"
12 changes: 12 additions & 0 deletions rules/unauthenticated-service/test/fail_service/input/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: operator
namespace: kubescape
spec:
selector:
app: operator
ports:
- protocol: TCP
port: 4002
targetPort: 8080
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: operator2
namespace: kubescape
spec:
selector:
app: operator2
ports:
- protocol: TCP
port: 4002
targetPort: 8080
1 change: 1 addition & 0 deletions rules/unauthenticated-service/test/pass/expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Loading
Loading