kubernetes安全框架
• K8S安全控制框架主要由下面3个阶段进行控制,每一个阶段都 支持插件方式,通过API Server配置来启用插件。
Authentication(认证)
Authorization(授权)
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:服务账号
# 案例:为新来的同事,指定用户授权访问特定的命名空间
示例:为zpj用户授权default命名空间Pod读取权限(只能查看,不能删除)
实验过程:
用K8S CA签发客户端证书 基于证书的客户端认证方式
生成kubeconfig授权文件 kubectl使用kubeconfig连接集群
创建RBAC权限策略 做一定的权限分配
也就是生成一个kubeconfig文件,让指定用户拿着这个文件去访问集群,如何查看资源
# CA签发客户端证书
生成ca证书的cert.ssh脚本
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF
cat > zpj-csr.json <<EOF
{
"CN": "zpj",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes zpj-csr.json | cfssljson -bare zpj
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 生成kubeconfig授权文件
kubeconfig.sh
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=https://172.16.30.177:6443 \
--kubeconfig=zpj.kubeconfig
# 设置客户端认证
kubectl config set-credentials zpj \
--client-key=zpj-key.pem \
--client-certificate=zpj.pem \
--embed-certs=true \
--kubeconfig=zpj.kubeconfig
# 设置默认上下文
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=zpj \
--kubeconfig=zpj.kubeconfig
# 设置当前使用配置
kubectl config use-context kubernetes --kubeconfig=zpj.kubeconfig
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 创建RBAC权限策略:
rbac文件
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: zpj
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@ansible ~]# kubectl get pod --kubeconfig=zpj.kubeconfig
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
2
3
4
5
6
现在 就可以把配置好的 zpj.kubeconfig 拷贝给你的新同事
# 总结
当使用kucetl调用其api或者使用K8S-UI 其实都是向apiserver组件发送的请求。
提取出证书里面的CN字段,该字段作为你的用户名。也就是从CA签发客户端证书当中提取出用户名 “CN”: “zpj”,
- kind: User name: zpj
同样也可以基于组 “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
2
3
4
通过创建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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
最后使用这个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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62