🚨 v1 API is deprecated, please read the release notes 🚨
For more examples visit Kubesec.io, which uses ControlPlane's hosted API at v2.kubesec.io/scan.
- Quick Start
- Download Kubesec
- Usage Examples
- HTTP Server Mode
- Kubesec-as-a-Service
- Contributing
- Getting Help
- Changelog
Create a Kubernetes resource file (e.g., kubesec-test.yaml) to scan. For a quick test, you can save the following Pod
manifest:
$ 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
EOFExecute a scan against your manifest file:
# Using the local binary
kubesec scan kubesec-test.yaml
# Or using Docker
docker run -i kubesec/kubesec:v2 scan /dev/stdin < kubesec-test.yaml
# Using the local binary with a human-readable table output format
kubesec scan kubesec-test.yaml --format tableTip
To view the results in a human-readable table instead of the default JSON format, use the --format table flag
kubesec will output a security score and a detailed analysis of your resource.
Kubesec is available as a:
- Docker container image at
docker.io/kubesec/kubesec:v2 - Linux/MacOS/Win binary (get the latest release)
- Kubernetes Admission Controller
- Kubectl plugin
Or install the latest commit from GitHub with:
$ go install github.com/controlplaneio/kubesec/v2@latest$ GO111MODULE="on" go get github.com/controlplaneio/kubesec/v2Scan Kubernetes resources from local files or standard input.
Kubesec can scan multiple YAML documents in a single input file, or scan documents from multiple files at once, as long
as they are correctly formatted as multiple documents separated by ---.
# Scan a specific local YAML file
kubesec scan ./deployment.yaml
# Scan from standard input (JSON or YAML)
cat file.json | kubesec scan -
# Scan a rendered Helm chart
helm template -f values.yaml ./chart | kubesec scan /dev/stdin
# Scan multiple YAML documents separated by '---'
{ cat test/asset/multi.yml; echo "---"; cat test/asset/critical.yml; } | kubesec scan -You can run the same scanning commands using the official Docker image:
# Scan a file via Docker using standard input
docker run -i kubesec/kubesec:v2 scan /dev/stdin < kubesec-test.yamlKubesec supports three different output formats, specified by the --format / -f flag: json (default),
table, and template, and can scan multiple YAML documents in a single input file.
# JSON array output (default behaviour)
kubesec scan ./deployment.yaml --format json
# Human-readable table output
kubesec scan ./deployment.yaml --format table
# Use a custom template for the output
kubesec scan ./deployment.yaml --format template --template report-template.tmpl# One rule
kubesec scan --rules CapSysAdmin kubesec-test.yaml
# Multiple rules
kubesec scan --rules RunAsNonRoot,SeccompAny,ApparmorAny kubesec-test.yaml[
{
"object": "Pod/security-context-demo.default",
"valid": true,
"message": "Failed with a score of -30 points",
"score": -30,
"scoring": {
"critical": [
{
"selector": "containers[] .securityContext .capabilities .add == SYS_ADMIN",
"reason": "CAP_SYS_ADMIN is the most privileged capability and should always be avoided",
"points": -30
}
],
"advise": [
{
"selector": "containers[] .securityContext .runAsNonRoot == true",
"reason": "Force the running image to run as a non-root user to ensure least privilege",
"points": 1
},
{
// ...
}
]
}
}
]# Print all scanning rules with their associated point scores
kubesec print-rules
# Print all scanning rules with their associated point scores as a table
kubesec print-rules --format table[
{
"id": "AllowPrivilegeEscalation",
"selector": "containers[] .securityContext .allowPrivilegeEscalation == true",
"reason": "Ensure a non-root process can not gain more privileges",
"kinds": [
"Pod",
"Deployment",
"StatefulSet",
"DaemonSet"
],
"points": -7,
"advise": 0
},
...
]Kubesec leverages kubeconform (thanks @yannh) to validate the manifests to scan. This implies that specifying different schema locations follows the rules as described in the kubeconform README.
# Usees the latest schema from upstream
# Schema will be fetched from: https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/master-standalone-strict/pod-v1.json
kubesec scan ./pod.yaml
# Use a specific schema version from upstream (format x.y.z with no v prefix)
# Schema will be fetched from: https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.25.3-standalone-strict/pod-v1.json
kubesec scan ./pod.yaml --kubernetes-version 1.25.3
# Use a specific schema version in an airgapped environment over HTTP
# Schema will be fetched from: `https://host.server/v<version>-standalone-strict/pod-v1.json`
kubesec scan ./deployment.yaml --kubernetes-version <version> --schema-location https://host.server
# Use a specific schema version in an airgap environment with local files
# Schema will be read from: `/opt/schemas/v<version>-standalone-strict/pod-v1.json`
kubesec scan ./deployment.yaml --kubernetes-version <version> --schema-location /opt/schemasNote: in order to limit external network calls and allow usage in airgap
environments, the kubesec image embeds schemas. If you are looking to change
the schema location, you'll need to change the K8S_SCHEMA_VER and SCHEMA_LOCATION
environment variables at runtime.
Kubesec includes a bundled HTTP server that you can run locally or in a container to accept scan requests over the network.
# Start the HTTP server in the background on port 8080
kubesec http 8080 &
# Send a file to the running server via POST
curl -sSX POST --data-binary @deployment.yaml http://localhost:8080/scan
# Stop the background local server when finished
kill %# Start the HTTP server using Docker
docker run -d -p 8080:8080 kubesec/kubesec:v2 http 8080
# Send a file to the running server via POST
curl -sSX POST --data-binary @deployment.yaml http://localhost:8080/scanDon't forget to stop the server.
Kubesec is also available via HTTPS at v2.kubesec.io/scan.
Do not submit sensitive YAML to this public service.
The service is ran on a good faith best effort basis.
# Submit a manifest directly to the hosted v2 API
curl -sSX POST --data-binary @"deployment.yaml" https://v2.kubesec.io/scan
# Parse the API output using jq to return a non-zero exit code if the score is <= 10
curl -sSX POST --data-binary @"deployment.yaml" https://v2.kubesec.io/scan | jq --exit-status '.score > 10'
# Use the "rule" query parameter to scan only specific rules (multiple supported)
curl -sSX POST --data-binary @test/asset/score-0-cap-sys-admin.yml "http://localhost:8080/scan?rule=SeccompAny&rule=ApparmorAny"You may also define a Bash function, e.g.:
# Define a BASH function
$ kubesec ()
{
local FILE="${1:-}";
[[ ! -e "${FILE}" ]] && {
echo "kubesec: ${FILE}: No such file" >&2;
return 1
};
curl --silent \
--compressed \
--connect-timeout 5 \
-sSX POST \
--data-binary=@"${FILE}" \
https://v2.kubesec.io/scan
}
# POST a Kubernetes resource to v2.kubesec.io/scan
$ kubesec ./deployment.yml
# Return non-zero status code is the score is not greater than 10
$ kubesec ./score-9-deployment.yml | jq --exit-status '.score > 10' >/dev/null
# status code 1Check out CONTRIBUTING.md for more information.
If you have any questions about Kubesec and Kubernetes security:
- Read the Kubesec docs
- Reach out on Twitter to @sublimino or @controlplaneio
- File an issue
Your feedback is always welcome!
Made with ❤ by ControlPlane


