Webhook 模式

WebHook 是一种 HTTP 回调:某些条件下触发的 HTTP POST 请求;通过 HTTP POST 发送的简单事件通知。一个基于 web 应用实现的 WebHook 会在特定事件发生时把消息发送给特定的 URL。

具体来说,当在判断用户权限时,Webhook 模式会使 Kubernetes 查询外部的 REST 服务。

配置文件格式

Webhook 模式需要一个 HTTP 配置文件,通过 --authorization-webhook-config-file=SOME_FILENAME 的参数声明。

配置文件的格式使用 kubeconfig。 在该文件中,“users” 代表着 API 服务器的 webhook,而 “cluster” 代表着远程服务。

使用 HTTPS 客户端认证的配置例子:

  1. # Kubernetes API 版本
  2. apiVersion: v1
  3. # API 对象种类
  4. kind: Config
  5. # clusters 代表远程服务。
  6. clusters:
  7. - name: name-of-remote-authz-service
  8. cluster:
  9. # 对远程服务进行身份认证的 CA。
  10. certificate-authority: /path/to/ca.pem
  11. # 远程服务的查询 URL。必须使用 'https'。
  12. server: https://authz.example.com/authorize
  13. # users 代表 API 服务器的 webhook 配置
  14. users:
  15. - name: name-of-api-server
  16. user:
  17. client-certificate: /path/to/cert.pem # webhook plugin 使用 cert
  18. client-key: /path/to/key.pem # cert 所对应的 key
  19. # kubeconfig 文件必须有 context。需要提供一个给 API 服务器。
  20. current-context: webhook
  21. contexts:
  22. - context:
  23. cluster: name-of-remote-authz-service
  24. user: name-of-api-server
  25. name: webhook

请求载荷

在做认证决策时,API 服务器会 POST 一个 JSON 序列化的 authorization.k8s.io/v1beta1 SubjectAccessReview 对象来描述这个动作。这个对象包含了描述用户请求的字段,同时也包含了需要被访问资源或请求特征的具体信息。

需要注意的是 webhook API 对象与其他 Kubernetes API 对象一样都同样都遵从版本兼容规则。 实施人员应该了解 beta 对象的更宽松的兼容性承诺,同时确认请求的 “apiVersion” 字段能被正确地反序列化。 此外,API 服务器还必须启用 authorization.k8s.io/v1beta1 API 扩展组 (--runtime-config=authorization.k8s.io/v1beta1=true)。

一个请求内容的例子:

  1. {
  2. "apiVersion": "authorization.k8s.io/v1beta1",
  3. "kind": "SubjectAccessReview",
  4. "spec": {
  5. "resourceAttributes": {
  6. "namespace": "kittensandponies",
  7. "verb": "get",
  8. "group": "unicorn.example.org",
  9. "resource": "pods"
  10. },
  11. "user": "jane",
  12. "group": [
  13. "group1",
  14. "group2"
  15. ]
  16. }
  17. }

期待远程服务填充请求的 status 字段并响应允许或禁止访问。响应主体的 spec 字段被忽略,可以省略。允许的响应将返回:

  1. {
  2. "apiVersion": "authorization.k8s.io/v1beta1",
  3. "kind": "SubjectAccessReview",
  4. "status": {
  5. "allowed": true
  6. }
  7. }

为了禁止访问,有两种方法。

在大多数情况下,第一种方法是首选方法,它指示授权 webhook 不允许或对请求 “无意见”。 但是,如果配置了其他授权者,则可以给他们机会允许请求。如果没有其他授权者,或者没有一个授权者,则该请求被禁止。webhook 将返回:

  1. {
  2. "apiVersion": "authorization.k8s.io/v1beta1",
  3. "kind": "SubjectAccessReview",
  4. "status": {
  5. "allowed": false,
  6. "reason": "user does not have read access to the namespace"
  7. }
  8. }

第二种方法立即拒绝其他配置的授权者进行短路评估。仅应由对集群的完整授权者配置有详细了解的 webhook 使用。webhook 将返回:

  1. {
  2. "apiVersion": "authorization.k8s.io/v1beta1",
  3. "kind": "SubjectAccessReview",
  4. "status": {
  5. "allowed": false,
  6. "denied": true,
  7. "reason": "user does not have read access to the namespace"
  8. }
  9. }

对于非资源的路径访问是这么发送的:

  1. {
  2. "apiVersion": "authorization.k8s.io/v1beta1",
  3. "kind": "SubjectAccessReview",
  4. "spec": {
  5. "nonResourceAttributes": {
  6. "path": "/debug",
  7. "verb": "get"
  8. },
  9. "user": "jane",
  10. "group": [
  11. "group1",
  12. "group2"
  13. ]
  14. }
  15. }

非资源类的路径包括:/api/apis/metrics/logs/debug/healthz/livez/openapi/v2/readyz、和 /version。 客户端需要访问 /api/api/*/apis/apis/*/version 以便 能发现服务器上有什么资源和版本。对于其他非资源类的路径访问在没有 REST API 访问限制的情况下拒绝。

更多信息可以参考 authorization.v1beta1 API 对象和 webhook.go