kubernetes中的RBAC权限管理
背景
RBAC是Role-based access control (RBAC)的缩写,即基于角色进行权限控制。
基础命令
先复习下基本的权限管理命令。
查看 service account
查看当前系统的ServiceAccount
# kubectl get serviceaccounts
NAME SECRETS AGE
default 1 5d12h
查看所有namespace的ServiceAccount
# kubectl get serviceaccounts --all-namespaces
NAMESPACE NAME SECRETS AGE
default default 1 5d14h
……………………
kube-system token-cleaner 1 5d14h
kube-system ttl-controller 1 5d14h
创建 service account
创建一个自己的service account:myaccount
# kubectl create serviceaccount myaccount
serviceaccount/myaccount created
确认创建成功
# kubectl get serviceaccounts
NAME SECRETS AGE
default 1 5d14h
myaccount 1 4m
创建service account的同时,会自动创建secrets,如:
# kubectl get secrets
NAME TYPE DATA AGE
default-token-qhcq8 kubernetes.io/service-account-token 3 5d14h
myaccount-token-s292c kubernetes.io/service-account-token 3 4m32s
查看 token
service account中会保存一个JWT格式的token
查看token名称:
# kubectl describe serviceaccount default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-qhcq8
Tokens: default-token-qhcq8
Events: <none>
拿着token名称,来查看token内容:
# kubectl describe secrets default-token-qhcq8
Name: default-token-qhcq8
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 38bba8ca-258d-46e6-9055-2bc3cdfd3304
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 7 bytes
token: eyJhb******dyoLzg
可以拿着token到JWT官网来解码,解码结果示例:
{
"alg": "RS256",
"kid": ""
}
{
"iss": "kubernetes/serviceaccount",
"kubernetes.io/serviceaccount/namespace": "default",
"kubernetes.io/serviceaccount/secret.name": "default-token-qhcq8",
"kubernetes.io/serviceaccount/service-account.name": "default",
"kubernetes.io/serviceaccount/service-account.uid": "38bba8ca-258d-46e6-9055-2bc3cdfd3304",
"sub": "system:serviceaccount:default:default"
}
Pod 和 account
每一个pod都对应着一个service account,默认是 default,可以在 yaml 文件中指定。
比如我们有一个 pod: kubernetes-bootcamp-7dc9765bf6-fk92j
,来查看其service account
# kubectl edit pod kubernetes-bootcamp-7dc9765bf6-fk92j
部分结果
…………
serviceAccount: default
serviceAccountName: default
…………
可见其 service account 确实为 default
。
此外,pod 在创建时,认证的相关文件会以 volume 的形式挂载在 pod 中,在 pod 访问 api server 时会使用。
# kubectl edit pod kubernetes-bootcamp-7dc9765bf6-fk92j
部分结果
…………
spec:
containers:
- image: docker.io/jocatalin/kubernetes-bootcamp:v1
imagePullPolicy: IfNotPresent
name: kubernetes-bootcamp
ports:
- containerPort: 8080
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-qhcq8
readOnly: true
…………
测试 token 的有效性
先进入容器,
# kubectl exec -it kubernetes-bootcamp-7dc9765bf6-fk92j bash
直接访问 api server,不使用 token,会提示为匿名访问,报错
# curl "https://10.96.0.1" -k
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
"reason": "Forbidden",
"details": {
},
"code": 403
}
使用 默认 token 来提交,会看到识别出来使用的 user 为 system:serviceaccount:default:default
,但是没有权限,报错,
root@kubernetes-bootcamp-7dc9765bf6-fk92j:~# KUBE_TOKEN=$(</var/run/secrets/kubernetes.io/serviceaccount/token)
root@kubernetes-bootcamp-7dc9765bf6-fk92j:~# curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" "https://10.96.0.1"
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "forbidden: User \"system:serviceaccount:default:default\" cannot get path \"/\"",
"reason": "Forbidden",
"details": {
},
"code": 403
}
其中 -H "Authorization: Bearer $KUBE_TOKEN"
部分为 JWT 认证的写法。
RBAC授权
在认证完成后,接下来就是授权的过程。现在默认使用的是RBAC(Role Based Access Control)授权,其中的关键点如下:
- Role: 即角色,可以给 role上指定权限, 比如 get, list, update, delete, add, watch权限。
- RoleBinding: 把 role 和 service account 关联起来。
- CluterRole: cluster role 的作用域是整个集群,相对 role 的作用域是name space。
- CluterRoleBinding: 把 cluster role 和 service account 关联起来。
注: RoleBinding 过程中,除了可以将 role 和 service account 关联,也可以将 role 和 user / group 关联。
复现没有权限
先复现一下,system:serviceaccount:default:default
这个账号,没有 list pods
权限
# kubectl auth can-i list pods -n default --as=system:serviceaccount:default:default
no
放开权限
创建 role
# kubectl create role default-read-pod --verb=get,list,watch --resource=pods
role.rbac.authorization.k8s.io/default-read-pod created
创建 role binding
kubectl create rolebinding default --role=default-read-pod --serviceaccount=default:default
rolebinding.rbac.authorization.k8s.io/default created
测试效果
使用 kubectl 来测试权限
# kubectl auth can-i list pods -n default --as=system:serviceaccount:default:default
yes
在容器中执行命令来测试权限
# curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" "https://10.96.0.1/api/v1/namespaces/default/pods/$HOSTNAME"
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "kubernetes-bootcamp-7dc9765bf6-fk92j",
"generateName": "kubernetes-bootcamp-7dc9765bf6-",
"namespace": "default",
……………………
],
"qosClass": "BestEffort"
}
}
可见是生效了的。
其它
查看有没有权限执行
有权限的例子
# kubectl auth can-i create deployments --namespace dev
yes
看看别的账号(dave)有没有权限
# kubectl auth can-i list secrets --namespace dev --as dave
no - no RBAC policy matched
查看当前账号
# kubectl get clusterrole