k8s-访问控制
访问控制是云原生中的一个重要组成部分。
访问控制
请求的发起,请求的发起分为两个部分:
第一个部分是人机交互的过程。 是大家非常熟悉的用 kubectl 对 api-server 的一个请求过程;
第二个部分是 Pod 中的业务逻辑与 api-server 之间的交互。
当api-server 收到请求后,就会开启访问控制流程。这里面分为三个步骤:
Authentication 认证阶段:判断请求用户是否为能够访问集群的合法用户。如果用户是个非法用户,那 api-server 会返回一个 401 的状态码,并终止该请求;
如果用户合法的话,我们的 api-server 会进入到访问控制的第二阶段 Authorization:鉴权阶段。在该阶段中 api-server 会判断用户是否有权限进行请求中的操作。如果无权进行操作,api-server 会返回 403 的状态码,并同样终止该请求;
如果用户有权进行该操作的话,访问控制会进入到第三个阶段:AdmissionControl。在该阶段中 api-server 的 Admission Control 会判断请求是否是一个安全合规的请求。如果最终验证通过的话,访问控制流程才会结束(此时请求将会转换为一个 Kubernetes objects 相应的变更请求,最终持久化到 ETCD 中)。
认证
Kubernetes 中的用户模型:
Kubernetes 没有自身的用户管理能力,无法像操作 Pod 一样,通过 API 的方式创建删除一个用户实例。同时也无法在 ETCD 中找到用户对应的存储对象。
Kubernetes 中的用户通常是通过请求凭证设置,经过 Kubernetes 认证流程之后,api-server 会将请求中凭证中的用户身份转化为对应的 User 和 Groups 这样的用户模型。在随后的鉴权操作和审计操作流程中,api-server 都会使用到该用户模型实例。
Kubernetes支持的请求认证方式主要包括:
Basic 认证:api-server 读取的静态配置文件进行认证,该方式一般用于测试场景,在安全方面是不推荐且不可拓展的一种方式。
X509 证书认证:该方式是 api-server 中相对应用较多的使用方式,首先访问者会使用由集群 CA 签发的,或是添加在 api-server Client CA 中授信 CA 签发的客户端证书去访问 api-server。api-server 服务端在接收到请求后,会进行 TLS 的握手流程。除了验证证书的合法性,api-server 还会校验客户端证书的请求源地址等信息。开启双向认证,X509 认证是一个比较安全的方式,也是 Kubernetes 组件之间默认使用的认证方式,同时也是 kubectl 客户端对应的 kube-config 中经常使用到的访问凭证。
Bearer Tokens(JSON Web Tokens):Service Account;OpenID Connect;Webhooks。
Kubernetes Pod 应用中经常使用到的 Service Account,其中就会自动绑定一个签名后的 JWT Token 用于请求 api-server。该方式的 Tokens 是通用的 JWT 的形式,其中包含了签发者、用户的身份、过期时间等多种元信息。它的认证方式也是常见的私钥加签,公钥验签的一个基本流程。
基于 OpenID 协议的 Token 认证,可以通过对 api-server 的配置连接一个指定的外部 IDP,同时可以通过 Keycloak,Dex 这样的开源服务来管理 IDP,请求者可以按照自己熟悉的方式在原身份认证服务上进行登录认证,并最终返回一个相应的 JWT token,为了后面的 api-server 的鉴权流程。
Webhooks 的方式,将请求的 Token 发送到指定外部服务进行 Token 的验签。
X509 证书认证
认证机构 (CA) 是一个非常重要的证书对。它会被默认放置在集群 Master 节点上的 /etc/Kubernetes/pki/ 目录下。集群中所有组件之间的通讯用到的证书,其实都是由集群根 CA 来签发的。在证书中有两个身份凭证相关的重要字段:一个是 CN(common name,认证过程中作为user),一个是 O(organization,认证过程中作为组 group)。
每个k8s系统组件在集群创建时都被签发了自身客户端的证书,这样的设置可以使各系统组件只绑定自身功能范围内的角色权限。从而保证了每个系统组件自身权限的最小化。
Service Account
除了证书认证之外,Service Account 也是 api-server 中应用比较广泛的一种方式。对于 Service Account 来说,它是 K8s中唯一能够通过 API 方式管理的 APIService 访问凭证。
在部署一个应用时,可以通过 Template-spec-serviceAccountName 字段声明需要使用的 Service Account 名称。注意如果是在 Pod 创建过程中,发现制定的 ServiceAccount 不存在,则该 Pod 创建过程会被终止。
在生成的 Pod 模板中可以看到指定 Service Account 对应的 secret 中的 CA namespace 和认证 token 会分别以文件的形式挂载到容器中的指定目录下,另外对于已经创建的 Pod,则不能更新其已经挂载的 ServiceAccount 内容。
鉴权 - RBAC
RBAC 鉴权三要素:
第一要素是 Subjects,也就是主体。可以是开发人员、集群管理员这样的自然人,也可以是系统组件进程,或者是 Pod 中的逻辑进程;
第二个要素是 API Resource,也就是请求对应的访问目标。在 Kubernetes 集群中也就是各类资源;
第三要素是 Verbs,对应为请求对象资源可以进行哪些操作,包括增删改查、list、get、watch 等。
在整个 RBAC 策略定义下,将访问角色绑定到一个具体的控制域内。就是 Kubernetes 悉的命名空间。通过 namespace 可以将 Kubernetes api 资源限定在不同的作用域内。从而帮助在一个多租户集群中,对用户进行逻辑上的隔离。
这里需要注意的是,如果不进行任何的权限绑定,RBAC 会拒绝所有访问。
RBAC 具体的绑定权限和对象:
Role,它定义了用户在指定的 Kubernetes 命名空间资源上可以进行哪些操作。比如可以定一个 namespace 中 pod 的只读权限,同时还可以定义一个 namespace 管理员权限,它具有对这个命名空间下所有对象资源的所有操作权限。
RoleBinding,将 Role 对应的权限模型绑定到对应的 Subject 上。一个绑定只能指定唯一的 Role。
ClusterRole ,定义一个集群维度的权限模型。在一个 Cluster 实例中,可以定义集群维度的权限使用权限,比如像 PV、Nodes 在 namespace 中不可见的资源权限,可以在 ClusterRole 中定义,而操作这些资源的动作同样是之前 Role 中支持的增删改查和 list、watch 等操作。
ClusterRoleBinding 模型实例可以帮助在集群所有命名空间上将 ClusterRole 绑定到具体的 Subject 对象上。
在集群创建的时候,处理系统各组件的客户端证书,它们各自的角色和环境对象也会被创建出来,以满足组件业务之间交互必须的权限要求。
角色中的 verbs:list,get,creat,watch,delete,patch
List:获取资源的列表。例子: kubectl get pods 会列举所有当前命名空间下的 Pod。
Get:获取指定资源对象的详细信息。例子: kubectl get pod <pod-name> 获取特定 Pod 的详细信息。
Create: 创建新的资源对象。例子: kubectl create -f pod-definition.yaml 创建一个 Pod,定义在 YAML 文件中。
Watch:在资源对象发生变化时持续获取更新。例子: kubectl get pods --watch 会在控制台上实时显示 Pod 列表,并持续更新。
Delete: 删除指定的资源对象。例子: kubectl delete pod <pod-name> 删除特定的 Pod。
Patch(部分更新): 部分更新资源对象的字段。例子: kubectl patch pod <pod-name> -p '{"spec":{"containers":[{"name":"container-name","image":"new-image"}]}}' 部分更新 Pod 的容器镜像。
Security Context 的使用
CVE-2019-5736:攻击者能够在容器内获取并修改宿主机runc从而获取root权限执行恶意代码。
Runtime 安全策略:
首先还是要遵循权限最小化原则,除了业务运行所必需的系统权限,其他权限都是可以去除的;
此外还可以通过在 pod 或者 container 维度设置 Security Context 参数,进行业务容器运行时刻的安全配置;
另外就是可以通过开启 Pod Security Policy,在 api-server 请求的 Admission 阶段强制校验容器的安全配置;
多租环境的安全加固


浙公网安备 33010602011771号