Secret 管理和审计

Secret 管理和审计

Secret 管理和审计日志是 Kubernetes 安全的最后一道防线。

Secret 管理

Secret 基础

# 创建 Secret
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
  namespace: production
type: Opaque
stringData:  # 自动 base64 编码
  username: admin
  password: P@ssw0rd123!
  api-key: abc123xyz789

在 Pod 中使用 Secret

方式 1:环境变量

apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
  - name: app
    image: myapp:1.0
    env:
    # 单个 key
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: password
    
    # 所有 key
    envFrom:
    - secretRef:
        name: app-secret

方式 2:Volume 挂载(推荐)

apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
  - name: app
    image: myapp:1.0
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secrets
      readOnly: true
  
  volumes:
  - name: secret-volume
    secret:
      secretName: app-secret
      defaultMode: 0400  # 只读权限

Secret 加密存储

Kubernetes 默认将 Secret 以 base64 编码存储在 etcd,并非加密

启用 etcd 加密

# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:
      keys:
      - name: key1
        secret: <base64-encoded-32-byte-key>
  - identity: {}  # 回退到未加密(用于读取旧数据)
# 生成加密密钥
head -c 32 /dev/urandom | base64

# 配置 kube-apiserver
# 在 /etc/kubernetes/manifests/kube-apiserver.yaml 中添加:
--encryption-provider-config=/etc/kubernetes/encryption-config.yaml

加密所有现有 Secret

# 重新写入所有 Secret 以使用新的加密配置
kubectl get secrets --all-namespaces -o json | \
  kubectl replace -f -

外部 Secret 管理

HashiCorp Vault

安装 Vault

# 使用 Helm 安装
helm repo add hashicorp https://helm.releases.hashicorp.com
helm install vault hashicorp/vault \
  --namespace vault \
  --create-namespace \
  --set server.dev.enabled=true

配置 Kubernetes Auth

# 进入 Vault Pod
kubectl exec -it vault-0 -n vault -- /bin/sh

# 启用 Kubernetes 认证
vault auth enable kubernetes

# 配置 Kubernetes 认证
vault write auth/kubernetes/config \
  kubernetes_host="https://kubernetes.default.svc:443"

# 创建策略
vault policy write myapp - <<EOF
path "secret/data/myapp/*" {
  capabilities = ["read"]
}
EOF

# 创建角色
vault write auth/kubernetes/role/myapp \
  bound_service_account_names=myapp-sa \
  bound_service_account_namespaces=production \
  policies=myapp \
  ttl=24h

存储 Secret

# 写入 Secret
vault kv put secret/myapp/database \
  username=dbuser \
  password=dbpass123

# 读取 Secret
vault kv get secret/myapp/database

在 Pod 中使用 Vault

apiVersion: v1
kind: Pod
metadata:
  name: myapp
  namespace: production
spec:
  serviceAccountName: myapp-sa
  containers:
  - name: app
    image: myapp:1.0
    env:
    - name: VAULT_ADDR
      value: "http://vault.vault:8200"
  
  # 使用 Vault Agent Sidecar
  initContainers:
  - name: vault-agent
    image: vault:1.15.0
    args:
    - agent
    - -config=/vault/config/agent.hcl
    volumeMounts:
    - name: config
      mountPath: /vault/config
    - name: shared-data
      mountPath: /vault/secrets
  
  volumes:
  - name: config
    configMap:
      name: vault-agent-config
  - name: shared-data
    emptyDir: {}

External Secrets Operator

# 安装 External Secrets Operator
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets \
  external-secrets/external-secrets \
  -n external-secrets-system \
  --create-namespace

配置 SecretStore

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-backend
  namespace: production
spec:
  provider:
    vault:
      server: "http://vault.vault:8200"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "myapp"
          serviceAccountRef:
            name: "myapp-sa"

创建 ExternalSecret

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: myapp-secret
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  
  target:
    name: myapp-secret
    creationPolicy: Owner
  
  data:
  - secretKey: database-password
    remoteRef:
      key: myapp/database
      property: password
  
  - secretKey: api-key
    remoteRef:
      key: myapp/api
      property: key

Sealed Secrets

Sealed Secrets 允许加密 Secret 后提交到 Git。

# 安装 Sealed Secrets Controller
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml

# 安装 kubeseal CLI
brew install kubeseal

使用 Sealed Secrets

# 1. 创建普通 Secret
kubectl create secret generic mysecret \
  --from-literal=password=mypassword \
  --dry-run=client -o yaml > secret.yaml

# 2. 加密 Secret
kubeseal -f secret.yaml -w sealed-secret.yaml

# 3. 应用加密的 Secret(安全,可提交到 Git)
kubectl apply -f sealed-secret.yaml

# 4. Controller 自动解密为普通 Secret
kubectl get secret mysecret

审计日志

审计日志记录所有对 API Server 的请求,是安全审计的关键。

启用审计日志

审计策略配置

# /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# 不记录只读请求
- level: None
  verbs: ["get", "list", "watch"]

# 记录 Secret 的所有操作
- level: RequestResponse
  resources:
  - group: ""
    resources: ["secrets"]

# 记录认证令牌
- level: Metadata
  resources:
  - group: ""
    resources: ["serviceaccounts/token"]

# 记录重要的配置变更
- level: Request
  verbs: ["create", "update", "patch", "delete"]
  resources:
  - group: ""
    resources: ["configmaps", "services"]
  - group: "apps"
    resources: ["deployments", "statefulsets", "daemonsets"]
  - group: "rbac.authorization.k8s.io"
    resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]

# 默认记录元数据
- level: Metadata

配置 kube-apiserver

# /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
  containers:
  - command:
    - kube-apiserver
    - --audit-policy-file=/etc/kubernetes/audit-policy.yaml
    - --audit-log-path=/var/log/kubernetes/audit.log
    - --audit-log-maxage=30
    - --audit-log-maxbackup=10
    - --audit-log-maxsize=100
    volumeMounts:
    - name: audit-policy
      mountPath: /etc/kubernetes/audit-policy.yaml
      readOnly: true
    - name: audit-log
      mountPath: /var/log/kubernetes
  volumes:
  - name: audit-policy
    hostPath:
      path: /etc/kubernetes/audit-policy.yaml
      type: File
  - name: audit-log
    hostPath:
      path: /var/log/kubernetes
      type: DirectoryOrCreate

审计日志示例

{
  "kind": "Event",
  "apiVersion": "audit.k8s.io/v1",
  "level": "RequestResponse",
  "auditID": "abc123-def456-ghi789",
  "stage": "ResponseComplete",
  "requestURI": "/api/v1/namespaces/production/secrets/app-secret",
  "verb": "get",
  "user": {
    "username": "alice",
    "groups": ["developers", "system:authenticated"]
  },
  "sourceIPs": ["192.168.1.100"],
  "userAgent": "kubectl/v1.28.0",
  "objectRef": {
    "resource": "secrets",
    "namespace": "production",
    "name": "app-secret",
    "apiVersion": "v1"
  },
  "responseStatus": {
    "code": 200
  },
  "requestReceivedTimestamp": "2024-01-08T12:00:00.000Z",
  "stageTimestamp": "2024-01-08T12:00:00.100Z"
}

审计日志分析

# 查看谁访问了 Secret
cat /var/log/kubernetes/audit.log | \
  jq 'select(.objectRef.resource=="secrets") | 
      {user: .user.username, secret: .objectRef.name, verb: .verb, time: .requestReceivedTimestamp}'

# 查看失败的认证尝试
cat /var/log/kubernetes/audit.log | \
  jq 'select(.responseStatus.code >= 400 and .responseStatus.code < 500)'

# 查看删除操作
cat /var/log/kubernetes/audit.log | \
  jq 'select(.verb=="delete") | 
      {user: .user.username, resource: .objectRef.resource, name: .objectRef.name}'

发送审计日志到 Elasticsearch

# kube-apiserver 配置
--audit-webhook-config-file=/etc/kubernetes/audit-webhook.yaml
--audit-webhook-batch-max-size=100
# audit-webhook.yaml
apiVersion: v1
kind: Config
clusters:
- name: elasticsearch
  cluster:
    server: http://elasticsearch.logging:9200/_bulk
contexts:
- context:
    cluster: elasticsearch
  name: default
current-context: default

Falco 运行时安全

Falco 监控运行时异常行为。

Falco 规则示例

# 检测访问 Secret 的异常行为
- rule: Suspicious Secret Access
  desc: Detect unusual access to Kubernetes secrets
  condition: >
    k8s_audit and ka.verb="get" and 
    ka.target.resource="secrets" and
    not user_known_secret_access
  output: >
    Suspicious secret access 
    (user=%ka.user.name secret=%ka.target.name 
    namespace=%ka.target.namespace)
  priority: WARNING

# 检测容器中执行的敏感命令
- rule: Sensitive Command in Container
  desc: Detect execution of sensitive commands
  condition: >
    spawned_process and container and
    (proc.name in (nc, ncat, nmap, socat, tcpdump, tshark))
  output: >
    Sensitive command executed in container
    (user=%user.name command=%proc.cmdline 
    container=%container.id)
  priority: CRITICAL

# 检测 SSH 登录到容器
- rule: SSH Connection to Container
  desc: Detect SSH connection to a container
  condition: >
    inbound_outbound and container and
    fd.sport=22 and fd.l4proto=tcp
  output: >
    SSH connection to container
    (container=%container.id ip=%fd.rip)
  priority: WARNING

Falco 告警集成

# 配置 Falco 发送告警到 Slack
# /etc/falco/falco.yaml
json_output: true
json_include_output_property: true

http_output:
  enabled: true
  url: "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"

安全扫描工具

Kube-bench

检查集群是否符合 CIS Kubernetes Benchmark。

# 运行 kube-bench
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml

# 查看结果
kubectl logs -f job/kube-bench

# 输出示例:
# [INFO] 1 Master Node Security Configuration
# [PASS] 1.1.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive
# [FAIL] 1.1.2 Ensure that the API server pod specification file ownership is set to root:root
# [WARN] 1.2.1 Ensure that the --anonymous-auth argument is set to false

Kube-hunter

寻找集群安全漏洞。

# 运行 kube-hunter
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-hunter/main/job.yaml

# 查看结果
kubectl logs -f job/kube-hunter

Kubescape

Kubernetes 安全合规性扫描。

# 安装
brew install kubescape

# 扫描集群
kubescape scan

# 扫描特定框架
kubescape scan framework nsa,mitre

# 扫描 YAML 文件
kubescape scan deployment.yaml

最佳实践清单

Secret 管理

  • ✅ 使用外部 Secret 管理系统(Vault)
  • ✅ 启用 etcd 加密
  • ✅ 定期轮换 Secret
  • ✅ 使用 Volume 挂载而非环境变量
  • ✅ 限制 Secret 访问权限(RBAC)
  • ❌ 不要在日志中打印 Secret
  • ❌ 不要将 Secret 提交到 Git

审计日志

  • ✅ 启用审计日志
  • ✅ 记录 Secret 访问
  • ✅ 记录 RBAC 变更
  • ✅ 定期分析审计日志
  • ✅ 设置日志告警
  • ✅ 保留足够的日志历史(30-90天)

运行时安全

  • ✅ 部署 Falco 监控异常行为
  • ✅ 定期运行安全扫描(kube-bench)
  • ✅ 监控容器行为
  • ✅ 设置告警通知
  • ✅ 定期审查安全策略

持续安全

# 在 CI/CD 中集成安全检查
stages:
- build
- scan
- deploy

security-scan:
  stage: scan
  script:
    # 镜像漏洞扫描
    - trivy image --severity HIGH,CRITICAL myapp:$CI_COMMIT_SHA
    
    # YAML 安全检查
    - kubescape scan k8s/*.yaml
    
    # Secret 检测
    - gitleaks detect --source .
    
    # Dockerfile 最佳实践检查
    - hadolint Dockerfile

小结

本节介绍了 Secret 管理和审计:

Secret 管理:加密存储、外部管理(Vault)、Sealed Secrets
审计日志:配置、分析、告警
Falco:运行时安全监控
安全扫描:kube-bench、kube-hunter、kubescape
最佳实践:Secret、审计、运行时、持续安全

至此,安全最佳实践章节全部完成!🎉

下一章:生产环境实践。