
17.Kubernetes访问控制
1.请求流程
,请求的发起分为两个部分:
- 第一个部分是人机交互的过程。 是大家非常熟悉的用 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 中。
2.认证方式
Kubernetes 没有自身的用户管理能力,我们无法像操作 Pod 一样,通过 API 的方式创建删除一个用户实例。同时我们也无法在 ETCD 中找到用户对应的存储对象。
- Basic 认证
该认证方式下,管理员会将 Username 和 Password 组成的白名单放置在 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
该方式的 Tokens 是通用的 JWT 的形式,其中包含了签发者、用户的身份、过期时间等多种元信息。它的认证方式也是常见的私钥加签,公钥验签的一个基本流程。基于 Token 的认证使用场景也很广泛,比如 Kubernetes Pod 应用中经常使用到的 Service Account,其中就会自动绑定一个签名后的 JWT Token 用于请求 api-server。
另外 api-server 还支持基于 OpenID 协议的 Token 认证,可以通过对 api-server 的配置连接一个指定的外部 IDP,同时可以通过 Keycloak,Dex 这样的开源服务来管理 IDP,请求者可以按照自己熟悉的方式在原身份认证服务上进行登录认证,并最终返回一个相应的 JWT token,为了后面的 api-server 的鉴权流程。
除此之外,还可以使用 Webhooks 的方式,将请求的 Token 发送到指定外部服务进行 Token 的验签。
3.安全框架
k8s安全框架主要由3个阶段进行控制,每一个阶段都支持插件方式,通过APi Server配置来启用插件
- Authentication(鉴全)
- Authorization(授权)
- Admission Control(准入控制)
Apiserver提供三种客户端身份认证
- HTTPS证书认证:基于CA证书签名的数据证书认证(kubuconfig)
- HTTP Token认证:通过一个Token来识别用户(serviceaccount)
- HTTP Base认证:用户名+密码认证方式,已弃用
4.准入控制
Admission Control准入控制
实现让用户自己定义准入规则插件,k8s自身也是模块化设计。
Adminssion Control实际上是一个准入控制器插件列表,发送到API Server的请求都需要经过这个列表的每个准入控制器插件的检查,检查不通过,则拒绝请求
启用一个准入控制器:
kube-apiserver --enable-admission-pluguns=NamespaceLifecycle,LimitRanger关闭一个准入控制器
kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny查看默认启用
kubectl exec kube-apiserver-k8s-master -n kube-system --kube-apiserver -h | grep enable-admission-plugins.
5.RBAC授权
RBAC(Role-Based Access Control 基于角色的访问控制):负责完成授权工作
RBAC根据API请求属性,决定允许还是拒绝。
比较常见的授权维度:
- user
- group
- 资源,pod,deployment
- 资源的操作,get,list,create,update
- 命名空间
- API组
基于角色的权限访问控制RBAC
RBAC是k8s默认授权策略,并且是动态配置策略
主体
- User
- Group
- ServiceAccount:服务帐号
角色
- Role:授权特定命名空间的访问权限
- ClusterRole:授权所有命名空间的访问权限
角色绑定
- RoleBinding:将角色绑定到主体
- ClusterRoleBinding:将集群角色绑定到主体
6.RBAC基于用户实验
需求:授权访问default命名空间Pod读取权限
实施步骤:
- 用k8s CA签发客户端证书
- 生成kubeconfig授权文件
- 创建RBAC权限策略
- 指定kubeconfig文件测试权限
kubectl get pods --kubeconfig=./config/user.kubeconfig1.签发客户端证书
使用cfssl工具生成客户端CA证书(链接:https://pan.baidu.com/s/12LXQBPFWAM9giYGeI679UA 提取码:CBMM)
#ls cert.sh kubeconfig.sh rbac.yaml #bash cert.sh #ll total 32 -rw-r--r-- 1 root root 997 Nov 28 18:18 aliang.csr -rw-r--r-- 1 root root 219 Nov 28 18:18 aliang-csr.json -rw------- 1 root root 1679 Nov 28 18:18 aliang-key.pem -rw-r--r-- 1 root root 1277 Nov 28 18:18 aliang.pem -rw-r--r-- 1 root root 292 Nov 28 18:18 ca-config.json -rw-r--r-- 1 root root 741 Sep 1 2019 cert.sh -rw-r--r-- 1 root root 622 Sep 1 2019 kubeconfig.sh -rw-r--r-- 1 root root 477 Aug 25 2019 rbac.yaml2.生成授权文件
生成kubeconfig授权文件,
embed-certs=true使用base64编码写入文件中# 设置集群 kubectl config set-cluster kubernetes \ # 集群的名字kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt \ --embed-certs=true \ --server=https://192.168.31.61:6443 \ --kubeconfig=aliang.kubeconfig # 设置客户端认证 kubectl config set-credentials aliang \ #客户端名字aliang --client-key=aliang-key.pem \ --client-certificate=aliang.pem \ --embed-certs=true \ --kubeconfig=aliang.kubeconfig # 设置默认上下文 (可以配置一个证书使用多个集群) kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=aliang \ --kubeconfig=aliang.kubeconfig # 设置当前使用配置 kubectl config use-context kubernetes --kubeconfig=aliang.kubeconfig查看生成的kubeconfig
apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1CRUdJTiBtCg== server: https://192.168.122.71:6443 name: kubernetes contexts: - context: cluster: kubernetes user: aliang name: kubernetes current-context: kubernetes kind: Config preferences: {} users: - name: aliang user: client-certificate-data: LS0tLBVEUtLS0tLQo= client-key-data: LS0tLS1CRUdJTiBSU3.创建RBAC权限策略
创建角色(权限集合):
kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: default name: pod-reader rules: - apiGroups: [""] # api组,例如apps组,空值表示是核心API组,像namespace、pod、service、pv、pvc都在里面 resources: ["pods","pods/log"] #资源名称(复数),例如pods、deployments、services verbs: ["get", "watch", "list"] # 资源操作方法查看api组的方式
- apiGroups: [“”]# kubectl api-resources | grep apps controllerrevisions apps/v1 true ControllerRevision daemonsets ds apps/v1 true DaemonSet deployments deploy apps/v1 true Deployment replicasets rs apps/v1 true ReplicaSet statefulsets sts apps/v1 true StatefulSet # kubectl api-resources | grep networking ingressclasses networking.k8s.io/v1 false IngressClass ingresses ing networking.k8s.io/v1 true Ingress networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy将用户与角色绑定:
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: default subjects: - kind: User # 主体 name: aliang # 主体名称 apiGroup: rbac.authorization.k8s.io roleRef: # 绑定的角色 kind: Role name: pod-reader # 角色名称 apiGroup: rbac.authorization.k8s.io查看当前权限
#kubectl get node --kubeconfig=./aliang.kubeconfig Error from server (Forbidden): nodes is forbidden: User "aliang" cannot list resource "nodes" in API group "" at the cluster scope #kubectl get pods --kubeconfig=./aliang.kubeconfig NAME READY STATUS RESTARTS AGE configmap-demo-pod1 1/1 Running 0 4h2m fluentd-elasticsearch-7vgqn 1/1 Running 0 7h12m fluentd-elasticsearch-g6dqw 1/1 Running 0 7h11m web6-0 1/1 Running 0 7h12m web6-1 1/1 Running 0 7h11m web6-2 1/1 Running 0 7h11m4.增加授权访问
修改rbac.yaml文件
kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: default name: pod-reader rules: - apiGroups: ["","apps"] # api组,例如apps组,空值表示是核心API组,像namespace、pod、service、pv、pvc都在里面 resources: ["pods","pods/log","services","deployment"] #资源名称(复数),例如pods、deployments、services verbs: ["get", "watch", "list"] # 资源操作方法验证权限
#kubectl get pods,svc,deploy --kubeconfig=./aliang.kubeconfig NAME READY STATUS RESTARTS AGE pod/configmap-demo-pod1 1/1 Running 0 4h11m pod/fluentd-elasticsearch-7vgqn 1/1 Running 0 7h21m pod/fluentd-elasticsearch-g6dqw 1/1 Running 0 7h21m pod/rbc-788cd8c47f-2q6vf 0/1 ContainerCreating 0 3s pod/web6-0 1/1 Running 0 7h21m pod/web6-1 1/1 Running 0 7h20m pod/web6-2 1/1 Running 0 7h20m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 21d service/web ClusterIP None <none> 80/TCP 8h service/web-01 NodePort 10.108.173.136 <none> 80:30897/TCP 14d service/web-02 NodePort 10.108.216.246 <none> 80:32006/TCP 14d NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/rbc 0/1 1 0 3s.
7.RBAC基于角色实验
为一个服务分配只能创建deployment,daemonset,statefulset的权限
命令行创建
# 创建集群角色 kubectl create clusterrole deployment-clusterrole \ --verb=create --resource=deployments,daemonsets,statefulsets # 创建服务账号 kubectl create serviceaccount cicd-token -n app-team1 # 将服务账号绑定角色 kubectl create rolebinding cicd-token \ --serviceaccount=app-team1:cicd-token \ --clusterrole=deployment-clusterrole -n app-team1 # 测试服务账号权限 kubectl --as=system:serviceaccount:app-team1:cicd-token get pods -n app-team1yaml创建
apiVersion: v1 kind: ServiceAccount metadata: name: cicd-token namespace: app-team1 --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: deployment-clusterrole rules: - apiGroups: ["apps"] resources: ["deployments","daemonsets","statefulsets"] verbs: ["create"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding # 角色绑定 metadata: name: cicd-token namespace: app-team1 roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: deployment-clusterrole subjects: - kind: ServiceAccount name: cicd-token # 服务帐号 namespace: app-team1.
8.查看授权信息
[root@cka-master ] cka-master #kubectl get role NAME CREATED AT leader-locking-nfs-client-provisioner 2021-11-27T16:17:11Z pod-reader 2021-11-28T10:58:22Z [root@cka-master ] cka-master #kubectl describe role pod-reader Name: pod-reader Labels: <none> Annotations: <none> PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- deployments [] [] [get watch list] pods/log [] [] [get watch list] pods [] [] [get watch list] services [] [] [get watch list] deployments.apps [] [] [get watch list] pods.apps/log [] [] [get watch list] pods.apps [] [] [get watch list] services.apps [] [] [get watch list].