RBAC认证授权策略
- RBAC介绍
- 资源的引用方式
- 常见角色(role)授权的案例
-
- 允许读取核心API组的Pod资源
- [允许读写apps API组中的deployment资源](#允许读写apps API组中的deployment资源)
- 允许读取Pod以及读写job信息
- 允许读取一个名为my-config的ConfigMap(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap):
- 读取核心组的Node资源(Node属于集群级的资源,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定):
- 允许对非资源端点"/healthz"及其所有子路径进行GET和POST操作(必须使用ClusterRole和ClusterRoleBinding):
- 常见的角色绑定示例
- [对Service Account的授权管理](#对Service Account的授权管理)
-
-
- [my-namespace中的my-sa Service Account授予只读权限:](#my-namespace中的my-sa Service Account授予只读权限:)
- [为一个命名空间中名为default的Service Account授权](#为一个命名空间中名为default的Service Account授权)
- [为命名空间中所有Service Account都授予一个角色](#为命名空间中所有Service Account都授予一个角色)
- [为集群范围内所有Service Account都授予一个低权限角色](#为集群范围内所有Service Account都授予一个低权限角色)
- [为所有Service Account授予超级用户权限](#为所有Service Account授予超级用户权限)
-
- 使用kubectl命令行工具创建资源对象
-
-
- [在命名空间rbac中为用户es授权admin ClusterRole](#在命名空间rbac中为用户es授权admin ClusterRole)
- [在命名空间rbac中为名为myapp的Service Account授予view ClusterRole:](#在命名空间rbac中为名为myapp的Service Account授予view ClusterRole:)
- [在全集群范围内为用户root授予cluster-admin ClusterRole:](#在全集群范围内为用户root授予cluster-admin ClusterRole:)
- [在全集群范围内为名为myapp的Service Account授予view ClusterRole:](#在全集群范围内为名为myapp的Service Account授予view ClusterRole:)
-
- 限制不同的用户操作k8s集群
RBAC介绍
在Kubernetes中,所有资源对象都是通过API进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现,上面的Service Account其实就是APIServer的认证过程,而授权的机制是通过RBAC:基于角色的访问控制实现。
RBAC有四个资源对象,分别是:
- Role
- ClusterRole
- RoleBinding
- ClusterRoleBinding
Role:角色
一组权限的集合,在一个命名空间中,可以用其来定义一个角色,只能对命名空间内的资源进行授权。如果是集群级别的资源,则需要使用ClusterRole。例如:定义一个角色用来读取Pod的权限
clike
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: rbac
name: pod-read
rules:
- apiGroups: [""]
resources: ["pods"]
resourceNames: []
verbs: ["get","watch","list"]
rules中的参数说明:
1、apiGroups:支持的API组列表,例如:"apiVersion: apps/v1"等
2、resources:支持的资源对象列表,例如pods、deployments、jobs等
3、resourceNames: 指定resource的名称
4、verbs:对资源对象的操作方法列表。
ClusterRole:集群角色
具有和角色一致的命名空间资源的管理能力,还可用于以下特殊元素的授权
- 集群范围的资源,例如Node
- 非资源型的路径,例如:/healthz
- 包含全部命名空间的资源,例如Pods
举例:定义一个集群角色可让用户访问任意secrets
clike
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secrets-clusterrole
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get","watch","list"]
RoleBinding:角色绑定、ClusterRolebinding:集群角色绑定
角色绑定和集群角色绑定用于把一个角色绑定在一个目标上,可以是User,Group,Service Account,使用RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权。
例如:将在rbac命名空间中把pod-read角色授予用户es
python
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-read-bind
namespace: rbac
subjects:
- kind: User
name: es
apiGroup: rbac.authorization.k8s.io
roleRef:
- kind: Role
name: pod-read
apiGroup: rbac.authorizatioin.k8s.io
RoleBinding也可以引用ClusterRole,对属于同一命名空间内的ClusterRole定义的资源主体进行授权, 例如:es能获取到集群中所有的资源信息
python
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: es-allresource
namespace: rbac
subjects:
- kind: User
name: es
apiGroup: rbac.authorization.k8s.io
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
资源的引用方式
多数资源可以用其名称的字符串表示,也就是Endpoint中的URL相对路径,例如pod中的日志是GET
python
/api/v1/namaspaces/{namespace}/pods/{podname}/log
如果需要在一个RBAC对象中体现上下级资源,就需要使用"/"分割资源和下级资源。
例如:若想授权让某个主体同时能够读取Pod和Pod log,则可以配置 resources为一个数组
python
kubectl create ns test
vim role-test.yaml
python
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: logs-reader
namespace: test
rules:
- apiGroups: [""]
resources: ["pods","pods/log"]
verbs: ["get","list","watch"]
python
kubectl apply -f role-test.yaml
kubectl create sa sa-test -n test
kubectl create rolebinding sa-test-1 -n test --role=logs-reader --serviceaccount=test:sa-test
python
vim pod-test.yaml
python
apiVersion: v1
kind: Pod
metadata:
name: sa-test-pod
namespace: test
labels:
app: sa
spec:
serviceAccountName: sa-test
containers:
- name: sa-tomcat
ports:
- containerPort: 80
image: nginx
imagePullPolicy: IfNotPresent
python
kubectl apply -f pod-test.yaml
python
kubectl exec -it sa-test-pod -n test -- /bin/bash
root@sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes.default/api/v1/namespaces/test/pods/sa-test-pod/logs
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "pods \"sa-test-pod\" is forbidden: User \"system:serviceaccount:test:sa-test\" cannot get resource \"pods/logs\" in API group \"\" in the namespace \"test\"",
"reason": "Forbidden",
"details": {
"name": "sa-test-pod",
"kind": "pods"
},
"code": 403
}
python
kubectl create rolebinding sa-test-2 -n test --role=logs-reader --user=system:serviceaccount:test:sa-test
root@sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes.default/api/v1/namespaces/test/pods/sa-test-pod/log
资源还可以通过名称(ResourceName)进行引用,在指定ResourceName后,使用get、delete、update、patch请求,就会被限制在这个资源实例范围内
例如,下面的声明让一个主体只能对名为my-configmap的Configmap进行get和update操作:
python
apiVersion: rabc.authorization.k8s.io/v1
kind: Role
metadata:
namaspace: default
name: configmap-update
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["get","update"]
常见角色(role)授权的案例
允许读取核心API组的Pod资源
python
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
允许读写apps API组中的deployment资源
python
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get","list","watch","create","update","patch","delete"]
允许读取Pod以及读写job信息
python
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["jobs"]
verbs: ["get","list","watch","create","update","patch","delete"]
允许读取一个名为my-config的ConfigMap(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap):
python
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["get"]
读取核心组的Node资源(Node属于集群级的资源,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定):
python
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get","list","watch"]
允许对非资源端点"/healthz"及其所有子路径进行GET和POST操作(必须使用ClusterRole和ClusterRoleBinding):
python
rules:
- nonResourceURLs: ["/healthz","/healthz/*"]
verbs: ["get","post"]
常见的角色绑定示例
用户名alice
python
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
组名alice
python
subjects:
- kind: Group
name: alice
apiGroup: rbac.authorization.k8s.io
kube-system命名空间中默认Service Account
python
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
对Service Account的授权管理
Service Account也是一种账号,是给运行在Pod里的进程提供了必要的身份证明。需要在Pod定义中指明引用的Service Account,这样就可以对Pod的进行赋权操作。
例如:pod内可获取rbac命名空间的所有Pod资源,pod-reader-sc的Service Account是绑定了名为pod-read的Role
python
kubectl create ns rbac
kubectl create sa pod-reader-sc -n rbac
cat pod-rbac.yaml
python
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: rbac
spec:
serviceAccountName: pod-reader-sc
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
python
kubectl apply -f pod-rbac.yaml
my-namespace中的my-sa Service Account授予只读权限:
python
kubectl create rolebinding my-sa-view --clusterrole=view --serviceaccount=my-namespace:my-sa --namespace=my-namespace
为一个命名空间中名为default的Service Account授权
- 如果一个应用没有指定 serviceAccountName,则会使用名为default的Service Account。注意,赋予Service Account "default"的权限会让所有没有指定serviceAccountName的Pod都具有这些权限
- 例如,在my-namespace命名空间中为Service Account"default"授予只读权限:
python
kubectl create rolebinding default-view --clusterrole=view --serviceaccount=my-namespace:default --namespace=my-namespace
为命名空间中所有Service Account都授予一个角色
如果希望在一个命名空间中,任何Service Account应用都具有一个角色,则可以为这一命名空间的Service Account群组进行授权
python
kubectl create rolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts:my-namespace --namespace=my-namespace
为集群范围内所有Service Account都授予一个低权限角色
如果不想为每个命名空间管理授权,则可以把一个集群级别的角色赋给所有Service Account。
python
kubectl create clusterrolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts
为所有Service Account授予超级用户权限
python
kubectl create clusterrolebinding serviceaccounts-view --clusterrole=cluster-admin --group=system:serviceaccounts
使用kubectl命令行工具创建资源对象
在命名空间rbac中为用户es授权admin ClusterRole
python
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=es --namespace=rbac
在命名空间rbac中为名为myapp的Service Account授予view ClusterRole:
python
kubctl create rolebinding myapp-role-binding --clusterrole=view --serviceaccount=rbac:myapp --namespace=rbac
在全集群范围内为用户root授予cluster-admin ClusterRole:
python
kubectl create clusterrolebinding cluster-binding --clusterrole=cluster-admin --user=root
在全集群范围内为名为myapp的Service Account授予view ClusterRole:
python
kubectl create clusterrolebinding service-account-binding --clusterrole=view --serviceaccount=myapp
限制不同的用户操作k8s集群
生成一个证书
生成一个私钥
python
cd /etc/kubernetes/pki/
(umask 077; openssl genrsa -out lucky.key 2048)
生成一个证书请求
python
openssl req -new -key lucky.key -out lucky.csr -subj "/CN=lucky"
生成一个证书
python
openssl x509 -req -in lucky.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky.crt -days 3650
在kubeconfig下新增加一个lucky这个用户
把lucky这个用户添加到kubernetes集群中,可以用来认证apiserver的连接
python
kubectl config set-credentials lucky --client-certificate=./lucky.crt --client-key=./lucky.key --embed-certs=true
在kubeconfig下新增加一个lucky这个账号
python
kubectl config set-context lucky@kubernetes --cluster=kubernetes --user=lucky
切换账号到lucky,默认没有任何权限
python
kubectl config use-context lucky@kubernetes
kubectl config use-context kubernetes-admin@kubernetes #这个是集群用户,有任何权限
把user这个用户通过rolebinding绑定到clusterrole上,授予权限,权限只是在lucky这个名称空间有效
python
kubectl create ns lucky-test
kubectl create rolebinding lucky -n lucky-test --clusterrole=cluster-admin --user=lucky
切换到lucky这个用户
python
kubectl config use-context lucky@kubernetes
测试是否有权限
python
kubectl get pods -n lucky-test
添加一个test的普通用户
python
useradd test
cp -ar /root/.kube /tmp/
#修改/tmp/.kube/config文件,把kubernetes-admin相关的删除,只留lucky用户
cp -ar /tmp/.kube/ /home/test/
chown -R test.test /home/test/
su - test
kubectl get pods -n lucky
退出test用户,需要在把集群环境切换成管理员权限
python
kubectl config use-context kubernetes-admin@kubernetes
授权kubectl用户能查看所有名称空间的pod的权限
生成一个私钥
python
cd /etc/kubernetes/pki/
(umask 077; openssl genrsa -out lucky1.key 2048)
生成一个证书请求
python
openssl req -new -key lucky1.key -out lucky1.csr -subj "/CN=lucky66"
生成一个证书
python
openssl x509 -req -in lucky1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky1.crt -days 3650
把lucky66这个用户添加到kubernetes集群中,可以用来认证apiserver的连接
python
kubectl config set-credentials lucky66 --client-certificate=./lucky1.crt --client-key=./lucky1.key --embed-certs=true
在kubeconfig下新增加一个lucky66这个账号
python
kubectl config set-context lucky66@kubernetes --cluster=kubernetes --user=lucky66
创建一个clusterrole
python
vim lucky66-clusterrole.yaml
python
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: lucky66-get-pod
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
python
kubectl apply -f lucky66-clusterrole.yaml
创建一个clusterrolebinding
python
kubectl create clusterrolebinding lucky66-get-pods --clusterrole=lucky66-get-pod --user=lucky66
添加一个test66的普通用户
python
useradd test66
rm -rf /tmp/.kube
cp -ar /root/.kube /tmp/
#修改/tmp/.kube/config文件,把kubernetes-admin和lucky相关的删除,只留lucky66用户
cp -ar /tmp/.kube/ /home/test66/
chown -R test66.test66 /home/test66/
python
vim /home/test66/.kube/config
#把current-context变成如下:
current-context: lucky66@kubernetes
python
su - test66
kubectl get pods
kubectl get pods -n kube-system