Kubernetes 安全框架
1. Authentication(认证)
2. Authorization(授权)
3. Admission Control(准入控制)
• 客户端要想访问K8s集群API Server,一般需要证书、Token或 者用户名+密码;如果Pod访问,需要ServiceAccount
认证(Authentication)
三种客户端身份认证:
• HTTPS 证书认证:基于CA证书签名的数字证书认证
• HTTP Token认证:通过一个Token来识别用户
• HTTP Base认证:用户名+密码的方式认证 [基本弃用】
鉴权(Authentication)
RBAC(Role-Based Access Control,基于角色的访问控制):负责完成授权(Authorization)工作。
RBAC根据API请求属性,决定允许还是拒绝。
比较常见的授权维度:
• user:用户名
• group:用户分组
• 资源,例如pod、deployment
• 资源操作方法:get,list,create,update,patch,watch,delete
• 命名空间
• API组
准入控制(Admission Control)
Adminssion Control实际上是一个准入控制器插件列表,发送到API Server 的 请求都需要经过这个列表中的每个准入控制器插件的检查,检查不通过, 则拒绝请求。
#查看准入控制的帮助信息
[root@master-1 bin]# /opt/kubernetes/bin/kube-apiserver -h | grep enable-admission
基于角色的权限访问控制:RBAC
RBAC(Role-Based Access Control,基于角色的访问控 制),允许通过Kubernetes API动态配置策略。
角色
• Role:授权特定命名空间的访问权限
• ClusterRole:授权所有命名空间的访问权限
角色绑定
• RoleBinding:将角色绑定到主体(即subject)
• ClusterRoleBinding:将集群角色绑定到主体
主体(subject)
• User:用户
• Group:用户组
• ServiceAccount:服务账号
案例:为新来的同事,指定用户授权访问特定的命名空间
示例:为fxkj用户授权default命名空间Pod读取权限(只能查看,不能删除)
实验过程:
1. 用K8S CA签发客户端证书 基于证书的客户端认证方式
2. 生成kubeconfig授权文件 kubectl使用kubeconfig连接集群
3. 创建RBAC权限策略 做一定的权限分配
也就是生成一个kubeconfig文件,让指定用户拿着这个文件去访问集群,如何查看资源
CA签发客户端证书
#查看之前生成的ca证书
[root@manager ssl]# ls ca*
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
#拷贝之前生成的ca证书到本机的/fxkj目录下
[root@manager fxkj]# mkdir /root/fxkj
[root@manager fxkj]# cp /opt/kubernetes/ssl/ca* /root/fxkj
[root@manager fxkj]# ls ca*
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
配置证书: 生成请求证书文件
API Server会把客户端证书的CN字段作为User,把names.O字段作为Group。
[root@manager fxkj]# vim fxkj-csr.json
{
"CN": "fxkj", #CN ,apiserver 通过CN 来确认用户名
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "k8s", #O ,apiserver 通过O 来确认组
"OU": "System"
}
]
}
#签发证书使用的cfssl 工具,安装生成证书工具
[root@manager fxkj]# curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl
[root@manager fxkj]# curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson
[root@manager fxkj]# curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo
[root@manager fxkj]# chmod +x /usr/local/bin/cfssl*
生成fxkj 客户端证书
#需要指定k8s根证书,如果使用的kubeadm 部署的话,指定的根证书 在 /etc/kubernetes/pki/下;二进制部署手动指定ca证书路径
[root@manager fxkj]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes fxkj-csr.json | cfssljson -bare fxkj
[root@ansible fxkj]# ll fxkj*
-rw-r--r-- 1 root root 993 Jan 23 14:26 fxkj.csr
-rw-r--r-- 1 root root 217 Jan 23 14:23 fxkj-csr.json
-rw------- 1 root root 1675 Jan 23 14:26 fxkj-key.pem
-rw------- 1 root root 6235 Jan 23 14:28 fxkj.kubeconfig
-rw-r--r-- 1 root root 1383 Jan 23 14:26 fxkj.pem
生成kubeconfig授权文件
集群参数设置
使用kubectl config这条命令生成kubeconfig证书,逐步生成kubeconfig里面的信息,生成证书的格式和/$HOME 目录的config内容是一样的
# 本段设置了所需要访问的集群的信息
- 使用set-cluster设置了需要访问的集群,如上为kubernetes,这只是个名称,实际为–server指向的apiserver
- –certificate-authority 设置了该集群的公钥
–enabed-certs为true 表示将–certificate-authority 证书写入到kubeconfig中
- –server则表示该集群的kube-apiserver地址
当然生成的kubeconfig 内容 被保存到当前目录中的 fxkj.kubeconfig文件 里
[root@ansible fxkj]# kubectl config set-cluster kubernetes
--certificate-authority=ca.pem
--embed-certs=true
--server=https://192.168.31.61:6443
--kubeconfig=fxkj.kubeconfig
设置客户端认证
#本段主要设置用户的相关信息,主要是用户证书。如上的用户名为fxkj,证书为:fxkj.pem,私钥为:fxkj-key.pem
注意客户端的证书首先要经过集群CA的签署,否则不会被集群认可,此处使用的是ca认证方式;
也可以使用token认证,如kubelet的 TLS Boostrap机制下的bootstrapping使用的就是token认证方式
[root@ansible fxkj]# kubectl config set-credentials fxkj
--client-key=fxkj-key.pem
--client-certificate=fxkj.pem
--embed-certs=true
--kubeconfig=fxkj.kubeconfig
设置默认上下文
# 集群参数和用户参数可以同时设置多对,在上下文参数中将集群参数和用户参数关联起来。上面的上下文名称为kubenetes,集群为kubenetes,用户为fxkj,
表示使用fxkj的用户凭证来访问kubenetes集群的default命名空间,也可以增加–namspace来指定访问的命名空间。
最后使用kubectl config use-context kubernetes来使用名为kubenetes的环境项来作为配置。如果配置了多个环境项,可以通过切换不同的环境项名字来访问到不同的集群环境。
[root@ansible fxkj]# kubectl config set-context kubernetes
--cluster=kubernetes
--user=fxkj
--kubeconfig=fxkj.kubeconfig
设置当前使用配置
[root@ansible fxkj]# kubectl config use-context kubernetes --kubeconfig=fxkj.kubeconfig
#验证连接apiserver
#–kubeconfig 指定kubeconfig 配置文件路径
[root@ansible fxkj]# kubectl --kubeconfig=fxkj.kubeconfig get pods
Error from server (Forbidden): pods is forbidden: User "fxkj" cannot list resource "pods" in API group "" in the namespace "default"
可以看到上面配置是没有问题的,给出的提示是用户fxkj是不能列出这方面资源
但是通过管理员的配置文件是可以访问到的
[root@master-1 .kube]# kubectl --kubeconfig=/root/.kube/config get pods
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-5c75c654c7-kc8r4 1/1 Running 2 26h
nfs-client-provisioner-nfs-85fcbf6445-6czb7 1/1 Running 1 26h
web-0 1/1 Running 1 26h
web-1 1/1 Running 1 26h
web-1-74d7d458df-kv6b5 1/1 Running 5 8d
web-2 1/1 Running 1 26h
web-2-84868454c9-4jvt8 1/1 Running 5 8d
上面说明了配置文件是没有问题的,只是缺少相应的权限 ,这个时候需要去配置RBAC 权限策略
创建RBAC权限策略:
需要创建role和rolebinding,role是权限的集合,rolebinding是要将role里面权限绑定到指定的用户,也就是我们上面的fxkj用户
比较常见的授权维度:
• user:用户名
• group:用户分组
• 资源,例如pod、deployment
• 资源操作方法:get,list,create,update,patch,watch,delete
• 命名空间
• API组
[root@ansible RBAC]# vim rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" 指定核心 API 组
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定使得用户 "fxkj" 能够读取 "default" 命名空间中的 Pods
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: fxkj # 此角色绑定使得用户 "fxkj"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role #this must be Role or ClusterRole,与上面保持一致
name: pod-reader # 这里的名称必须与你想要绑定的 Role 或 ClusterRole 名称一致
apiGroup: rbac.authorization.k8s.io
已经授权了,只能查看default 命名空间下的Pod,其他资源不能查看,且只有查看的权限
[root@ansible fxkj]# kubectl --kubeconfig=/root/fxkj/fxkj.kubeconfig get pods
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-5c75c654c7-kc8r4 1/1 Running 2 26h
nfs-client-provisioner-nfs-85fcbf6445-6czb7 1/1 Running 1 26h
web-0 1/1 Running 1 26h
web-1 1/1 Running 1 26h
web-1-74d7d458df-kv6b5 1/1 Running 5 8d
web-2 1/1 Running 1 26h
web-2-84868454c9-4jvt8 1/1 Running 5 8d
#同样也是无法删除POD
[root@ansible fxkj]# kubectl –kubeconfig=/root/fxkj/fxkj.kubeconfig delete pod web-0
Error from server (Forbidden): pods “web-0” is forbidden: User “fxkj” cannot delete resource “pods” in API group “” in the namespace “default”
现在我们给fxkj 这个用户 再添加一个查看deployment控制器,service 的权限
修改 rbac.yaml 文件
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods","deployments","services"]
verbs: ["get", "watch", "list"]
.............
[root@master-1 RBAC]# kubectl apply -f rbac.yaml
role.rbac.authorization.k8s.io/pod-reader configured
rolebinding.rbac.authorization.k8s.io/read-pods unchanged
[root@ansible ~]# kubectl --kubeconfig=/root/fxkj/fxkj.kubeconfig get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 26d
web ClusterIP None <none> 80/TCP 28h
web-1 NodePort 10.0.0.16 <none> 80:30588/TCP 18d
web-2 NodePort 10.0.0.80 <none> 80:31620/TCP 18d
[root@ansible ~]# kubectl --kubeconfig=/root/fxkj/fxkj.kubeconfig get deployment
Error from server (Forbidden): deployments.apps is forbidden: User "fxkj" cannot list resource "deployments" in API group "apps" in the namespace "default"
发现 service 可以查询,但是deployment 无法查询到
原因是 ,deployment 控制器 属于 apps 组名里的,而默认的 apiGroups: [“”] 核心组名里不包含deployment 控制器
如果不确定 Role 里的一些resources
方法1: 可以去官网查看示例: https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/
方法2: 查看k8s 下有哪些api-service 组名
[root@master-1 ~]# kubectl api-versions
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
batch/v1
batch/v1beta1
certificates.k8s.io/v1beta1
coordination.k8s.io/v1
coordination.k8s.io/v1beta1
discovery.k8s.io/v1beta1
events.k8s.io/v1beta1
extensions/v1beta1
metrics.k8s.io/v1beta1
networking.k8s.io/v1
networking.k8s.io/v1beta1
node.k8s.io/v1beta1
policy/v1beta1
rbac.authorization.k8s.io/v1
rbac.authorization.k8s.io/v1beta1
scheduling.k8s.io/v1
scheduling.k8s.io/v1beta1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1
或者 使用 kubectl get api-service 也能查看到
现在 我们只需要修改下rbac.yaml 文件 ,在apiGroups: [“”] 里添加 apps 组名即可
[root@master-1 RBAC]# cat rbac.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: ["","apps"]
resources: ["pods","deployments","services"]
verbs: ["get", "watch", "list"]
............
添加完之后 apply 从新加载下yaml 文件,就可以看到 deployment 控制器了
[root@ansible ~]# kubectl --kubeconfig=/root/fxkj/fxkj.kubeconfig get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nfs-client-provisioner 1/1 1 1 40h
nfs-client-provisioner-nfs 1/1 1 1 26h
web-1 1/1 1 1 18d
web-2 1/1 1 1 18d
现在 就可以把配置好的 fxkj.kubeconfig 拷贝给你的新同事
如果不想每次输入kubeconfig 路径 kubectl –kubeconfig=/root/fxkj/fxkj.kubeconfig
可以这样做:
[root@ansible ~]# mv fxkj.kubeconfig /root/.kube/config
#同样可以查看POD
[root@ansible .kube]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-5c75c654c7-kc8r4 1/1 Running 2 26h
nfs-client-provisioner-nfs-85fcbf6445-6czb7 1/1 Running 1 26h
web-0 1/1 Running 1 26h
web-1 1/1 Running 1 26h
web-1-74d7d458df-kv6b5 1/1 Running 5 8d
web-2 1/1 Running 1 26h
web-2-84868454c9-4jvt8 1/1 Running 5 8d
总结
当使用kucetl调用其api或者使用K8S-UI 其实都是向apiserver组件发送的请求。
提取出证书里面的CN字段,该字段作为你的用户名。也就是从CA签发客户端证书当中提取出用户名 “CN”: “fxkj”,
- kind: User
name: fxkj
同样也可以基于组 “O”: “k8s”
使用 ClusterRoleBinding 可以对整个集群中的所有命名空间资源权限进行授权;
下面k8s 官方的 ClusterRoleBinding 样例展示了授权 manager 组内所有用户在全部命名空间中对 secrets 进行访问
补充内容: serviceaccounts 主体
主体里的 user,Group 的都是针对人的身份 来进行验证 来访问 apiserver
而 服务账户 serviceaccounts 是针对 程序来验证 来访问apiserver ,比如 我们部署的coredns, k8s-ui,calico,falnel 等等
访问流程:K8S-UI ——> token ——> apiserver ——> rbac
例如: 看下之前部署的kubernetes-dashboard 的serviceaccounts :
[root@master-1 ~]# kubectl get serviceaccounts -n kubernetes-dashboard
NAME SECRETS AGE
dashboard-admin 1 26d
default 1 26d
通过创建serviceaccounts 来 创建secrets 中的 token
[root@master-1 ~]# kubectl get secrets -n kubernetes-dashboard
NAME TYPE DATA AGE
dashboard-admin-token-25b5h kubernetes.io/service-account-token 3 26d
[root@master-1 ~]# kubectl describe secrets -n kubernetes-dashboard dashboard-admin-token-25b5h
Name: dashboard-admin-token-25b5h
Namespace: kubernetes-dashboard
Labels: <none>
Annotations: kubernetes.io/service-account.name: dashboard-admin
kubernetes.io/service-account.uid: fdf94e5a-5b5f-4d40-95d9-4cb5d2409991
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1359 bytes
namespace: 20 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjVReUxQWFQyVzdvRjQ3TTRCZWtjR1Rja01CSUc4Qi1PNjdib1pfQXBURjgifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tMjViNWgiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiZmRmOTRlNWEtNWI1Zi00ZDQwLTk1ZDktNGNiNWQyNDA5OTkxIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmVybmV0ZXMtZGFzaGJvYXJkOmRhc2hib2FyZC1hZG1pbiJ9.U4NEeAg1hg0hkCcZrfA4nFPfqNGUlEKIcIEMSrXuxoOIi2wrFJadohzpipmAb0DUItx-K0QPprQ7V0EYJlZbDnKExp2uqJqFsG_TmcZ4T741OUpkTRX9sy0AqC_XkB-2GUj9KHRhi_2M_QMYif4XfB9kS_EpEfMUg9l8K97LnHSMo2ZFbCk2XcpCUe21uNegOtFqVka7RbtiikqVc4sJEPJuA0nwmtqehaJZB7obBHTmACzYMU2WlILzv0QJdL2b--Koa8dkekERsd89ExTZBnxVZw5eB26cFwSUFZzpEZuq8SVicokh90JgswyV3REQwPwU85lpO6yF3tbhIU6jXQ
最后使用这个token 去登陆k8s-ui 的控制台
这个就是就是 serviceaccounts 来创建token 的案例.
案例: 基于nfs 存储模式 创建动态PV 的授权(基于serviceaccount)
[root@master-1 nfs-client]# cat rbac.yaml
kind: ServiceAccount
apiVersion: v1
metadata:
name: nfs-client-provisioner
—
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
– apiGroups: [“”]
resources: [“persistentvolumes”]
verbs: [“get”, “list”, “watch”, “create”, “delete”]
– apiGroups: [“”]
resources: [“persistentvolumeclaims”]
verbs: [“get”, “list”, “watch”, “update”]
– apiGroups: [“storage.k8s.io”]
resources: [“storageclasses”]
verbs: [“get”, “list”, “watch”]
– apiGroups: [“”]
resources: [“events”]
verbs: [“create”, “update”, “patch”]
—
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
– kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
—
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
rules:
– apiGroups: [“”]
resources: [“endpoints”]
verbs: [“get”, “list”, “watch”, “create”, “update”, “patch”]
—
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
subjects:
– kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
暂无评论内容