在kubernetes裡使用AppArmor限制容器對資源的訪問

人生的哲理發表於2024-05-29

目錄
  • 一.系統環境
  • 二.前言
  • 三.AppArmor簡介
  • 四.AppArmor和SELinux的區別
  • 五.使用AppArmor限制nginx程式訪問目錄
    • 5.1 安裝nginx
    • 5.2 修改nginx的預設主頁
    • 5.3 安裝AppArmor實用工具
    • 5.4 AppArmor規則解釋
    • 5.5 配置AppArmor規則限制nginx程式訪問目錄
  • 六.在kubernetes裡使用AppArmor限制容器對資源的訪問
    • 6.1 檢查環境
    • 6.2 配置AppArmor規則
    • 6.3 使用AppArmor限制容器對資源的訪問
  • 七.總結

一.系統環境

本文主要基於Kubernetes1.22.2和Linux作業系統Ubuntu 18.04。

伺服器版本 docker軟體版本 Kubernetes(k8s)叢集版本 kube-bench版本 CPU架構
Ubuntu 18.04.5 LTS Docker version 20.10.14 v1.22.2 0.6.7 x86_64

Kubernetes叢集架構:k8scludes1作為master節點,k8scludes2,k8scludes3作為worker節點。

伺服器 作業系統版本 CPU架構 程序 功能描述
k8scludes1/192.168.110.128 Ubuntu 18.04.5 LTS x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master節點
k8scludes2/192.168.110.129 Ubuntu 18.04.5 LTS x86_64 docker,kubelet,kube-proxy,calico k8s worker節點
k8scludes3/192.168.110.130 Ubuntu 18.04.5 LTS x86_64 docker,kubelet,kube-proxy,calico k8s worker節點

二.前言

在現代的雲端計算環境中,安全是每個開發者和運維人員必須關注的問題。尤其是在執行容器的環境中,如何確保容器之間以及容器與宿主機之間的安全隔離,防止惡意行為對系統造成破壞,是一個非常重要的課題。本文將介紹如何使用 AppArmor 來限制容器對資源的訪問,提高系統的安全性。

使用 AppArmor 來限制容器對資源的訪問的前提是已經有一套可以正常執行的Kubernetes叢集,關於Kubernetes(k8s)叢集的安裝部署,可以檢視部落格《Ubuntu 安裝部署Kubernetes(k8s)叢集》https://www.cnblogs.com/renshengdezheli/p/17632858.html。

三.AppArmor簡介

AppArmor 是一種 Linux 核心模組,用於提供強制訪問控制(MAC)功能。它允許管理員為每個程序定義詳細的訪問控制策略,從而限制程序對檔案、目錄、網路介面等資源的訪問。透過使用 AppArmor,我們可以有效地防止惡意軟體或錯誤配置的應用程式對系統資源造成不必要的影響。

AppArmor 的規則檔案通常位於 /etc/apparmor.d/ 目錄下。每個規則檔案對應一個應用或服務,檔名通常以路徑開頭,後面跟著應用的名稱。例如,對於 Nginx 伺服器,其規則檔名為 /etc/apparmor.d/usr.sbin.nginx

AppArmor 規則由一系列的匹配語句組成,每條語句表示一個訪問控制規則。規則的基本結構如下:

<profile> <options> <match> <permissions> <files> <paths> <commands> </profile>

其中:

  • <profile>:指定規則所屬的 profile,可以是預定義的 profile(如 usr.sbin.nginx),也可以是自定義的 profile。
  • <options>:可選欄位,用於指定 profile 的行為選項,如是否啟用日誌記錄等。
  • <match>:必選欄位,用於指定規則適用的條件,如程序名稱、使用者等。
  • <permissions>:必選欄位,用於指定允許或拒絕的操作型別,如讀、寫、執行等。
  • <files>:可選欄位,用於指定規則適用的檔案型別,如普通檔案、目錄、裝置檔案等。
  • <paths>:可選欄位,用於指定規則適用的檔案路徑模式。
  • <commands>:可選欄位,用於指定規則適用的命令名稱。

四.AppArmor和SELinux的區別

雖然 AppArmor 和 SELinux 都是 Linux 上的訪問控制工具,但它們之間存在一些區別:

  • 設計理念:AppArmor 的設計目標是簡單易用,而 SELinux 則更注重細粒度的控制。因此,AppArmor 的策略配置檔案通常比 SELinux 更簡潔。
  • 配置方式:AppArmor 的策略配置檔案採用一種類似於 DSL(領域特定語言)的語法,易於閱讀和編寫;而 SELinux 的策略配置檔案則採用一種更復雜的布林表示式語法。
  • 社群支援:由於 AppArmor 的配置相對簡單,因此在社群中得到了更廣泛的支援和應用。

五.使用AppArmor限制nginx程式訪問目錄

5.1 安裝nginx

建立目錄存放檔案。

root@k8scludes1:~# mkdir systemsafe   

root@k8scludes1:~# cd systemsafe/

安裝nginx。

root@k8scludes1:~/systemsafe# apt-get install nginx

root@k8scludes1:~/systemsafe# which nginx
/usr/sbin/nginx

nginx安裝好之後就可以訪問nginx了。

root@k8scludes1:~/systemsafe# curl 192.168.110.128
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
......
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

5.2 修改nginx的預設主頁

建立一個safe目錄和一個unsafe目錄。

root@k8scludes1:~/systemsafe# mkdir -p /data/www/safe /data/www/unsafe

在safe目錄寫入index.html。

root@k8scludes1:~/systemsafe# vim /data/www/safe/index.html

root@k8scludes1:~/systemsafe# cat /data/www/safe/index.html
<html> 
        <b>Hello! Accessing this file is allowed.</b> 
</html>

在unsafe目錄寫入index.html。

root@k8scludes1:~/systemsafe# vim /data/www/unsafe/index.html

root@k8scludes1:~/systemsafe# cat /data/www/unsafe/index.html
<html> 
        <b>Hello! Accessing this file is forbidden.</b> 
</html>

修改nginx配置檔案,修改nginx的預設主頁目錄為/data/www。

root@k8scludes1:~/systemsafe# vim /etc/nginx/nginx.conf 

root@k8scludes1:~/systemsafe# grep -A10 sites-enabled /etc/nginx/nginx.conf
        #include /etc/nginx/sites-enabled/*;

        server {
          listen 8080;
          location / {
              #root /data/www; 改變nginx的預設主頁
              root /data/www;
            }
        }
}

重啟nginx。

root@k8scludes1:~/systemsafe# systemctl restart nginx

訪問nginx目錄,現在safe和unsafe都可以訪問。

root@k8scludes1:~/systemsafe# curl 192.168.110.128:8080/safe/
<html> 
        <b>Hello! Accessing this file is allowed.</b> 
</html>

root@k8scludes1:~/systemsafe# curl 192.168.110.128:8080/unsafe/
<html> 
        <b>Hello! Accessing this file is forbidden.</b> 
</html>

我們需要配置AppArmor,使nginx可以訪問/data/www/safe/目錄,不可以訪問/data/www/unsafe/目錄,保護敏感資料。

5.3 安裝AppArmor實用工具

檢視系統有沒有安裝AppArmor。

root@k8scludes1:~/systemsafe# dpkg -l | grep apparmor
ii  apparmor                               2.12-4ubuntu5.1                                 amd64        user-space parser utility for AppArmor
ii  libapparmor1:amd64                     2.12-4ubuntu5.1                                 amd64        changehat AppArmor library

更新軟體源。

root@k8scludes1:~/systemsafe# apt-get update

安裝apparmor-utils ,apparmor-profiles, apparmor-profiles-extra。

apparmor-utils 是一組使用者空間的命令列實用工具,可以幫助我們很好的管理 AppArmor 。

apparmor-profiles, apparmor-profiles-extra是一些預先配置的配置檔案,這些配置檔案一般來說是比較完善的,但是也需要根據實際需要進行修改。

root@k8scludes1:~# apt-get install apparmor-utils apparmor-profiles apparmor-profiles-extra -y

檢視apparmor軟體包,現在apparmor工具包就安裝好了。

root@k8scludes1:~# cd systemsafe/

root@k8scludes1:~/systemsafe# dpkg -l | grep apparmor
ii  apparmor                               2.12-4ubuntu5.1                                 amd64        user-space parser utility for AppArmor
ii  apparmor-profiles                      2.12-4ubuntu5.1                                 all          experimental profiles for AppArmor security policies
ii  apparmor-profiles-extra                1.19                                            all          Extra profiles for AppArmor Security policies
ii  apparmor-utils                         2.12-4ubuntu5.1                                 amd64        utilities for controlling AppArmor
ii  libapparmor1:amd64                     2.12-4ubuntu5.1                                 amd64        changehat AppArmor library
ii  python3-apparmor                       2.12-4ubuntu5.1                                 amd64        AppArmor Python3 utility library
ii  python3-libapparmor                    2.12-4ubuntu5.1                                 amd64        AppArmor library Python3 bindings

檢視apparmor是否開啟。

root@k8scludes1:~/systemsafe# aa-enabled 
Yes

apparmor的配置檔案在/etc/apparmor.d目錄下。

root@k8scludes1:~/systemsafe# cd /etc/apparmor.d/

root@k8scludes1:/etc/apparmor.d# pwd
/etc/apparmor.d

usr.bin.man表示 /usr/bin/man的man程式。

root@k8scludes1:/etc/apparmor.d# ls
abstractions        local           tunables                  usr.bin.totem-previewers      usr.lib.dovecot.dovecot-lda        usr.lib.dovecot.pop3             usr.sbin.dovecot   usr.sbin.smbldap-useradd
apache2.d           lxc             usr.bin.chromium-browser  usr.lib.dovecot.anvil         usr.lib.dovecot.imap               usr.lib.dovecot.pop3-login       usr.sbin.identd    usr.sbin.tcpdump
bin.ping            lxc-containers  usr.bin.irssi             usr.lib.dovecot.auth          usr.lib.dovecot.imap-login         usr.lib.dovecot.ssl-params       usr.sbin.mdnsd     usr.sbin.traceroute
cache               sbin.dhclient   usr.bin.lxc-start         usr.lib.dovecot.config        usr.lib.dovecot.lmtp               usr.lib.snapd.snap-confine.real  usr.sbin.nmbd
disable             sbin.klogd      usr.bin.man               usr.lib.dovecot.deliver       usr.lib.dovecot.log                usr.sbin.apt-cacher-ng           usr.sbin.nscd
force-complain      sbin.syslogd    usr.bin.pidgin            usr.lib.dovecot.dict          usr.lib.dovecot.managesieve        usr.sbin.avahi-daemon            usr.sbin.rsyslogd
gst_plugin_scanner  sbin.syslog-ng  usr.bin.totem             usr.lib.dovecot.dovecot-auth  usr.lib.dovecot.managesieve-login  usr.sbin.dnsmasq                 usr.sbin.smbd

5.4 AppArmor規則解釋

aa-autodep生成nginx程序的apparmor配置檔案,aa-autodep nginx自動給nginx生成一套規則。

root@k8scludes1:/etc/apparmor.d# aa-autodep nginx
Writing updated profile for /usr/sbin/nginx.

root@k8scludes1:/etc/apparmor.d# pwd
/etc/apparmor.d

root@k8scludes1:/etc/apparmor.d# ls usr.sbin.nginx 
usr.sbin.nginx

檢視自動生成的規則檔案。

apparmor涉及兩種模式,每個配置檔案都可以在強制(enforcing)模式(阻止訪問不允許的資源)或投訴(complain)模式 (僅報告衝突)下執行:

  1. complain模式(即使沒有滿足條件也放行) ;
  2. enforce模式(必須滿足條件)。

/usr/sbin/nginx flags=(complain)表示啟用的是complain模式。

root@k8scludes1:/etc/apparmor.d# vim usr.sbin.nginx

root@k8scludes1:/etc/apparmor.d# cat usr.sbin.nginx
# Last Modified: Thu May 12 16:12:18 2022
#include <tunables/global>

/usr/sbin/nginx flags=(complain) {
  #include <abstractions/base>

  /lib/x86_64-linux-gnu/ld-*.so mr,
  /usr/sbin/nginx mr,

}

把usr.sbin.nginx的模式變為enforce模式。

root@k8scludes1:/etc/apparmor.d# aa-enforce nginx
Setting /usr/sbin/nginx to enforce mode.

現在usr.sbin.nginx就是enforce模式。

root@k8scludes1:/etc/apparmor.d# cat usr.sbin.nginx
# Last Modified: Thu May 12 16:12:18 2022
#include <tunables/global>

/usr/sbin/nginx {
  #include <abstractions/base>

  /lib/x86_64-linux-gnu/ld-*.so mr,
  /usr/sbin/nginx mr,

}

檢視apparmor許可權幫助。

root@k8scludes1:/etc/apparmor.d# man 5 apparmor.d 

AppArmor允許規則說明:

  • allow /path/file (允許訪問/path/file檔案) ,allow /path/file 規則也可以寫為/path/file ,因為預設是allow規則;
  • allow /path/* (允許訪問/path/目錄下所有檔案,不支援遞迴) ;
  • allow /path/** (允許訪問/path/目錄下所有檔案,支援遞迴),對於/path/aa/aa1/aaa1目錄,allow /path/*規則能匹配到/path/aa 不能匹配到/path/aa/aa1和/path/aa/aa1/aaa1 ,allow /path/** 規則能匹配 /path/目錄下所有檔案。

AppArmor拒絕規則說明:

  • deny /path/file
  • deny /path/*
  • deny /path/**

AppArmor許可權說明:

  • r: 讀;
  • w: 寫;
  • m: 儲存器對映;
  • k: 檔案鎖定;
  • l: 建立硬連結;
  • ix: 執行並繼承該安全配置;
  • Px: 在清理環境之後,執行並使用其他安全配置;
  • Ux: 在清理環境之後,執行不做限制。

apparmor常用命令:

  • aa-unconfined:用於檢測執行在系統上監聽網路連線且不受AppArmor保護的應用程式;
  • aa-autodep:用於建立配置檔案的基本框架,該模板投入使用前需要完善。生成的配置檔案被載入時進入complain模式,報告應用程式中(尚未)被AppArmor規則覆蓋的行為。
  • aa-genprof:生成一個基本配置檔案。透過執行應用程式會激發一系列事件並記錄在日誌中,在配置策略時要認真考慮其中存在的問題,進一步細化配置檔案。生成並被載入時會進入enforce模式。
  • aa-logprof:當應用程式已生成配置檔案並處於complain模式時,其可互動式地掃描和檢查由應用程式生成的日誌條目,輔助完善配置策略。
  • aa-complain:將AppArmor配置檔案從enforce切換為complain模式。不符合配置檔案策略的行為會被記錄,但不會被拒絕。
  • aa-enforce:將AppArmor配置檔案的模式從complain切換到enforce。不符合配置檔案策略的行為會被記錄,且會被拒絕。

5.5 配置AppArmor規則限制nginx程式訪問目錄

編寫AppArmor規則,deny /data/www/unsafe/** r 表示禁止讀/data/www/unsafe/目錄下的檔案。

root@k8scludes1:/etc/apparmor.d# vim usr.sbin.nginx 

root@k8scludes1:/etc/apparmor.d# cat usr.sbin.nginx
# Last Modified: Thu May 12 16:12:18 2022
#include <tunables/global>

/usr/sbin/nginx {
  #include <abstractions/base>
  
  deny /data/www/unsafe/** r,
  /lib/x86_64-linux-gnu/ld-*.so mr,
  /usr/sbin/nginx mr,

}

aa-complain nginx將usr.sbin.nginx切換為complain模式。

root@k8scludes1:/etc/apparmor.d# aa-complain nginx
Setting /usr/sbin/nginx to complain mode.

aa-logprof:當應用程式已生成配置檔案並處於complain模式時,其可互動式地掃描和檢查由應用程式生成的日誌條目,輔助完善配置策略。

root@k8scludes1:/etc/apparmor.d# aa-logprof 
Reading log entries from /var/log/syslog.
Updating AppArmor profiles in /etc/apparmor.d.
Complain-mode changes:

Profile:    /usr/sbin/nginx
Capability: dac_override
Severity:   9

 [1 - #include <abstractions/lxc/container-base>]
  2 - #include <abstractions/lxc/start-container> 
  3 - capability dac_override, 
(A)llow / [(D)eny] / (I)gnore / Audi(t) / Abo(r)t / (F)inish
Adding #include <abstractions/lxc/container-base> to profile.
Deleted 5 previous matching profile entries.
Enforce-mode changes:

= Changed Local Profiles =

The following local profiles were changed. Would you like to save them?

 [1 - /usr/sbin/nginx]
(S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Changes b/w (C)lean profiles / Abo(r)t

= Changed Local Profiles =

The following local profiles were changed. Would you like to save them?

 [1 - /usr/sbin/nginx]
(S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Changes b/w (C)lean profiles / Abo(r)t
Writing updated profile for /usr/sbin/nginx.

檢視新的apparmor規則,拒絕訪問/data/www/unsafe/**目錄。

  • #include <tunables/global>:這一行包含了一個核心引數,tunables/global 提供了對核心引數的訪問,這些引數可以影響AppArmor如何載入和處理規則。
  • /usr/sbin/nginx flags=(complain) {:這行定義了規則集的應用範圍。這裡是針對位於 /usr/sbin/nginx 的程式(即Nginx伺服器)應用這些規則。flags=(complain) 表示這些規則是以complain 模式(complain mode)執行,即AppArmor會記錄不允許的操作,但不會阻止它們。
  • #include <abstractions/base>:包含基礎抽象規則,這些規則提供了最基本的安全策略,比如禁止寫檔案系統等。
  • #include <abstractions/lxc/container-base>:包含LXC容器基礎抽象規則,這些規則適用於容器環境,提供了與容器相關的安全策略。
  • deny /data/www/unsafe/** r,:這一行表示禁止對 /data/www/unsafe/ 目錄及其所有子目錄進行讀取操作。r 代表讀取操作。這意味著Nginx不能訪問這個目錄或其子目錄中的任何檔案。這通常用於限制對敏感資料的訪問。
#include <abstractions/lxc/container-base> 表示載入預設的規則庫
root@k8scludes1:/etc/apparmor.d# cat usr.sbin.nginx 
# Last Modified: Fri May 13 11:37:31 2022
#include <tunables/global>

/usr/sbin/nginx flags=(complain) {
  #include <abstractions/base>
  #include <abstractions/lxc/container-base>

  deny /data/www/unsafe/** r,

}

現在訪問nginx,safe目錄能訪問,unsafe目錄訪問不了。

root@k8scludes1:/etc/apparmor.d# curl 192.168.110.128:8080/safe/
<html> 
        <b>Hello! Accessing this file is allowed.</b> 
</html>


root@k8scludes1:/etc/apparmor.d# curl 192.168.110.128:8080/unsafe/
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.14.0 (Ubuntu)</center>
</body>
</html>

切換為enforce模式。

root@k8scludes1:/etc/apparmor.d# aa-enforce nginx
Setting /usr/sbin/nginx to enforce mode.

root@k8scludes1:/etc/apparmor.d# cat usr.sbin.nginx 
# Last Modified: Fri May 13 11:37:31 2022
#include <tunables/global>

/usr/sbin/nginx {
  #include <abstractions/base>
  #include <abstractions/lxc/container-base>

  deny /data/www/unsafe/** r,

}

enforce模式下,safe可以訪問,unsafe訪問不了,滿足需求了

root@k8scludes1:/etc/apparmor.d# curl 192.168.110.128:8080/safe/
<html> 
        <b>Hello! Accessing this file is allowed.</b> 
</html>

root@k8scludes1:/etc/apparmor.d# curl 192.168.110.128:8080/unsafe/
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.14.0 (Ubuntu)</center>
</body>
</html>

現在修改apparmor規則,使safe不能訪問,unsafe能訪問。

root@k8scludes1:/etc/apparmor.d# vim usr.sbin.nginx 

root@k8scludes1:/etc/apparmor.d# cat usr.sbin.nginx 
# Last Modified: Fri May 13 11:37:31 2022
#include <tunables/global>

/usr/sbin/nginx {
  #include <abstractions/base>
  #include <abstractions/lxc/container-base>

  deny /data/www/safe/** r,

}

重新載入apparmor規則,使配置檔案生效。

root@k8scludes1:/etc/apparmor.d# /etc/init.d/apparmor reload
[ ok ] Reloading apparmor configuration (via systemctl): apparmor.service.

重新載入apparmor規則之後,safe不能訪問,unsafe能訪問。

root@k8scludes1:/etc/apparmor.d# curl 192.168.110.128:8080/unsafe/
<html> 
        <b>Hello! Accessing this file is forbidden.</b> 
</html>

root@k8scludes1:/etc/apparmor.d# curl 192.168.110.128:8080/safe/
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.14.0 (Ubuntu)</center>
</body>
</html>

六.在kubernetes裡使用AppArmor限制容器對資源的訪問

6.1 檢查環境

在 Kubernetes v1.4 版本中才新增了對 AppArmor 的支援。驗證節點的 Kubelet 版本。

root@k8scludes1:~# kubectl get nodes -o=jsonpath={range .items[*]}{@.metadata.name}: {@.status.nodeInfo.kubeletVersion}\n{end}' 

k8scludes1: v1.22.2 

k8scludes2: v1.22.2 

k8scludes3: v1.22.2 

檢視AppArmor 核心模組是否啟用 。

root@k8scludes1:/etc/apparmor.d# cat /sys/module/apparmor/parameters/enabled 
Y 

現在還沒有pod。

root@k8scludes1:/etc/apparmor.d# cd 

root@k8scludes1:~# cd systemsafe/ 

root@k8scludes1:~/systemsafe# kubectl get pod 
No resources found in systemsafe namespace. 

檢視node節點的標籤。

root@k8scludes1:~/systemsafe# kubectl get nodes --show-labels
NAME         STATUS   ROLES                  AGE   VERSION   LABELS
k8scludes1   Ready    control-plane,master   30d   v1.22.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8scludes1,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8scludes2   Ready    <none>                 30d   v1.22.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8scludes2,kubernetes.io/os=linux
k8scludes3   Ready    <none>                 30d   v1.22.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8scludes3,kubernetes.io/os=linux

給k8scludes3節點設定一個標籤yy=xx。

root@k8scludes1:~/systemsafe# kubectl label nodes k8scludes3 yy=xx  

檢視標籤為yy=xx的節點,等下建立的pod,我們讓其執行在k8scludes3節點。

root@k8scludes1:~/systemsafe# kubectl get node -l yy=xx
NAME         STATUS   ROLES    AGE   VERSION
k8scludes3   Ready    <none>   30d   v1.22.2

6.2 配置AppArmor規則

先在k8scludes3節點設定apparmor規則。

root@k8scludes3:~# cd /etc/apparmor.d/ 

root@k8scludes3:/etc/apparmor.d# ls 
abstractions  cache  disable  force-complain  local  lxc  lxc-containers  
sbin.dhclient  tunables  usr.bin.lxc-start  usr.bin.man  usr.lib.snapd.snap-confine.real 
usr.sbin.rsyslogd  usr.sbin.tcpdump 

檢視AppArmor 核心模組是否啟用

root@k8scludes3:~# cat /sys/module/apparmor/parameters/enabled 
Y 

建立一個k8s的apparmor規則檔案。

注意:拒絕的優先順序高於允許的優先順序 。

apparmor的規則為 deny /tmp/aa/** rw 禁止在/tmp/aa/目錄下讀寫 。

k8s-apparmor-profile-deny-write是AppArmor規則的名字。

root@k8scludes3:/etc/apparmor.d# vim k8s-apparmorprofile 

root@k8scludes3:/etc/apparmor.d# cat k8s-apparmorprofile 
#include <tunables/global> 
profile k8s-apparmor-profile-deny-write flags=(attach_disconnected) { 
#include <abstractions/base> 
#include <abstractions/lxc/container-base> 
#file, 
allow /proc/** rw, 
allow /usr/bin/sleep rwkix, 
allow /bin/* rwkix, 
allow /root/** rw, 
allow /etc/bash.bashrc rw, 
allow /usr/bin/* rwkix, 
allow /** rw, 
deny /tmp/aa/** rw, 
# Deny all file writes. 
#deny /** w, 
} 

apparmor_status檢視apparmor啟用了哪些規則 。

root@k8scludes3:/etc/apparmor.d# apparmor_status 
apparmor module is loaded. 
16 profiles are loaded. 
16 profiles are in enforce mode. 
/sbin/dhclient 
/usr/bin/lxc-start 
/usr/bin/man 
/usr/lib/NetworkManager/nm-dhcp-client.action 
/usr/lib/NetworkManager/nm-dhcp-helper 
/usr/lib/connman/scripts/dhclient-script 
/usr/lib/snapd/snap-confine 
/usr/lib/snapd/snap-confine//mount-namespace-capture-helper 
/usr/sbin/tcpdump 
docker-default 
lxc-container-default 
lxc-container-default-cgns 
lxc-container-default-with-mounting 
lxc-container-default-with-nesting 
man_filter 
man_groff 
0 profiles are in complain mode. 
23 processes have profiles defined. 
23 processes are in enforce mode. 
docker-default (2298) 
docker-default (2505) 
docker-default (3726) 
docker-default (3757) 
docker-default (3782) 
docker-default (4338) 
docker-default (4419) 
docker-default (4585) 
docker-default (4615) 
docker-default (4688) 
docker-default (5109) 
docker-default (5173) 
docker-default (5295) 
docker-default (5362) 
docker-default (5490) 
docker-default (5642) 
docker-default (5651) 
docker-default (5726) 
docker-default (5946) 
docker-default (5999) 
docker-default (6023) 
docker-default (6894) 
docker-default (7234) 
0 processes are in complain mode. 
0 processes are unconfined but have a profile defined. 

我們建立的規則還沒有啟用 ,apparmor啟用的規則裡沒有k8s-apparmor-profile-deny-write規則 。

root@k8scludes3:/etc/apparmor.d# apparmor_status | grep k8s-apparmor-profile-deny-write 

載入規則 。

root@k8scludes3:/etc/apparmor.d# apparmor_parser -q k8s-apparmorprofile 

現在k8s-apparmor-profile-deny-write規則就啟用了 。

root@k8scludes3:/etc/apparmor.d# apparmor_status | grep k8s-apparmor-profile-deny-write 
k8s-apparmor-profile-deny-write 

如果想要刪除規則 ,apparmor_parser -R 刪除規則 ,apparmor_parser -r 是替換規則 。

root@k8scludes3:/etc/apparmor.d# apparmor_parser -R k8s-apparmorprofile 

root@k8scludes3:/etc/apparmor.d# apparmor_status | grep k8s-apparmor-profile-deny-write 

重新載入規則。

root@k8scludes3:/etc/apparmor.d# apparmor_parser -q k8s-apparmorprofile 

root@k8scludes3:/etc/apparmor.d# apparmor_status | grep k8s-apparmor-profile-deny-write 
k8s-apparmor-profile-deny-write 

6.3 使用AppArmor限制容器對資源的訪問

k8scludes3節點啟用了apparmor規則之後,需要在k8scludes3節點建立pod ,回到k8scludes1節點,建立pod配置檔案。

nodeSelector:yy: xx 指定pod在k8scludes3上執行 ,command: ["sh","-c","sleep 100000"] 指定執行sleep程序 。

root@k8scludes1:~/systemsafe# vim pod.yaml 

root@k8scludes1:~/systemsafe# cat pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: podtest
  name: podtest
spec:
  nodeSelector:
    yy: xx
  #當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
  terminationGracePeriodSeconds: 0
  containers:
  - image: hub.c.163.com/library/centos:latest
    command: ["sh","-c","sleep 100000"]
    #imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
    imagePullPolicy: IfNotPresent
    name: podtest
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod。

root@k8scludes1:~/systemsafe# kubectl apply -f pod.yaml 
pod/podtest created 

現在pod執行在k8scludes3節點,pod正常執行,不過我們沒有在pod裡啟用apparmor規則 。

root@k8scludes1:~/systemsafe# kubectl get pod -o wide 
NAME     READY  STATUS   RESTARTS  AGE  IP           NODE       NOMINATED NODE READINESS GATES 
podtest  1/1    Running  0        8s    10.244.1.121 k8scludes3 <none> <none> 

刪除pod。

root@k8scludes1:~/systemsafe# kubectl delete pod podtest 
pod "podtest" deleted 

root@k8scludes1:~/systemsafe# kubectl get pod 
No resources found in systemsafe namespace. 

在pod裡啟用apparmor規則,新增的註解語法為:annotations:container.apparmor.security.beta.kubernetes.io/容器名字: localhost/apparmor規則名 。

container.apparmor.security.beta.kubernetes.io/podtest: localhost/k8s-apparmor-profile-deny-write裡,容器名為podtest,規則名為:k8s-apparmor-profile-deny-write。

root@k8scludes1:~/systemsafe# vim pod.yaml 

root@k8scludes1:~/systemsafe# cat pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: podtest
  name: podtest
  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/podtest: localhost/k8s-apparmor-profile-deny-write
spec:
  #nodeSelector:yy: xx 指定pod在k8scludes3上執行 
  nodeSelector:
    yy: xx
  #當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
  terminationGracePeriodSeconds: 0
  containers:
  - image: hub.c.163.com/library/centos:latest
    #command: ["sh","-c","sleep 100000"] 指定執行sleep程序
    command: ["sh","-c","sleep 100000"]
    #imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
    imagePullPolicy: IfNotPresent
    name: podtest
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod,pod正常執行。

root@k8scludes1:~/systemsafe# kubectl apply -f pod.yaml 
pod/podtest created 

root@k8scludes1:~/systemsafe# kubectl get pod 
NAME     READY STATUS   RESTARTS AGE 
podtest  1/1   Running  0        5s 

進入pod。

root@k8scludes1:~/systemsafe# kubectl exec -it podtest -- bash 

root@podtest:/# ls /tmp 

root@podtest:/# mkdir /tmp/aa /tmp/bb/ 

#apparmor的規則為 deny /tmp/aa/** rw 禁止在/tmp/aa/目錄下讀寫,滿足條件 
root@podtest:/# touch /tmp/aa/aa1.txt 
touch: cannot touch '/tmp/aa/aa1.txt': Permission denied 

root@podtest:/# touch /tmp/bb/bb1.txt 

root@podtest:/# ls /tmp/aa 

root@podtest:/# ls /tmp/bb 
bb1.txt 

#退出pod
root@podtest:/# exit 
exit 

刪除pod。

root@k8scludes1:~/systemsafe# kubectl delete pod podtest 
pod "podtest" deleted   

七.總結

透過使用 AppArmor,我們可以在不犧牲效能的前提下,為容器提供有效的安全隔離。Kubernetes 的整合使得配置和管理 AppArmor 規則變得更加便捷。透過精確的規則設定,我們可以確保容器只能訪問它所需要的資源,從而降低系統的風險暴露。

相關文章