学习笔记三十二:RBAC认证授权策略

RBAC认证授权策略

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
相关推荐
知识分享小能手5 分钟前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
汇能感知2 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
阿巴Jun3 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao3 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾3 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT4 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
aaaweiaaaaaa4 小时前
HTML和CSS学习
前端·css·学习·html
ST.J4 小时前
前端笔记2025
前端·javascript·css·vue.js·笔记
Suckerbin4 小时前
LAMPSecurity: CTF5靶场渗透
笔记·安全·web安全·网络安全
看海天一色听风起雨落5 小时前
Python学习之装饰器
开发语言·python·学习