Kubernetes——访问控制

访问控制

  在用户租户的系统上,认证和授权都是两个必不可少的功能。认证用于身份鉴别,授权是用于实现权限分派。

  Kubernetes 以插件化方式实现了这两种功能,且分别存在多种可用的插件。

  API Server 是 Kubernetes 集群系统的唯一网关入口,像 kube-controller-manager、kube-scheduler、kubelet、kubeclt 和 kube-proxy 等集群组件、CoreDNS 等集群的附加组件都需要经由 API Server 网关进行集群访问和管理。这些客户端均要经由 API Server 访问或改变集群状态并完成 etcd 数据存储,API Server 会对每次访问请求进行合法校验,包括身份鉴权,操作权限验证,以及操作是否符合全局规范约束等。

  API Server 通过一个或者多个认证插件完成访问控制。当收到客户端请求后,API Server 依次调用为其配置的认证插件来认证客户端身份,直到其中一个插件可以识别出请求者的身份为止。授权操作也是由一个或多个授权插件完成。通过认证、授权检测的用户请求,还要经过一个到多个的准入控制器插件的遍历检查。

一、用户帐号与用户组

  Kubernetes 并不会存储由认证插件从客户端请求中提取出的用户及所属组的信息,它们仅仅用于检验用户是否有权限执行其所请求的操作。

  客户端访问 API 服务的途径通常有三种:

    • kubectl
    • 客户端库
    • REST 接口进行请求

  客户端请求的主体一般分为两类(也就是Kubernetes系统中 User Account 和 Service Account):

    • User Account(用户帐号):一般是指由独立于 Kubernetes 之外的其他服务管理的用户帐号,例如由管理员分发的密钥、Keystone 一类的用户存储(账号库),甚至包含有用户名和密码列表的文件等。Kubernetes 中不存在表示此类用户帐号的对象,因此不能被直接添加进 Kubernetes 系统中。
    • Service Account(服务帐号):是指由 Kubernetes API 管理帐号,用于为 Pod 之中的服务进程在访问 Kubernetes API 时提供身份表示(identity)。Service Account 通常要绑定于特定的名称空间,它们由 API Server 创建,或者通过 API 调用手动创建,附带一组存储为 Secret 的用于访问 API Server 的凭据。
  • User Account 通常用于复杂的业务逻辑管控,它作用于系统全局,故其名称必须全局唯一。
  • Service Account 隶属于名称空间,仅用于实现某些特定的操作任务。

  这两类的帐号可以隶属于同一个或多个用户组。用户组只是用户帐号的逻辑集合,它本身并没有操作权限,但附加于组上的权限可由其内部的所有用户继承,以实现高效的授权管理机制。

  Kubernetes 有以下几个内建的组:

    • system:unauthenticated: 未能通过任何一个授权插件检验的帐号,即未通过认证测试的用户所属的组。
    • system:authenticated: 认证成功后的用户自动加入的一个组,用于快捷引用所有正常通过认证的用户帐号。
    • system:serviceaccounts: 当系统上的所有 Service Account 对象。
    • system:serviceaccounts:<namespace>: 特定名称空间内所有的 Service Account 对象。

  API 请求要么与普通用户或服务帐户进行绑定,要么被视为匿名请求。这意味着集群内部或外部的每个进程,包括由人类用户使用的 kubectl,到节点上的 kubelet,再到控制平面的成员组件,必须在向 API 服务器发出请求时进行身份认证,否则被视为匿名用户。

二、API Server 常见认证方式

  API Server 处理请求的过程中,认证插件负责鉴定用户身份,授权插件用于操作权限许可鉴别,而准入控制则用于在资源对象的创建、删除、更新或连接(proxy)操作时实现更精细的许可检查。

  Kubernetes 使用身份验证插件对 API 请求进行身份验证,支持的认证方式包括客户端证书、承载令牌(bearer tokens)、身份验证代理(authenticating proxy)或 HTTP basic 认证等。

  API Server 接收到访问请求时,它将调用认证插件尝试将以下属性与访问请求相关联:

    • Username: 用户名,如 kubernetes-admin 等。
    • UID: 用户的数字标签符,用于确保用户身份的唯一性。
    • Groups: 用户所属的组,用于权限指派和继承。
    • Extra: 键值数据类型的字符串,用于提供认证时需要用到的额外信息。 

  API Server 支持同时启用多种认证机制,但至少应该分别为 Service Account 和 User Account 各自启用一个认证插件。启用多种认证机制时,认证过程会以串行的方式进行,直到一种认证机制成功完成即结束。若认证失败,则服务器会响应 401 状态码,反之,请求者就会被识别为某个具体的用户(以其用户名进行标识),并且随后的操作都将以此用户身份来进行。

  具体来说,API Server 支持以下几种具体的认证方式,其中所有的令牌认证机制通常被统称为承载令牌认证:

1)X509客户端证书认证

  客户端在请求报文中携带 X509 格式的数字证书用于认证,认证通过之后,证书中的主体标识(Subject)将被识别为用户标识,其中的 CN(CommonName)字段是用户名,O(Organization)是用户所属的组,如 "/CN=iliux/O=opmasters/O=admin"中,用户名为 ilinux,其属于 opmasters 和 admin 两个组。

2)静态令牌文件(Static Token File)

  即保存着令牌信息的文件,由 kube-apiserver 的命令行选项 --token-auth-file 加载,且服务器启动后不可更改;HTTP 客户端也能使用承载令牌进行身份验证,将令牌进行编码后,通过请求报文中的 Authorization 首部承载传递给 API Server 即可。

3)引导令牌(Bootstrap Token)

  一种动态管理承载令牌进行身份认证的方式,常用于简化新建 Kubernetes 集群的节点认证过程,需要通过 --experimental-bootstrap-token-auth 选项启用。

  有新的个工作节点首次加入时,Master 使用引导令牌确认节点身份的合法性之后自动为其签署数字证书以用于后续的安全通信,使用 kubeadm join 命令将节点加入 kubeadm 初始化的集群时使用的就是这种认证方式。

  这些令牌作为 Secret 存储在 kube-system 命名空间中时,可以动态管理和创建它们,而 Controller Manager 包含一个 TokenCleaner 控制器,用于删除过期的引导令牌。

4)静态密码文件

  用户名和密码等令牌以明文格式存储的 CSV 格式文件,由 kube-apiserver 使用 --basic-auth-file 选项进行加载。客户端在 HTTP basic 认证中将认证用户的用户名和密码编码后以承载令牌的格式进行认证。

5)服务账户令牌

  由 kube-apiserver 自动启用,并可使用可选选项加载 --service-account-key-file 验证承载令牌的密钥,省略时将使用 kube-apiserver 自己的证书匹配的私钥文件。

  Service Account 通常由 API Server 自动创建,并通过 ServiceAccount 准入控制器将其注入 Pod 对象,包括 Service Account 上的承载令牌,容器中的应用程序请求 API Server 的服务时将以此完成身份认证。

6)OpenID 连接令牌

  OAuth2 的一种认证风格,由 Azure AD、Salesfore 和 Google 等 OAuth2 服务商所支持,协议的主要扩展是返回的附加字段,其中的访问令牌也称为 ID 令牌。

  它属于 JSON Web 令牌(JWT)类型,有着服务器签名过的常用字段,如 email 等。

  kube-apiserver 启用这种认证功能的相关选项较多。

7)Webhook 令牌

  HTTP 身份验证允许将服务器的 URL 注册为 Webhook,并接收带有承载令牌的 POST 请求进行身份认证。

  客户端使用 kubeconfig 格式的配置文件,在文件中,"user" 指的是 API 服务器 Webhook,"cluster" 指的是 API Server。

 8)认证代理

  API Server 支持从请求首部的值中识别用户,如 X-Remote-User 首部,它旨在与身份验证代理服务结合,并由该代理设置相应的请求首部。

9)Keystone 密码

  借助于外部的 Keystone 服务器进行身份验证。

10)匿名请求

  未被任何验证机制明确拒绝的用户即为匿名用户,其会被自动标识为用户名为 system:anonymous,并隶属于 system:unauthenticated 用户组。

  在 API Server 启用了除 AlwaysAllow 以外的认证机制时,匿名用户处于启用状态,不过管理员可以通过 --anonymous-auth=false 选项将其禁用。

三、API Server 请求报文信息格式

  API Server 是一种 REST API,除了身份认证信息之外,一个请求报文还需要提供操作方法及目标对象,如针对某 Pod 资源对象进行的创建、查看、修改或删除操作等,具体来说,请求报文包含如下信息:

    • API:用于定义请求的目标是否为一个 API 资源。
    • Request path: 请求的非资源型路径,如 /api 或 /healthz。
    • API group: 要访问的 API 组,仅对资源型请求有效;默认为“ core API group”。
    • Namespace: 目标资源所属的名称空间,仅对隶属于 名称空间类型 的资源有效。
    • API request verb: API 请求类的操作,即资源型请求(对资源执行的操作),包括 get、list、create、update、patch、watch、proxy、redirect、delete 和 deletecollection。
    • HTTP request verb: HTTP 请求类的操作,即非资源型请求要执行的操作,如 get、post、put 和 delete。
    • Resource :请求的目标资源的 ID 或名称。
    • Subresource 请求的子资源。

 四、API Server 四种内建授权插件

  为了核验用户的操作许可,成功通过身份认证后的操作请求还需要转交给授权插件进行许可权限检查,以确保其拥有执行相应的操作的许可。API Server 主要支持使用四中内建的授权插件来定义用户的操作权限。

    • Node 基于 Pod 资源的目标调度节点来实现的对 kubelet 的访问控制。
    • ABAC: attribute-based access control 基于属性的访问控制。
    • RBAC: role-based access control ,基于角色的访问控制。
    • Webhook 基于 HTTP 回调机制通过外部 REST 服务检查确认用户授权的访问控制。

五、AlwaysDeny 和 AlwaysAllow 两种特殊授权插件

  AlwaysDeny 和 AlwaysAllow 两个是特殊的插件,其中 AlwaysDeny(总是拒绝)仅用于测试,而 AlwaysAllow(总是允许)则用于不期望进行授权检查时直接于授权检查阶段放行的所有操作请求。

  启动 API Server 时,"--authorization-mode" 选项用于定义要启用的授权机制,多个选项彼此之间以逗号分隔。

六、API Server 内置准入控制器

  准入控制器(Admission Controller)则用于在客户端请求经过身份验证和授权检查之后,但在对象持久化存储 etcd 之前拦截请求,用于实现在资源的创建、更新和删除操作期间强制执行对象的语义验证等功能,读取资源信息的操作请求不会经由准入控制器的检查。

  API Server 内置了许多准入控制器,常用的包含如下几种:

  • AlwaysAdmit: 允许所有请求。
  • AlwaysDeny: 拒绝所有请求,仅应该用于测试。
  • AlwaysPulllmages: 总是下载镜像,即每次创建 Pod 对象之前都要去下载镜像,常用于多租户环境中以确保私有镜像仅能够被拥有权限的用户使用。
  • NamespaceLifecycle: 拒绝于不存在的名称空间中创建资源 ,而删除名称空间将会级联删除其下的所有其他资源。
  • LimitRanger: 可用资源范围界定,用于监控对设置了 LimitRange 的对象所发出的所有请求,以确保其资源、请求不会超限。
  • ServiceAccount: 用于实现 Service Account 管控机制的自动化,实现创建 Pod 对象时自动为其附加相关的 Service Account 对象。
  • PersistentVolumeLabel: 为那些由云计算服务商提供的 PV 自动附加 region 和 zone 标签,以确保这些存储卷能够正确关联且仅能关联到所属的 region zone。
  • DefaultStorageClass: 监控所有创建 PVC 对象的请求,以保证那些没有附加任何专用 StorageClass 的请求会自动设定一个默认值。
  • ResourceQuota: 用于对名称空间设置可用资源的上限,并确保在其中创建的任何设置了资源限额的对象都不会超出名称空间的资源配额。
  • DefaultTolerationSeconds: 如果 Pod 对象上不存在污点宽容期限,则为它们设置默认的宽容期,以宽容 "notready: NoExecute" 和 "unreachable:NoExctute" 类的污点 5分钟 时间。
  • MutatingAdmissionWebhook: 串行调用匹配当前请求的所有变异类的 Webhook,每个调用都可能会更改对象。
posted @ 2022-07-02 11:27  左扬  阅读(117)  评论(0编辑  收藏  举报
levels of contents