# 安全

從安全的角度來看，Kubernetes 中包含如下圖所示的潛在攻擊面：

![](https://3353600920-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDrteWAzILcdCn0Xcnw23%2Fuploads%2Fgit-blob-d982567aa71c4f9dbd8a5a51e6c57397384da2fd%2Fattach-vectors.png?alt=media)

（圖片來自《Kubernetes Security - Operating Kubernetes Clusters and Applications Safely》）

爲了保證集群以及容器應用的安全，Kubernetes 提供了多種安全機制，限制容器的行爲，減少容器和集群的攻擊面，保證整個系統的安全性。

* 集群安全，比如組件（如 kube-apiserver、etcd、kubelet 等）只開放安全 API並開啓 TLS 認證、開啓 RBAC 等；
* Security Context：限制容器的行爲，包括 Capabilities、ReadOnlyRootFilesystem、Privileged、RunAsNonRoot、RunAsUser 以及 SELinuxOptions 等；
* Pod Security Policy：集群級的 Pod 安全策略，自動爲集群內的 Pod 和 Volume 設置 Security Context；
* Sysctls：允許容器設置內核參數，分爲安全 Sysctls 和非安全 Sysctls；
* AppArmor：限制應用的訪問權限；
* Network Policies：精細控制容器應用和集群中的網絡訪問；
* Seccomp：Secure computing mode 的縮寫，限制容器應用可執行的系統調用。

除此之外，推薦儘量使用較新版本的 Kubernetes，因爲它們通常會包含常見安全問題的修復。你可以參考 [kubernetes-announce](https://groups.google.com/forum/#!forum/kubernetes-announce) 來查詢最新的 Kubernetes 發佈情況，也可以參考 [cvedetails.com](https://www.cvedetails.com/version-list/15867/34016/1/Kubernetes-Kubernetes.html) 查詢 Kubernetes 各個版本的 CVE (Common Vulnerabilities and Exposures) 列表。

## 集群安全

* Kubernetes 組件（如 kube-apiserver、etcd、kubelet 等）只開放安全 API 並開啓 TLS 認證。
* 開啓 RBAC 授權，賦予容器應用最小權限，並開啓 NodeRestriction 准入控制（限制 Kubelet 權限）。
  * RBAC 規則過多或者無法滿足實際需要時，推薦使用 [Open Policy Agent (OPA)](https://www.openpolicyagent.org/) 配置更靈活的訪問策略
* 開啓 Secret 加密存儲（Secret Encryption），並配置 etcd 的 TLS 認證；
* 禁止 Kubelet 的匿名訪問和只讀端口，開啓 Kubelet 的證書輪替更新（Certificate Rotation）。
* 禁止默認 ServiceAccount 的 automountServiceAccountToken，並在需要時創建容器應用的專用 ServiceAccount。
* 禁止 Dashboard 的匿名訪問，通過 RBAC 限制 Dashboard 的訪問權限，並確保 Dashboard 僅可在內網訪問（通過 kubectl proxy）。
* 定期運行 [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/)，確保集群的配置或更新符合最佳的安全實踐（使用 [kube-bench](https://github.com/aquasecurity/kube-bench) 和 [kube-hunter](https://github.com/aquasecurity/kube-hunter)）。
* 在多租戶場景中，還可以使用 Kata Containers、gVisor 等對容器進程進行強隔離，或者使用 Istio、Linkerd 等對容器應用之間的通信也進行自動加密。

## TLS 安全

爲保障 TLS 安全，並避免 [Zombie POODLE and GOLDENDOODLE Vulnerabilities](https://blog.qualys.com/technology/2019/04/22/zombie-poodle-and-goldendoodle-vulnerabilities)，請爲 TLS 1.2 禁止 CBC (Cipher Block Chaining) 模式。

你可以使用 <https://www.ssllabs.com/> 來測試 TLS 的安全問題。

## Security Context 和 Pod Security Policy

```yaml
apiVersion: extensions/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
  annotations:
    # Seccomp v1.11 使用 'runtime/default'，而 v1.10 及更早版本使用 'docker/default'
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'runtime/default'
    seccomp.security.alpha.kubernetes.io/defaultProfileName:  'runtime/default'
    apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
    apparmor.security.beta.kubernetes.io/defaultProfileName:  'runtime/default'
spec:
  privileged: false
  # Required to prevent escalations to root.
  allowPrivilegeEscalation: false
  # This is redundant with non-root + disallow privilege escalation,
  # but we can provide it for defense in depth.
  requiredDropCapabilities:
    - ALL
  # Allow core volume types.
  volumes:
    - 'configMap'
    - 'emptyDir'
    - 'projected'
    - 'secret'
    - 'downwardAPI'
    # Assume that persistentVolumes set up by the cluster admin are safe to use.
    - 'persistentVolumeClaim'
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    # Require the container to run without root privileges.
    rule: 'MustRunAsNonRoot'
  seLinux:
    # This policy assumes the nodes are using AppArmor rather than SELinux.
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'MustRunAs'
    ranges:
      # Forbid adding the root group.
      - min: 1
        max: 65535
  fsGroup:
    rule: 'MustRunAs'
    ranges:
      # Forbid adding the root group.
      - min: 1
        max: 65535
  readOnlyRootFilesystem: false
```

完整參考見[這裏](https://xu-min-chang.gitbook.io/kubernetes/concepts/objects/security-context)。

## Sysctls

Sysctls 允許容器設置內核參數，分爲安全 Sysctls 和非安全 Sysctls

* 安全 Sysctls：即設置後不影響其他 Pod 的內核選項，只作用在容器 namespace 中，默認開啓。包括以下幾種
  * `kernel.shm_rmid_forced`
  * `net.ipv4.ip_local_port_range`
  * `net.ipv4.tcp_syncookies`
* 非安全 Sysctls：即設置好有可能影響其他 Pod 和 Node 上其他服務的內核選項，默認禁止。如果使用，需要管理員在配置 kubelet 時開啓，如 `kubelet --experimental-allowed-unsafe-sysctls 'kernel.msg*,net.ipv4.route.min_pmtu'`

Sysctls 在 v1.11 升級爲 Beta 版，可以通過 PSP spec 直接設置，如

```yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: sysctl-psp
spec:
  allowedUnsafeSysctls:
  - kernel.msg*
  forbiddenSysctls:
  - kernel.shm_rmid_forced
```

而 v1.10 及更早版本則爲 Alpha 階段，需要通過 Pod annotation 設置，如：

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: sysctl-example
  annotations:
    security.alpha.kubernetes.io/sysctls: kernel.shm_rmid_forced=1
    security.alpha.kubernetes.io/unsafe-sysctls: net.ipv4.route.min_pmtu=1000,kernel.msgmax=1 2 3
spec:
  ...
```

## AppArmor

[AppArmor(Application Armor)](http://wiki.apparmor.net/index.php/AppArmor_Core_Policy_Reference) 是 Linux 內核的一個安全模塊，允許系統管理員將每個程序與一個安全配置文件關聯，從而限制程序的功能。通過它你可以指定程序可以讀、寫或運行哪些文件，是否可以打開網絡端口等。作爲對傳統 Unix 的自主訪問控制模塊的補充，AppArmor 提供了強制訪問控制機制。

在使用 AppArmor 之前需要注意

* Kubernetes 版本 >=v1.4
* apiserver 和 kubelet 已開啓 AppArmor 特性，`--feature-gates=AppArmor=true`
* 已開啓 apparmor 內核模塊，通過 `cat /sys/module/apparmor/parameters/enabled` 查看
* 僅支持 docker container runtime
* AppArmor profile 已經加載到內核，通過 `cat /sys/kernel/security/apparmor/profiles` 查看

AppArmor 還在 alpha 階段，需要通過 Pod annotation `container.apparmor.security.beta.kubernetes.io/<container_name>` 來設置。可選的值包括

* `runtime/default`: 使用 Container Runtime 的默認配置
* `localhost/<profile_name>`: 使用已加載到內核的 AppArmor profile

```bash
$ sudo apparmor_parser -q <<EOF
#include <tunables/global>

profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
  #include <abstractions/base>

  file,

  # Deny all file writes.
  deny /** w,
}
EOF'

$ kubectl create -f /dev/stdin <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: hello-apparmor
  annotations:
    container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
spec:
  containers:
  - name: hello
    image: busybox
    command: ["sh", "-c", "echo'Hello AppArmor!'&& sleep 1h"]
EOF
pod "hello-apparmor" created

$ kubectl exec hello-apparmor cat /proc/1/attr/current
k8s-apparmor-example-deny-write (enforce)

$ kubectl exec hello-apparmor touch /tmp/test
touch: /tmp/test: Permission denied
error: error executing remote command: command terminated with non-zero exit code: Error executing in Docker Container: 1
```

## Seccomp

[Seccomp](https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt) 是 Secure computing mode 的縮寫，它是 Linux 內核提供的一個操作，用於限制一個進程可以執行的系統調用．Seccomp 需要有一個配置文件來指明容器進程允許和禁止執行的系統調用。

在 Kubernetes 中，需要將 seccomp 配置文件放到 `/var/lib/kubelet/seccomp` 目錄中（可以通過 kubelet 選項 `--seccomp-profile-root` 修改）。比如禁止 chmod 的格式爲

```bash
$ cat /var/lib/kubelet/seccomp/chmod.json
{
    "defaultAction": "SCMP_ACT_ALLOW",
    "syscalls": [
        {
            "name": "chmod",
            "action": "SCMP_ACT_ERRNO"
        }
    ]
}
```

Seccomp 還在 alpha 階段，需要通過 Pod annotation 設置，包括

* `security.alpha.kubernetes.io/seccomp/pod`：應用到該 Pod 的所有容器
* `security.alpha.kubernetes.io/seccomp/container/<container name>`：應用到指定容器

而 value 有三個選項

* `runtime/default`: 使用 Container Runtime 的默認配置
* `unconfined`: 允許所有系統調用
* `localhost/<profile-name>`: 使用 Node 本地安裝的 seccomp，需要放到 `/var/lib/kubelet/seccomp` 目錄中

比如使用剛纔創建的 seccomp 配置：

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: trustworthy-pod
  annotations:
    seccomp.security.alpha.kubernetes.io/pod: localhost/chmod
spec:
  containers:
    - name: trustworthy-container
      image: sotrustworthy:latest
```

## kube-bench

[kube-bench](https://github.com/aquasecurity/kube-bench) 提供了一個簡單的工具來檢查 Kubernetes 的配置（包括 master 和 node）是否符合最佳的安全實踐（基於 [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/)）。

**推薦所有生產環境的 Kubernetes 集群定期運行 kube-bench，保證集群配置符合最佳的安全實踐。**

安裝 `kube-bench`：

```bash
$ docker run --rm -v `pwd`:/host aquasec/kube-bench:latest install
$ ./kube-bench <master|node>
```

當然，kube-bench 也可以直接在容器內運行，比如通常對 Master 和 Node 的檢查命令分別爲：

```bash
$ kubectl apply -f https://github.com/feiskyer/kubernetes-handbook/raw/master/examples/job-master.yaml
job.batch/kube-bench-master created

$ kubectl apply -f https://github.com/feiskyer/kubernetes-handbook/raw/master/examples/job-node.yaml
job.batch/kube-bench-node created

# Wait for a few seconds for the job to complete
$ kubectl get pods
NAME                      READY   STATUS      RESTARTS   AGE
kube-bench-master-k7jdd   0/1     Completed   0          2m15s
kube-bench-node-p9sl9     0/1     Completed   0          2m15s

# The results are held in the pod's logs
$ kubectl logs kube-bench-master-k7jdd
[INFO] 1 Master Node Security Configuration
[INFO] 1.1 API Server
...
```

## 鏡像安全

### Clair

[Clair](https://github.com/coreos/clair/) 是 CoreOS 開源的容器安全工具，用來靜態分析鏡像中潛在的安全問題。推薦將 Clair 集成到 Devops 流程中，自動對所有鏡像進行安全掃描。

安裝 Clair 的方法爲：

```bash
git clone https://github.com/coreos/clair
cd clair/contrib/helm
helm dependency update clair
helm install clair
```

Clair 項目本身只提供了 API，在實際使用中還需要一個[客戶端（或集成Clair的服務）](https://quay.github.io/clair/howto/deployment.html)配合使用。比如，使用 [reg](https://github.com/genuinetools/reg) 的方法爲

```bash
# Install
$ go get github.com/genuinetools/reg

# Vulnerability Reports
$ reg vulns --clair https://clair.j3ss.co r.j3ss.co/chrome

# Generating Static Website for a Registry
$ $ reg server --clair https://clair.j3ss.co
```

### trivy

[trivy](https://github.com/aquasecurity/trivy) 是 Aqua Security 開源的容器漏洞掃描工具。相對於 Clair 來說，使用起來更爲簡單，可以更方便集成到 CI 中。

```bash
# Install
sudo apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install -y trivy

# Image Scanning
trivy python:3.4-alpine
```

### 其他工具

其他鏡像安全掃描工具還有：

* [National Vulnerability Database](https://nvd.nist.gov/)
* [OpenSCAP tools](https://www.open-scap.org/tools/)
* [coreos/clair](https://github.com/coreos/clair)
* [aquasecurity/microscanner](https://github.com/aquasecurity/microscanner)
* [Docker Registry Server](https://docs.docker.com/registry/deploying/)
* [GitLab Container Registry](https://docs.gitlab.com/ee/user/project/container_registry.html)
* [Red Hat Quay container registry](https://www.openshift.com/products/quay)
* [Amazon Elastic Container Registry](https://aws.amazon.com/ecr/)
* [theupdateframework/notary](https://github.com/theupdateframework/notary)
* [weaveworks/flux](https://github.com/weaveworks/flux)
* [IBM/portieris](https://github.com/IBM/portieris)
* [Grafeas](https://grafeas.io/)
* [in-toto](https://in-toto.github.io/)

## 安全工具

開源產品：

* [falco](https://github.com/falcosecurity/falco)：容器運行時安全行爲監控工具。
* [docker-bench-security](https://github.com/docker/docker-bench-security)：Docker 環境安全檢查工具。
* [kube-hunter](https://github.com/aquasecurity/kube-hunter)：Kubernetes 集群滲透測試工具。
* <https://github.com/shyiko/kubesec>
* [Istio](https://istio.io/)
* [Linkerd](https://linkerd.io/)
* [Open Vulnerability and Assessment Language](https://oval.mitre.org/index.html)
* [jetstack/cert-manager](https://github.com/jetstack/cert-manager/)
* [Kata Containers](https://katacontainers.io/)
* [google/gvisor](https://github.com/google/gvisor)
* [SPIFFE](https://spiffe.io/)
* [Open Policy Agent](https://www.openpolicyagent.org/)

商業產品

* [Twistlock](https://www.twistlock.com/)
* [Aqua Container Security Platform](https://www.aquasec.com/)
* [Sysdig Secure](https://sysdig.com/products/secure/)
* [Neuvector](https://neuvector.com/)

## 參考文檔

* [Securing a Kubernetes cluster](https://kubernetes.io/docs/tasks/administer-cluster/securing-a-cluster/)
* [kube-bench](https://github.com/aquasecurity/kube-bench)
* [Kubernetes Security - Operating Kubernetes Clusters and Applications Safely](https://kubernetes-security.info)
* [Kubernetes Security - Best Practice Guide](https://github.com/freach/kubernetes-security-best-practice)
