Kube API 访问控制
身份认证策略
kubernetes 通过身份认证插件利用客户端证书、持有者令牌或身份代理来认证 API 请求的身份。HTTP 请求发给 kube-apiserver 时,插件会将以下属性关联到请求本身:
- 用户名
- 用户 ID
- 用户组:一组字符串,用来标明用户是哪些命名的用户组集合的成员,如系统组 system:masters(这个组的使用有一定的风险),这里只是为了说明
- 附加字段:一组额外的 KV 映射,用来保存一些认证组件可能觉得有用的额外价值
所有属性值对于身份认证系统都是非透明的,只有被认证组件解释过之后才有意义,才会被 kubernetes 集群所识别。可以同时启用多种身份认证方法,并且通常至少会有 2 种:
- 针对服务账号使用的令牌
- 针对普通人类用户的身份认证
认证组件的执行顺序是不确定的,对于完成身份认证的用户,system:authenticated 组都会被添加到用户的组属性中。
X.509 客户端证书
通过 TLS 的非对称加密完成的双向身份认证,使用--client-ca-file=<client-ca-file>
,参考证书管理
静态令牌
这种方式就跟我们不同服务之间内部交互,直接使用一个随机字符串去互相认证类似。目前令牌会长期有效,且 kube-apiserver 不重启的情况下无法更新令牌,使用--token-auth-file=<token-file>
。当使用 HTTP 客户端执行身份认证时,http 请求需要携带一个Authorization: Bearer <token string>
的头信息。
启动引导令牌
像执行 kubeadm join 中使用的 token 就是这个,这个主要用于平滑启动引导集群,这些令牌以 Secret 的形式保存在 kube-system 命名空间中,可以被动态管理和创建。TokenCleaner
控制器能够在启动引导令牌过期时将其删除。
它也被设计成可通过 RBAC 策略,结合 kubelet TLS 启动引导系统进行工作。这个令牌被定义成一个特定的 Secret 类型bootstrap.kubernetes.io/token
,并存在于 kube-system 命名空间中。这些 secret 会被 kube-apiserver 启动引导认证组件(Bootstrap Authenticator)读取,TokenCleaner
能够删除过期的启动引导令牌,也被用来在节点发现的过程中使用的一个特殊的 ConfigMap 对象,BootstrapSigner
控制器也会使用这个 ConfigMap。参考Bootstrap Tokens
服务账号令牌
可以被用在集群内部或者集群外部,token 数据可以被保存在 Secret 中,也可以不保存,如果挂载到 Pod 中的容器内可使用 volume 或者环境变量等方式(这种就需要用到 Secret 了),是一种自动启动的用户认证机制。该组件有 2 个参数可以设置:
--service-account-key-file=<X509 rsa 或 ecdsa私钥或公钥>
,可以指定多个文件,若未指定默认使用--tls-private-key-file
参数--service-account-lookup
如果启用,则从 kube-apiserver 删除的令牌会被回收
服务账号被认证通过后,所确定的用户名为system:serviceaccount:<namespace>:<服务账号名>
,并被分配到用户组system:serviceaccounts
和system:serviceaccounts:<namespace>
OIDC 令牌
这是一种比较广泛接受的用于各种不同服务之间共享账号信息的认证的方式,也被 kubernetes 官方推荐为一种作为集群外部使用的方式。一般要配合 OAuth2 的授权,完成用户身份认证。OpenID Connect。第三方组件有:
也可以使用官方已经集成的 OIDC,可以直接使用 kubectl,对于用于而言,可以自己将 kubectl 配置的 OIDC 各项参数封装成一个 shell 脚本
webhook 令牌
这是一种回调机制,可以在启动 kube-apiserver 时添加参数,有--authentication-token-webhook-config-file
,--authentication-token-webhook-cache-ttl
,--authentication-token-webhook-version
,也可以配置在 kubeconfig 中
身份认证代理
这是一种代理的方式,主要用户 HTTP 请求,需要设置一些请求头信息,--requestheader-username-headers
,--requestheader-group-headers
,--requestheader-extra-headers-prefix
等,要使用这种方式,需要使用 TLS 加密,配置合适的 ca 证书,但是不应该在不同的上下文中复用 ca 证书。
匿名请求
如果用户没有经过身份认证,或者类似集群中的 kubelet 绕过了准入控制,这类请求会被标记为system:anonymous
和对应的用户组system:unauthenticated
用户伪装
是一个可以用来伪装成集群中其他用户的手段,以完成一些该用户具有权限的操作。以下 HTTP 请求头用来执行伪装请求:
Impersonate-User
要伪装的用户名Impersonate-Group
要伪装的用户组Impersonate-Extra-<附加名称>
Impersonate-UID
有对应伪装权限的用户也可以使用 kubectl 加参数--as
,--as-group
来伪装目标用户执行该用户具有权限的操作。
client-go credentials 插件
这一特性的目的是便于客户端与 k8s.io/client-go 并不原生支持的身份认证协议(LDAP、Kerberos、OAuth2、SAML 等)集成。该插件实现特定于协议的逻辑,之后返回非透明的凭据供 webhook 组件进行身份认证,然后解析用户数据给集群。
为客户端提供的对身份验证信息的 API 访问
如果启用了此 API,可以使用SelfSubjectReview
API 对象来了解 kubernetes 集群如何映射用户身份验证信息从而识别为某客户端。可用于身份认证调试等目的。默认情况下,所有经过身份验证的用户都可以在 APISelfSubjectReview 特性被启用时创建 SelfSubjectReview 对象,这是由 system:basic-user 集群角色允许的操作。
基于 RBAC 的良好实践
- 最小特权
- 尽可能在命名空间级别分配权限,尽可能使用
RoleBinding
,而不是ClusterRoleBinding
- 尽可能避免通过通配符设置权限
- 尽可能不使用
cluster-admin
账号 - 避免添加用户到
system:masters
组
- 尽可能在命名空间级别分配权限,尽可能使用
- 最大限度减少特权令牌的分发
- 限制具有特权令牌 Pod 的节点数量
- 避免将拥有特权令牌的 Pod 与其他不可信或公开的 Pod 在一个节点运行,可通过使用
Taint
,Toleration
,PodAffinity
,PodAntiAffinity
来实现
- 加固
- 审查
system:unauthenticated
组的绑定,如果可能,将其删掉 - 设置
automountServiceAccountToken: false
来避免服务账号令牌的默认自动挂载
- 审查
- 定期检查 RBAC 的配置是否有冗余条目和提权可能性是至关重要的。如果攻击者能够创建与已删除用户同名的服务账户,它们可以自动继承被铲除用户的所有权限,尤其是分配给该用户的权限
- 警惕 RBAC 权限提升的风险,如 RoleBinding 转换为 ClusterRoleBinding 等行为
- 限制 Secret 的访问与使用
- 通过 Pod 安全性准入来尽可能规避工作负载类的控制器的创建产生的风险
- 持久卷的创建,慎用 hostPath 卷,受信任的人可以用 PV,受约束的人应使用 PVC
- 只允许需要此权限才能工作的用户以及信任的人员
- kubernetes 控制平面组件,这些组件基于已配置为自动制备的 PVC 创建的 PV,通常由 kubernetes 提供商或某些 CSI 插件运行需要
- 小心具有访问 Node 的 Proxy 子资源权限的 Pod 或用户
- 尽量避免使用 esclate,拥有此权限的用户可提升自身的权限
- 尽量避免使用 bind,拥有此权限的用户可以创建并绑定不具有权限的角色
- 尽量避免使用 impersonate,此操作允许用户伪装并获得其他用户的权限
- 小心使用 CSR 和证书颁发,CSR API 允许用户有 create
CSR
和 updatecertificatesigningrequests/approval
的权限,有可能会特权提升 - 令牌请求:拥有
serviceaccount/token
的 create 权限的用户可以创建 TokenRequest 来发布现有服务账户的令牌 - 控制准入 Webhook:可以控制
validatingwebhookconfigurations
或mutatingwebhookconfigurations
的用户可以控制能读取任何允许进入集群的对象的 webhook,并且在有变更 webhook 的情况下,还可以变更准入的对象。 - 为所有 Pod 配置资源配额,以限制可以创建的 Pod 数量,来避免 RBAC 拒绝服务攻击的风险