0%

k8s-Authorization

k8s-Authorization

Authorization鉴权

RBAC授权模式

RBAC(Role-Based Access Control)基于角色的访问控制,拥有以下的优势:

  • 对cluster中的resource资源和非资源均有完整的覆盖
  • 整个RBAC完全由几个API对象完成,和其他API对象一样,可以用kubectl或者API进行操作。
  • 可以在运行时进行调整,无需重启API server

RBAC的API 资源对象

RBAC API声明了4个最高级别的类型:RoleClusterRoleRoleBindingClusterRoleBinding,4种对象类型都可以使用kubectlAPI进行操作。

1613959572193

需要注意的是,k8s并不会提供用户管理,那么User、Group、ServiceAccount指定的用户又是从哪里来的呢?

k8s组件(kubectl、kube-proxy)或是其他自定义的用户在向CA申请证书时,需要提供一个证书请求文件,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"ST": "Oregon",
"L": "Portland",
"O": "system:masters",
"OU": "System"
}
]
}

注:names字段里面各个字段的意义

1
2
3
4
5
6
C = <国家>
ST = <州/省>
L = <市>
O = <组织>
OU = <部门>
CN = <MASTER_IP>

API Server会把client证书的CN字段作为user,把names.O(Organization)字段作为Group

kubelete使用TLS Bootstaping认证时,API Server可以使用Bootstrap Tokens,或者使用Token authentication file来验证=token。无论哪一种,k8s都会为token绑定一个默认的User和Group。

Pod使用ServiceAccount认证时,service-account-token中的JWT会保存User信息。

有了User信息,在创建一对Role/RoleBinding(ClusterRole/CLusterRolebinding)资源对象,就可以完成权限绑定了。

Role and ClusterRole

Role (对应一个namespace)

在RBAC API中,Role表示一组规则权限,权限只会增加(累加权限),不存在一个resource一开有很多权限但是通过RBAC对其进行减少的操作;Role只能授予单个namespace 中资源的访问权限,如果想要跨越namespace则可以创建ClusterRole

1
2
3
4
5
6
7
8
9
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] #"" indicates the core API group
resources: ["pods"]
verbs: ["get","watch","list"]

解释:

  • apiGroups 为 "":声明core API group
  • resources:要使用的资源,例如pods,deployments等
  • verbs:对资源执行的动作。

ClusterRole

ClusterRole授权 >= Role授予(与Role类似),但ClusterRole属于集群级别对象,因此ClusterRole不需要定义namespace。特点:

  • 集群范围(cluster-scoped)的资源访问控制(如:node访问权限)
  • 非资源类型(如/ healthz访问)
  • 所有namespaces 中的namespaced 资源(如 pods)
1
2
3
4
5
6
7
8
9
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
# "namespace" omitted since ClusterRoles are not namespaced
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]

RoleBinding和ClusterRoleBinding

RoleBinding是将Role中定义的权限授予给用户或用户组。RoleBinding包含一组subjects(权限)列表,表中包含有不同形式的待授予权限资源类型(users,groups ,service accounts),并引用该Role。RoleBinding在某个namespace 内授权,ClusterRoleBinding适用在集群范围内使用。

RoleBinding可以引用相同namespace下定义的Role。

例子:RoleBindingdefaultnamespace中将pod-readerRole授予用户jane。将允许janedefaultnamespace中读取pod权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-pods #该RoleBinding的名称
namespace: default
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef: #要授予用户的Role
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io

subjects字段的kind字段:

  • User
  • Group
  • ServiceAccount

使用RoleBinding绑定ClusterRole

RoleBinding还可以引用ClusterRole,来对当前namespace内用户、用户组或ServiceAccount进行授权。这种操作允许管理员为整个集群定义一组通用Role,然后在不同namespace中使用RoleBinding引用。

例如:ClusterRole secret-reader具有整个cluster内对secrets的访问权限;但是其授权用户dave只能访问development namespace中的secrets(因为RoleBinding定义在development namespace)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This role binding allows "dave" to read secrets in the "development" namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-secrets
namespace: development # This only grants permissions within the "development" namespace.
subjects:
- kind: User
name: dave
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io

subjects的kind

  • User
  • Group
  • ServiceAccount(pod中的应用程序)

ClusterRoleBinding

最后,ClusterRoleBinding可以用于集群中所有命名空间中授予权限。以下ClusterRoleBinding允许“manager” Group中的任何用户在任何命名空间中读取secrets。

1
2
3
4
5
6
7
8
9
10
11
12
13
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-secret-global
subjects:
- kind: Group
name: manager
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io

Referring to Resources

k8s cluster内一些resource一般以name string来表示,这些strings一般会在API的URL地址中出现;同时某些resource也会包含子资源,例如:logs资源就属于pods的子资源,API中URL样例如下

1
GET /api/v1/namespaces/{namespace}/pods/{name}/log

如果要在RBAC授权模型中控制这些子资源的访问权限,可以通过/分隔符来实现,以下是一个定义pods resource logs访问权限的Role例子

例如:定义pods的子资源log

1
2
3
4
5
6
7
8
9
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
resources: ["pods","pods/log"]
verbs: ["get","list"]

资源也可以通过resourceNames列表的某些请求的资源名称来引用。

如下例子:允许在核心API Group中,get(读取)和update(更新)名称为 my-config的 ConfigMap:

1
2
3
4
5
6
7
8
9
10
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: configmap-updater
rules:
- apiGroups: [""]
resources: ["configmap"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]

注意:如果设置了resourceNames,那么verbs不能指定为listwatchcreatedeletecollection

Practice:创建一个user只能管理dev namespace

  • client证书请求文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"CN": "devuser",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"ST": "Oregon",
"L": "Portland",
"O": "k8s",
"OU": "System"
}
]
}
  • 下载证书生成工具
1
2
3
4
5
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
  • 生成client证书
1
cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /root/devuser-csr.json | cfssljson -bare devuser
  • 设置cluster参数
1
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
export KUBE_APISERVER="https://ip_address:6443"

#设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=devuser.kubeconfig

#设置客户端认证参数
kubectl config set-credentials devuser \
--client-certificate=/etc/kubernetes/ssl/devuser.pem \
--client-key=/etc/kubernetes/ssl/devuser-key.pem \
--embed-certs=true \
--kubeconfig=devuser.kubeconfig

#设置上下文参数
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=devuser \
--namespace=dev \
--kubeconfig=devuser.kubeconfig

#设置默认上下文
kubectl config use-context kubernetes --kubeconfig=devuser.kubeconfig

cp -f ./devuser.kubeconfig /root/.kube/config

#给devuser在dev namespace创建admin级别的rolebinding
kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev