学习笔记三十二: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
相关推荐
OopspoO17 分钟前
qcow2镜像大小压缩
学习·性能优化
A懿轩A41 分钟前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
居居飒1 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
kkflash31 小时前
提升专业素养的实用指南
学习·职场和发展
Hejjon2 小时前
SpringBoot 整合 SQLite 数据库
笔记
1 9 J2 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
6.943 小时前
Scala——身份证号码查询籍贯
学习·scala
爱吃西瓜的小菜鸡3 小时前
【C语言】矩阵乘法
c语言·学习·算法
西洼工作室4 小时前
【java 正则表达式 笔记】
java·笔记·正则表达式
初学者7.4 小时前
Webpack学习笔记(2)
笔记·学习·webpack