内容:记录k8s的访问控制
数字证书:
数字证书: 数字证书是用来认证公钥持有者身份合法性的电子文档,以防止第三方冒充行为。 数字证书由 CA(Certifacate Authority) 负责签发,关键内容包括 颁发者、 证书有效期、使用者组织、使用者公钥等信息。 CA 数字签名包括两个过程:签发证书(Signing) 和 验证证书(Verification)签发和验证过程:
签发证书的过程 1、撰写证书元数据:包括 签发人(Issuer)、地址、签发时间、有效期 等,还包括证书持有者 (Owner)基本信息,比如 DN(DNS Name,即证书生效的域名)、 Owner 公钥 等信息使用通用 的 Hash 算法(如SHA-256)对证书元数据计算生成数字摘要 2、使用 Issuer 的私钥对该数字摘要进行加密,生成一个加密的数字摘要,也就是Issuer的 数字签名 3、将数字签名附加到数字证书上,变成一个签过名的数字证书 4、将签过名的数字证书与 Issuer 的公钥,一同发给证书使用者 验证证书的过程 1、证书使用者获通过某种途径(如浏览器访问)获取到该数字证书,解压后分别获得 证书元数据和数字签名 2、使用同样的Hash算法计算证书元数据的 数字摘要 3、使用 Issuer 的公钥 对数字签名进行解密,得到 解密后的数字摘要 4、对比2和3两个步骤得到的数字摘要值,如果相同,则说明这个数字证书确实是被Issuer验证 过合法证书,证书中的信息(最主要的是 Owner 的公钥)是可信的证书链:
证书信任链(Certificate Authority Chain) 证书签发者,很可能不是该CA认证机构的根证书,因为中间会存在一级或多级的中级证书颁发 机构(Intermediate Certificate),因此在验证过程中可能会存在"证书链"的验证逻辑为什么x509在kubernetes使用广泛:
为什么一定是X.509证书? 在介绍数字证书中,重点提到了一种证书类型—X.509,它是CA认证体系的重要组成部分。 为什么X.509证书在Kubernetes环境中广泛使用? CA认证体系(即X.509证书)并不是唯一的选择。Kubernetes集群支持很多种认证方式: Static Token File Static Password File OIDC—Open ID Connect X509 Client Certs 1、从信息安全的角度来看,x509证书运用了非对称加密算法(即双钥加密)以及数字签名, 相对于使用password和token方式来讲,更为安全,更难破解。 2、从用户管理存储介质的角度来看,Kubernetes是不管理普通用户(Normal User)的, 而是将它解耦出来,交给外部的独立组件。单就Kubernetes控制平台的相关用户和组来说, x509证书没有使用任何外部用户管理系统来存储相关的认证信息,而是将这些用户信息内置 到证书文件中,使用者不需要付出额外的精力来完成前面提到用户管理的工作。 3、从Kubernetes认证和授权体系来看,Kubernetes使用x509证书中 CN(Common Name)以及O(Organization)字段对应Kubernetes中的user和group, 将Authentication和RBAC Authorization结合到了一起,巧妙地将Control Plane 中的各个核心User和Group、与操作权限(ClusterRole)进行绑定(ClusterRoleBinding)service account 与 user account:
Servic Account(服务账号): 是指由Kubernetes API管理的账号,用于为Pod之中的服务进程在访问Kubernetes API时 提供身份标识。Service Account通常绑定于特定的名称空间,由API Server创建,或者 通过API调用手动创建。 User Account(用户账号): 独立于Kubernetes之外的其他服务管理用户账号,例如由管理员分发秘钥、Keystone一类 的用户存储(账号库)、甚至是保函有用户名和密码列表的文件等。 区别1、 User Account是为外部用户设计的; Service Account则是为Pod中的进程调用Kubernetes API而设计; 区别2、 User Account是跨namespace的; 而Service Account则是仅局限它所在的namespace; 注意:每个namespace都会自动创建一个default service account实践:
自建证书和账号进行访问apiserver
1)为目标用户账号kube-user1创建私钥及证书文件,保存于/etc/kubernetes/pki目录中 (1)生成私钥 # cd /etc/kubernetes/pki/ # openssl genrsa -out kube-user1.key 2048 (2)创建证书签署请求,-subj选项中的CN的值将被kubeconfig作为用户名使用,O的值将被 识别为用户组 # openssl req -new -key kube-user1.key -out kube-user1.csr -subj \ "/CN=kube-user1/O=kubernetes" (3)基于安装Kubernetes集群时的CA签署证书,这里设置其有效时长为3650天 # openssl x509 -req -in kube-user1.csr -CA ca.crt -CAkey ca.key - \ CAcreateserial -out kube-user1.crt -days 3650 (4)验证证书信息 # openssl x509 -in kube-user1.crt -text -noout # 使用默认的管理员kubernetes-admin@kubernetes为新建的kube-user1设定 kube-config配置文件。配置结果默认保存于当前系统用户的.kube/config文件中。 (5)添加用户到认证 # kubectl config set-credentials kube-user1 --embed-certs=true --client- \ certificate=/etc/kubernetes/pki/kube-user1.crt --client- \ key=/etc/kubernetes/pki/kube-user1.key (6)配置context,用来组合cluster和credentials,即访问的集群的上下文 # kubectl config set-context kube-user1@kubernetes --cluster=kubernetes \ --user=kube-user1 (7)查看配置文件信息 # kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://192.168.1.31:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kube-user1 name: kube-user1@kubernetes - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes current-context: kubernetes-admin@kubernetes kind: Config preferences: {} users: - name: kube-user1 user: client-certificate-data: REDACTED client-key-data: REDACTED - name: kubernetes-admin user: client-certificate-data: REDACTED client-key-data: REDACTED (8)指定要使用的上下文,切换为kube-user1访问集群 # kubectl config use-context kube-user1@kubernetes Switched to context "kube-user1@kubernetes". (9)测试访问kubernetes的资源 # kubectl get pods Error from server (Forbidden): pods is forbidden: User "kube-user1" cannot list resource "pods" in API group "" in the namespace "default" 当切换为kube-user1用户进行访问集群时,由于kube-user1用户没有管理集群的权限,所以 在获取pods资源信息时,会提示Forbidden。接下来更细的权限控制则需要用到rabc:
User --> Rolebinding --> Role 1)角色(Role)创建。 (注意:一个Role对象只能用于授予对某一单一名称空间中资源的访问权限) # vim role-demo.yaml #编写资源清单文件 apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pods-reader namespace: default rules: - apiGroups: - "" resources: - pods verbs: - get - list - watch # kubectl apply -f role-demo.yaml role.rbac.authorization.k8s.io/pods-reader created # kubectl get role NAME AGE pods-reader 4s [root@k8s-master manfests]# kubectl describe role/pods-reader Name: pods-reader Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"rbac.authorization.k8s.io/v1","kind": "Role","metadata":{"annotations":{},"name":"pods-reader" ,"namespace":"default"},"rules... PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- pods [] [] [get list watch] //这里表示当前定义了pods-reader这个角色对pods资源拥有get、list、watch的权限。 2)角色的绑定。(RoleBinding可以引用在同一名称空间定义的Role对象) # vim rolebinding-demo.yaml 编辑资源清单文件 apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kube-user1-read-pods roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: pods-reader subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: kube-user1 # kubectl apply -f rolebinding-demo.yaml rolebinding.rbac.authorization.k8s.io/kube-user1-read-pods created # kubectl get rolebinding NAME AGE kube-user1-read-pods 9s # kubectl describe rolebinding kube-user1-read-pods //查看角色绑定的信息,这里可以看到user kube-user1绑定到了pods-reader这个角色上。 Name: kube-user1-read-pods Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"rbac.authorization.k8s.io/v1","kind": "RoleBinding","metadata":{"annotations":{},"name" :"kube-user1-read-pods","namespace":"... Role: Kind: Role Name: pods-reader Subjects: Kind Name Namespace ---- ---- --------- User kube-user1 3)权限测试 这时候使用kube-user1用户进行测试 # kubectl config use-context kube-user1@kubernetes //如果没有切换到该kube-user1用户,通过kubectl config use-context进行切换 # kubectl get pods #在default名称空间获取pods信息 NAME READY STATUS RESTARTS AGE nginx-statefulset-0 1/1 Running 0 3d nginx-statefulset-1 1/1 Running 0 3d nginx-statefulset-2 1/1 Running 0 3d nginx-statefulset-3 1/1 Running 0 3d pod-sa-demo 1/1 Running 0 27h # kubectl get pods -n kube-system #测试获取kube-system名称空间中的pods Error from server (Forbidden): pods is forbidden: User "kube-user1" cannot list resource "pods" in API group "" in namespace "kube-system" 从上面的操作可以看出,role的定义和绑定,仅作用于当前名称空间,在获取别的名称空间 比如kube-system名称空间时,一样会出现Forbidden。 User --> ClusterRolebinding --> ClusterRole ClusterRole资源对象可以授予与Role资源对象相同的权限,但由于它们属于集群范围的对象, 也可以使用它们授予对以下几种资源的访问权限: 集群范围资源(例如节点,即Node) 非资源类型endpoint(例如/api、/healthz等。) 跨所有名称空间的名称空间资源(例如:运行kubectl get pods --all-namespaces来 查询集群中所有的pod) # vim clusterrole-demo.yaml #编辑资源清单 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cluster-reader rules: - apiGroups: - "" resources: - pods verbs: - get - list - watch # kubectl apply -f clusterrole-demo.yaml #创建clusterrole clusterrole.rbac.authorization.k8s.io/cluster-reader created # kubectl describe clusterrole/cluster-reader Name: cluster-reader Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"rbac.authorization.k8s.io/v1","kind" :"ClusterRole","metadata":{"annotations":{},"name": "cluster-reader"},"rules":[{"apiGrou... PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- pods [] [] [get list watch] 2)ClusterRoleBinding定义 #这里还是使用kube-user1用户,所以先将上面的角色绑定信息删除 # kubectl get rolebinding #查看角色绑定信息 NAME AGE kube-user1-read-pods 27m # kubectl delete rolebinding kube-user1-read-pods #删除前面的绑定 rolebinding.rbac.authorization.k8s.io "kube-user1-read-pods" delete # kubectl get pods //删除后再用kube-user1用户获取pods资源信息,就立马出现Forbidden了 Error from server (Forbidden): pods is forbidden: User "kube-user1" cannot list resource "pods" in API group "" in the namespace "default" # vim clusterrolebinding-demo.yaml #编辑资源清单文件 cat clusterrolebinding-demo.yaml apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: kube-user1-read-all-pods roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-reader subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: kube-user1 # kubectl apply -f clusterrolebinding-demo.yaml 创建clusterrolebinding clusterrolebinding.rbac.authorization.k8s.io/kube-user1-read-all-pods created # kubectl get clusterrolebinding/kube-user1-read-all-pods NAME AGE kube-user1-read-all-pods 25s # kubectl describe clusterrolebinding/kube-user1-read-all-pods //查看clusterrolebinding资源kube-user1-read-all-pods详细信息, //可以看到kube-user1用户已经绑定到clusterrole资源cluster-reader上了。 Name: kube-user1-read-all-pods Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind": "ClusterRoleBinding","metadata":{"annotations": {},"name":"kube-user1-read-all-pod... Role: Kind: ClusterRole Name: cluster-reader Subjects: Kind Name Namespace ---- ---- --------- User kube-user1 3)权限测试 # kubectl get pods #角色绑定后再次获取pods信息,已经可以正常查看 NAME READY STATUS RESTARTS AGE nginx-statefulset-0 1/1 Running 0 3d1h nginx-statefulset-1 1/1 Running 0 3d1h nginx-statefulset-2 1/1 Running 0 3d1h nginx-statefulset-3 1/1 Running 0 3d1h pod-sa-demo 1/1 Running 0 28h # kubectl get pods -n kube-system #切换名称空间也是可以查看的 NAME READY STATUS RESTARTS AGE coredns-bccdc95cf-9gsn8 1/1 Running 0 8d coredns-bccdc95cf-x7m8g 1/1 Running 0 8d etcd-k8s-master 1/1 Running 0 8d kube-apiserver-k8s-master 1/1 Running 0 8d kube-controller-manager-k8s-master 1/1 Running 0 8d kube-flannel-ds-amd64-gg55s 1/1 Running 0 8d kube-flannel-ds-amd64-ssr7j 1/1 Running 5 8d kube-flannel-ds-amd64-w6f9h 1/1 Running 4 8d kube-proxy-77pbc 1/1 Running 3 8d kube-proxy-qs655 1/1 Running 3 8d kube-proxy-xffq4 1/1 Running 0 8d kube-scheduler-k8s-master 1/1 Running 0 8d //从上面的操作可以看出,clusterrole的定义和clusterrolebinding的绑定,可以获取到 //集群内所有资源的对应权限。 User --> Rolebinding --> Clusterrole 将用户kube-user1通过角色绑定(RoleBinding)到集群角色cluster-reader当中, 此时kube-user1仅作用于当前名称空间的所有pods资源的权限。 1)绑定 #首先删除上面的clusterrolebinding # kubectl delete clusterrolebinding kube-user1-read-all-pods clusterrolebinding.rbac.authorization.k8s.io "kube-user1-read-all-pods" deleted # vim rolebinding-clusterrole-demo.yaml #编辑资源清单文件 apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kube-user1-read-pods roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-reader subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: kube-user1 # kubectl apply -f rolebinding-clusterrole-demo.yaml rolebinding.rbac.authorization.k8s.io/kube-user1-read-pods created # kubectl get rolebinding kube-user1-read-pods NAME AGE kube-user1-read-pods 32s # kubectl describe rolebinding kube-user1-read-pods Name: kube-user1-read-pods Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"rbac.authorization.k8s.io/v1","kind" :"RoleBinding","metadata":{"annotations":{},"name" :"kube-user1-read-pods","namespace":"... Role: Kind: ClusterRole Name: cluster-reader Subjects: Kind Name Namespace ---- ---- --------- User kube-user1 2)权限测试 # kubectl get pods NAME READY STATUS RESTARTS AGE nginx-statefulset-0 1/1 Running 0 3d1h nginx-statefulset-1 1/1 Running 0 3d1h nginx-statefulset-2 1/1 Running 0 3d1h nginx-statefulset-3 1/1 Running 0 3d1h pod-sa-demo 1/1 Running 0 28h # kubectl get pods -n kube-system Error from server (Forbidden): pods is forbidden: User "kube-user1" cannot list resource "pods" in API group "" in namespace "kube-system" 从上面的操作可以看出,角色绑定(Rolebinding)和集群角色(ClusterRole)绑定后, 用户只拥有自己当前名称空间的对应的权限。