前言:
kunernetes1.6开始集群安全性显著提高,特别是1.80版本中,RBAC授权插件升级为GA(通用可用性)并且在很多集群上默认开启。RBAC会阻止未授权的用户查看和修改集群状态。除非你授权默认的serviceaccount额外的特权,否则默认的serviceaccount不允许查看集群状态,更不用说以任何方式去修改集群状态。
1、介绍RBAC授权插件
kubernetes api服务器可以配置使用一些授权插件来检查是否允许用户请求的动作执行。因为api服务器对外暴露了rest接口,用户可以通过向服务器发送http请求来执行动作,通过在请求中包含认证凭证来进行认证(认证token、用户名和密码或者客户端证书)
了解动作
REST客户端发送get、post、put、delete和其他类型的http请求在特定的url路径上,这些路径表示特定的rest资源。在kubernetes中,这些资源是pod、service、secret等。 除了可以对全部资源类型应用安全权限,RBAC规则还可以应用于特定的资源实例,并且权限也可以应用于non-resource(非资源)url路径,因为并不是api服务器对外暴露的每个路径都映射到一个资源。
了解RBAC插件
RBAC授权插件将用户角色作为决定用户能否执行操作的关键因素。主体(可以是一个人去、一个serviceaccount、或者一组用户或serviceaccount)和一个或多个角色相关联,每个角色被允许在特定的资源上执行特定的动词。 如果一个用户有多个角色,他们可以做任何他们的角色允许他们做的事情。 通过RBAC插件管理授权是简单的,这一切都是通过创建四种RBAC特定的kubernetes资源来完成。
2、介绍RBAC资源
RBAC授权规则是通过四种资源来进行配置的,他们可以分为两个组:
- Role(角色)和ClusterRole(集群角色),它们指定了在资源上可以执行哪些动词
- RoleBuilding(角色绑定)和ClusterBuilding(集群角色绑定),它们将上述角色绑定到特定的用户、组或serviceaccount上
角色定义了可以做什么操作,而绑定定义了谁可以做这些操作
角色和集群角色,或者角色绑定和集群角色绑定之间的区别在于角色和角色绑定是命名空间的资源,而集群角色和集群角色绑定是集群级别的资源(不是命名空间)。
多个角色绑定可以存在于单个命名空间)对于角色也是如此)。同样的,可以创建多个集群绑定和集群角色。
尽管角色绑定是在命名空间下的,但他们也可以引用不同命名空间下的集群角色。
开始练习
创建命名空间和运行pod
$kubectl create ns foo
$kunectl run test - -image=luksa/kubectl-proxy -n foo
3、使用Role和RoleBuilding
Role资源定义了那些操作可以在哪些资源上执行
创建角色
$kunectl create -f service-reader.yaml -n foo
注意:-n选项是- -namespace的缩写
$kubectl create role service-reader - -verb=get - -verb=list - -resource=services -n bar
绑定角色到ServiceAccount
角色定义了那些操作可以执行,但没有指定谁可以执行这些操作,要做到这一点,必须将角色绑定到一个主体,它可以是一个user(用户)、一个serviceaccount或一个组(用户或serviceaccount组) 通过创建一个RoleBuilding资源来实现将角色绑定到主体。
运行以下命令,可以将角色绑定到default serviceaccount
$kubectl create rolebuilding test - -role =service-reader - -serviceaccount =foo :default -n foo
如上命令,会创建一个rolebuilding资源,它将service-reader角色绑定到命名空间foo中的default serviceaccount上。这个RoleBuilding资源会被创建在命名空间foo中。
注意:如果要绑定一个角色到一个user(用户)而不是ServiceAccount上,使用- -user作为参数来指定用户名,如果要绑定角色到组,可以使用- -group参数
4、使用ClusterRole和ClusterRoleBuilding
Role和RoleBuilding都是命名空间的资源,这意味着它们属于和应用在一个单一的命名空间资源上。RoleBuilding可以引用来自其他命名空间中的ServiceAccount。
除了这两个命名空间的资源,还存在两个集群级别的的RBAC资源:ClusterRole和ClusterRoleBuilding,它们不在命名空间里。
一个常规的角色只允许访问和角色在同一个命名空间中的资源,如果需要跨不同命名空间访问资源,就必须要在每个命名空间中创建一个role和rolebuilding。如果想将这种行为扩展到所有的命名空间,需要在每个命名空间中创建相同的role和rolebuilding。当创建一个新的命名空间时,必须记住也要在新的命名空间中创建这两个资源。
一些特定的资源完全不在命名空间中(包括node、PersistentVolume、NameSpace等),还有api服务器对外暴露了一些不表示资源的url路径。常规角色不能对这些资源或非资源型的url进行授权,但是ClusteeRole可以。
ClusterRole是一种集群级资源,它可以访问没有命名空间的资源和非资源型的url,或者作为单个命名空间内部绑定的公共角色,从而避免必须在每个命名空间中重新定义相同的角色。
允许访问集群级别的资源
创建一个叫做pv-reader的ClusterRole:
$kubectl create clusterrole pv-reader - -verb=get,list - -resource=persistentvolumes
删除rolebuilding
$kubect delete rolebuildinv pv-test
创建ClusterRoleBuilding
$kubectl create clusterrolebuilding pv-test - -clusteerole =pv-reader - -serviceaccount =foo:default
允许访问非资源的url
和集群级别的资源一样,非资源型的url ClusterRole必须和ClusterRoleBuilding结合使用 使用ClusteeRole来授权访问指定命名空间中的资源 ClusterRole不是必须一直和集群级别的ClusterRoleBuilding捆绑使用。它们也可以和常规的命名空间的RoleBuilding进行捆绑
总结Role、ClusterRole、Rolebuilding和ClusterRoleBuilding的组合
表何时使用具体的role和building的组合
访问的资源 | 使用的角色类型 | 使用的绑定类型 |
集群级别的资源(nodes、PersistentVolumes,。。。) | ClusterRole | ClusterRoleBuilding |
非资源型URL(/api、/healhz、。。。) | ClusterRole | ClusterRoleBuilding |
在任何命名空间中的资源(和跨所有命名空间的资源) | ClusterRole | ClusterRoleBuilding |
在具体命名空间中的资源(在多个命名空间中重用这个相同的ClusterRole) | ClusterRole | RoleBuilding |
在具体的命名空间中的资源(Role必须在每个命名空间中定义好) | Role | RoleBuilding |
5、了解默认的ClusterRole和ClusterRoleBuilding
kubernetes提供了一组默认的ClusterROle和ClusterRoleBuilding,每次api服务器启动时都会更新他们,这保证了在错误的删除角色和绑定,或者kubernetes的新版本使用了不同的集群角色和绑定配置时,所有的默认角色和绑定都会被重新创建。
用view ClusterRole允许对资源的只读访问
之前使用默认的view ClusterRole,它允许读取一个命名空间的大多数资源,Secret中的某一个可能包含一个认证token,它必定已在view ClusterRole中的资源有更大的权限,并且运行用户伪装成不同的用户来获取额外的权限(权限扩散)
用edit ClusterRole允许对资源的修改
edit ClusterRole,允许你修改一个命名空间的资源,同时允许读取和修改secret,但是不允许查看或修改role和RoleBuilding,这是为了防止权限扩散
用admin ClusterRole赋予一个命名空间全部的控制权
一个命名空间中的资源的完全控制权由admin ClusterRole赋予。有这个ClusterRole的主体可以读取和修改命名空间中的任何资源,除了ResourceQuota和命名空间资源本身。edit和admin ClusterRole之间的主要区别是能否在命名空间中查看和修改Role和RoleBilding
注意:为了防止权限扩散,api服务器只允许用户在已经拥有了一个角色中列出所有权限(以及相同范围内的所有权限)的情况下,创建和更新这个角色
用Cluster-adim ClusterRole得到完全的控制
通过讲cluster-admin ClusterRole赋予主体,主体可以获得kubernetes集群完全控制的权限。正如上面讲的,admin ClusterRole不允许用户修改命名空间的ResourceQuota对下或者命名空间资源本身,如果想允许用户这么做,需要创建一个指向cluster-admin ClusterRole的RoleBuilding,这使得RoleBuilding中包含的用户能够完全控制创建RoleBuilding所在命名空间上的所有方面。
通过在ClusterRoleBuilding而不是RoleBuilding中引用cluster-admin Cluster可以赋予用户已饿集群所有命名空间的完全控制权
了解其他默认的clusterRole
默认的ClusterRole列表包含了大量其他的ClusterRole,他们以System:为前缀。这些角色用于各种kubernetes组件中,在他们之中,开业找到如:system:kube-scheduler之类的角色,它是给调度器使用的。
虽然Controller Manager作为一个独立的pod运行,但是其中运行的玫瑰控制器都可以使用单独的ClusterRole和ClusterRoleBuilding(他们以system:controller:为前缀)
6、理性授予权限
默认情况下,命名空间中的默认ServiceAccount除了未经身份验证的用户没有其他权限,默认情况下,pod甚至不能查看集群状态,应该授予他们适当的权限来做这些操作。
讲所有的ServiceAccount赋予cluster-admin ClusterRole是一个坏主意,和安全问题一样,最好每个人提供他们工作所需要的权限,一个单独权限也不能多(最小权限原则)
为每个pod创建特定的ServiceAccount
一个好的想法是为每一个pod(或一组pod的副本)创建一个特定ServiceAccount,并且把他和一个特定的Role(或ClusterRole)通过RoleBuilding联系起来(而不是ClusterRoleBuilding)
如果一个pod只需读取pod,而其他pod也需要修改他们,然后创建两个不同的ServiceAccount,并且然这些pod通过指定的pod spec中的serviceAccountName属性来进行使用。不要讲两个pod所需要的所有必要权限添加到命名空间总的默认ServiceAccount上。
12章小结:
API服务器的客户端有真实用户和pod中运行的应用
- pod中的应用与一个ServiceAccount关联
- 用户和ServiceAccount都与组进行关联
- 在默认情况下,pod运行在每个命名空间自动创建的默认ServiceAccount下
- 额外的ServiceAccount可以手动创建,并且和一个pod关联
- ServiceAccount通过配置可以运行只挂载给定pod中首先的Secret列表
- 一个ServiceAccount 也可以用来给pod添加镜像拉取密钥,因此不需要在每一个pod都制定密钥
- ROle和ClusterRole定义了可以在那些资源上执行什么操作
- RoleBuilding和ClusterRoleBuilding讲Role和ClusterRole绑定给用户、组合ServiceAccount
- 每个集群都有默认的ClusterRole和ClusterRoleBuilding