【云原生渗透】- k8s的安全机制
1. 认证阶段2. 鉴权阶段3. RBAC、角色、账号、命名空间参考链接
访问k8s集群的时候,需要经过三个安全步骤完成具体操作。过程中都要经过apiserver,apiserver做统一协调。
第一步 认证,判断用户是否为能够访问集群的合法用户。
第二步 鉴权,通过鉴权策略决定一个API调用是否合法。
第三步 准入控制,就算通过了上面两步,客户端的调用请求还需要通过准入控制的层层考验,才能获得成功的响应。大致意思就是到了这步还有一个类似acl的列表,如果列表有请求内容,就通过,否则不通。它以插件的形式运行在API Server进程中,会在鉴权阶段之后,对象被持久化etcd之前,拦截API Server的请求,对请求的资源对象执行自定义(校验、修改、拒绝等)操作。
这里学习认证和鉴权的安全机制。
1. 认证阶段
认证策略大概有4种:
匿名认证:(Anonymous requests)
匿名认证一般默认是关闭的。
白名单认证:(BasicAuth认证)
白名单认证一般是服务启动时加载的basic用户配置文件,并且通常没有更多设置的话basic认证仅仅只能访问但是没有操作权限。
Token认证:(Webhooks、ServiceAccount Tokens、OpenID Connect Tokens等)
token认证更涉及到对集群和pod的操作,这是我们比较关注的。
X509证书认证:(clientCA认证,TLS bootstrapping等)
X509证书认证是kubernetes组件间内部默认使用的认证方式,同时也是kubectl客户端对应的kube-config
中经常使用到的访问凭证,是一种比较安全的认证方式。
2. 鉴权阶段
当API Server内部通过用户认证后,就会执行用户鉴权流程,即通过鉴权策略决定一个API调用是否合法,API Server目前支持以下鉴权策略:
Always:当集群不需要鉴权时选择AlwaysAllow
ABAC:基于属性的访问控制
RBAC:基于角色的访问控制
RBAC是目前k8s中最主要的鉴权方式。
Node:一种对kubelet进行授权的特殊模式
Node鉴权策略主要是用于对kubelet发出的请求进行访问控制,限制每个Node只访问它自身运行的Pod及相关Service、Endpoints等信息。
Webhook:通过调用外部REST服务对用户鉴权
可自行编写鉴权逻辑并通过Webhook方式注册为kubernetes的授权服务,以实现更加复杂的授权规则。
3. RBAC、角色、账号、命名空间
RBAC,基于角色的访问控制(Role-Based Access Control)
在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。
在k8s中,只有对角色的权限控制,访问主体都必须通过角色绑定,绑定成k8s集群中对应的角色,然后根据绑定的角色去访问资源。而每种角色又只能访问它所对应的命名空间中的资源。
命名空间
k8s支持多个虚拟集群,它们底层依赖于同一个物理集群。这些虚拟集群被称为命名空间(namespace)。
# 查看命名空间
kubectl get ns
系统默认4个命名空间,分别是:
default:没有指明使用其它命名空间的对象所使用的默认命名空间
kube-system:Kubernetes 系统创建对象所使用的命名空间
kube-public:此命名空间下的资源可被所有人访问(包括未授权用户)
kube-node-lease:集群之间的心跳维护
重点关注default和kube-system两个命名空间。
角色分配
RBAC中一直强调角色,这里角色也分为两种,一种是普通角色role,一种是集群角色clusterrole。
普通角色role用于平常分配给运行的容器,而集群角色更多承担管理工作。
查看普通角色,没有特别指明的话查看都是在default空间中。
指定kube-system空间,可以看到很多系统自带的角色。
kubectl get role -n kube-system
集群角色在default和kube-system中都是一样的。
kubectl get clusterrole
集群中有个最高权限角色cluster-admin,它的拥有集群所有资源的所有权限。因此如果访问主体绑定到该角色的话,就会引发很大的安全问题,后续说到的未授权访问就是基于此种情形。
普通的admin权限也比较大,但是比起cluster-admin还是差了太多。
角色权限授予用户:
# 创建一个clusterrolebinding,名称为cluster-admin
# --clusterrole=cluster-admin 角色
# --user=user1 授权给user1用户
# --group=group1 授权给group1组
kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1
服务账号 service account
访问主体中除了常用的用户,组以外,还有一类叫做服务账号,service account。service account是k8s为pod内部的进程访问apiserver创建的一种用户。因为是pod里面的,所以也会对应各自的命名空间。
在k8s中设计了一种资源对象叫做Secret,分为两类,其中一类是容器运行时配置的敏感信息(如密码等),另一类就是用于记录ServiceAccount的service-account-token。
看看kube-system中的secret存储的serviceaccount信息。
可以看到很多serviceaccount name,每个name下都有3个标识,分别是Token、ca.crt、namespace。
token是使用API Server私钥签名的JWT。用于访问API Server时,Server端认证。
ca.crt,根证书。用于Client端验证API Server发送的证书。
namespace, 标识这个service-account-token的作用域名空间,这里的namespace就是kube-system。
举个例子:
账号名在-token前,就叫default。
给这个服务账号绑定cluster-admin这个角色:
kubectl create clusterrolebinding default-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default
# namespace:账号名
我们把这个账号赋予新角色名default-admin,成功绑定到集群角色cluster-admin了,这就意味着我们的default这个serviceaccount拥有了集群最高权限,自然以它建立的pod也是集群最高权限的pod。
参考链接