Kubernetes_静态Pod网关apiserver的audit审计日志

共 7449字,需浏览 15分钟

 ·

2023-05-21 10:34

前言

审计日志是kube-apiserver中比较常见的一种加固手段,通过对每一次请求的行为进行审计,从而达到加固集群的目的,同时,审计日志还能够帮助我们troubleshooting,因为每一次请求的内容都会被记录下来,如果请求的内容本身有问题,从而导致api返回5xx的错误,我们可以从审计日志中直接把报错信息抓出来给开发,帮助他们定位问题。


一、理论:kube-apiserver的审计日志

1.1 kube-apiserver.yaml 文件的五行修改

kube-apiserver.yaml 文件的五行修改

–audit-policy-file=/etc/kubernetes/simple-policy.yaml:审计日志policy文件的位置,如果我们的apiserver是容器启动的,那么我们可能需要再添加一个卷组和一个挂载点

–audit-log-path=/var/log/audit.log:审计日志存放的位置,我们同样需要一个volume和一个挂载点。

–audit-log-maxbackup=2:日志在retention之后保存几份

–audit-log-maxage=7:日志保留几天

–audit-log-maxsize=200:每个日志的大小,这里面是200m

需要注意的是,根据我们策略的不同,审计日志大小也会有所不同,简单来说说,粒度越洗,日志的量越大,所以我们一定要配置日志的retention

1.2 audit-policy.yaml文件的修改

审计功能被开启之后,所有的api调用都需要经过审计的流程,这样就会让我们的集群使用更多的内存。每个调用都会有三个阶段,RequestReceived,ResponseStarted,ResponseCompeted。

每个阶段都会有相应的规则。一个或者多个规则都会对应事件的某一个审计级别,审计级别有四个:

None:没有审计
Metadata:只有metadata,没有请求或者回应的内容
Request:请求的内容和metadata
RequestResponse:响应的内容和metadata

二、实践:编写策略文件,打印想要的审计日志

三个步骤:

步骤1:编写修改policy.yaml文件
步骤2:重启 apiserver ,这样修改的策略文件才会生效
步骤3:查看新日志

2.1 步骤1:编写修改policy.yaml文件

vim /etc/kubernetes/simple-policy.yaml

    apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata

两个错误:编辑 simple-policy.yaml 的时候
复制:一定要先输入 i,否则复制过来,apiVersion 变成了 piVersion
格式:rules应该和kind同一层级,- level 应该在rules下一层级(不能同一层级)

2.2 步骤2:重启 apiserver ,这样修改的策略文件才会生效

    cd /etc/kubernetes/manifests
mkdir bak
cp kube-apiserver.yaml bak/kube-apiserver-bak.yaml
vi kube-apiserver.yaml

只要vi 修改了这个配置文件 kubectl get pod -o wide -n kube-system 里面的 apiserver就会重新应用, 如果 6443 refused 不要担心,docker ps | grep apiserver ,只需要等一下,等apiserver启动起来 6443 refused 就会消失

注意:不需要手动 kubectl apply -f kube-apiserver.yaml ,这样反而造成刚刚新建出来的这个处于Pending状态,使用 kubectl delete pod pod-name -n kube-system 删除掉这个处于Pending状态 (为什么可以使用 delete pod ,因为 apiserver.yaml 里面的 kind:Pod 类型 另外一个真实的 apiserver-xxx 也可以使用 delete pod 删除,只是删除会立马重建)

2.3 步骤3:查看新日志

tail -f /var/log/audit.log

问题:如果手动删除linux上的 rm -rf /var/log/audit.log ,audit.log 会变成一个目录
解决:将 vi kube-apiserver.yaml 将三个地方的 audio.log 变成 audio2.log (一个从来没有被使用过的名称就好了)就不会是目录了

2.4 编写策略文件和apiserver配置文件需要注意的三个点

编写 simple-policy.yaml 注意三个点
编写 kube-apiserver.yaml 注意三个点

simple-policy.yaml 注意三个点

1、审计时机和审计级别

审计时机:审计时机即记录事件的时机,分为四种类型

RequestReceived:接收到请求的时候,响应头发出之前,记录审计日志;
RequestStarted:响应头发出之后,响应消息体未发出之前,记录审计日志,一般用于长连接或耗时任务的场景;
ResponseComplete:响应消息体完成之后,记录审计日志;
Panic:出现panic的时候,记录审计日志。

审计级别:代表记录审计日志的完整程度,分为四种:
None:不记录审计日志,审计日志为空;
Metadata:记录请求的原子信息比如请求user、method、时间、资源类型等,但是不包括请求消息体和响应消息体;
Request:在Metadata基础上,加上请求消息体;
RequestResponse:在Metadata基础上,加上请求消息体和响应消息体,或者说,在Request的基础上,加上响应消息体。

2、从上到下:因为规则是从上到下进行匹配的,所以不需要记录的规则一般往上面放着,只要上面匹配了,就不会记录了
3、一般去掉静态pod和 查询类操作verb:[“list”,“get”] ,因为打印系统类日志或查询类日志,就导致日志太多了

kube-apiserver.yaml 注意三个点

1、采用 mkdir bak 新建一层目录保存 kube-apiserver-bak.yaml , 而不是同一级目录保存 kube-apiserver-bak.yaml (非必须,笔者自己的习惯)
2、vi kube-apiserver.yaml 然后 :wq 立马会生效
3、tail.log 变成了目录就重新搞一个 (注意 kube-apiserver.yaml 需要修改三个地方)

2.5 最后两个易错点

两个易错点:策略文件必须可读(chmod 777 audit-policy.yaml),审计日志文件自动创建不可删除

策略文件必须可读:策略文件audit-policy.yaml 必须可读 chmod 640 audit-policy.yaml 最好是是 chmod 777 audit-policy.yaml(scp),如果因为策略文件权限低造成 apiserver 起不来,使用 docker ps | grep apiserver 查看

审计日志文件自动创建不可删除:审计日志文件 audit.log 重启apiserver 就会被创建,一定不能手动删除,要不然会打印不了日志(因为日志文件已经被你删掉了)

7620f238531c5e0b5dacd20a98aa7d28.webp

【技巧】kubernetes查看日志的方式
方式1:如果是container容器,kubectl logs pod-name -n kube-system (注意一定是pod-name,就是xxx后缀的那种)(logs日志和exec进去的都是pod)
方式2:如果是服务的日志,使用 systemctl status kubelet
systemctl status docker
systemctl status firewalld
方式3:还有一种 -v 9

三、看懂审计日志和策略文件

3.1 看懂打印出来的audit.log日志

audit.log日志包括元数据(metadata)、请求内容(requestObject)和响应内容(responseObject)3个部分。其中元数据一定会存在,请求和响应内容是否存在取决于审计级别。元数据包含了请求的上下文信息,例如谁发起的请求,从哪里发起的,访问的 URI 等等,如下:

d32789c15bb1cf8812835406bab27227.webp

发生了什么? 干什么? requestUri + verb + objectRef (就这三个,没有 request)

谁发起的? user 下面有两个 username 和 group

从哪里发生? 查看 source 和 userAgent

结果是什么? responseStatus

什么时候发生的? stage字段是什么时候 level 是记录等级 两个 timestamp 是具体时间,需要加上 8 小时

3.2 看懂策略文件

1、rule是白名单,配置了规则rule才会被打印 (验证:如果none类型后面还配置了 metadata类型,就会打印日志;如果去掉后面的metadata类型,只保留前面的none类型的,不会打印任何日志)
2、rule规则中 最前面那个是 结果 select 输出结果,后面的是条件 where 条件 (验证:查看输出结果就知道)
3、每条rule规则中,多个条件是与的关系,任何一次操作同时满足这些条件才能打印指定类型日志
4、rules是数组,越前面优先级越高,一条日志走策略文件,先匹配到哪条就返回指定结果
5、omitStage 可以配置全局的,也可以配置在每条规则下 (验证:略)
6、annotations/reason解释为什么这一条会被选中

验证多个条件是与的关系

策略文件的每条rule规则中,多个条件是与的关系,任何一次操作同时满足这些条件才能打印指定类型日志

audit-policy.yaml策略文件中,条件可以最多包括四个,即

verbs 动作
user 用户
namespace 命名空间
resources 资源

verbs动词选项是:
查询:list get watch (区别:get 列出单个资源、list 列出资源类型的集合、watch 动态监控)
新建:create 创建
修改:update patch (区别:update 修改全部资源、patch 修改部分资源)
删除:delete

kubectl get pod ,因为具体到了pod-name为,就是会被策略文件识别为 list
kubectl get pod xxx ,因为具体到了pod-name为xxx,就是会被策略文件识别为 get

178d21027a256d87f9d5d1d4c859d8e6.webp

verbs动词其他还包括:
proxy 代理
redirect 重定向
use 调用
delete 删除
deletecollection 级联删除

验证优先级是从上到小的

验证(优先级是从上到小的):
kubectl create ns mao
策略文件:

    apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: None
verbs: ["create"]
- level: RequestResponse
users:
- kubernetes-admin

结果:不打印
解释:kubectl create ns mao 先匹配到了第一条,所以输出结果是None,就不打印日志

kubectl create ns mao
策略文件:

    apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
users:
- kubernetes-admin
- level: None
verbs: ["create"]

结果:打印
解释:kubectl create ns mao 先匹配到了第一条,所以输出结果是RequestResponse,就打印日志

a131a497342bca942583b3df1ed7cea8.webp

验证annotations/reason的解释作用

看 reason 字段, 表示为什么会匹配上
因为 userGroup 和

    "requestURI": "/apis/batch/v1?timeout=32s",
"verb": "get",
    {
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"level": "RequestResponse",
"auditID": "406cf051-ba51-4d13-acdd-7f19f3746e29",
"stage": "ResponseComplete",
"requestURI": "/apis/batch/v1?timeout=32s",
"verb": "get",
"user": {
"username": "system:serviceaccount:kube-system:generic-garbage-collector",
"uid": "0446178d-04b9-11ed-a57e-000c291867b4",
"groups": ["system:serviceaccounts", "system:serviceaccounts:kube-system", "system:authenticated"]
},
"sourceIPs": ["192.168.100.151"],
"userAgent": "kube-controller-manager/v1.14.0 (linux/amd64) kubernetes/641856d/system:serviceaccount:kube-system:generic-garbage-collector",
"responseStatus": {
"metadata": {},
"code": 200
},
"responseObject": {
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "batch/v1",
"resources": [{
"name": "jobs",
"singularName": "",
"namespaced": true,
"kind": "Job",
"verbs": ["create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"],
"categories": ["all"]
}, {
"name": "jobs/status",
"singularName": "",
"namespaced": true,
"kind": "Job",
"verbs": ["get", "patch", "update"]
}]
},
"requestReceivedTimestamp": "2022-07-16T07:20:24.959584Z",
"stageTimestamp": "2022-07-16T07:20:24.959723Z",
"annotations": {
"authorization.k8s.io/decision": "allow",
"authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding \"system:discovery\" of ClusterRole \"system:discovery\" to Group \"system:authenticated\""
}
}

“authorization.k8s.io/reason”: “RBAC: allowed by ClusterRoleBinding “system:discovery” of ClusterRole “system:discovery” to Group “system:authenticated””

解释:这次操作是用户 system:discovery 发起的,它已经取得了 system:authenticated 的权限
583f6e1d38abf81cdaaa4df88dc308ae.webp

3.3 实践:审计日志仅打印kubernetes-admin相关的

如此编写策略文件,就可以了,如下:

    ## 最完美的过滤
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
omitStages:
- "RequestReceived"
rules:
- level: RequestResponse
users:
- kubernetes-admin

问题:如何知道 users kubernetes-admin
回答:可以在 cat /root/.kube/config 里面看到,所以前端的请求都是这个

总结

静态Pod网关apiserver的audit审计日志,完成了。

天天打码,天天进步!


浏览 42
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报