2021-11-02
wget <https://github.com/controlplaneio/kubesec/releases/download/v2.11.0/kubesec_linux_amd64.tar.gz>
tar -xvf kubesec_linux_amd64.tar.gz
mv kubesec /usr/bin
root@controlplane:~# kubesec
Validate Kubernetes resource security policies
Usage:
kubesec [command]
Available Commands:
help Help about any command
http Starts kubesec HTTP server on the specified port
scan Scans Kubernetes resource YAML or JSON
version Prints kubesec version
Flags:
-h, --help help for kubesec
Use "kubesec [command] --help" for more information about a command.
root@controlplane:~# kubesec scan /root/node.yaml --help
Scans Kubernetes resource YAML or JSON
Usage:
kubesec scan [file] [flags]
Examples:
kubesec scan ./deployment.yaml
cat file.json | kubesec scan -
helm template -f values.yaml ./chart | kubesec scan /dev/stdin
Flags:
--absolute-path use the absolute path for the file name
--debug turn on debug logs
--exit-code int Set the exit-code to use on failure (default 2)
-f, --format string Set output format (json, template) (default "json")
-h, --help help for scan
-o, --output string Set output location
-t, --template string Set output template, it will check for a file or read input as the
root@controlplane:~# kubesec scan /root/node.yaml --output /root/kubesec_report.json
[
{
"object": "Pod/node.default",
"valid": true,
"fileName": "/root/node.yaml",
"message": "Failed with a score of -27 points",
"score": -27,
"scoring": {
"critical": [
{
"id": "Privileged",
"selector": "containers[] .securityContext .privileged == true",
"reason": "Privileged containers can allow almost completely unrestricted host access",
"points": -30
}
],
"passed": [
{
"id": "ServiceAccountName",
"selector": ".spec .serviceAccountName",
"reason": "Service accounts restrict Kubernetes API access and should be configured with least privilege",
"points": 3
}
],
"advise": [
{
"id": "ApparmorAny",
"selector": ".metadata .annotations .\\"container.apparmor.security.beta.kubernetes.io/nginx\\"",
"reason": "Well defined AppArmor policies may provide greater protection from unknown threats. WARNING: NOT PRODUCTION READY",
"points": 3
},
{
"id": "SeccompAny",
"selector": ".metadata .annotations .\\"container.seccomp.security.alpha.kubernetes.io/pod\\"",
"reason": "Seccomp profiles set minimum privilege and secure against unknown threats",
"points": 1
},
{
"id": "LimitsCPU",
"selector": "containers[] .resources .limits .cpu",
"reason": "Enforcing CPU limits prevents DOS via resource exhaustion",
"points": 1
},
{
"id": "RequestsMemory",
"selector": "containers[] .resources .limits .memory",
"reason": "Enforcing memory limits prevents DOS via resource exhaustion",
"points": 1
},
{
"id": "RequestsCPU",
"selector": "containers[] .resources .requests .cpu",
"reason": "Enforcing CPU requests aids a fair balancing of resources across the cluster",
"points": 1
},
{
"id": "RequestsMemory",
"selector": "containers[] .resources .requests .memory",
"reason": "Enforcing memory requests aids a fair balancing of resources across the cluster",
"points": 1
},
{
"id": "CapDropAny",
"selector": "containers[] .securityContext .capabilities .drop",
"reason": "Reducing kernel capabilities available to a container limits its attack surface",
"points": 1
},
{
"id": "CapDropAll",
"selector": "containers[] .securityContext .capabilities .drop | index(\\"ALL\\")",
"reason": "Drop all capabilities and add only those required to reduce syscall attack surface",
"points": 1
},
{
"id": "ReadOnlyRootFilesystem",
"selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
"reason": "An immutable root filesystem can prevent malicious binaries being added to PATH and increase attack cost",
"points": 1
},
{
"id": "RunAsNonRoot",
"selector": "containers[] .securityContext .runAsNonRoot == true",
"reason": "Force the running image to run as a non-root user to ensure least privilege",
"points": 1
},
{
"id": "RunAsUser",
"selector": "containers[] .securityContext .runAsUser -gt 10000",
"reason": "Run as a high-UID user to avoid conflicts with the host's user table",
"points": 1
}
]
}
}
]
root@controlplane:~# kubesec scan /root/node.yaml
[
{
"object": "Pod/node.default",
"valid": true,
"fileName": "/root/node.yaml",
"message": "Passed with a score of 4 points",
"score": 4,
"scoring": {
"passed": [
{
"id": "ServiceAccountName",
"selector": ".spec .serviceAccountName",
"reason": "Service accounts restrict Kubernetes API access and should be configured with least privilege",
"points": 3
},
{
"id": "ReadOnlyRootFilesystem",
"selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
"reason": "An immutable root filesystem can prevent malicious binaries being added to PATH and increase attack cost",
"points": 1
}
],
"advise": [
{
"id": "ApparmorAny",
"selector": ".metadata .annotations .\\"container.apparmor.security.beta.kubernetes.io/nginx\\"",
"reason": "Well defined AppArmor policies may provide greater protection from unknown threats. WARNING: NOT PRODUCTION READY",
"points": 3
},
{
"id": "SeccompAny",
"selector": ".metadata .annotations .\\"container.seccomp.security.alpha.kubernetes.io/pod\\"",
"reason": "Seccomp profiles set minimum privilege and secure against unknown threats",
"points": 1
},
{
"id": "LimitsCPU",
"selector": "containers[] .resources .limits .cpu",
"reason": "Enforcing CPU limits prevents DOS via resource exhaustion",
"points": 1
},
{
"id": "RequestsMemory",
"selector": "containers[] .resources .limits .memory",
"reason": "Enforcing memory limits prevents DOS via resource exhaustion",
"points": 1
},
{
"id": "RequestsCPU",
"selector": "containers[] .resources .requests .cpu",
"reason": "Enforcing CPU requests aids a fair balancing of resources across the cluster",
"points": 1
},
{
"id": "RequestsMemory",
"selector": "containers[] .resources .requests .memory",
"reason": "Enforcing memory requests aids a fair balancing of resources across the cluster",
"points": 1
},
{
"id": "CapDropAny",
"selector": "containers[] .securityContext .capabilities .drop",
"reason": "Reducing kernel capabilities available to a container limits its attack surface",
"points": 1
},
{
"id": "CapDropAll",
"selector": "containers[] .securityContext .capabilities .drop | index(\\"ALL\\")",
"reason": "Drop all capabilities and add only those required to reduce syscall attack surface",
"points": 1
},
{
"id": "RunAsNonRoot",
"selector": "containers[] .securityContext .runAsNonRoot == true",
"reason": "Force the running image to run as a non-root user to ensure least privilege",
"points": 1
},
{
"id": "RunAsUser",
"selector": "containers[] .securityContext .runAsUser -gt 10000",
"reason": "Run as a high-UID user to avoid conflicts with the host's user table",
"points": 1
}
]
}
}
]
root@controlplane:~#