Skip to content

Commit

Permalink
Merge pull request #617 from kubescape/fix-volumes
Browse files Browse the repository at this point in the history
improve remediations - C-0020, C-0045
  • Loading branch information
YiscahLevySilas1 authored Apr 3, 2024
2 parents ab73dad + 0cf5571 commit e98a0d4
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 126 deletions.
41 changes: 24 additions & 17 deletions rules/alert-mount-potential-credentials-paths/raw.rego
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,54 @@ deny[msga] {
provider := data.dataControlInputs.cloudProvider
provider != ""
resources := input[_]
volumes_data := get_volumes(resources)
volumes := volumes_data["volumes"]
spec_data := get_pod_spec(resources)
spec := spec_data["spec"]
volumes := spec.volumes
volume := volumes[i]
start_of_path := volumes_data["start_of_path"]
result := is_unsafe_paths(volume, start_of_path, provider,i)
start_of_path := spec_data["start_of_path"]
result := is_unsafe_paths(volume, start_of_path, provider, i)
volumeMounts := spec.containers[j].volumeMounts
pathMounts = volume_mounts(volume.name, volumeMounts, sprintf("%vcontainers[%d]", [start_of_path, j]))
finalPath := array.concat([result], pathMounts)

msga := {
"alertMessage": sprintf("%v: %v has: %v as volume with potential credentials access.", [resources.kind, resources.metadata.name, volume.name]),
"packagename": "armo_builtins",
"alertScore": 7,
"deletePaths": [result],
"failedPaths": [result],
"deletePaths": finalPath,
"failedPaths": finalPath,
"fixPaths":[],
"alertObject": {
"k8sApiObjects": [resources]
}
}
}


# get_volume - get resource volumes paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"}
get_volumes(resources) := result {
# get_volume - get resource spec paths for {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"}
get_pod_spec(resources) := result {
resources_kinds := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"}
resources_kinds[resources.kind]
result = {"volumes": resources.spec.template.spec.volumes, "start_of_path": "spec.template.spec."}
result = {"spec": resources.spec.template.spec, "start_of_path": "spec.template.spec."}
}

# get_volume - get resource volumes paths for "Pod"
get_volumes(resources) := result {
# get_volume - get resource spec paths for "Pod"
get_pod_spec(resources) := result {
resources.kind == "Pod"
result = {"volumes": resources.spec.volumes, "start_of_path": "spec."}
result = {"spec": resources.spec, "start_of_path": "spec."}
}

# get_volume - get resource volumes paths for "CronJob"
get_volumes(resources) := result {
# get_volume - get resource spec paths for "CronJob"
get_pod_spec(resources) := result {
resources.kind == "CronJob"
result = {"volumes": resources.spec.jobTemplate.spec.template.spec.volumes, "start_of_path": "spec.jobTemplate.spec.template.spec."}
result = {"spec": resources.spec.jobTemplate.spec.template.spec, "start_of_path": "spec.jobTemplate.spec.template.spec."}
}


# is_unsafe_paths - looking for cloud provider (eks/gke/aks) paths that have the potential of accessing credentials
is_unsafe_paths(volume, start_of_path, provider, i) = result {
unsafe := unsafe_paths(provider)
unsafe[_] == fix_path(volume.hostPath.path)
result= sprintf("%vvolumes[%d].hostPath.path", [start_of_path, i])
result = sprintf("%vvolumes[%d]", [start_of_path, i])
}


Expand Down Expand Up @@ -89,3 +92,7 @@ unsafe_paths(x) := ["/.config/gcloud/",
"/.config/gcloud/application_default_credentials.json",
"/gcloud/application_default_credentials.json"] if {x=="gke"}

volume_mounts(name, volume_mounts, str) = [path] {
name == volume_mounts[j].name
path := sprintf("%s.volumeMounts[%v]", [str, j])
} else = []
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
[
{
"alertMessage": "Deployment: my-deployment has: test-volume as volume with potential credentials access.",
"deletePaths": [
"spec.template.spec.volumes[0].hostPath.path"
],
"failedPaths": [
"spec.template.spec.volumes[0].hostPath.path"
"spec.template.spec.volumes[0]",
"spec.template.spec.containers[0].volumeMounts[0]"
],
"deletePaths": [
"spec.template.spec.volumes[0]",
"spec.template.spec.containers[0].volumeMounts[0]"
],
"fixPaths": [],
"ruleStatus": "",
Expand All @@ -28,11 +30,13 @@
},
{
"alertMessage": "Deployment: my-deployment has: test-volume2 as volume with potential credentials access.",
"deletePaths": [
"spec.template.spec.volumes[1].hostPath.path"
],
"failedPaths": [
"spec.template.spec.volumes[1].hostPath.path"
"spec.template.spec.volumes[1]",
"spec.template.spec.containers[0].volumeMounts[1]"
],
"deletePaths": [
"spec.template.spec.volumes[1]",
"spec.template.spec.containers[0].volumeMounts[1]"
],
"fixPaths": [],
"ruleStatus": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ spec:
name : test-volume

- mountPath : /test-pd2
name : test-volume
name : test-volume2
volumes :
- name : test-volume
hostPath :
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
{
"alertMessage": "Pod: test-pd has: test-volume as volume with potential credentials access.",
"deletePaths": [
"spec.volumes[0].hostPath.path"
],
"failedPaths": [
"spec.volumes[0].hostPath.path"
],
"fixPaths": [],
"ruleStatus": "",
"packagename": "armo_builtins",
"alertScore": 7,
"alertObject": {
"k8sApiObjects": [
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "test-pd"
[
{
"alertMessage": "Pod: test-pd has: test-volume as volume with potential credentials access.",
"failedPaths": [
"spec.volumes[0]",
"spec.containers[0].volumeMounts[0]"
],
"deletePaths": [
"spec.volumes[0]",
"spec.containers[0].volumeMounts[0]"
],
"fixPaths": [],
"ruleStatus": "",
"packagename": "armo_builtins",
"alertScore": 7,
"alertObject": {
"k8sApiObjects": [
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "test-pd"
}
}
}
]
]
}
}
}
]
45 changes: 8 additions & 37 deletions rules/alert-rw-hostpath/raw.rego
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,15 @@ deny[msga] {
volume_mount := container.volumeMounts[k]
volume_mount.name == volume.name
start_of_path := "spec."
result := is_rw_mount(volume_mount, start_of_path, i, k)
failed_path := get_failed_path(result)
fixed_path := get_fixed_path(result)
fix_path := is_rw_mount(volume_mount, start_of_path, i, k)

podname := pod.metadata.name

msga := {
"alertMessage": sprintf("pod: %v has: %v as hostPath volume", [podname, volume.name]),
"packagename": "armo_builtins",
"alertScore": 7,
"fixPaths": fixed_path,
"deletePaths": failed_path,
"failedPaths": failed_path,
"fixPaths": [fix_path],
"alertObject": {
"k8sApiObjects": [pod]
}
Expand All @@ -43,17 +39,13 @@ deny[msga] {
volume_mount := container.volumeMounts[k]
volume_mount.name == volume.name
start_of_path := "spec.template.spec."
result := is_rw_mount(volume_mount, start_of_path, i, k)
failed_path := get_failed_path(result)
fixed_path := get_fixed_path(result)
fix_path := is_rw_mount(volume_mount, start_of_path, i, k)

msga := {
"alertMessage": sprintf("%v: %v has: %v as hostPath volume", [wl.kind, wl.metadata.name, volume.name]),
"packagename": "armo_builtins",
"alertScore": 7,
"fixPaths": fixed_path,
"deletePaths": failed_path,
"failedPaths": failed_path,
"fixPaths": [fix_path],
"alertObject": {
"k8sApiObjects": [wl]
}
Expand All @@ -73,43 +65,22 @@ deny[msga] {
volume_mount := container.volumeMounts[k]
volume_mount.name == volume.name
start_of_path := "spec.jobTemplate.spec.template.spec."
result := is_rw_mount(volume_mount, start_of_path, i, k)
failed_path := get_failed_path(result)
fixed_path := get_fixed_path(result)
fix_path := is_rw_mount(volume_mount, start_of_path, i, k)


msga := {
"alertMessage": sprintf("%v: %v has: %v as hostPath volume", [wl.kind, wl.metadata.name, volume.name]),
"packagename": "armo_builtins",
"alertScore": 7,
"fixPaths": fixed_path,
"deletePaths": failed_path,
"failedPaths": failed_path,
"fixPaths": [fix_path],
"alertObject": {
"k8sApiObjects": [wl]
}
}
}

get_failed_path(paths) = [paths[0]] {
paths[0] != ""
} else = []


get_fixed_path(paths) = [paths[1]] {
paths[1] != ""
} else = []


is_rw_mount(mount, start_of_path, i, k) = [failed_path, fix_path] {
is_rw_mount(mount, start_of_path, i, k) = fix_path {
not mount.readOnly == true
not mount.readOnly == false
failed_path = ""
fix_path = {"path": sprintf("%vcontainers[%v].volumeMounts[%v].readOnly", [start_of_path, format_int(i, 10), format_int(k, 10)]), "value":"true"}
fix_path = {"path": sprintf("%vcontainers[%v].volumeMounts[%v].readOnly", [start_of_path, i, k]), "value":"true"}
}

is_rw_mount(mount, start_of_path, i, k) = [failed_path, fix_path] {
mount.readOnly == false
failed_path = sprintf("%vcontainers[%v].volumeMounts[%v].readOnly", [start_of_path, format_int(i, 10), format_int(k, 10)])
fix_path = ""
}
92 changes: 51 additions & 41 deletions rules/alert-rw-hostpath/test/deployment/expected.json
Original file line number Diff line number Diff line change
@@ -1,44 +1,54 @@
[{
"alertMessage": "Deployment: my-deployment has: test-volume as hostPath volume",
"deletePaths": ["spec.template.spec.containers[0].volumeMounts[0].readOnly"],
"failedPaths": ["spec.template.spec.containers[0].volumeMounts[0].readOnly"],
"fixPaths": [],
"ruleStatus": "",
"packagename": "armo_builtins",
"alertScore": 7,
"alertObject": {
"k8sApiObjects": [{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"labels": {
"purpose": "demonstrate-command"
},
"name": "my-deployment"
[
{
"alertMessage": "Deployment: my-deployment has: test-volume as hostPath volume",
"fixPaths": [
{
"path": "spec.template.spec.containers[0].volumeMounts[0].readOnly",
"value": "true"
}
}]
}
}, {
"alertMessage": "Deployment: my-deployment has: test-volume as hostPath volume",
"deletePaths": [],
"failedPaths": [],
"fixPaths": [{
"path": "spec.template.spec.containers[0].volumeMounts[1].readOnly",
"value": "true"
}],
"ruleStatus": "",
"packagename": "armo_builtins",
"alertScore": 7,
"alertObject": {
"k8sApiObjects": [{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"labels": {
"purpose": "demonstrate-command"
},
"name": "my-deployment"
],
"ruleStatus": "",
"packagename": "armo_builtins",
"alertScore": 7,
"alertObject": {
"k8sApiObjects": [
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"labels": {
"purpose": "demonstrate-command"
},
"name": "my-deployment"
}
}
]
}
},
{
"alertMessage": "Deployment: my-deployment has: test-volume as hostPath volume",
"fixPaths": [
{
"path": "spec.template.spec.containers[0].volumeMounts[1].readOnly",
"value": "true"
}
}]
],
"ruleStatus": "",
"packagename": "armo_builtins",
"alertScore": 7,
"alertObject": {
"k8sApiObjects": [
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"labels": {
"purpose": "demonstrate-command"
},
"name": "my-deployment"
}
}
]
}
}
}]
]

0 comments on commit e98a0d4

Please sign in to comment.