Kubernetes访问控制之RBAC

Posted 风的影子001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes访问控制之RBAC相关的知识,希望对你有一定的参考价值。

kubernete中账户分为两种:

  • User Account (用户账户):kubernetes集群外部用户使用
  • Service Account (服务账号):用于集群内部使用

Kubernetes设计了一种Secret资源,分为两类,一种是用于 ServiceAccount,每创建一个SA,就会随之创建一个Secret;另一种就是用户自定义的保密信息Opaque

一、ServiceAccount中添加Image pull secrets

创建用于拉取镜像的secret
# kubectl create secret docker-registry harbor-registrykey \\
--docker-server=devops.harbor.com \\
--docker-username=admin \\
--docker-password=admin@123
创建sa并绑定secret
# cat imagepull-sa.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: imagepull-sa
namespace: devops
imagePullSecrets: #添加此字段
- name: harbor-registrykey

这个时候,只要是使用此 SA 的Pod,都可以在docker-registry拉取镜像了。

二、RBAC

RBAC介绍

在Kubernetes中,所有资源对象都是通过API对象进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现,上面的Service Account其实就是APIServer的认证过程,而授权的机制是通过RBAC:基于角色的访问控制实现。RBAC使用rbac.authorization.k8s.io API Group 来实现授权决策,允许管理员通过 Kubernetes API 动态配置策略,要启用RBAC,需要在 apiserver 中添加参数--authorization-mode=RBAC

Role and ClusterRole

在RBAC API中,Role表示一组规则权限,Role 是定义在一个 namespace 中,而 ClusterRole 是集群级别 下面定义一个Role

# cat test-role.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: test-role
namespace: devops
rules:
- apiGroups: [""] # 为空表示为默认的core api group
resources: ["pods"] # 数据源类型
verbs: ["get","watch","list"] #赋予的权限

以上策略表示对devops名称空间下的Pods有get,watch,list的权限

ClusterRole 具有与 Role 相同权限角色控制能力,不同的就是 Cluster Role是集群级别,主要用于:

  • 集群级别的资源控制(例如 node 访问权限)
  • 非资源型 endpoints(例如对某个目录或文件的访问:/healthz)
  • 所有命名空间资源控制(Pod、Deployment等)
# cat test-clusterrole.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: test-clusterrole
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get","create","list"]

以上策略表示,有get,create,list整个集群service的权限

创建以上规则

kubectl apply -f test-role.yml
kubectl apply -f test-clusterrole.yml

RoleBinding 和 ClusterRoleBinding

RoleBinding可以将角色中定义的权限授予用户或用户组,RoleBinding包含一组权限列表(Subjects),权限列表中包含有不同形式的待授予权限资源类型(users,groups, or Service Account)

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding1
namespace: devops
subjects:
- kind: User # 权限资源类型
name: liheng # 名称
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role #要绑定的Role的类型(可以是Role或ClusterRole)
name: test-role # Role的名称
apiGroup: rbac.authorization.k8s.io

将名称为test-role的Role的权限资源赋予名为devops的用户,作用域为devops名称空间

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

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding2
namespace: devops
subjects:
- kind: User
name: devops
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: test-clusterrole
apiGroup: rbac.authorization.k8s.io

将名称为test-clusterrole的ClusterRole的资源权限赋予给了名称为devops的用户,但由于Role仅作用于单个namespace,所以此资源策略仅仅对devops名称空间下的资源有效

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: test-clusterrolebinding
subjects:
- kind: Group
name: devops
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: test-clusterrole
apiGroup: rbac.authorization.k8s.io

将名称为test-clusterrole的ClusterRole的资源权限赋予给groupname为devops的用户组,对此用户组下所有用户生效。

创建一个用户只能查看devops名称空间下的pod资源

1、生成用户(liheng)私钥

# openssl genrsa -out liheng.key 2048

2、通过生成的私钥生成证书签名请求文件:liheng.csr,注意-subj中的CN表示用户名,O表示用户组。

# openssl req -new -key liheng.key -out liheng.csr -subj "/CN=liheng/O=yunweizhongxi"

3、通过kubernetes集群的CA证书为用户颁发签名证书

# openssl x509 -req -in liheng.csr -CA /opt/kubernetes/ssl/ca.pem \\
-CAkey /opt/kubernetes/ssl/ca-key.pem \\
-CAcreateserial -out liheng.crt -days 500

4、使用创建的证书文件和私钥创建用户(客户端)认证凭据

# kubectl config set-credentials liheng \\
--client-certificate=liheng.crt \\
--embed-certs=true \\
--client-key=liheng.key \\
--kubeconfig=liheng.kubeconfig

5、创建用户上下文(Context)

# kubectl config set-context liheng-context \\
--cluster=kubernetes \\
--namespace=kube-system \\
--user=liheng \\
--kubeconfig=liheng.kubeconfig

6、设置要访问的集群信息

# kubectl config set-cluster kubernetes \\
--certificate-authority=/opt/kubernetes/ssl/ca.pem \\
--embed-certs=true \\ #表示将--certificate-authority证书写入到kubeconfig中
--server=$KUBE_APISERVER \\
--kubeconfig=liheng.kubeconfig

7、为用户(liheng)设置RBAC权限

# cat test-role.yml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: test-role
namespace: devops
rules:
- apiGroups: [""] # 为空表示为默认的core api group
resources: ["pods"] # 数据源类型
verbs: ["get","watch","list"] #赋予的权限
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding
namespace: devops
subjects:
- kind: User
name: liheng
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: test-role # 绑定上文中创建的名称为 test-rbac 的Role,具体权限,往上翻下哈
apiGroup: rbac.authorization.k8s.io
# kubectl apply -f test-role.yml

8、设置默认上下文

# kubectl config use-context liheng-context

9、测试

# [root@sl-k8s-master-01 devops]# kubectl get pod
NAME READY STATUS RESTARTS AGE
jenkins-745596c48d-fjt59 1/1 Running 0 2d20h
# [root@sl-k8s-master-01 devops]# kubectl exec jenkins-745596c48d-fjt59 -n devops -- sh
Error from server (Forbidden): pods "jenkins-745596c48d-fjt59" is forbidden: User "liheng" cannot create resource "pods/exec" in API group "" in the namespace "devops"
# [root@sl-k8s-master-01 devops]# kubectl get svc
Error from server (Forbidden): services is forbidden: User "liheng" cannot list resource "services" in API group "" in the namespace "devops"

可以看到liheng用户只有查看devops名称空间下pod的权限。

cfssl颁发签名证书方法

1、创建CA证书签名请求文件

# cat liheng-csr.json

"CN": "liheng", # 用户名,必填
"hosts": [], # 主机地址,不填表示所有主机都可使用
"key":
"algo": "rsa",
"size": 2048
,
"names": [

"C": "CN",
"L": "BeiJing",
"ST": "Beijing",
"O": "yunweizhongxin",
"OU": "System"

]

2、创建访问证书

# cfssl gencert -ca=/opt/kubernetes/ssl/ca.pem \\
-ca-key=/opt/kubernetes/ssl/ca-key.pem \\
-profile=kubernetes liheng-csr.json|cfssljson -bare liheng

3、为liheng用户生成集群配置文件

# kubectl config set-cluster kubernetes \\
--certificate-authority=/opt/kubernetes/ssl/ca.pem \\
--embed-certs=true \\
--server=$KUBE_APISERVER --kubeconfig=liheng.kubeconfig
# kubectl config set-credentials liheng \\
--client-certificate=liheng.pem \\
--client-key=liheng-key.pem \\
--embed-certs=true --kubeconfig=liheng.kubeconfig
# kubectl config set-context liheng-context \\
--cluster=kubernetes \\
--user=liheng \\
--namespace=devops \\
--kubeconfig=liheng.kubeconfig

4、切换上下文

# kubectl config use-context liheng-context --kubeconfig=liheng.kubeconfig

5、测试

# [root@sl-k8s-master-01 src]# kubectl get pod -n kube-system --kubeconfig=liheng.kubeconfig 
Error from server (Forbidden): pods is forbidden: User "liheng" cannot list resource "pods" in API group "" in the namespace "kube-system"

配置具有操作整个集群的管理员用户(admin)

1、生成用户(admin)私钥

# openssl genrsa -out admin.key 2048

2、通过生成的私钥生成证书签名请求文件:admin.csr.

# openssl req -new -key admin.key -out admin.csr \\
-subj "/CN=admin/O=system:masters"

使用config还需要注意用户已经经过授权(如RBAC授权),上述例子中用户的证书中O字段为system:masters,kube-apiserver预定义的ClusterRoleBinding cluster-admin默认将Group system:masters与ClusterRole cluster-admin进行了绑定,该ClusterRole授予了调用kube-apiserver相关API的权限;-subj中的CN表示用户名,O表示用户组

3、通过kubernetes集群的CA证书为用户颁发签名证书

# openssl x509 -req -in admin.csr -CA /opt/kubernetes/ssl/ca.pem \\
-CAkey /opt/kubernetes/ssl/ca-key.pem \\
-CAcreateserial -out admin.crt -days 500

4、使用创建的证书文件和私钥创建用户(客户端)认证凭据

# kubectl config set-credentials admin \\
--client-certificate=admin.crt \\
--embed-certs=true \\
--client-key=admin.key
--kubeconfig=admin.kubeconfig

5、创建用户上下文(Context)

# kubectl config set-context admin-context \\
--cluster=kubernetes \\
--user=admin
--kubeconfig=admin.kubeconfig

6、设置默认上下文

# kubectl config use-context admin-context

创建一个只能访问某个 namespace 的ServiceAccount

接下来配置创建一个ServiceAccount来访问特定名称空间下资源的示例 1、创建名为liheng-sa的ServiceAccount

# kubectl create sa liheng-sa -n devops

2、新建一个 Role和RoleBinding 对象

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: liheng-sa-role
namespace: devops
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
# 将上面的 liheng-sa 和角色 liheng-sa-role 进行绑定
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: liheng-sa-rolebinding
namespace: devops
subjects:
- kind: ServiceAccount
name: liheng-sa
namespace: devops
roleRef:
kind: Role
name: liheng-sa-role
apiGroup: rbac.authorization.k8s.io

3、验证 每个ServiceAccount会生成一个Secret对象和它进行映射,这个Secret里面包含一个 token,我们可以利用这个token去登录Dashboard进行验证

# kubectl get secret -n devops |grep liheng-sa
# kubectl get secret liheng-sa-token-klju -o jsonpath=.data.token -n devops |base64 -d

以上是关于Kubernetes访问控制之RBAC的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes(k8s)集群安全机制之访问控制

干货 | K8S 1.6新增特性之RBAC

kubernetes API 访问控制之:授权

云原生 kubernetes - 基于角色的访问控制RBAC

「走进k8s」Kubernetes1.15.1的RBAC(28)

kubernetes rbac 权限管理