scanning-kubernetes-manifests-with-kubesec

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Scanning Kubernetes Manifests with Kubesec

使用Kubesec扫描Kubernetes资源清单

Overview

概述

Kubesec is an open-source security risk analysis tool developed by ControlPlane that inspects Kubernetes resource manifests for common exploitable risks such as privilege escalation, writable host mounts, and excessive capabilities. It assigns a numerical security score to each resource and provides actionable recommendations for hardening. Kubesec can be used as a CLI binary, Docker container, kubectl plugin, admission webhook, or REST API endpoint.
Kubesec是ControlPlane开发的一款开源安全风险分析工具,用于检查Kubernetes资源清单中常见的可利用风险,如权限提升、可写主机挂载和过度权限。它为每个资源分配一个数值安全评分,并提供可操作的加固建议。Kubesec可作为CLI二进制文件、Docker容器、kubectl插件、准入Webhook或REST API端点使用。

When to Use

使用场景

  • When conducting security assessments that involve scanning kubernetes manifests with kubesec
  • When following incident response procedures for related security events
  • When performing scheduled security testing or auditing activities
  • When validating security controls through hands-on testing
  • 开展涉及用Kubesec扫描Kubernetes资源清单的安全评估时
  • 遵循相关安全事件的应急响应流程时
  • 执行定期安全测试或审计活动时
  • 通过实操测试验证安全控制措施时

Prerequisites

前置条件

  • Kubernetes manifest files (YAML/JSON) for Deployments, Pods, DaemonSets, StatefulSets
  • Docker or Go runtime for local installation
  • kubectl access for scanning live cluster resources
  • CI/CD pipeline access for automated scanning integration
  • 用于Deployment、Pod、DaemonSet、StatefulSet的Kubernetes资源清单文件(YAML/JSON格式)
  • 用于本地安装的Docker或Go运行时
  • 用于扫描集群实时资源的kubectl访问权限
  • 用于集成自动化扫描的CI/CD流水线访问权限

Core Concepts

核心概念

Security Scoring System

安全评分系统

Kubesec assigns a score to each Kubernetes resource based on security checks:
  • Positive scores: Awarded for security-enhancing configurations (readOnlyRootFilesystem, runAsNonRoot)
  • Zero or negative scores: Indicate missing security controls or dangerous configurations
  • Critical advisories: Flagged configurations that represent immediate security risks
Kubesec基于安全检查为每个Kubernetes资源分配评分:
  • 正分数:授予具备安全增强配置的资源(如ReadOnlyRootFilesystem、runAsNonRoot)
  • 零分或负分数:表示缺少安全控制措施或存在危险配置
  • 关键警告:标记代表即时安全风险的配置

Check Categories

检查类别

  1. Privilege Controls: Checks for privileged containers, host PID/network access, root execution
  2. Capabilities: Identifies excessive Linux capabilities (SYS_ADMIN, NET_RAW)
  3. Volume Mounts: Detects dangerous host path mounts and writable sensitive paths
  4. Resource Limits: Validates presence of CPU/memory resource constraints
  5. Security Context: Verifies seccomp profiles, AppArmor annotations, SELinux contexts
  1. 权限控制:检查特权容器、主机PID/网络访问、以root用户运行等情况
  2. 权限能力:识别过度的Linux权限能力(如SYS_ADMIN、NET_RAW)
  3. 卷挂载:检测危险的主机路径挂载和可写敏感路径
  4. 资源限制:验证是否存在CPU/内存资源约束
  5. 安全上下文:检查seccomp配置文件、AppArmor注解、SELinux上下文

Installation

安装

Binary Installation

二进制安装

bash
undefined
bash
undefined

Linux/macOS

Linux/macOS

Verify installation

验证安装

kubesec version
undefined
kubesec version
undefined

Docker Installation

Docker安装

bash
docker pull kubesec/kubesec:v2
bash
docker pull kubesec/kubesec:v2

Scan a manifest file

扫描资源清单文件

docker run -i kubesec/kubesec:v2 scan /dev/stdin < deployment.yaml
undefined
docker run -i kubesec/kubesec:v2 scan /dev/stdin < deployment.yaml
undefined

kubectl Plugin

kubectl插件

bash
kubectl krew install kubesec-scan
kubectl kubesec-scan pod mypod -n default
bash
kubectl krew install kubesec-scan
kubectl kubesec-scan pod mypod -n default

Practical Scanning

实操扫描

Scanning a Single Manifest

扫描单个资源清单

bash
undefined
bash
undefined

Scan a deployment manifest

扫描Deployment资源清单

kubesec scan deployment.yaml
kubesec scan deployment.yaml

Scan with JSON output

以JSON格式输出扫描结果

kubesec scan -o json deployment.yaml
kubesec scan -o json deployment.yaml

Scan from stdin

从标准输入扫描

cat pod.yaml | kubesec scan -
undefined
cat pod.yaml | kubesec scan -
undefined

Sample Output

示例输出

json
[
  {
    "object": "Pod/web-app.default",
    "valid": true,
    "fileName": "pod.yaml",
    "message": "Passed with a score of 3 points",
    "score": 3,
    "scoring": {
      "passed": [
        {
          "id": "ReadOnlyRootFilesystem",
          "selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
          "reason": "An immutable root filesystem prevents applications from writing to their local disk",
          "points": 1
        },
        {
          "id": "RunAsNonRoot",
          "selector": "containers[] .securityContext .runAsNonRoot == true",
          "reason": "Force the running image to run as a non-root user",
          "points": 1
        },
        {
          "id": "LimitsCPU",
          "selector": "containers[] .resources .limits .cpu",
          "reason": "Enforcing CPU limits prevents DOS via resource exhaustion",
          "points": 1
        }
      ],
      "advise": [
        {
          "id": "ApparmorAny",
          "selector": "metadata .annotations .\"container.apparmor.security.beta.kubernetes.io/nginx\"",
          "reason": "Well defined AppArmor policies reduce the attack surface of the container",
          "points": 3
        },
        {
          "id": "ServiceAccountName",
          "selector": ".spec .serviceAccountName",
          "reason": "Service accounts restrict Kubernetes API access and should be configured",
          "points": 3
        }
      ]
    }
  }
]
json
[
  {
    "object": "Pod/web-app.default",
    "valid": true,
    "fileName": "pod.yaml",
    "message": "Passed with a score of 3 points",
    "score": 3,
    "scoring": {
      "passed": [
        {
          "id": "ReadOnlyRootFilesystem",
          "selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
          "reason": "An immutable root filesystem prevents applications from writing to their local disk",
          "points": 1
        },
        {
          "id": "RunAsNonRoot",
          "selector": "containers[] .securityContext .runAsNonRoot == true",
          "reason": "Force the running image to run as a non-root user",
          "points": 1
        },
        {
          "id": "LimitsCPU",
          "selector": "containers[] .resources .limits .cpu",
          "reason": "Enforcing CPU limits prevents DOS via resource exhaustion",
          "points": 1
        }
      ],
      "advise": [
        {
          "id": "ApparmorAny",
          "selector": "metadata .annotations .\"container.apparmor.security.beta.kubernetes.io/nginx\"",
          "reason": "Well defined AppArmor policies reduce the attack surface of the container",
          "points": 3
        },
        {
          "id": "ServiceAccountName",
          "selector": ".spec .serviceAccountName",
          "reason": "Service accounts restrict Kubernetes API access and should be configured",
          "points": 3
        }
      ]
    }
  }
]

Scanning Multiple Resources

扫描多个资源

bash
undefined
bash
undefined

Scan all YAML files in a directory

扫描目录下所有YAML文件

for file in manifests/*.yaml; do echo "=== Scanning $file ===" kubesec scan "$file" done
for file in manifests/*.yaml; do echo "=== 扫描 $file ===" kubesec scan "$file" done

Scan multi-document YAML

扫描多文档YAML文件

kubesec scan multi-resource.yaml
undefined
kubesec scan multi-resource.yaml
undefined

Using the HTTP API

使用HTTP API

bash
undefined
bash
undefined

Scan via the public API

通过公共API扫描

curl -sSX POST --data-binary @deployment.yaml
https://v2.kubesec.io/scan
curl -sSX POST --data-binary @deployment.yaml
https://v2.kubesec.io/scan

Run a local API server

运行本地API服务器

kubesec http --port 8080 &
kubesec http --port 8080 &

Scan against local server

针对本地服务器扫描

curl -sSX POST --data-binary @deployment.yaml
http://localhost:8080/scan
undefined
curl -sSX POST --data-binary @deployment.yaml
http://localhost:8080/scan
undefined

CI/CD Integration

CI/CD集成

GitHub Actions

GitHub Actions

yaml
name: Kubesec Scan
on: [pull_request]
jobs:
  kubesec:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Kubesec
        run: |
          curl -sSL https://github.com/controlplaneio/kubesec/releases/latest/download/kubesec_linux_amd64.tar.gz | \
            tar xz -C /usr/local/bin/ kubesec
      - name: Scan Manifests
        run: |
          FAIL=0
          for file in k8s/*.yaml; do
            SCORE=$(kubesec scan "$file" | jq '.[0].score')
            echo "$file: score=$SCORE"
            if [ "$SCORE" -lt 0 ]; then
              echo "FAIL: $file has critical issues (score: $SCORE)"
              FAIL=1
            fi
          done
          exit $FAIL
yaml
name: Kubesec Scan
on: [pull_request]
jobs:
  kubesec:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Kubesec
        run: |
          curl -sSL https://github.com/controlplaneio/kubesec/releases/latest/download/kubesec_linux_amd64.tar.gz | \
            tar xz -C /usr/local/bin/ kubesec
      - name: Scan Manifests
        run: |
          FAIL=0
          for file in k8s/*.yaml; do
            SCORE=$(kubesec scan "$file" | jq '.[0].score')
            echo "$file: score=$SCORE"
            if [ "$SCORE" -lt 0 ]; then
              echo "FAIL: $file 存在严重问题(评分: $SCORE)"
              FAIL=1
            fi
          done
          exit $FAIL

GitLab CI

GitLab CI

yaml
kubesec-scan:
  stage: security
  image: kubesec/kubesec:v2
  script:
    - |
      for file in k8s/*.yaml; do
        kubesec scan "$file" > /tmp/result.json
        SCORE=$(cat /tmp/result.json | jq '.[0].score')
        if [ "$SCORE" -lt 0 ]; then
          echo "CRITICAL: $file scored $SCORE"
          cat /tmp/result.json | jq '.[0].scoring.critical'
          exit 1
        fi
      done
  artifacts:
    paths:
      - kubesec-results/
yaml
kubesec-scan:
  stage: security
  image: kubesec/kubesec:v2
  script:
    - |
      for file in k8s/*.yaml; do
        kubesec scan "$file" > /tmp/result.json
        SCORE=$(cat /tmp/result.json | jq '.[0].score')
        if [ "$SCORE" -lt 0 ]; then
          echo "CRITICAL: $file 评分为 $SCORE"
          cat /tmp/result.json | jq '.[0].scoring.critical'
          exit 1
        fi
      done
  artifacts:
    paths:
      - kubesec-results/

Admission Webhook

准入Webhook

Deploy Kubesec as a ValidatingWebhookConfiguration to reject insecure manifests at deploy time:
yaml
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: kubesec-webhook
webhooks:
  - name: kubesec.controlplane.io
    rules:
      - apiGroups: [""]
        apiVersions: ["v1"]
        operations: ["CREATE", "UPDATE"]
        resources: ["pods"]
      - apiGroups: ["apps"]
        apiVersions: ["v1"]
        operations: ["CREATE", "UPDATE"]
        resources: ["deployments", "daemonsets", "statefulsets"]
    clientConfig:
      service:
        name: kubesec-webhook
        namespace: kube-system
        path: /scan
    failurePolicy: Fail
    sideEffects: None
    admissionReviewVersions: ["v1"]
将Kubesec部署为ValidatingWebhookConfiguration,在部署阶段拒绝不安全的资源清单:
yaml
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: kubesec-webhook
webhooks:
  - name: kubesec.controlplane.io
    rules:
      - apiGroups: [""]
        apiVersions: ["v1"]
        operations: ["CREATE", "UPDATE"]
        resources: ["pods"]
      - apiGroups: ["apps"]
        apiVersions: ["v1"]
        operations: ["CREATE", "UPDATE"]
        resources: ["deployments", "daemonsets", "statefulsets"]
    clientConfig:
      service:
        name: kubesec-webhook
        namespace: kube-system
        path: /scan
    failurePolicy: Fail
    sideEffects: None
    admissionReviewVersions: ["v1"]

Security Checks Reference

安全检查参考

Critical Checks (Negative Score)

关键检查(负分)

CheckSelectorRisk
Privileged
securityContext.privileged == true
Full host access
HostPID
spec.hostPID == true
Process namespace escape
HostNetwork
spec.hostNetwork == true
Network namespace escape
SYS_ADMIN
capabilities.add contains SYS_ADMIN
Near-root capability
检查项选择器风险
Privileged
securityContext.privileged == true
完全主机访问权限
HostPID
spec.hostPID == true
进程命名空间逃逸
HostNetwork
spec.hostNetwork == true
网络命名空间逃逸
SYS_ADMIN
capabilities.add contains SYS_ADMIN
接近root的权限能力

Best Practice Checks (Positive Score)

最佳实践检查(正分)

CheckPointsDescription
ReadOnlyRootFilesystem+1Prevents filesystem writes
RunAsNonRoot+1Non-root process execution
RunAsUser > 10000+1High UID reduces collision risk
LimitsCPU+1Prevents CPU resource exhaustion
LimitsMemory+1Prevents memory resource exhaustion
RequestsCPU+1Ensures scheduler resource awareness
ServiceAccountName+3Explicit service account
AppArmor annotation+3Kernel-level MAC enforcement
Seccomp profile+4Syscall filtering
检查项分值描述
ReadOnlyRootFilesystem+1阻止文件系统写入
RunAsNonRoot+1以非root进程执行
RunAsUser > 10000+1高UID降低冲突风险
LimitsCPU+1防止CPU资源耗尽
LimitsMemory+1防止内存资源耗尽
RequestsCPU+1确保调度器感知资源需求
ServiceAccountName+3显式配置服务账户
AppArmor annotation+3内核级强制访问控制(MAC)
Seccomp profile+4系统调用过滤

References

参考资料