k8s进阶5——AppArmor、Seccomp、ImagePolicyWebhook

news/2024/12/23 2:00:08/

文章目录

  • 一、AppArmor限制容器对资源访问
    • 1.1 实现步骤
      • 1.1.1 定义策略
      • 1.1.2 加载策略
      • 1.1.3 引用策略
    • 2.2 案例
  • 二、Seccomp 限制容器进程系统调用
    • 案例一:使用自定义策略
    • 案例二:使用容器运行时默认策略
  • 三、动态准入控制Webhook
    • 3.1 ImagePolicyWebhook控制器
      • 3.1.1 apiserver服务器准备操作
      • 3.1.2 部署webhook服务器
      • 3.1.3 测试验证

一、AppArmor限制容器对资源访问

概念:

  • AppArmor(Application Armor) 是一个 Linux 内核安全模块,用于限制主机操作系统上运行的进程。每个进程都可以拥有自己的安全配置文件,安全配置文件用来允许或禁止特定功能,例如网络访问、文件读/写/执行权限等。
  • 是Linux发行版的内置功能,比如Ubuntu、Debian、SUSE,而CentOS和redhat系统没有这个AppArmor,其功能相当于selinux,但selinux安全程度不高,也不方便使用,所以一般人不用。
  • Ubuntu系统携带了许多没有合并到上游 Linux 内核中的 AppArmor 补丁, 包括添加附加钩子和特性的补丁。Kubernetes 只在上游版本中测试过,不承诺支持其他特性。

工作模式:

  1. Enforcement(强制模式) :在这种模式下,配置文件里列出的限制条件都会得到执行,并且对于违反这些限制条件的程序会进行日志记录,相当于selinux的enforcing模式。
  2. Complain(投诉模式):在这种模式下,配置文件里的限制条件不会得到执行,Apparmor只是对程序的行为进行记录,一般用于调试,相当于selinux的permissive模式。

K8s使用AppArmor的先决条件:

  1. K8s版本v1.4+,检查是否支持:kubectl describe node |grep AppArmor。
  2. Linux内核已启用AppArmor,查看 cat /sys/module/apparmor/parameters/enabled。
  3. 容器运行时需要支持AppArmor,docker、CRI-O 、containerd都支持。
  4. 比如以下ubuntu系统核内核是支持的,但在centos系统是看不到apparmor进程的。
    在这里插入图片描述

工作流程图:在这里插入图片描述

1.1 实现步骤

****:

  1. 将自定义策略配置文件保存到默认目录/etc/apparmor.d/下。
  2. 加载配置文件到内核。
  3. 定义pod.yaml文件时,在注解参数下指定策略名。因为AppArmor目前还处于测试阶段,因此以注解形式设定,日后进入正式阶段就可以使用安全上下文格式来配置了。

1.1.1 定义策略

配置策略:

vim /etc/apparmor.d/k8s-deny-write      ##文件名称自定义。
#include <tunables/global>     ##默认格式,导入依赖,遵循C语言约定。
profile k8s-deny-write flags=(attach_disconnected) {    ##指定策略名,也就是命令能查到显示出来的策略名称。#include <abstractions/base>      ##定义策略。file,                             ##允许所有文件读写。deny /bin/** w,                   ##递归匹配,拒绝/bin目录下的所有目录和文件写权限。deny /data/www/** w,              ##递归匹配,拒绝/data/www目录下的所有目录和文件写权限。
}

1.1.2 加载策略

  • 使用以下命令将策略加载到内核。
常用命令释义
apparmor_status查看AppArmor配置文件的当前状态的。
apparmor_parser将AppArmor配置文件加载到内核中。
apparmor_parser < profile >加载到内核中。
apparmor_parser -r < profile >重新加载配置。
apparmor_parser -R < profile >删除配置。
aa-complain将AppArmor配置文件设置为投诉模式,需要安装apparmor-utils软件包。
aa-enforce将AppArmor配置文件设置为强制模式,需要安装apparmor-utils软件包。

1.1.3 引用策略

  • 定义pod.yaml时添加注解加以引用。
  • 注意,引用的策略文件必须是要pod所在的宿主机上,实际生产中是需要运维来维护的,可以写脚本把策略文件给K8s集群每个节点分配上去并加载到内核。
apiVersion: v1
kind: Pod
metadata:name: hello-apparmorannotations:container.apparmor.security.beta.kubernetes.io/<container_name>: localhost/<profile_ref>......##< container_name >: Pod中容器名称。##< profile_ref >: Pod所在宿主机上策略名,默认目录/etc/apparmor.d。
访问文件权限模式字符描述
r
w
a追加
k文件锁定
l链接
x可执行
通配符描述示例
*在目录级别匹配零个或多个字符。/dir/* :匹配目录中的任何文件。
/dir/a* :匹配目录中以a开头的任意文件。
/dir/.png: 匹配目录中以.png结尾的任意文件。
/dir/a
/ :匹配/dir里面以a开头的目录。
/dir/*a/ :匹配/dir里面以a结尾的目录。
**在多个目录级别匹配零个或多个字符。/dir/** : 匹配/dir目录或者/dir目录下任何文件和目录。
/dir/**/ : 匹配/dir或者/dir下面任何目录。
[]
[^]
字符串,匹配其中任意字符。/dir/[^.]* :匹配/dir目录中以.之外的任何文件。
/dir/**[^/] :匹配/dir目录或者/dir下面的任何目录中的任何文件。
pod.yaml字段释义
<container_name>pod.yaml文件里所针对的容器名称。
<profile_def>Pod所在宿主机上策略名,引用刚刚定义的配置文件。
<profile_ref>可以是以下取值之一:
runtime/default:应用运行时的默认配置。
localhost/<profile_name>:应用在主机上加载的名为 <profile_name> 的配置文件。
unconfined:表示不加载配置文件。

2.2 案例

案例:容器文件系统访问限制。

1.先查看默认生效的策略名称,我们定义的策略生效后就会显示在该列表中。
在这里插入图片描述
2.查看策略文件所在目录。
在这里插入图片描述
3.在K8s每个节点的/etc/apparmor.d目录下生成策略文件。策略是禁止在/bin目录下写,然后将策略文件加载到内核,查看结果。因为在编写pod.yaml里指定策略地址时,是使用的localhost读取本地。
在这里插入图片描述
在这里插入图片描述
4.先测试下使用我们生成策略之前效果,进入测试容器,可以在/bin目录下正常创建文件。
在这里插入图片描述
5.创建一个pod,其yaml文件里指定策略名称。
在这里插入图片描述
在这里插入图片描述
6.进入该容器创建目录测试效果。
在这里插入图片描述
7.若要修改策略,则修改后需要重新加载,并且需要重建pod容器。

apparmor parser -r k8s-deny-write

二、Seccomp 限制容器进程系统调用

前提了解:

  • 在Linux上, 我们操作的所有跟资源相关的命令都是通过系统调用来完成的。
  • 系统调用实现技术层次上解耦,内核只关心系统调用API的实现,而不必关心谁调用的。

调用关系图:
在这里插入图片描述

基本概念:

  1. Seccomp(Secure computing mode) 是一个 Linux 内核安全模块,可用于应用进程允许使用的系统调用。容器实际上是在宿主机上运行的一个进程,共享宿主机内核,如果所有容器都具有任何系统调用的能力,那么容器如果被入侵,就很轻松绕过容器隔离更改宿主机系统权限或者进入宿主机。这就可以使用Seccomp机制限制容器系统调用,有效减少攻击面。
  2. Linux发行版内置:CentOS、Ubuntu。

Type类型:

  • pod.yaml中会定义Type字段,表示将应用哪种类型的seccomp配置文件,具有如下选项:
    • Localhost:应该使用在节点上的文件中定义的配置文件。
    • RuntimeDefault:应该使用容器运行时默认配置文件。
    • Unconfined:无限制,不使用策略。

注意事项:

  1. 引用的策略文件必须是要pod所在的宿主机上,实际生产中是需要运维来维护的,可以写脚本把策略文件给K8s集群每个节点分配上去并加载到内核。
  2. Seccomp在Kubernetes 1.3版本引入,在1.19版本成为GA版本,因此K8s中使用Seccomp可以通过以下两种方式:
    • 1.19版本之前使用注解:
    annotations:seccomp.security.alpha.kubernetes.io/pod: "localhost/<profile>"
    
    • 1.19版本+配置安全上下文:
    apiVersion: v1
    kind: Pod
    metadata:name: hello-seccomp
    spec:securityContext:seccompProfile:type: LocalhostlocalhostProfile: <profile> # Pod所在宿主机上策略文件名,默认目录:/var/lib/kubelet/seccompcontainers:
    ...
    

案例一:使用自定义策略

  • 需求:禁止容器使用chmod。

1.创建默认文件路径。

[root@k8s-master1 ~]# mkdir /var/lib/kubelet/seccomp

2.在默认路径下生成限制策略。

[root@k8s-master1 seccomp]# cat chmod.json 
{"defaultAction": "SCMP_ACT_ALLOW",       ##在syscalls部分未定义的任何系统调用默认动作为允许。"syscalls": [{"names": [                      ##系统调用名称,可以换行写多个。"chmod"],"action": "SCMP_ACT_ERRNO"      ## 阻止自定义的系统调用。}]  
}

3.创建pod时,引用该策略。

[root@k8s-master1 ResourceQuota]# cat pod.yaml 
apiVersion: v1
kind: Pod
metadata:name: baimu
spec:nodeName: k8s-master1    ##需要执行该pod被分配的机器上是有限制策略的。securityContext:         ##添加此参数。seccompProfile:type: Localhost      ##指定类型,调用本地自定义策略文件。localhostProfile: chmod.json       ##使用相对路径,指定应用策略名称。containers:- image: busyboxname: testcommand:- sleep- 24h

4.进入普通容器测试可以修改权限。
在这里插入图片描述
5.进入指定限制策略的容器修改权限失败,限制成功。
在这里插入图片描述
6.此时需要再限制创建目录权限,就直接在chmod.json文件里加。
在这里插入图片描述
7.限制策略文件内容更改后,指定该策略的pod需要重新创建,先删除再创建容器,最后进入容器测试。
在这里插入图片描述

案例二:使用容器运行时默认策略

  • 大多数容器运行时都提供一组允许或不允许的默认系统调用。

  • 通过使用 runtime/default 注释 或将Pod 或容器的安全上下文中的 seccomp 类型设置为 RuntimeDefault,可以轻松地在 Kubernetes中应用默认值。

  • docker默认配置说明
    在这里插入图片描述

1.指定docker默认策略创建pod。

[root@k8s-master1 ResourceQuota]# cat pod.yaml 
apiVersion: v1
kind: Pod
metadata:name: baimu
spec:nodeName: k8s-master1securityContext:seccompProfile:type: RuntimeDefault    ##修改类型,使用容器运行时默认策略。#  localhostProfile: chmod.json    ##注释掉。containers:- image: busyboxname: testcommand:- sleep- 24h

2.查看系统调用。查看操作命令用到哪些系统调用可以使用strace命令查看,一个命令通常会使用多个系统调用,若是在实际生产中使用需要挨个调试。

[root@k8s-master1 seccomp]# yum -y install strace

在这里插入图片描述

三、动态准入控制Webhook

基本概念:

  • 前面讲过的准入控制是通过添加K8s内置的准入插件来实现,当然也可以作为扩展独立开发,并以运行时所配置的 Webhook 的形式运行。
  • 准入控制器Webhook是准入控制插件的一种,是一种用于接收准入请求并对其进行处理的 HTTP 回调机制 ,常用于拦截所有向apiserver发送的请求,并且可以修改请求或拒绝请求。
  • Admission webhook为开发者提供了非常灵活的插件模式,在kubernetes资源持久化之前,管理员通过程序可以对指定资源做校验、修改等操作。例如为资源自动打标签、pod设置默认SA,自动注入sidecar容器等。

Webhook准入控制器分类:

  1. Mutating Admission Webhook:先调用,修改资源,理论上可以监听并修改任何经过ApiServer处理的请求。
  2. Validating Admission Webhook:后调用,验证资源。
  3. ImagePolicyWebhook:镜像策略,主要验证镜像字段是否满足条件,允许使用后端 Webhook 做出准入决策。

工作流程图:
在这里插入图片描述

3.1 ImagePolicyWebhook控制器

工作流程图:
在这里插入图片描述
玩法思路:

  1. 签发证书。镜像策略服务器是以https启用,需要给它自签证书,访问它时也要携带根证书或者客户端证书。
  2. 准备imgaepolicywebhook配置文件,指定镜像策略服务器配置文件存放目录。
  3. 准备镜像策略服务器配置文件,指定连接服务器IP地址、端口、API、根证书、客户端证书。
  4. 启用准入控制插件。

3.1.1 apiserver服务器准备操作

1.定义镜像策略控制器配置文件,指定配置文件存放路径。

##镜像策略控制器配置文件,指定连接镜像策略服务器配置文件地址,连接服务器通用策略。
[root@k8s-master1 imagepolicywebhook]# cat admission_configuration.yaml 
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: ImagePolicyWebhookconfiguration:imagePolicy:kubeConfigFile: /etc/kubernetes/image-policy/connect_webhook.yaml  # 指定镜像策略服务器配置文件。allowTTL: 50       # 控制批准请求的缓存时间,单位秒denyTTL: 50        # 控制批准请求的缓存时间,单位秒retryBackoff: 500    # 控制重试间隔,单位毫秒defaultAllow: true    # 确定webhook后端失效的行为

2.定义镜像策略服务器连接配置文件,指定它的根证书、连接它的客户端证书、连接地址、端口和API。

[root@k8s-master1 imagepolicywebhook]# cat connect_webhook.yaml 
apiVersion: v1
kind: Config
clusters:
- cluster:certificate-authority: /etc/kubernetes/image-policy/webhook.pem # 数字证书,用于验证远程服务server: https://192.168.130.146:8080/image_policy # 镜像策略服务器地址,必须是httpsname: webhook
contexts:
- context:cluster: webhookuser: apiservername: webhook
current-context: webhook 
preferences: {}
users:
- name: apiserveruser:client-certificate: /etc/kubernetes/image-policy/apiserver-client.pem # webhook准入控制器使用的证书client-key: /etc/kubernetes/image-policy/apiserver-client-key.pem # 对应私钥证书

3.统一两文件存放目录。

[root@k8s-master1 imagepolicywebhook]# mkdir -p /etc/kubernetes/image-policy  
[root@k8s-master1 imagepolicywebhook]# mv admission_configuration.yaml connect_webhook.yaml /etc/kubernetes/image-policy/

4.签发证书。

[root@k8s-master1 ssl]# cat image-policy-certs.sh 
cat > ca-config.json <<EOF    ##k8s根证书。
{"signing": {"default": {"expiry": "87600h"},"profiles": {"kubernetes": {"expiry": "87600h","usages": ["signing","key encipherment","server auth","client auth"]}}}
}
EOFcat > ca-csr.json <<EOF
{"CN": "kubernetes","key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "Beijing","ST": "Beijing"}]
}
EOFcfssl gencert -initca ca-csr.json | cfssljson -bare ca -cat > webhook-csr.json <<EOF   ##镜像策略服务器根证书。
{"CN": "webhook","hosts": ["192.168.130.146"     ##镜像策略服务器地址。],"key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "BeiJing","ST": "BeiJing"}]
}
EOFcfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes webhook-csr.json | cfssljson -bare webhookcat > apiserver-client-csr.json <<EOF            ##连接镜像策略服务器的客户端证书。
{"CN": "apiserver","hosts": [],"key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "BeiJing","ST": "BeiJing"}]
}
EOFcfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes apiserver-client-csr.json | cfssljson -bare apiserver-client

在这里插入图片描述

5.将证书放入前面两文件目录里,文件里有指定读取这两个证书。

[root@k8s-master1 ssl]# mv apiserver-client*.pem webhook.pem /etc/kubernetes/image-policy/

6.修改apiserver配置文件,开启ImagePolicyWebhook插件,指定imagepolicywebhook配置文件位置,并挂载到容器里面。

 - --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook- --admission-control-config-file=/etc/kubernetes/image-policy/admission_configuration.yaml

在这里插入图片描述
在这里插入图片描述

3.1.2 部署webhook服务器

在这里插入图片描述

1.部署webhook站点服务器,我这里是写了一个python程序来实现对部署时的镜像没有指定标签(即latest)进行拒绝。

[root@k8s-master2 imagepolicywebhook]# cat main.py 
from flask import Flask,request
import jsonapp = Flask(__name__)@app.route('/image_policy',methods=["POST"])     ##处理发送过来的post请求。
def image_policy():post_data = request.get_data().decode()           ##接受发送过来的post请求。#print("POST数据: %s" %post_data)                  ##将post请求打印出来。data = json.loads(post_data)                      ##解析这个post请求。for c in data['spec']['containers']:                  ##过滤这个post请求中的spec.containers字段下的内容。if ":" not in c['image'] or ":latest" in c['image']:  ##如果镜像里不带冒号或者带:latest说明是镜像使用latest标签。allowed, reason = False, "检查镜像失败!镜像标签不允许使用latest!"breakelse:allowed, reason = True, "检查镜像通过."print("检查结果: %s" %reason)result = {"apiVersion": "imagepolicy.k8s.io/v1alpha1","kind": "ImageReview",     ##返回个apiserver的api,固定格式。"status": {"allowed": allowed,"reason": reason}}return json.dumps(result,ensure_ascii=False) if __name__ == "__main__":                               ##监听服务端口8999,需要把证书传到该服务器,后面会挂载到容器里。app.run(host="0.0.0.0",port=8080,ssl_context=('/data/www/webhook.pem','/data/www/webhook-key.pem'))

2.构建镜像。

[root@k8s-master2 imagepolicywebhook]# cat Dockerfile 
FROM python
RUN useradd python
RUN mkdir /data/www -p
COPY . /data/www
RUN chown -R python /data
RUN pip install flask -i https://mirrors.aliyun.com/pypi/simple/
WORKDIR /data/www
USER python
CMD python main.py [root@k8s-master2 imagepolicywebhook]# docker build -t qingjun:v1  .

3.准备好之前在apiserver服务器上创建的证书,并运行一个容器进入查看,容器日志会显示python程序检查apiserver发过来的请求结果。

docker run -d -u root --name=baimu1 \
-v $PWD/webhook.pem:/data/www/webhook.pem \
-v $PWD/webhook-key.pem:/data/www/webhook-key.pem \
-e PYTHONUNBUFFERED=1 -p 8080:8080 \
qingjun:v1

在这里插入图片描述

3.1.3 测试验证

1.创建pod容器时,使用不带标签的镜像,则返回false。
在这里插入图片描述
2.创建pod容器时,使用带latest标签的镜像,返回false。
在这里插入图片描述
3.创建pod容器时,使用带标签的镜像,返回true。
在这里插入图片描述


http://www.ppmy.cn/news/85943.html

相关文章

易观分析:消费金融机构以APP为触点,创新消费场景,激发消费活力

易观&#xff1a;随着“用好消费金融、释放消费潜力”等金融支持扩内需的持续深入&#xff0c;消费金融APP活跃用户规模将保持稳健增长的态势&#xff0c;进而在拉动内需、促进消费升级、服务实体经济中扮演更重要的角色。 一、疫情防控较快平稳转段&#xff0c;激发消费市场活…

Spring之DI(依赖注入)

依赖注入&#xff08;DI&#xff09;是一个过程&#xff0c;在这个过程中&#xff0c;对象仅通过构造函数参数、工厂方法的参数或在对象被实例化后通过属性设置来定义它们的依赖项&#xff08;即与该对象一起工作的其他对象&#xff09;。然后&#xff0c;容器在创建 bean 时注…

finally 和 return的执行关系,try..catch..finally

目录 结论 基础类型Int&#xff0c;返回值 基础类型String&#xff0c;返回值 基础类型StringBuffer&#xff0c;返回值 复合类型Map&#xff0c;返回引用 自定义类型&#xff0c;返回引用 执行了finally 里的return 结论 程序执行到return时 如果返回的是基础变量&#…

SpringCloud Sentinel实战限流熔断降级应用

目录 1 Sentinel核心库1.1 Sentinel介绍1.2 Sentinel核心功能1.2.1 流量控制1.2.2 熔断降级 2 Sentinel 限流熔断降级2.1 SentinelResource定义资源2.2 Sentinel的规则2.2.1 流量控制规则 (FlowRule)2.2.2 熔断降级规则 (DegradeRule)2.2.3 系统保护规则 (SystemRule)2.2.4 访问…

(浙大陈越版)数据结构 第三章 树(上) 3.2 二叉树及存储结构

目录 3.2.1 二叉树的定义及性质 定义: 二叉树五种基本形态&#xff1a; 特殊二叉树 二叉树的几个重要性质 二叉树的抽象数据类型定义 操作集&#xff1a; 常用遍历&#xff1a; 3.2.2 二叉树的存储结构 顺序存储结构 数组实现 链表实现 3.2.1 二叉树的定义及性质 …

基础篇009.1 STM32驱动RC522 RFID模块之一:基础知识

目录 1. RFID概述 1.1 RFID工作原理 1.2 RFID分类 1.3 RFID模块 1.4 RFID卡片 1.5 IC卡和ID卡介绍 1.6 IC卡和ID的区分 2. Mifare卡结构原理 2.1 Mifare卡概述 2.2 Mifare非接触式 IC 卡性能简介&#xff08;M1&#xff09; 2.2.1 Mifare S50与Mifare S70 2.2.2 S5…

甘肃棒球发展建设·棒球1号位

概述 甘肃省位于中国西北部&#xff0c;地理环境独特&#xff0c;拥有丰富的历史文化底蕴。近年来&#xff0c;棒球在甘肃得到了较快的发展&#xff0c;但仍存在一些问题和挑战。本报告将分析甘肃棒球的现状、发展潜力以及应对策略。 现状分析 1. 基础设施&#xff1a;甘肃省…

英文论文(sci)解读复现【NO.11】一种先进的基于深度学习模型的植物病害检测:近期研究综述

此前出了目标检测算法改进专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读发表高水平学术期刊中的 SCI论文&a…