kubenetes RBAC

k8s 角色基础访问控制权限

Posted by minicool on August 10, 2018

在Kubernetes中,授权有ABAC(基于属性的访问控制)、RBAC(基于角色的访问控制)、Webhook、Node、AlwaysDeny(一直拒绝)和AlwaysAllow(一直允许)这6种模式。从1.6版本起,Kubernetes 默认启用RBAC访问控制策略。从1.8开始,RBAC已作为稳定的功能。通过设置–authorization-mode=RBAC,启用RABC。在RABC API中,通过如下的步骤进行授权:1)定义角色:在定义角色时会指定此角色对于资源的访问控制的规则;2)绑定角色:将主体与角色进行绑定,对用户进行访问授权。

授权主体(Subject)

RBAC授权中的主体可以是组,用户或者服务帐户。用户通过字符串表示,比如“alice”、 “bob@example.com”等,具体的形式取决于管理员在认证模块中所配置的用户名。system:被保留作为用来Kubernetes系统使用,因此不能作为用户的前缀。组也有认证模块提供,格式与用户类似。

用户(UserAccount)

用户,这是有外部独立服务进行管理的,管理员进行私钥的分配,用户可以使用KeyStone或者Goolge 帐号,甚至一个用户名和密码的文件列表也可以。对于用户的管理集群内部没有一个关联的资源对象,所以用户不能通过集群内部的API 来进行管理

创建一个只能访问某个 namespace 的用户 namespace:test-ns username:test-user group:test-group

  1. 创建命名空间“test-user” command line:命令行
$kubectl create namespace test-ns #创建命名空间
namespace "test-ns" created

$kubectl get ns                         #获取命名空间列表
NAME           STATUS    AGE
default        Active    9d
test-ns        Active    35s
docker         Active    9d
kube-public    Active    9d
kube-system    Active    9d

yaml:格式文件配置

#test-ns.yaml
$ cat test-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
 name: test-ns

$ kubectl create -f test-ns.ymal
namespace "test-ns" created 
  1. 创建用户凭证 Kubernetes没有User Account的API 对象,不过要创建一个用户帐号的话也是挺简单的,利用管理员分配的一个私钥就可以创建了。 在此利用openssl来创建,创建私钥,命名为wolken.key

(1)使用openssl创建私钥

openssl genrsa -out test-user.key 2048

(2)使用私钥创建证书签名请求文件 使用刚刚创建的私钥创建一个证书签名请求文件:test-user.csr,要注意需要确保在-subj参数中指定用户名和组(CN表示用户名,O表示组):

openssl req -new -key test-user.key -out test-user.csr -subj "/CN=test-user/O=test-group"

(3)使用Kubernetes集群的授权创建的证书请求 然后找到Kubernetes集群的CA, kubeadm安装的集群,CA相关证书位于/etc/kubernetes/pki/目录下面, 二进制方式搭建的,应该在最开始搭建集群的时候就已经指定好了CA的目录(/data/kubernetes/ssl), 然后利用该目录下面的ca.crt和ca.key两个文件来批准上面的证书请求。 找到kubernetes集群认证中心,位置通常在/etc/kubernetes/pki,检查是否存在ca.crt、ca.key。生成最终的证书test-user.crt,有效期30天。

openssl x509 -req -in test-user.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out test-user.crt -days 30 到此凭证已经可用。可直接在kubeconfig中指定client-certificate与client-key文件位置。但是我需要在本地机器连接该账号。于是将wolken.crt与wolken.key转为base64。通过client-certificate-data与client-key-data配置。

(4)生成凭证及上下文 现在可以使用刚刚创建的证书文件和私钥文件在集群中创建新的凭证和上下文(Context):

创建用户凭证

$ kubectl config set-credentials test-user-cre --client-certificate=test-user.crt  --client-key=test-user.key

用户凭证也可以通过certificate-data及key-data写入

cat test-user.crt|base64 --wrap=0  #获取base64位test-user.crt
cat test-user.key|base64 --wrap=0  #获取base64位test-user.key
将输出写进kubeconfig,或者通过命令创建用户,将上面的输出替换对应位置{CRT_BASE64}{KEY_BASE64}
kubectl config set-credentials test-user-cre --client-certificate-data={CRT_BASE64}  --client-key-data={KEY_BASE64}

创建该用户新的Context:

$ kubectl config set-context test-user-context --cluster=kubernetes --namespace=test-user --user=test-user-cre

检测上下文:

$ kubectl --context=test-user-context get pods
Error from server (Forbidden): pods is forbidden: User "test-user-cre" cannot list pods in the namespace "default"

会发现请求被forbidden,是因为没有配置权限给test-user。

按照现有环境配置,k8s 组件访问 apiserver 使用基于证书的认证方式,apiserver 接受请求时会从client 证书中提取 CN、O字段,分别作为 subjects 中的 User 和 Group

用户组(Group)

用来关联多个账户的,集群中有一些默认创建的组,比如cluster-admin

服务账户(Service Account)

通过Kubernetes API 来管理的一些用户帐号,和namespace 进行关联的,适用于集群内部运行的应用程序,需要通过API 来完成权限认证,所以在集群内部进行权限操作,都需要使用到 ServiceAccount

规则(Rule)

Kubernetes有一个很基本的特性就是它的所有资源对象都是模型化的 API 对象,允许执行 CRUD(Create、Read、Update、Delete)操作(也就是我们常说的增、删、改、查操作),比如下面的这下资源:

resourse: Pods、 Nodes、 Services、 Deployment、 Replicasets、 Statefulsets、 Namespace、 Persistents、 Secrets和ConfigMaps 上面这些资源对象的可能存在的操作有:

verbs: create get delete list update edit watch exec 在更上层,这些资源和API Group 进行关联,比如Pods属于Core API Group,而Deployements属于 apps API Group,

角色和集群角色 (Role & ClusterRole)

在RBAC API中,角色包含代表权限集合的规则。在这里,权限只有被授予,而没有被拒绝的设置。在Kubernetes中有两类角色,即普通角色和集群角色。可以通过Role定义在一个命名空间中的角色,或者可以使用ClusterRole定义集群范围的角色。

Role 和 ClusterRole:角色和集群角色,这两个对象都包含上面的Rules 元素,二者的区别在于,在Role 中,定义的规则只适用于单个命名空间,也就是和namespace 关联的,而ClusterRole 是集群范围内的,因此定义的规则不受命名空间的约束。另外Role和 ClusterRole在Kubernetes中都被定义为集群内部的API 资源,和Pod、ConfigMap 这些类似,都是集群的资源对象,所以同样的可以使用kubectl相关的命令来进行操作

角色(Role)

一个角色只能被用来授予访问单一命令空间中的资源。一般来说角色都是被限定在某个命名空间中。

example: “default”命令空间中定义了一个名为“pod-reader”的角色,此角色能够对在“default”命名空间中访问Pod:

  1. 查询role角色在”default”命名空间 或者查询所有命名空间
$kubectl get roles --namespace=default

$kubectl get roles --all-namespaces
  1. 创建角色信息

yaml格式载入

$ cat test-pod-reader-role.yaml
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
    namespace: test-ns
    name: test-pod-reader
    rules:
    - apiGroups: [""] # "" indicates the core API group
    resources: ["pods"]
    resourceNames: ["readablepod","anotherpod"]
    verbs: ["get", "watch", "list"]

$kubectl create -f create-role.yaml

命令行

#标准语法
$ role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]

$ kubectl create role test-pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod --resource-name=anotherpod --namespace=test-ns

集群角色(ClusterRole)

集群角色(ClusterRole)能够被授予如下资源的权限:

集群范围的资源(类似于Node) 非资源端点(类似于”/healthz”) 集群中所有命名空间的资源(类似Pod) 下面是授予集群角色读取秘密字典文件访问权限的例子:

  1. 查询clusterrole角色
$kubectl get clusterrole
  1. 创建集群角色 yaml格式
#test-clusterrole.yaml
kind:ClusterRole
apiVersion:rbac.authorization.k8s.io/v1
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name:test-clusterrole-secret-reader
rules:
- apiGroups:[""]
  resources:["secrets"] #明确资源类型
  verbs:["get","watch","list"]

$ kubectl create -f test-clusterrole.yaml  

命令行

$ clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]

$ kubectl create role test-pod-reader\
--verb=get,list,watch\
--resource=secrets

角色绑定和集群角色绑定(RoleBinding & ClusterRoleBinding)

角色绑定用于将角色与一个或一组用户进行绑定,从而实现将对用户进行授权的目的。主体分为用户、组和服务帐户。角色绑定也分为角色普通角色绑定和集群角色绑定。 角色绑定和集群角色绑定,简单来说就是把声明的Subject和Role 进行绑定的过程(给某个用户绑定上操作的权限),二者的区别也是作用范围的区别:RoleBinding只会影响到当前namespace 下面的资源操作权限,而ClusterRoleBinding会影响到所有的 namespace。

角色绑定 (RoleBinding)

角色绑定只能引用同一个命名空间下的角色。在下面的例子中,在”default”命名空间中角色绑定将‘jane’用户和“pod-reader”角色进行了绑定,这就授予了“jane”能够访问“default”命名空间下的Pod。

RoleBinding既可以引用相同namespace下的Role;又可以引用一个ClusterRole,RoleBinding引用ClusterRole时用户继承的权限会被限制在RoleBinding所在的namespace下。

  1. yaml 文件创建
#test-rolebinging.yaml
# This role binding allows "jane" to read pods in the "default" namespace.
kind:RoleBinding
apiVersion:rbac.authorization.k8s.io/v1
metadata:
  name:read-pods
  namespace:test-user
subjects: #主体
- kind:User
  name:test-user-csr
  apiGroup:rbac.authorization.k8s.io
roleRef: #引用的角色
  kind:Role
  name:test-role
  apiGroup:rbac.authorization.k8s.io
  1. 命令行创建
$ rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]

kubectl create rolebinding read-pods \
--role=test-role \
--user=test-user-csr \
--user=test-user-csr1 \
--group=test-user-group

集群角色绑定

1.查询

名称为 “alice@example.com”用户:

subjects:
- kind:User
  name:"alice@example.com"
  apiGroup:rbac.authorization.k8s.io

名称为“frontend-admins”的组:

subjects:
- kind:Group
  name:"frontend-admins"
  apiGroup:rbac.authorization.k8s.io

在kube-system命名空间中,名称为“default”的服务帐户:

subjects:
- kind:ServiceAccount
  name:default
  namespace:kube-system

在“qa”命名空间中,所有的服务帐户:

subjects:
- kind:Group
  name:system:serviceaccounts:qa
  apiGroup:rbac.authorization.k8s.io

所有的服务帐户:

subjects:
- kind:Group
  name:system:serviceaccounts
  apiGroup:rbac.authorization.k8s.io

所有被认证的用户 (version 1.5+):

subjects:
- kind:Group
  name:system:authenticated
  apiGroup:rbac.authorization.k8s.io

所有未被认证的用户 (version 1.5+):

subjects:
- kind:Group
  name:system:unauthenticated
  apiGroup:rbac.authorization.k8s.io

所有用户(version 1.5+):

subjects:
- kind:Group
  name:system:authenticated
  apiGroup:rbac.authorization.k8s.io
- kind:Group
  name:system:unauthenticated
  apiGroup:rbac.authorization.k8s.io

cfssl 创建用户私钥及凭证

  1. 安装cfssl $brew install cfssl

kubenetes config