在介绍源码之前还是解释一下这个RBAC吧,RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间,一般者是多对多的关系。
在kubernetes1.6以后正式引入RBAC这个东西,其实这个事情要分两个方面看,在增加了安全性的同时降低了易用性,应为在真实的环境中不会直接把kubernetes放到公网环境中,内网环境中的网络也是隔离的,当然你可以可以选择关闭RBAC这个服务。
开启服务,在apiserver启动参数设定
--authorization-mode=RBAC --runtime-config=rbac.authorization.k8s.io/v1beta1
RBAC首先看角色定义,Role是命名空间级别的
type Role struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"`
}
集群角色是集群级别的
type ClusterRole struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"`
}
角色里面关联的是Rules规则,一个角色有哪些权限,通过rule去定义,下面是rule的属性,这些主要事控制访问的资源、访问URL限制。
type PolicyRule struct {
Verbs []string `json:"verbs" protobuf:"bytes,1,rep,name=verbs"`
APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,2,rep,name=apiGroups"`
Resources []string `json:"resources,omitempty" protobuf:"bytes,3,rep,name=resources"`
ResourceNames []string `json:"resourceNames,omitempty" protobuf:"bytes,4,rep,name=resourceNames"`
NonResourceURLs []string `json:"nonResourceURLs,omitempty" protobuf:"bytes,5,rep,name=nonResourceURLs"`
}
那角色是怎么和绑定的呢,这就要看RoleBinding和ClusterRoleBinding
type RoleBinding struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"`
RoleRef RoleRef `json:"roleRef" protobuf:"bytes,3,opt,name=roleRef"`
}
相同属性的的结构体
type ClusterRoleBinding struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Subjects []Subject `json:"subjects" protobuf:"bytes,2,rep,name=subjects"`
RoleRef RoleRef `json:"roleRef" protobuf:"bytes,3,opt,name=roleRef"`
}
主要看两个,第一个是Subjects,它就是关联的对象(”User”, “Group”, 和指定命名空间下的: “ServiceAccount”),第二个是RoleRef,他是是角色的关联。可以看上一篇heapster的rbac就理解怎样使用了。
kubernetes系统自身组件的运行也是需要这些权限管理的,所以系统初始了一些角色和默认的权限,看代码plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go:
先看读写权限的定义
ReadWrite = []string{"get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"}
Read = []string{"get", "list", "watch"}
对应于API的各种操作。
{
// a "root" role which can do absolutely anything
ObjectMeta: metav1.ObjectMeta{Name: "cluster-admin"},
Rules: []rbac.PolicyRule{
rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(),
rbac.NewRule("*").URLs("*").RuleOrDie(),
},
},
{
// a role which provides just enough power to determine if the server is ready and discover API versions for negotiation
ObjectMeta: metav1.ObjectMeta{Name: "system:discovery"},
Rules: []rbac.PolicyRule{
rbac.NewRule("get").URLs("/healthz", "/version", "/swaggerapi", "/swaggerapi/*", "/api", "/api/*", "/apis", "/apis/*").RuleOrDie(),
},
},
{
// a role which provides minimal resource access to allow a "normal" user to learn information about themselves
ObjectMeta: metav1.ObjectMeta{Name: "system:basic-user"},
Rules: []rbac.PolicyRule{
// TODO add future selfsubjectrulesreview, project request APIs, project listing APIs
rbac.NewRule("create").Groups(authorizationGroup).Resources("selfsubjectaccessreviews").RuleOrDie(),
},
},
....
上面截取了部分代码,他们是系统角色的定义,譬如cluster-admin角色,它的权限是
rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(),
rbac.NewRule("*").URLs("*").RuleOrDie(),
匹配所有规则,所有URL,所有资源,那么它将是一个“root”级别,最高权限,所以在kubernetes中kubectl的证书里面”O”: “system:masters”,这个用户组管理的就是cluster-admin这个角色,下面会细说。
先简单分析一下系统里面主要角色:
1.cluster-admin:最高管理角色
2.system:discovery:接口发现角色,主要是接口查询
rbac.NewRule("get").URLs("/healthz", "/version", "/swaggerapi", "/swaggerapi/*", "/api", "/api/*", "/apis", "/apis/*")
3.system:basic-user基础角色,最少访问权限
4.admin 空间级别的管理员,有基础资源的增删改查
rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(),
rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers","replicationcontrollers/scale","serviceaccounts","services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie()
...
5.edit空间级别修改角色
6.view空间级别查看角色
7.system:heapster集群级别heapster角色,提供资源查询权限
rbac.NewRule(Read...).Groups(legacyGroup).Resources("events", "pods", "nodes", "namespaces").RuleOrDie(),
8.system:node系统级别node节点操作角色
9.system:node-proxier系统级别proxy操作角色
10.system:node-bootstrapper系统级别node启动操作角色,启动时候证书签名用
rbac.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(),
11.system:kube-controller-manager系统级别kube-controller-manager操作角色
12.system:kube-scheduler系统级别kube-scheduler操作角色
13.system:kube-dns系统级别kube-dns操作角色,看过之前源码阅读的就理解了这里为啥是endpoints和services的listwatch了。
rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("endpoints", "services").RuleOrDie(),
14.system:persistent-volume-provisioner系统级别PV、PVC操作。
看完系统初始化的这些角色和对应的权限后,看看系统初始化的角色绑定
func ClusterRoleBindings() []rbac.ClusterRoleBinding {
rolebindings := []rbac.ClusterRoleBinding{
rbac.NewClusterBinding("cluster-admin").Groups(user.SystemPrivilegedGroup).BindingOrDie(),
rbac.NewClusterBinding("system:discovery").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(),
rbac.NewClusterBinding("system:basic-user").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(),
rbac.NewClusterBinding("system:node").Groups(user.NodesGroup).BindingOrDie(),
rbac.NewClusterBinding("system:node-proxier").Users(user.KubeProxy).BindingOrDie(),
rbac.NewClusterBinding("system:kube-controller-manager").Users(user.KubeControllerManager).BindingOrDie(),
rbac.NewClusterBinding("system:kube-dns").SAs("kube-system", "kube-dns").BindingOrDie(),
rbac.NewClusterBinding("system:kube-scheduler").Users(user.KubeScheduler).BindingOrDie(),
}
addClusterRoleBindingLabel(rolebindings)
return rolebindings
}
这样就可以看到cluster-admin这个角色关联到system:masters这个用户组,system:node-proxier关联到system:kube-proxy这个用户,其它也都是类似的。