使用內建 Linux 安全性功能存取資源的安全性容器
在本文中,您將瞭解如何保護 Azure Kubernetes Service (AKS) 工作負載對資源的容器存取。
概觀
就如同您應授與使用者或群組所需的最低權限一樣,也應限制容器只能執行必要動作和流程。 為了將攻擊風險降到最低,請避免設定需要提升權限或根存取的應用程式和容器。
您可以使用內建 Kubernetes Pod 安全性內容 來定義更多許可權,例如要執行身分的使用者或群組、要公開的 Linux 功能,或在 Pod 指令清單中設定 allowPrivilegeEscalation: false
。 如需最佳做法詳細資訊,請參閱保護 Pod 對資源的存取。
如需更細微的容器動作控制,您可以使用內建的Linux安全性功能,例如 AppArmor 和 seccomp。
- 在節點層級定義 Linux 安全性功能。
- 透過 Pod 資訊清單實作功能。
內建 Linux 安全性功能僅適用於 Linux 節點和 Pod。
注意
目前,Kubernetes 環境對於惡意多租使用者使用並不完全安全。 其他安全性功能,例如 Microsoft適用於容器的 Defender、AppArmor、seccomp、Pod 安全性許可或適用於節點的 Kubernetes RBAC,有效率地封鎖惡意探索。
執行惡意多租用戶工作負載時,若要真正確保安全性,應該只信任 Hypervisor。 Kubernetes 的安全性網域會變成整個叢集,而不是個別節點。
對於這些類型的惡意多租用戶工作負載,您應使用實際隔離的叢集。
App Armor
若要限制容器動作,您可以使用 AppArmor Linux 核心安全性模組。 AppArmor 是基礎 AKS 節點 OS 的一部分,預設為啟用。 您可以建立 AppArmor 設定檔來限制讀取、寫入或執行動作,也可以限制系統功能,例如裝載檔案系統。 默認 AppArmor 配置檔會限制對各種 /proc
和 /sys
位置的存取,並提供一種方法,以邏輯方式隔離容器與基礎節點。 AppArmor 適用於任何在 Linux 上執行的應用程式,而不只是 Kubernetes Pod。
若要了解 AppArmor 如何運作,下列範例會建立防止寫入檔案的設定檔。
AKS 節點的 SSH。
建立名為 deny-write.profile 的檔案。
複製並貼上下列內容:
#include <tunables/global> profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { #include <abstractions/base> file, # Deny all file writes. deny /** w, }
使用 apparmor_parser
命令新增 AppArmor 設定檔。
將設定檔新增至 AppArmor。
指定在上個步驟中所建立設定檔的名稱:
sudo apparmor_parser deny-write.profile
如果設定檔已正確剖析並套用至 AppArmor,您就不會看到任何輸出,而且您將返回命令提示字元。
現在,在本機電腦上建立名為 aks-apparmor.yaml 的 Pod 資訊清單。 此資訊清單:
- 定義
container.apparmor.security.beta.kubernetes
的註釋。 - 參考在前面步驟中建立的 deny-write 設定檔。
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: mcr.microsoft.com/dotnet/runtime-deps:6.0 command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
- 定義
部署 Pod 後,請執行下列命令來確認 hello-apparmor Pod 會顯示執行狀態:
kubectl get pods NAME READY STATUS RESTARTS AGE aks-ssh 1/1 Running 0 4m2s hello-apparmor 0/1 Running 0 50s
如需 AppArmor 的詳細資訊,請參閱 Kube 中的 AppArmor 設定檔。
安全運算 (seccomp)
AppArmor 適用於任何的 Linux 應用程式,而 seccomp (安全運算) 則是在處理序層級運作。 Seccomp 也是 Linux 核心安全性模組,由 AKS 節點所使用的運行時間原生支援 containerd
。 使用 seccomp,您可以限制容器的系統呼叫。 Seccomp 會針對惡意執行者惡意探索的常見系統呼叫弱點建立額外的保護層,並可讓您指定節點中所有工作負載的預設配置檔。
設定預設 seccomp 設定檔 (預覽)
您可以在建立新的 Linux 節點集區時,使用自訂節點組態來套用預設 seccomp 設定檔。 AKS 支援兩個值: RuntimeDefault
和 Unconfined
。 某些工作負載可能需要比其他工作負載少一些 syscall 限制。 這表示它們可以在運行時間期間使用 『RuntimeDefault』 設定文件失敗。 若要減輕這類失敗,您可以指定 Unconfined
配置檔。 如果您的工作負載需要自定義配置檔,請參閱 設定自定義 seccomp 配置檔。
限制
- SeccompDefault 不是 Windows 節點集區支援的參數。
- SeccompDefault 從 2024-09-02-preview API 開始提供。
重要
AKS 預覽功能可透過自助服務,以加入方式使用。 預覽會以「現狀」和「可供使用時」提供,其其不受服務等級協定和有限瑕疵擔保所保護。 客戶支援部門會盡最大努力,部分支援 AKS 預覽。 因此,這些功能不適合實際執行用途。 如需詳細資訊,請參閱下列支援文章:
註冊 KubeletDefaultSeccompProfilePreview
功能旗標
使用
az feature register
命令註冊KubeletDefaultSeccompProfilePreview
功能旗標。az feature register --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
狀態需要幾分鐘的時間才會顯示「已註冊」。
使用
az feature show
命令確認註冊狀態。az feature show --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
當狀態顯示為「已註冊」時,請使用
az provider register
命令,重新整理 Microsoft.ContainerService 資源提供者的註冊。az provider register --namespace Microsoft.ContainerService
使用 seccomp 限制容器的系統呼叫
1.請遵循步驟,藉由指定 "seccompDefault": "RuntimeDefault"
,在 kubelet 設定中套用 seccomp 配置檔。
RuntimeDefault
會使用 containerd 的預設 seccomp 配置檔,限制特定系統呼叫來增強安全性。 受限制的 syscalls 將會失敗。 如需詳細資訊,請參閱 containerD default seccomp 配置檔。
2.檢查是否已套用設定。
您可以連線 到主機 ,並確認已在文件系統上進行組態變更,以確認這些設定已套用至節點。
3.針對工作負載失敗進行疑難解答。
啟用 SeccompDefault 時,預設會針對節點上排程的所有工作負載使用容器運行時間預設 seccomp 配置檔。 這可能會導致工作負載因為封鎖的 syscalls 而失敗。 如果工作負載失敗發生,您可能會看到錯誤,例如:
- 啟用功能之後,工作負載會意外存在,並出現「許可權遭拒」錯誤。
- 您也可以在稽核或 syslog 中看到 Seccomp 錯誤訊息,方法是將SCMP_ACT_ERRNO取代為預設配置檔中的SCMP_ACT_LOG。
如果您遇到錯誤,建議您將 seccomp 設定檔案變更為 Unconfined
。 Unconfined
不會限制 syscalls,允許所有系統呼叫,以減少安全性。
設定自訂 seccomp 設定檔
使用自定義 seccomp 設定檔,您可以更細微地控制受限制的 syscalls。 符合只授與容器最小執行權限的最佳做法:
- 使用篩選要允許或拒絕的動作來定義。
- 在 Pod YAML 資訊清單內標註,以與 seccomp 篩選建立關聯。
若要看 Seccomp 實際運作,請建立一個防止變更檔案權限的篩選。
AKS 節點的 SSH。
建立名為 /var/lib/kubelet/seccomp/prevent-chmod 的 seccomp 篩選。
複製並貼上下列內容:
{ "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "name": "chmod", "action": "SCMP_ACT_ERRNO" }, { "name": "fchmodat", "action": "SCMP_ACT_ERRNO" }, { "name": "chmodat", "action": "SCMP_ACT_ERRNO" } ] }
在 1.19 版和更新版本中,您需要設定:
{ "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "names": ["chmod","fchmodat","chmodat"], "action": "SCMP_ACT_ERRNO" } ] }
在本機電腦上建立名為 aks-seccomp.yaml 的 Pod 資訊清單,然後貼上下列內容。 此資訊清單:
- 定義
seccomp.security.alpha.kubernetes.io
的註釋。 - 參考在上一步中建立的 prevent-chmod 篩選條件。
apiVersion: v1 kind: Pod metadata: name: chmod-prevented annotations: seccomp.security.alpha.kubernetes.io/pod: localhost/prevent-chmod spec: containers: - name: chmod image: mcr.microsoft.com/dotnet/runtime-deps:6.0 command: - "chmod" args: - "777" - /etc/hostname restartPolicy: Never
在 1.19 版和更新版本中,您需要設定:
apiVersion: v1 kind: Pod metadata: name: chmod-prevented spec: securityContext: seccompProfile: type: Localhost localhostProfile: prevent-chmod containers: - name: chmod image: mcr.microsoft.com/dotnet/runtime-deps:6.0 command: - "chmod" args: - "777" - /etc/hostname restartPolicy: Never
- 定義
使用 kubectl apply 命令部署範例 Pod:
kubectl apply -f ./aks-seccomp.yaml
使用 kubectl get pods 命令檢視 Pod 的狀態。
- Pod 會回報錯誤。
- 命令
chmod
無法由 seccomp 篩選條件執行,如範例輸出所示:
kubectl get pods NAME READY STATUS RESTARTS AGE chmod-prevented 0/1 Error 0 7s
Seccomp 安全性設定檔選項
Seccomp 安全性設定檔是一組已定義的 syscalls,允許或限制。 大部分的容器運行時間都有預設 seccomp 配置檔,如果與 Docker 所使用的配置檔不同,則類似。 如需可用配置檔的詳細資訊,請參閱 Docker 或 containerD 預設 seccomp 配置檔。
當您使用自定義節點組態設定 seccomp 時,AKS 會針對 RuntimeDefault 使用 containerD default seccomp 配置檔。
默認配置文件封鎖的重大 syscalls
Docker 和 containerD 都會維護安全 syscalls 的 allowlist。 下表列出有效封鎖的重大(但並非全部)syscalls,因為它們不在允許清單中。 如果您的工作負載需要任何封鎖的 syscalls,請勿使用 RuntimeDefault
seccomp 配置檔。
對 Docker 和 containerD 進行變更時,AKS 會更新其預設組態以符合。 此清單的更新可能會導致工作負載失敗。 如需版本更新,請參閱 AKS 版本資訊。
封鎖的 syscall | 描述 |
---|---|
acct |
帳戶 syscall 可讓容器停用自己的資源限制或處理會計。 也由 CAP_SYS_PACCT 閘道。 |
add_key |
防止容器使用非命名空間的核心索引鍵器。 |
bpf |
拒絕將潛在的持續性 bpf 程式載入核心,且已由 CAP_SYS_ADMIN 閘道。 |
clock_adjtime |
時間/日期不是命名空間。 也由 CAP_SYS_TIME 閘道。 |
clock_settime |
時間/日期不是命名空間。 也由 CAP_SYS_TIME 閘道。 |
clone |
拒絕複製新的命名空間。 此外,依 CAP_SYS_ADMIN for CLONE_* 旗標進行閘道,但 除外 CLONE_NEWUSER 。 |
create_module |
拒絕核心模組上的操作和函式。 已過時。 也由 CAP_SYS_MODULE 閘道。 |
delete_module |
拒絕核心模組上的操作和函式。 也由 CAP_SYS_MODULE 閘道。 |
finit_module |
拒絕核心模組上的操作和函式。 也由 CAP_SYS_MODULE 閘道。 |
get_kernel_syms |
拒絕擷取導出的核心和模組符號。 已過時。 |
get_mempolicy |
修改核心記憶體和 NUMA 設定的 Syscall。 已經由 CAP_SYS_NICE 閘道。 |
init_module |
拒絕核心模組上的操作和函式。 也由 CAP_SYS_MODULE 閘道。 |
ioperm |
防止容器修改核心 I/O 許可權等級。 已經由 CAP_SYS_RAWIO 閘道。 |
iopl |
防止容器修改核心 I/O 許可權等級。 已經由 CAP_SYS_RAWIO 閘道。 |
kcmp |
藉由卸 CAP_SYS_PTRACE 除 來限制已封鎖的進程檢查功能。 |
kexec_file_load |
kexec_load的妹妹, 做同樣的事情, 稍微不同的自變數。 也由 CAP_SYS_BOOT 閘道。 |
kexec_load |
拒絕載入新的核心以供稍後執行。 也由 CAP_SYS_BOOT 閘道。 |
keyctl |
防止容器使用非命名空間的核心索引鍵器。 |
lookup_dcookie |
追蹤/分析 syscall,這可能會洩漏主機上的資訊。 也由 CAP_SYS_ADMIN 閘道。 |
mbind |
修改核心記憶體和 NUMA 設定的 Syscall。 已經由 CAP_SYS_NICE 閘道。 |
mount |
拒絕掛接,已由閘道 CAP_SYS_ADMIN 。 |
move_pages |
修改核心記憶體和 NUMA 設定的 Syscall。 |
nfsservctl |
拒絕與核心 nfs 精靈的互動。 自 Linux 3.1 起已過時。 |
open_by_handle_at |
舊容器中斷的原因。 也由 CAP_DAC_READ_SEARCH 閘道。 |
perf_event_open |
追蹤/分析 syscall,這可能會洩漏主機上的資訊。 |
personality |
防止容器啟用 BSD 模擬。 並非本質上是危險的,但測試不佳,有可能是核心巨魔。 |
pivot_root |
拒絕pivot_root,應該是特殊許可權作業。 |
process_vm_readv |
藉由卸 CAP_SYS_PTRACE 除 來限制已封鎖的進程檢查功能。 |
process_vm_writev |
藉由卸 CAP_SYS_PTRACE 除 來限制已封鎖的進程檢查功能。 |
ptrace |
追蹤/分析 syscall。 在 4.8 之前的 Linux 核心版本中封鎖,以避免 seccomp 略過。 追蹤/分析任意進程已經遭到封鎖,因為可能會洩漏主機上的資訊CAP_SYS_PTRACE。 |
query_module |
拒絕核心模組上的操作和函式。 已過時。 |
quotactl |
配額 syscall 可讓容器停用自己的資源限制或處理會計。 也由 CAP_SYS_ADMIN 閘道。 |
reboot |
不要讓容器重新啟動主機。 也由 CAP_SYS_BOOT 閘道。 |
request_key |
防止容器使用非命名空間的核心索引鍵器。 |
set_mempolicy |
修改核心記憶體和 NUMA 設定的 Syscall。 已經由 CAP_SYS_NICE 閘道。 |
setns |
拒絕將線程與命名空間產生關聯。 也由 CAP_SYS_ADMIN 閘道。 |
settimeofday |
時間/日期不是命名空間。 也由 CAP_SYS_TIME 閘道。 |
stime |
時間/日期不是命名空間。 也由 CAP_SYS_TIME 閘道。 |
swapon |
拒絕開始/停止交換至檔案/裝置。 也由 CAP_SYS_ADMIN 閘道。 |
swapoff |
拒絕開始/停止交換至檔案/裝置。 也由 CAP_SYS_ADMIN 閘道。 |
sysfs |
過時的 syscall。 |
_sysctl |
已過時,由 /proc/sys 取代。 |
umount |
應該是特殊許可權作業。 也由 CAP_SYS_ADMIN 閘道。 |
umount2 |
應該是特殊許可權作業。 也由 CAP_SYS_ADMIN 閘道。 |
unshare |
拒絕複製進程的新命名空間。 此外,除了 unshare --user 之外,也會受到 CAP_SYS_ADMIN 閘道。 |
uselib |
與共享連結庫相關的舊版 syscall,長時間未使用。 |
userfaultfd |
Userspace 頁面錯誤處理,基本上需要處理移轉。 |
ustat |
過時的 syscall。 |
vm86 |
在核心 x86 實際模式虛擬機中。 也由 CAP_SYS_ADMIN 閘道。 |
vm86old |
在核心 x86 實際模式虛擬機中。 也由 CAP_SYS_ADMIN 閘道。 |
下一步
如需相關聯的最佳做法,請參閱 AKS 中叢集安全性和升級的最佳做法以及 AKS 中 Pod 安全性的最佳做法。