KubernetesAPI审计日志方案

当前Kubernetes(K8S)已经成为事实上的容器编排标准,大家关注的重点也不再是最新发布的功能、稳定性提升等,正如Kubernetes项目创始人和维护者谈到,Kubernetes已经不再是buzzword,当我们谈起它的时候,变得越发的boring,它作为成熟项目已经走向了IT基础设施的中台,为适应更大规模的生产环境和更多场景的应用不断延展迭代。

而现在我们更加专注于如何利用K8S平台进行CICD、发布管理、监控、日志管理、安全、审计等等。本期我们将介绍如何利用K8S中的Audit事件日志来对平台进行安全监控和审计分析。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zho2h2I7-1606798413403)(/Users/zhaobei/Library/Application Support/typora-user-images/image-20201022095953045.png)]

IT设施/系统是当今每个互联网公司最为重要的资产之一,除了成本外,这里承载了所有的用户访问,同时保存了非常多的用户、订单、交易、身份等敏感信息。因此每个公司都有必要确保IT设施/系统是可靠、安全、未泄漏的。其中必不可少的环节是审计,通过审计我们可以知道系统在任一时间段内发生的事件以及对应关联的内外部人员、系统,在损失发生后能够立即知道具体是谁、在哪个时间对系统做了什么事,同时基于审计事件的实时分析和告警,能够提前发现问题并及时止损。

Kubernetes审计日志概览
Kubernetes作为容器编排领域的领导者、未来PAAS平台的标准基座,在IT领域有着举足轻重的影响,因此审计功能也是Kubernetes比不可少的安全功能之一。

图片描述

Kubernetes在1.7版本中发布了审计(Audit)日志功能,审计(Audit)提供了安全相关的时序操作记录(包括时间、来源、操作结果、发起操作的用户、操作的资源以及请求/响应的详细信息等),通过审计日志,我们能够非常清晰的知道K8S集群到底发生了什么事情,包括但不限于:

当前/历史上集群发生了哪些变更事件。
这些变更操作者是谁,是系统组件还是用户,是哪个系统组件/用户。
重要变更事件的详细内容是什么,比如修改了POD中的哪个参数。
事件的结果是什么,成功还是失败。
操作用户来自哪里,集群内还是集群外。

img

日志格式与策略
K8S中的审计日志是标准的JSON格式,APIServer会根据具体的日志策略将对应的审计日志保存本地,并可以设置最大保存周期、时间、轮转策略等。
关于审计日志格式和策略的详细介绍,可以参考Audit官方文档。

日志记录阶段
审计日志根据日志策略可以选择在事件执行的某个阶段记录,目前支持的事件阶段有:

RequestReceived - 接收到事件且在分配给对应handler前记录。
ResponseStarted - 开始响应数据的Header但在响应数据Body发送前记录,这种一般应用在持续很长的操作事件,例如watch操作。
ResponseComplete - 事件响应完毕后记录。
Panic - 内部出现panic时记录。
日志记录等级
审计日志根据日志策略可以选择事件保存的等级,根据等级不同,APIServer记录日志的详细程度也不同。目前支持的事件等级有:

None - 不记录日志.
Metadata - 只记录Request的一些metadata (例如user, timestamp, resource, verb等),但不记录Request或Response的body。
Request - 记录Request的metadata和body。
RequestResponse - 最全记录方式,会记录所有的metadata、Request和Response的Body。
日志记录策略
APIServer支持对每类不同的资源设置不同的审计日志策略,包括日志记录阶段以及日志记录等级,目前官方以及很多云厂商都会提供日志策略,一般都遵循以下原则:

在收到请求后不立即记录日志,当返回体header发送后才开始记录。
对于大量冗余的kube-proxy watch请求,kubelet和system:nodes对于node的get请求,kube组件在kube-system下对于endpoint的操作,以及apiserver对于namespaces的get请求等不作审计。
对于/healthz,/version, /swagger*等只读url不作审计。
对于可能包含敏感信息或二进制文件的secrets,configmaps,tokenreviews接口的日志等级设为metadata,该level只记录请求事件的用户、时间戳、请求资源和动作,而不包含请求体和返回体。
对于一些如authenticatioin、rbac、certificates、autoscaling、storage等敏感接口,根据读写记录相应的请求体和返回体。
审计日志分析
审计日志分析现状
目前对于K8S上的APIServer审计日志的支持,大部分厂商还停留在策略设置或日志采集的阶段,最多只支持将数据采集到日志中心,配合索引进行关键词查询。
下图是一个Level为Metadata的审计日志记录,各类字段有20多个,如果是Level为Request或RequestResponse的日志字段会更多,可能达到上百个。要实现审计日志分析,必须理解这些字段的含义,此外还需理解每个字段的取值范围以及每种取值对应的含义,学习代价非常之大。

{
“kind”: “Event”,
“apiVersion”: “audit.k8s.io/v1beta1”,
“metadata”: {

"creationTimestamp": "2019-01-14T07:48:38Z"

},
“level”: “Metadata”,
“timestamp”: “2019-01-14T07:48:38Z”,
“auditID”: “cf2915c0-0b43-4e1d-9d66-fbae481a0e0a”,
“stage”: “ResponseComplete”,
“requestURI”: “/apis/authentication.k8s.io/v1beta1?timeout=32s”,
“verb”: “get”,
“user”: {

"username": "system:serviceaccount:kube-system:generic-garbage-collector",



"uid": "cd3fbe04-0508-11e9-965f-00163e0c7cbe",



"groups": [



  "system:serviceaccounts",



  "system:serviceaccounts:kube-system",



  "system:authenticated"



]

},
“sourceIPs”: [

"192.168.0.249"

],
“responseStatus”: {

"metadata": {},



"code": 200

},
“requestReceivedTimestamp”: “2019-01-14T07:48:38.214979Z”,
“stageTimestamp”: “2019-01-14T07:48:38.215102Z”,
“annotations”: {

"authorization.k8s.io/decision": "allow",



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

}
}
阿里云Kubernetes审计日志方案
为尽可能减少用户对于审计日志的分析代价,阿里云容器服务将Kubernetes审计日志与日志服务SLS打通,推出了一站式的Kubernetes审计日志方案,让每个用户都能够以图形化报表的方式进行集群的审计分析。

图片描述

为尽可能保证集群安全性,阿里云容器服务Kubernetes默认为用户打开了APIServer审计日志并设置了较为安全且通用的审计日志策略,所有(符合审计策略)用户、组件对APIServer的访问都会被记录下来;
Kubernetes集群中预置的日志组件Logtail会将APIServer的审计日志自动采集到阿里云日志服务;
日志服务默认会为APIServer的审计日志创建索引、报表等;
容器服务控制台已经和日志服务打通,集群管理员可以直接在控制台上查看审计日志的各项报表以及指标;
若集群管理员还有设置告警、自定义分析等需求,可直接登录日志服务控制台进行操作。
得益于阿里云日志服务的强大功能,该方案不仅大大降低了K8S审计日志分析的门槛,从分析能力、可视化、交互方式、性能等各方面都具有很强的优势:

审计日志方案概览
审计报表
我们默认为Kubernetes集群创建了3个报表,分别是审计中心概览、资源操作概览和资源详细操作列表:

审计中心概览展示Kubernetes集群中的事件整体概览信息以及重要事件(公网访问、命令执行、删除资源、访问保密字典等)的详细信息。
资源操作概览展示Kubernetes集群中常见的计算资源、网络资源以及存储资源的操作统计信息,操作包括创建、更新、删除、访问。其中

计算资源包括:Deployment、StatefulSet、CronJob、DaemonSet、Job、Pod;
网络资源包括:Service、Ingress;
存储资源包括:ConfigMap、Secret、PersistentVolumeClaim。
资源详细操作列表用于展示Kubernetes集群中某类资源的详细操作列表,通过选择或输入指定的资源类型进行实时查询,该表报会显示:资源操作各类事件的总数、namespace分布、成功率、时序趋势以及详细操作列表等。
所有的报表均支持设置时间范围、子账号ID、Namespace等进行自定义过滤并实时刷新,通过这些报表,集群管理员只用点击鼠标就可以获取到:

最近任一时间段内创建/删除/修改了哪些资源;
事件的时序趋势如何;
具体是哪个子账号操作了资源;
操作的IP源是否为公网、地域分布如何、来源IP是否高危;
具体操作的事件ID、时间、结果、涉及的资源等详细日志;
哪个子账号登录了容器或访问了保密字典…
这里我们选择一个图标做详细说明:上图是Kubernetes资源操作列表,这个报表完全是交互式的,用户可以指定一种资源(比如Deployment、Ingress、Secret等),表报会自动渲染出关于这个资源的所有操作,功能包括:

左上角会显示对这个资源操作的用户数、涉及Namespace数、涉及方法数、请求成功率等概览信息;
每种不同操作(增、删、改、查)的数量以及Namespace分布,用来确定涉及的Namespace;
各类操作的时序分布(按小时),数量较多的点一般都是发布或系统被攻击的时间点;
各类操作的详细列表,包括:事件ID、操作事件、操作资源、操作结果、账号、地址;
图表中所有的事件ID都可以点击并跳转到原始的日志,查看具体和这个事件ID关联的详细日志;
图表中所有的IP地址都可以点击并跳转到外部的IP查询库,查询该IP对应的地理位置、运营商等信息;
图表还支持根据账号、namespace、请求码等过滤,比如对某个用户进行审计时,可以过滤子账号,只关心该用户的操作。
自定义告警
例如需要对公网访问设置告警策略:出现公网访问时立即告警,则只需3步就可完成设置:

在审计报表的公网访问图表中点击右上角高级选项-新建告警
填入告警名称、事件、判断条件
填入告警通知方式以及通知内容
自定义分析
如果容器服务Kubernetes版提供的默认报表无法满足您的分析需求,可以直接使用日志服务SQL、仪表盘等功能进行自定义的分析和可视化。

实践

实践环境应具有:es、fluentd、kibana

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aaSAcfwT-1606798413409)(/Users/zhaobei/Library/Application Support/typora-user-images/image-20201022150121703.png)]

Kubernetes 审计功能提供了与安全相关的按时间顺序排列的记录集,记录每个用户、管理员 或系统其他组件影响系统的活动顺序。 它能帮助集群管理员处理以下问题:

  • 发生了什么?
  • 什么时候发生的?
  • 谁触发的?
  • 活动发生在哪个(些)对象上?
  • 在哪观察到的?
  • 它从哪触发的?
  • 活动的后续处理行为是什么?

kube-apiserver 执行审计。每个执行阶段的每个请求都会生成一个事件,然后根据特定策略对事件进行预处理并写入后端。 该策略确定要记录的内容和用来存储记录的后端。当前的后端支持日志文件和 webhook。

每个请求都可以用相关的 “stage” 记录。已知的 stage 有:

  • RequestReceived - 事件的 stage 将在审计处理器接收到请求后,并且在委托给其余处理器之前生成。
  • ResponseStarted - 在响应消息的头部发送后,但是响应消息体发送前。 这个阶段仅为长时间运行的请求生成(例如 watch)。
  • ResponseComplete - 当响应消息体完成并且没有更多数据需要传输的时候。
  • Panic - 当 panic 发生时生成。

说明: 审计日志记录功能会增加 API server 的内存消耗,因为需要为每个请求存储审计所需的某些上下文。 此外,内存消耗取决于审计日志记录的配置。

审计策略

审计政策定义了关于应记录哪些事件以及应包含哪些数据的规则。 审计策略对象结构定义在 audit.k8s.io API 组 处理事件时,将按顺序与规则列表进行比较。第一个匹配规则设置事件的 “审计级别”。已知的审计级别有:

  • None - 符合这条规则的日志将不会记录。
  • Metadata - 记录请求的元数据(请求的用户、时间戳、资源、动词等等), 但是不记录请求或者响应的消息体。
  • Request - 记录事件的元数据和请求的消息体,但是不记录响应的消息体。 这不适用于非资源类型的请求。
  • RequestResponse - 记录事件的元数据,请求和响应的消息体。这不适用于非资源类型的请求。

你可以使用 --audit-policy-file 标志将包含策略的文件传递给 kube-apiserver。 如果不设置该标志,则不记录事件。 注意 rules 字段 必须 在审计策略文件中提供。没有(0)规则的策略将被视为非法配置。

以下是一个审计策略文件的示例:

apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "RequestReceived"
rules:
  # Log pod changes at RequestResponse level
  - level: RequestResponse
    resources:
    - group: ""
      # Resource "pods" doesn't match requests to any subresource of pods,
      # which is consistent with the RBAC policy.
      resources: ["pods"]
  # Log "pods/log", "pods/status" at Metadata level
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]

  # Don't log requests to a configmap called "controller-leader"
  - level: None
    resources:
    - group: ""
      resources: ["configmaps"]
      resourceNames: ["controller-leader"]

  # Don't log watch requests by the "system:kube-proxy" on endpoints or services
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
    - group: "" # core API group
      resources: ["endpoints", "services"]

  # Don't log authenticated requests to certain non-resource URL paths.
  - level: None
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*" # Wildcard matching.
    - "/version"

  # Log the request body of configmap changes in kube-system.
  - level: Request
    resources:
    - group: "" # core API group
      resources: ["configmaps"]
    # This rule only applies to resources in the "kube-system" namespace.
    # The empty string "" can be used to select non-namespaced resources.
    namespaces: ["kube-system"]

  # Log configmap and secret changes in all other namespaces at the Metadata level.
  - level: Metadata
    resources:
    - group: "" # core API group
      resources: ["secrets", "configmaps"]

  # Log all other resources in core and extensions at the Request level.
  - level: Request
    resources:
    - group: "" # core API group
    - group: "extensions" # Version of group should NOT be included.

  # A catch-all rule to log all other requests at the Metadata level.
  - level: Metadata
    # Long-running requests like watches that fall under this rule will not
    # generate an audit event in RequestReceived.
    omitStages:
      - "RequestReceived"

编写我们的审计文件

规划出 audit 策略

审计日志的详尽程度与 kube-apiserver 的性能直接相关,因为仅关注 “谁操作了那种资源”,所以原则上:

  1. 我们仅打印出 RequestReceived 级别的日志,知道 “谁操作的什么资源” 即可
  2. 仅打印出关乎集群可用性、应用可用性的资源操作,这些资源初步会规划包括:
    1. ConfigMap
    2. ClusterRole
    3. RoleBinding
    4. ClusterRoleBinding
    5. Role
    6. Deployment
apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
  - "ResponseStarted"
  - "Panic"
  - "RequestReceived"
rules:
  - level: RequestResponse
    resources:
    - group: "rbac.authorization.k8s.io"
      resources: ["clusterroles","rolebindings","clusterrolebindings","roles"]

  - level: RequestResponse
    resources:
      - group: "apps"
        resources: ["deployments"]

  - level: RequestResponse
    resources:
      - group: ""
        resources: ["configmaps"]
~

采集 kube-apiserver audit log

把日志打到标准输出,使用 fluentd 去采集

/etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=10.9.21.108
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction
    - --enable-bootstrap-token-auth=true
    - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
    - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
    - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
    - --etcd-servers=https://127.0.0.1:2379
    - --audit-policy-file=/etc/pki/audit-logging.yml
    
    
    - --audit-log-path=-  # 标准输出
    - --audit-log-format=json   # 输出为json 格式
    - --feature-gates=TTLAfterFinished=true   # 开启审计


    - --insecure-port=0
    - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
   

使用 Kibana 做分析

创建 kibana pattern,然后根具字段做日志分析:

  1. 每种资源被操作的次数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6WF4PsxR-1606798413410)(/Users/zhaobei/Library/Application Support/typora-user-images/image-20201022150721133.png)]

  1. 每种 action 的操作次数
  2. 都有哪些人做了操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j4PAS4jq-1606798413410)(/Users/zhaobei/Library/Application Support/typora-user-images/image-20201022150751249.png)]

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐