kubesec
Security risk analysis for Kubernetes resources
install kubesec from tar.gz
[root@m-k8s ~]# curl -OL https://github.com/controlplaneio/kubesec/releases/download/v2.11.2/kubesec_linux_amd64.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 634 100 634 0 0 2164 0 --:--:-- --:--:-- --:--:-- 2171
100 3970k 100 3970k 0 0 2115k 0 0:00:01 0:00:01 --:--:-- 2569k
[root@m-k8s ~]# tar xvfz kubesec_linux_amd64.tar.gz
CHANGELOG.md
LICENSE
README.md
kubesec
[root@m-k8s ~]# mv kubesec /usr/local/bin
run kubesec scan
[root@m-k8s ~]# kubesec scan components.yaml
[
{
"object": "ServiceAccount/metrics-server.kube-system",
"valid": true,
"fileName": "components.yaml",
"message": "This resource kind is not supported by kubesec",
"score": 0,
"scoring": {}
},
{
"object": "ClusterRole/system:aggregated-metrics-reader.default",
"valid": true,
"fileName": "components.yaml",
"message": "This resource kind is not supported by kubesec",
"score": 0,
"scoring": {}
},
{
"object": "ClusterRole/system:metrics-server.default",
"valid": true,
"fileName": "components.yaml",
"message": "This resource kind is not supported by kubesec",
"score": 0,
"scoring": {}
},
{
"object": "RoleBinding/metrics-server-auth-reader.kube-system",
"valid": true,
"fileName": "components.yaml",
"message": "This resource kind is not supported by kubesec",
"score": 0,
"scoring": {}
},
{
"object": "ClusterRoleBinding/metrics-server:system:auth-delegator.default",
"valid": true,
"fileName": "components.yaml",
"message": "This resource kind is not supported by kubesec",
"score": 0,
"scoring": {}
},
{
"object": "ClusterRoleBinding/system:metrics-server.default",
"valid": true,
"fileName": "components.yaml",
"message": "This resource kind is not supported by kubesec",
"score": 0,
"scoring": {}
},
{
"object": "Service/metrics-server.kube-system",
"valid": true,
"fileName": "components.yaml",
"message": "This resource kind is not supported by kubesec",
"score": 0,
"scoring": {}
},
{
"object": "Deployment/metrics-server.kube-system",
"valid": true,
"fileName": "components.yaml",
"message": "Passed with a score of 7 points",
"score": 7,
"scoring": {
"passed": [
{
"id": "ServiceAccountName",
"selector": ".spec .serviceAccountName",
"reason": "Service accounts restrict Kubernetes API access and should be configured with least privilege",
"points": 3
},
{
"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": "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
}
],
"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": "LimitsMemory",
"selector": "containers[] .resources .limits .memory",
"reason": "Enforcing memory limits prevents DOS via resource exhaustion",
"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": "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
}
]
}
},
{
"object": "APIService/v1beta1.metrics.k8s.io.default",
"valid": true,
"fileName": "components.yaml",
"message": "This resource kind is not supported by kubesec",
"score": 0,
"scoring": {}
}
]
[root@m-k8s ~]# cat <<EOF > kubesec-test.yaml
> apiVersion: v1
> kind: Pod
> metadata:
> name: kubesec-demo
> spec:
> containers:
> - name: kubesec-demo
> image: gcr.io/google-samples/node-hello:1.0
> securityContext:
> readOnlyRootFilesystem: true
> EOF
[root@m-k8s ~]# kubesec scan kubesec-test.yaml
[
{
"object": "Pod/kubesec-demo.default",
"valid": true,
"fileName": "kubesec-test.yaml",
"message": "Passed with a score of 1 points",
"score": 1,
"scoring": {
"passed": [
{
"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": "ServiceAccountName",
"selector": ".spec .serviceAccountName",
"reason": "Service accounts restrict Kubernetes API access and should be configured with least privilege",
"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": "LimitsMemory",
"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
}
]
}
}
]
Last updated