赞
踩
对合法用户进行授权并且随后在用户访问时进行鉴权,是权限与安全系统的重要一环。
简单地说,授权就是授予不同的用户不同的访问权限。
API Server目前支持以下几种授权策略(通过API Server的启动参数“–authorization-mode”设置)。
API Server在接收到请求后,会读取该请求中的数据,生成一个访问策略对象,如果在该请求中不带某些属性(如Namespace),则这些属性的值将根据属性类型的不同,设置不同的默认值(例如,为字符串类型的属性设置一个空字符串;为布尔类型的属性设置false;为数值类型的属性设置0)。
然后将这个访问策略对象和授权策略文件中的所有访问策略对象逐条匹配,如果至少有一个策略对象被匹配,则该请求被鉴权通过,否则终止API调用流程,并返回客户端的错误调用码。
在API Server启用ABAC模式时,需要指定授权策略文件的路径和名称(–authorization-policy-file=SOME_FILENAME),授权策略文件里的每一行都以一个Map类型的JSON对象进行设置,这被称为**“访问策略对象**”。
通过设置访问策略对象中的apiVersion、kind、spec属性来确定具体的授权策略,其中:
API Server进行ABAC授权的算法为:在API Server收到请求之后,首先识别出请求携带的策略对象的属性,然后根据在策略文件中定义的策略对这些属性进行逐条匹配,以判定是否允许授权。
如果有至少一条匹配成功,那么这个请求就通过了授权(不过还是可能在后续其他授权校验中失败)。
常见的策略配置如下:
kubectl使用API Server的/api和/apis端点来获取版本信息。
要验证kubectl create/update命令发送给服务器的对象,kubectl需要向OpenAPI进行查询,对应的URL路径为/openapi/v2。
当使用ABAC授权模式时,下列特殊资源必须显式地通nonResourcePath属性进行设置。
在使用kubectl操作时,如果需要查看发送到API Server的HTTP请求,则可以将日志级别设置为8,例如:
# kubectl --v=8 version
下面通过几个授权策略文件(JSON格式)示例说明ABAC的访问控制用法。
(1)允许用户alice对所有资源做任何操作:
(2)kubelet可以读取任意Pod:
(3)kubelet可以读写Event对象:
(4)用户bob只能读取projectCaribou中的Pod:
(5)任何用户都可以对非资源类路径进行只读请求:
如果添加了新的ABAC策略,则需要重启API Server以使其生效。
Service Account会自动生成一个ABAC用户名(username),用户名按照以下命名规则生成:
system:serviceaccount:<namespace>:<serviceaccountname>
创建新的命名空间时,会产生一个如下名称的Service Account:
system:serviceaccount:<mamespace>:default
如果希望kube-system命名空间中的Service Account“default”具有全部权限,就要在策略文件中加入如下内容:
Webhook定义了一个HTTP回调接口,实现Webhook的应用会在指定事件发生时,向一个URL地址发送(POST)通知信息。
启用Webhook授权模式后,Kubernetes会调用外部REST服务对用户进行授权。
Webhook模式用参数:
–authorization-webhook-config-file=SOME_FILENAME来设置远端授权服务的信息。
配置文件使用的是kubeconfig文件的格式。文件里:
在授权开始时,API Server会生成一个api.authorization.v1beta1.SubjectAccessReview对象,用于描述操作信息,在进行JSON序列化之后POST出来。
在这个对象中包含用户尝试访问资源的请求动作的描述,以及被访问资源的属性。
Webhook API对象和其他API对象一样,遵循同样的版本兼容性规则,在实现时要注意apiVersion字段的版本,以实现正确的反序列化操作。
另外,API Server必须启用authorization.k8s.io/v1beta1 API扩展(–runtime-config=authorization.k8s.io/v1beta1=true)。
下面是一个希望获取Pod列表的请求报文示例:
远端服务需要填充请求中的SubjectAccessReviewStatus字段,并返回允许或不允许访问的结果。应答报文中的spec字段是无效的,也可以省略。
一个返回“运行访问”的应答报文示例如下:
一个返回“不允许访问”的应答报文示例如下:
非资源的访问请求路径包括/api、/apis、/metrics、/resetMetrics、/logs、/debug、/healthz、/swagger-ui/、/swaggerapi/、/ui和/version。
通常可以对/api、/api/*、/apis、/apis/*和/version对于客户端发现服务器提供的资源和版本信息给予“允许”授权,对于其他非资源的访问一般可以禁止,以限制客户端对API Server进行没有必要的查询。
查询/debug的请求报文示例如下:
{
"apiVersion": "authorization.k8s.io/v1beta1",
"kind": "SubjectAccessReview",
"spec": {
"nonResourceAttribures": {
"path": "/debug",
"verb": "get"
},
"user": "jane",
"group": {
"group1",
"group2"
}
}
}
RBAC(Role-Based Access Control,基于角色的访问控制)。相对于其他访问控制方式,新的RBAC具有如下优势:
要使用RBAC授权模式,需要在API Server的启动参数中加上–authorization-mode=RBAC。
下面对RBAC的原理和用法进行说明。
RBAC引入了4个新的顶级资源对象:Role、ClusterRole、RoleBinding和ClusterRoleBinding。同其他API资源对象一样,用户可以使用kubectl或者API调用等方式操作这些资源对象。
1)角色(Role)
一个角色就是一组权限的集合,这里的权限都是许可形式的,不存在拒绝的规则。
在一个命名空间中,可以用角色来定义一个角色,如果是集群级别的,就需要使用ClusterRole了。
角色只能对命名空间内的资源进行授权,在下面例子中定义的角色具备读取Pod的权限:
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" 空字符串, 表示核心API群
resources: ["pods"]
verbs: ["get", "watch", "list"]
rules中的参数说明如下:
2)集群角色(ClusterRole)
集群角色除了具有和角色一致的命名空间内资源的管理能力,因其集群级别的范围,还可以用于以下特殊元素的授权。
下面的集群角色可以让用户有权访问任意一个或所有命名空间的secrets(视其绑定方式而定):
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata: # ClusterRole不受限于命令空间, 所以无须设置Namespace的名称
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
3)角色绑定(RoleBinding)和集群角色绑定(ClusterRoleBinding)
角色绑定或集群角色绑定用来把一个角色绑定到一个目标上,绑定目标可以是User(用户)、Group(组)或者Service Account。
使用RoleBinding为某个命名空间授权
使用ClusterRoleBinding为集群范围内授权
RoleBinding可以引用Role进行授权。
下面的例子中的RoleBinding将在default命名空间中把pod-reader角色授予用户jane,这一操作可以让jane读取default命名空间中的Pod:
---
kind: RoleBinding # 重点1
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default # 重点2
subjects:
- kind: User # 重点3
name: jane # 重点4
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # 重点5
name: pod-reader # 重点6
apiGroup: rbac.authorization.k8s.io
RoleBinding也可以引用ClusterRole,对属于同一命名空间内ClusterRole定义的资源主体进行授权。
一种常见的做法是集群管理员为集群范围预先定义好一组ClusterRole,然后在多个命名空间中重复使用这些ClusterRole。
例如,在下面的例子中,虽然secret-reader是一个集群角色,但是因为使用了RoleBinding,所以dave只能读取development命名空间中的secret:
---
kind: RoleBinding # 重点1
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-secrets
namespace: development # 集群角色中, 只有development命令空间中的权限才能赋予dave
subjects:
- kind: User # 重点2
name: dave # 重点3
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole # 重点4
name: secret-reader # 重点5
apiGroup: rbac.authorization.k8s.io
集群角色绑定中的角色只能是集群角色,用于进行集群级别或者对所有命名空间都生效的授权。
下面的例子允许manager组的用户读取任意Namespace中的secret:
---
kind: ClusterRoleBinding # 重点1
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-secrets-global
subjects:
- kind: Group # 重点2
name: manager # 重点3
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole # 重点4
name: secret-reader # 重点5
apiGroup: rbac.authorization.k8s.io
RoleBinding、Role与对Pod的操作授权:
多数资源可以用其名称的字符串来表达,也就是Endpoint中的URL相对路径,例如pods。
然而,某些Kubernetes API包含下级资源,例如Pod的日志(logs)。Pod日志的Endpoint是GET/ api/v1/namespaces/{namespace}/pods/{name}/log。
在这个例子中,Pod是一个命名空间内的资源,log就是一个下级资源。
要在一个RBAC角色中体现,就需要用斜线“/”来分隔资源和下级资源。
若想授权让某个主体同时能够读取Pod和Pod log,则可以配置resources为一个数组:
# resources reference
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"] # 重点
verbs: ["get", "list"]
资源还可以通过名称(ResourceName)进行引用。
在指定ResourceName后,使用get、delete、update和patch动词的请求,就会被限制在这个资源实例范围内。
例如,下面的声明让一个主体只能对一个Configmap进行get和update操作:
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: configmap\-updater
rules:
- apiGroups: [""]
resources: ["configmap"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]
可想而知,resourceName这种用法对list、watch、create或deletecollection操作是无效的,这是因为必须要通过URL进行鉴权,而资源名称在list、watch、create或deletecollection请求中只是请求Body数据的一部分。
注意,下面的例子只展示了rules部分的内容。
1)允许读取核心API组中的Pod资源:
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
2)允许读写extensions和apps两个API组中的deployment资源:
rules:
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
3)允许读取pods及读写jobs:
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
resources: ["jods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
4)允许读取一个名为my-config的ConfigMap(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap):
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceName: ["my-config"]
verbs: ["get"]
5)读取核心组的Node资源(Node属于集群级的资源,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定):
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
6)允许对非资源端点“/healthz”及其所有子路径进行GET和POST操作(必须使用ClusterRole和ClusterRoleBinding):
rules:
- nonResourceURLs: ["/healthz", "/healthz/*"]
verbs: ["get", "post"]
注意,在下面的例子中只包含subjects部分的内容。
(1)用户名alice@example.com:
subjects:
- kind: User
name: "alice@example.com"
apiGroup: rbac.authorization.k8s.io
(2)组名frontend-admins:
subjects:
- kind: Group
name: "frontend-admins"
apiGroup: rbac.authorization.k8s.io
(3)kube-system命名空间中的默认Service Account:
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
(4)qa命名空间中的所有Service Account:
subjects:
- kind: Group
name: system:serviceaccounts:qa
apiGroup: rbac.authorization.k8s.io
(5)所有Service Account:
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
(6)所有认证用户(Kubernetes 1.5以上版本):
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
(7)所有未认证用户(Kubernetes 1.5以上版本):
subjects:
- kind: User
name: "alice@example.com"
apiGroup: tbac.authorization.k8s.io
(8)全部用户(Kubernetes 1.5以上版本):
subjects:
- kind: User
name: "alice@example.com"
apiGroup: tbac.authorization.k8s.io
API Server会创建一套默认的ClusterRole和ClusterRoleBinding对象,其中很多是以“system:”为前缀的,以表明这些资源属于基础架构,对这些对象的改动可能造成集群故障。
举例来说,system:node这个ClusterRole为kubelet定义了权限,如果这个集群角色被改动了,kubelet就会停止工作。
所有默认的ClusterRole和RoleBinding都会用标签kubernetes.io/bootstrapping=rbac-defaults进行标记。
下面对一些常见的默认ClusterRole和ClusterRoleBinding对象进行说明。
对系统角色的说明如表所示:
1)在命名空间acme中为用户bob授权admin ClusterRole:
# kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
2)在命名空间acme中为名为myapp的Service Account授予view ClusterRole:
kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccout=acme:myapp --namespace=acme
3)在全集群范围内为用户root授予cluster-admin ClusterRole:
kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
4)在全集群范围内为用户kubelet授予system:node ClusterRole:
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
5)在全集群范围内为名为myapp的Service Account授予view ClusterRole:
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。