W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
特性狀態(tài): Kubernetes v1.4 [beta]
AppArmor 是一個 Linux 內(nèi)核安全模塊, 它補充了基于標準 Linux 用戶和組的權(quán)限,將程序限制在一組有限的資源中。 AppArmor 可以配置為任何應用程序減少潛在的攻擊面,并且提供更加深入的防御。 它通過調(diào)整配置文件進行配置,以允許特定程序或容器所需的訪問, 如 Linux 權(quán)能字、網(wǎng)絡訪問、文件權(quán)限等。 每個配置文件都可以在 強制(enforcing) 模式(阻止訪問不允許的資源)或 投訴(complain) 模式(僅報告沖突)下運行。
AppArmor 可以通過限制允許容器執(zhí)行的操作, 和/或通過系統(tǒng)日志提供更好的審計來幫助你運行更安全的部署。 但是,重要的是要記住 AppArmor 不是靈丹妙藥, 只能做部分事情來防止應用程序代碼中的漏洞。 提供良好的限制性配置文件,并從其他角度強化你的應用程序和集群非常重要。
確保:
kubectl get nodes -o=jsonpath={range .items[*]}{@.metadata.name}: {@.status.nodeInfo.kubeletVersion}\n{end}'
gke-test-default-pool-239f5d02-gyn2: v1.4.0
gke-test-default-pool-239f5d02-x1kf: v1.4.0
gke-test-default-pool-239f5d02-xwux: v1.4.0
/sys/module/apparmor/parameters/enabled
? 文件:cat /sys/module/apparmor/parameters/enabled
Y
如果 Kubelet 包含 AppArmor 支持(>= v1.4), 但是內(nèi)核模塊未啟用,它將拒絕運行帶有 AppArmor 選項的 Pod。
說明: Ubuntu 攜帶了許多沒有合并到上游 Linux 內(nèi)核中的 AppArmor 補丁, 包括添加附加鉤子和特性的補丁。Kubernetes 只在上游版本中測試過,不承諾支持其他特性。
/sys/kernel/security/apparmor/profiles
? 文件, 可以查看節(jié)點加載了哪些配置文件。例如:ssh gke-test-default-pool-239f5d02-gyn2 "sudo cat /sys/kernel/security/apparmor/profiles | sort"
apparmor-test-deny-write (enforce)
apparmor-test-audit-write (enforce)
docker-default (enforce)
k8s-nginx (enforce)
只要 Kubelet 版本包含 AppArmor 支持(>=v1.4), 如果不滿足這些先決條件,Kubelet 將拒絕帶有 AppArmor 選項的 Pod。 你還可以通過檢查節(jié)點就緒狀況消息來驗證節(jié)點上的 AppArmor 支持(盡管這可能會在以后的版本中刪除):
kubectl get nodes -o=jsonpath={range .items[*]}{@.metadata.name}: {.status.conditions[?(@.reason=="KubeletReady")].message}\n{end}'
gke-test-default-pool-239f5d02-gyn2: kubelet is posting ready status. AppArmor enabled
gke-test-default-pool-239f5d02-x1kf: kubelet is posting ready status. AppArmor enabled
gke-test-default-pool-239f5d02-xwux: kubelet is posting ready status. AppArmor enabled
說明:
AppArmor 目前處于 Beta 階段,因此選項以注解形式設定。 一旦 AppArmor 支持進入正式發(fā)布階段,注解將被替換為一階的資源字段。
AppArmor 配置文件是按 逐個容器 的形式來設置的。 要指定用來運行 Pod 容器的 AppArmor 配置文件,請向 Pod 的 metadata 添加注解:
container.apparmor.security.beta.kubernetes.io/<container_name>: <profile_ref>
?<container_name>
? 的名稱是配置文件所針對的容器的名稱,?<profile_def>
? 則設置要應用的配置文件。 ?<profile_ref>
? 可以是以下取值之一:
runtime/default
? 應用運行時的默認配置localhost/<profile_name>
? 應用在主機上加載的名為 ?<profile_name>
? 的配置文件unconfined
?表示不加載配置文件Kubernetes AppArmor 強制執(zhí)行機制首先檢查所有先決條件都已滿足, 然后將所選的配置文件轉(zhuǎn)發(fā)到容器運行時進行強制執(zhí)行。 如果未滿足先決條件,Pod 將被拒絕,并且不會運行。
要驗證是否應用了配置文件,可以在容器創(chuàng)建事件中查找所列出的 AppArmor 安全選項:
kubectl get events | grep Created
22s 22s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet e2e-test-stclair-node-pool-31nt} Created container with docker id 269a53b202d3; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write]
你還可以通過檢查容器的 proc attr,直接驗證容器的根進程是否以正確的配置文件運行:
kubectl exec <pod_name> cat /proc/1/attr/current
k8s-apparmor-example-deny-write (enforce)
本例假設你已經(jīng)設置了一個集群使用 AppArmor 支持。
首先,我們需要將要使用的配置文件加載到節(jié)點上。配置文件拒絕所有文件寫入:
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
由于我們不知道 Pod 將被調(diào)度到哪里,我們需要在所有節(jié)點上加載配置文件。在本例中,我們將使用 SSH 來安裝概要文件。
NODES=(
# The SSH-accessible domain names of your nodes
gke-test-default-pool-239f5d02-gyn2.us-central1-a.my-k8s
gke-test-default-pool-239f5d02-x1kf.us-central1-a.my-k8s
gke-test-default-pool-239f5d02-xwux.us-central1-a.my-k8s)
for NODE in ${NODES[*]}; do ssh $NODE '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'
done
接下來,我們將運行一個帶有拒絕寫入配置文件的簡單 “Hello AppArmor” Pod:
apiVersion: v1
kind: Pod
metadata:
name: hello-apparmor
annotations:
# Tell Kubernetes to apply the AppArmor profile "k8s-apparmor-example-deny-write".
# Note that this is ignored if the Kubernetes node is not running version 1.4 or greater.
container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
spec:
containers:
- name: hello
image: busybox:1.28
command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
kubectl create -f ./hello-apparmor.yaml
如果我們查看 Pod 事件,我們可以看到 Pod 容器是用 AppArmor 配置文件 “k8s-apparmor-example-deny-write” 所創(chuàng)建的:
kubectl get events | grep hello-apparmor
14s 14s 1 hello-apparmor Pod Normal Scheduled {default-scheduler } Successfully assigned hello-apparmor to gke-test-default-pool-239f5d02-gyn2
14s 14s 1 hello-apparmor Pod spec.containers{hello} Normal Pulling {kubelet gke-test-default-pool-239f5d02-gyn2} pulling image "busybox"
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Pulled {kubelet gke-test-default-pool-239f5d02-gyn2} Successfully pulled image "busybox"
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet gke-test-default-pool-239f5d02-gyn2} Created container with docker id 06b6cd1c0989; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write]
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Started {kubelet gke-test-default-pool-239f5d02-gyn2} Started container with docker id 06b6cd1c0989
我們可以通過檢查該配置文件的 proc attr 來驗證容器是否實際使用該配置文件運行:
kubectl exec hello-apparmor -- cat /proc/1/attr/current
k8s-apparmor-example-deny-write (enforce)
最后,我們可以看到,如果我們嘗試通過寫入文件來違反配置文件會發(fā)生什么:
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
最后,讓我們看看如果我們試圖指定一個尚未加載的配置文件會發(fā)生什么:
kubectl create -f /dev/stdin <<EOF
apiVersion: v1
kind: Pod
metadata:
name: hello-apparmor-2
annotations:
container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-allow-write
spec:
containers:
- name: hello
image: busybox:1.28
command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
EOF
pod/hello-apparmor-2 created
kubectl describe pod hello-apparmor-2
Name: hello-apparmor-2
Namespace: default
Node: gke-test-default-pool-239f5d02-x1kf/
Start Time: Tue, 30 Aug 2016 17:58:56 -0700
Labels: <none>
Annotations: container.apparmor.security.beta.kubernetes.io/hello=localhost/k8s-apparmor-example-allow-write
Status: Pending
Reason: AppArmor
Message: Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
IP:
Controllers: <none>
Containers:
hello:
Container ID:
Image: busybox
Image ID:
Port:
Command:
sh
-c
echo 'Hello AppArmor!' && sleep 1h
State: Waiting
Reason: Blocked
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-dnz7v (ro)
Conditions:
Type Status
Initialized True
Ready False
PodScheduled True
Volumes:
default-token-dnz7v:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-dnz7v
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
23s 23s 1 {default-scheduler } Normal Scheduled Successfully assigned hello-apparmor-2 to e2e-test-stclair-node-pool-t1f5
23s 23s 1 {kubelet e2e-test-stclair-node-pool-t1f5} Warning AppArmor Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
注意 Pod 呈現(xiàn) Pending 狀態(tài),并且顯示一條有用的錯誤信息: ?Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
?。 還用相同的消息記錄了一個事件。
Kubernetes 目前不提供任何本地機制來將 AppArmor 配置文件加載到節(jié)點上。 有很多方法可以設置配置文件,例如:
調(diào)度程序不知道哪些配置文件加載到哪個節(jié)點上,因此必須將全套配置文件加載到每個節(jié)點上。 另一種方法是為節(jié)點上的每個配置文件(或配置文件類)添加節(jié)點標簽, 并使用節(jié)點選擇器確保 Pod 在具有所需配置文件的節(jié)點上運行。
說明:
PodSecurityPolicy 在 Kubernetes v1.21 版本中已被廢棄,將在 v1.25 版本移除。
如果啟用了 PodSecurityPolicy 擴展,則可以應用集群范圍的 AppArmor 限制。 要啟用 PodSecurityPolicy,必須在 ?apiserver
?上設置以下標志:
--enable-admission-plugins=PodSecurityPolicy[,others...]
AppArmor 選項可以指定為 PodSecurityPolicy 上的注解:
apparmor.security.beta.kubernetes.io/defaultProfileName: <profile_ref>
apparmor.security.beta.kubernetes.io/allowedProfileNames: <profile_ref>[,others...]
默認配置文件名選項指定默認情況下在未指定任何配置文件時應用于容器的配置文件。 所允許的配置文件名稱選項指定允許 Pod 容器運行期間所對應的配置文件列表。 如果同時提供了這兩個選項,則必須允許默認值。 配置文件的指定格式與容器上的相同。
如果你不希望 AppArmor 在集群上可用,可以通過命令行標志禁用它:
--feature-gates=AppArmor=false
禁用時,任何包含 AppArmor 配置文件的 Pod 都將導致驗證失敗,且返回 “Forbidden” 錯誤。
說明:
即使此 Kubernetes 特性被禁用,運行時仍可能強制執(zhí)行默認配置文件。 當 AppArmor 升級為正式版 (GA) 時,禁用 AppArmor 功能的選項將被刪除。
獲得正確指定的 AppArmor 配置文件可能是一件棘手的事情。幸運的是,有一些工具可以幫助你做到這一點:
aa-genprof
? 和 ?aa-logprof
? 通過監(jiān)視應用程序的活動和日志并準許它所執(zhí)行的操作來生成配置文件規(guī)則。 AppArmor 文檔提供了進一步的指導。想要調(diào)試 AppArmor 的問題,你可以檢查系統(tǒng)日志,查看具體拒絕了什么。 AppArmor 將詳細消息記錄到 ?dmesg
?, 錯誤通常可以在系統(tǒng)日志中或通過 ?journalctl
?找到。 更多詳細信息見 AppArmor 失敗。
指定容器將使用的配置文件:
container.apparmor.security.beta.kubernetes.io/<container_name>
? ,其中 ?<container_name>
? 與 Pod 中某容器的名稱匹配。 可以為 Pod 中的每個容器指定單獨的配置文件。runtime/default
?: 指默認運行時配置文件。localhost/<profile_name>
?: 按名稱引用加載到節(jié)點(localhost)上的配置文件。unconfined
?: 這相當于為容器禁用 AppArmor。任何其他配置文件引用格式無效。
指定在未提供容器時應用于容器的默認配置文件:
apparmor.security.beta.kubernetes.io/defaultProfileName
?上面描述的指定配置文件,Pod 容器列表的配置文件引用允許指定:
apparmor.security.beta.kubernetes.io/allowedProfileNames
?盡管轉(zhuǎn)義逗號是配置文件名中的合法字符,但此處不能顯式允許。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: