在Kubernetes中实施审计策略

在Kubernetes 中实施审计策略

作者:Vinod Kumar Nair

翻译:Bach (K8sMeetup)

校对:星空下的文仔

如果我们想检查 Kubernetes 生产环境中的以下活动:

  1. 谁登录了 Kubernetes 集群?

  2. 哪个服务帐户或用户访问了集群中的哪些资源?

  3. 谁创建了 secret 或 configmap?

  4. 谁看了 ETCD 的 secrets ,或者其他更多?

那么在 Kubernetes 中执行审计策略(Audit Policy)是非常正确的选择。

典型的 Kubernetes 环境

图片

没有审计策略的 Kubernetes

启用后,审计记录将在 kube-apiserver 组件内开始其生命周期。每个请求在其执行的每个阶段都会生成一个审计事件,然后根据特定策略对其进行预处理,并写入后端。该策略确定记录的内容,后端将保留记录。当前的后端实现包括日志文件和 webhooks。

每个请求都可以记录一个关联的阶段(stage)。定义的阶段有:

  • RequestReceived - 此阶段对应审计处理器接收到请求后,并且在委托给其余处理器之前生成的事件。

  • ResponseStarted - 在响应消息的头部发送后,响应消息体发送前生成的事件。只有长时间运行的请求(例如 watch)才会生成这个阶段。

  • ResponseComplete - 当响应消息体完成并且没有更多数据需要传输的时候。

  • Panic - 当 panic 发生时生成。

审计策略规则和级别

审计策略定义了有关应该记录哪些事件以及应包含哪些数据的规则。审核策略对象结构在 audit.k8s.ioAPI 组中定义。处理事件时,会按顺序将其与规则列表进行比较。第一个匹配规则设置事件的级别(audit levels)。定义的审核级别有:

  • None - 符合这条规则的日志将不会记录。

  • Metadata - 记录请求的元数据(请求的用户、时间戳、资源、动词等等),但是不记录请求或者响应的消息体。

  • Request - 记录事件的元数据和请求的消息体,但是不记录响应的消息体。这不适用于非资源类型的请求。

  • RequestResponse - 记录事件的元数据,请求和响应的消息体。这不适用于非资源类型的请求。

下面是一个典型的审计策略文件:

Log all requests at the Metadata level.

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

复杂一点就是:

apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:

  • “RequestReceived”
    rules:

  • level: RequestResponse
    resources:

    • group: “”
      resources: [“pods”]
  • level: Metadata
    resources:

    • group: “”
      resources: [“pods/log”, “pods/status”]
  • level: None
    resources:

    • group: “”
      resources: [“configmaps”]
      resourceNames: [“controller-leader”]
  • level: None
    users: [“system:kube-proxy”]
    verbs: [“watch”]
    resources:

    • group: “” # core API group
      resources: [“endpoints”, “services”]
  • level: None
    userGroups: [“system:authenticated”]
    nonResourceURLs:

    • “/api*“ # Wildcard matching.
    • “/version”
  • level: Request
    resources:

    • group: “” # core API group
      resources: [“configmaps”]
      namespaces: [“kube-system”]
  • level: Metadata
    resources:

    • group: “” # core API group
      resources: [“secrets”, “configmaps”]
  • level: Request
    resources:

    • group: “” # core API group
    • group: “extensions” # Version of group should NOT be included.
  • level: Metadata
    omitStages:

    • “RequestReceived”

架构-Kubernetes 中的审计策略

图片

Kubernetes 启用了审计策略

我们可以使用 Webhooks 将审核日志发送到文件或远程 Web API。

在本文中,我们将强制 kube api-server 将审核日志发送到文件。

在 Kubernetes 中启用审计策略(对于审计日志文件)

  1. 创建审计策略 YAML 文件:前往 Kubernetes 集群,并使用以下规则创建 audit-policy.yaml:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:

Log the request body of configmap changes in kube-system.

  • level: Request
    resources:

    • group: “” # core API group
      resources: [“configmaps”]
      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”]

    A catch-all rule to log all other requests at the Metadata level.

  • level: Metadata
    omitStages:

    • “RequestReceived”
  1. 更新 kube api-server 清单文件:

- kube-apiserver
- –advertise-address=10.156.0.6
- –audit-policy-file=/etc/kubernetes/audit-policy.yaml
- –audit-log-path=/var/log/audit.log


  • mountPath: /etc/kubernetes/audit-policy.yaml
    name: audit
    readOnly: true
    — mountPath: /var/log/audit.log
    name: audit-log
    readOnly: false
    -–
    volumes:
  • name: audit
    hostPath:
    path: /etc/kubernetes/audit-policy.yaml
    type: File
  • name: audit-log
    hostPath:
    path: /var/log/audit.log
    type: FileOrCreate

图片

k8s-api-server —清单文件

图片

k8s-api-server —清单文件

就这样,转到生成的审计日志文件。

在这个案例中,这是 audit.log。我们可以看到在阶段级别捕获的有关 Kubernetes 集群的审计日志信息,如以下示例中所示:

{
“kind”:”Event”,
“apiVersion”:”audit.k8s.io/v1”,
“level”:”Metadata”,
“auditID”:”a42fa658-f143–43d8-b5e6–4e101d3e15ea”,
“stage”:”ResponseComplete”,
“requestURI”:”/api/v1/namespaces/default/secrets?fieldManager=kubectl-create”,
“verb”:”create”,
“user”:{
“username”:”kubernetes-admin”,
“groups”:[
“system:masters”,
“system:authenticated”
]
},
“sourceIPs”:[
“10.156.0.2”
],
“userAgent”:”kubectl/v1.20.2 (linux/amd64) kubernetes/faecb19”,
“objectRef”:{
“resource”:”secrets”,
“namespace”:”default”,
“name”:”test-secret”,
“apiVersion”:”v1”
},
“responseStatus”:{
“metadata”:{

},
“code”:201
},
“requestReceivedTimestamp”:”2021–04–03T13:50:37.009656Z”,
“stageTimestamp”:”2021–04–03T13:50:38.040874Z”,
“annotations”:{
“authorization.k8s.io/decision”:”allow”,
“authorization.k8s.io/reason”:””
}
}
{
“kind”:”Event”,
“apiVersion”:”audit.k8s.io/v1”,
“level”:”Metadata”,
“auditID”:”f1466b01–9b68–45ec-b3bb-b440397f6481”,
“stage”:”ResponseComplete”,
“requestURI”:”/api/v1/namespaces/default/secrets/test-secret”,
“verb”:”get”,
“user”:{
“username”:”kubernetes-admin”,
“groups”:[
“system:masters”,
“system:authenticated”
]
},
“sourceIPs”:[
“10.156.0.2”
],
“userAgent”:”kubectl/v1.20.2 (linux/amd64) kubernetes/faecb19”,
“objectRef”:{
“resource”:”secrets”,
“namespace”:”default”,
“name”:”test-secret”,
“apiVersion”:”v1”
},
“responseStatus”:{
“metadata”:{

},
“code”:200
},
“requestReceivedTimestamp”:”2021–04–03T13:51:08.603724Z”,
“stageTimestamp”:”2021–04–03T13:51:08.607716Z”,
“annotations”:{
“authorization.k8s.io/decision”:”allow”,
“authorization.k8s.io/reason”:””
}
}
{
“kind”:”Event”,
“apiVersion”:”audit.k8s.io/v1”,
“level”:”Metadata”,
“auditID”:”30be8c70-fda6–44de-8a83–3fe56161d44e”,
“stage”:”ResponseComplete”,
“requestURI”:”/api/v1/namespaces/default/secrets/test-secret”,
“verb”:”get”,
“user”:{
“username”:”kubernetes-admin”,
“groups”:[
“system:masters”,
“system:authenticated”
]
},
“sourceIPs”:[
“10.156.0.2”
],
“userAgent”:”kubectl/v1.20.2 (linux/amd64) kubernetes/faecb19”,
“objectRef”:{
“resource”:”secrets”,
“namespace”:”default”,
“name”:”test-secret”,
“apiVersion”:”v1”
},
“responseStatus”:{
“metadata”:{

},
“code”:200
},
“requestReceivedTimestamp”:”2021–04–03T13:54:57.867317Z”,
“stageTimestamp”:”2021–04–03T13:54:57.871369Z”,
“annotations”:{
“authorization.k8s.io/decision”:”allow”,
“authorization.k8s.io/reason”:””
}
}

此外, 我们可以使用以下 kube-apiserver 标志配置 Log 审计后端,来更改审计日志文件的状态:

  • --audit-log-maxage 定义保留旧审计日志文件的最大天数。

  • --audit-log-maxbackup 定义要保留的审计日志文件的最大数量。

  • --audit-log-maxsize 定义审计日志文件的最大大小(兆字节)。

总结

审计策略会检查 Kubernetes 集群中发生的所有请求、响应。这是一个最佳实践,应在早期阶段就启用。在本文示例中,和大家展示了如何将审计数据发送到文件。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 1209453173@qq.com