了解什麼是 Security Context
實作:
在前兩天的文章中,我們了解了「人」與「服務」的權限設定,今天我們來看看「容器內部」的權限。
容器內部的權限和「Linux 的權限設定」比較有關,例如 UID、GID、Linux Capabilities 等等。當我們在 Pod 中執行特定的指令時,這些指令預設會以 root 的身分在容器中執行:
sleep 3600
指令:kubectl run busybox --image=busybox --command -- sleep 3600
kubectl exec busybox -- ps aux
PID USER TIME COMMAND
1 root 0:00 sleep 3600
6 root 0:00 ps aux
不過預設用 root 來跑指令,在安全性上是有風險的,因為 root 身分的在容器內可以進行任何操作,包括讀取、寫入、刪除檔案等等。
除了安全上的風險,容器中的「檔案權限」也是個問題。如果在容器中用 root 身分建立了一個檔案,就只有 root 身分可以讀取,其他使用者想讀取出非改權限,會造成一定程度的麻煩。
為了解決這些問題,我們來看看今天的主角:Security Context。
Security Context 可以在 yaml 中對 Pod 進行以下設定:
UID、GID:指定 Pod 中執行的使用者身分、群組身分
SELinux:指定 SELinux 的標籤
fsGroup:指定 volume 檔案的群組身分 (GID)
Linux Capabilities:指定可以有哪些 Linux Capabilities,capabilities 的清單可以參考這裡
Seccomp:過濾 container 中的 system call
allowPrivilegeEscalation:允許某個 process 的權限大於其 parent process
Security Context 還有很多其他玩法,可以參考官方文件
下面我們來實際嘗試 Security Context 三種設定:UID & GID、fsGroup、Linux Capabilities。
在 Linux 中,每個使用者都會有自己的 UID、GID,這會直接影響到使用者的權限。
UID、GID 可以用 id
指令查看:
id
輸出:
id
uid=0(root) gid=0(root) groups=0(root)
spec.securityContext
中指定容器「預設」的 UID、GID:# sc-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: sc-test
spec:
securityContext:
runAsUser: 1000
runAsGroup: 2000
containers:
- name: sc-test
image: busybox
command: [ "sleep", "3600"]
kubectl apply -f busybox.yaml
kubectl exec sc-test -- ps aux
PID USER TIME COMMAND
1 1000 0:00 sleep 3600
7 1000 0:00 ps aux
kubectl exec -it sc-test -- id
uid=1000 gid=2000 groups=2000
如果 Pod 中有多個容器,某個容器不想使用預設的 UID、GID,可以在spec.containers[].securityContext
中指定:
# multi-sc-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: multi-sc-test
spec:
securityContext:
runAsUser: 1000
runAsGroup: 2000
containers:
- name: use-default
image: busybox
command: [ "sleep", "3600"]
- name: use-custom
image: busybox
command: [ "sleep", "3600"]
securityContext:
runAsUser: 1001
runAsGroup: 2001
kubectl apply -f multi-sc-test.yaml
kubectl exec multi-sc-test -c use-default -- id
uid=1000 gid=2000 groups=2000
kubectl exec multi-sc-test -c use-custom -- id
uid=1001 gid=2001 groups=2001
所以,Pod Level 的 Security Context 用來設定所有容器的預設值,如果容器有自己的 Security Context,則會覆蓋 Pod Level 的設定。
為了解決檔案權限的問題,Security Context 可以讓容器裡「volume 的檔案」都屬於同一個群組,進而達到共享的目的,這可以使用 spec.securityContext.fsGroup
來設定:
下面的 fsgroup-demo 有兩個容器:writer & reader。
# fsgroup-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: fsgroup-demo
spec:
securityContext:
fsGroup: 2000
containers:
- name: writer
image: busybox
command: ["sh", "-c", "sleep 1h"]
volumeMounts:
- name: shared-data
mountPath: /data
- name: reader
image: busybox
command: ["sh", "-c", "sleep 1h"]
volumeMounts:
- name: shared-data
mountPath: /data
securityContext:
runAsUser: 1000
runAsGroup: 2000
volumes:
- name: shared-data
emptyDir: {}
kubectl apply -f fsgroup-demo.yaml
kubectl exec -it fsgroup-demo -c writer -- sh
id
uid=0(root) gid=0(root) groups=0(root),10(wheel),2000
echo "test fsgroup" > /data/test.txt
kubectl exec fsgroup-demo -c reader -- ls -l /data
total 4
-rw-r--r-- 1 root 2000 13 Sep 16 05:21 test.txt
可以看到,雖然 writer 是 root 的身分,但是建立出的 test.txt 檔案只有擁有者為 root,而所屬群組則是 2000,而 2000 群組有「r」權限,所以 reader 容器可以讀取 test.txt 檔案:
kubectl exec fsgroup-demo -c reader -- cat /data/test.txt
輸出:
test fsgroup
Linux Capabilities 是一種可以讓「process 擁有部分 root 權限」的機制,可以讓 process 在不需要完整 root 權限的情況下執行某些操作。
# normal.yaml
apiVersion: v1
kind: Pod
metadata:
name: normal
spec:
containers:
- name: ubuntu
image: ubuntu
command: ["sh", "-c", "sleep 1h"]
kubectl apply -f normal.yaml
kubectl exec normal -- cat /proc/1/status | grep CapPrm
CapPrm: 00000000a80425fb
以16進位表示的 capabilities,每個 bit 代表一個 capability (等下比較時我們會轉成2進位)
SYS_TIME
的 capability:# set-time.yaml
apiVersion: v1
kind: Pod
metadata:
name: set-time
spec:
containers:
- name: ubuntu
image: ubuntu
command: ["sh", "-c", "sleep 1h"]
securityContext:
capabilities:
add: ["SYS_TIME"]
kubectl apply -f set-time.yaml
kubectl exec -it set-time -- cat /proc/1/status | grep CapPrm
CapPrm: 00000000aa0425fb
底下我們將兩個 Pod 的 capabilities 轉成2進位,這樣比對起來比較清楚:
normal:
1010 1000 0000 0100 0010 0101 1111 1011
set-time:
1010 1010 0000 0100 0010 0101 1111 1011
可以看到 set-time 多了一個 bit (左邊數來第七個),這個 bit 就是 SYS_TIME 的 capability。
練習後別忘了清理環境喔
kubectl delete pod --all
Security Context 可以讓我們控制 Pod 的權限、檔案權限、capabilities 等等,關於其他 Security Context 的玩法,可以參考官方文件。
今天是 【Cluster Configuration】的最後一篇,明天我們來看這個系列的最後一個章節:【Troubleshooting & Monitoring】。
參考資料
Configure a Security Context for a Pod or Container