RBAC认证授权
1、k8s安全管理:认证、授权、准入控制概述
k8s对我们整个系统的认证,授权,访问控制做了精密的设置;对于k8s集群来说,apiserver是整个集群访问控制的唯一入口,我们在k8s集群之上部署应用程序的时候,也可以通过宿主机的NodePort暴露的端口访问里面的程序,用户访问kubernetes集群需要经历如下认证过程:认证->授权->准入控制(adminationcontroller)
1.认证(Authenticating)是对客户端的认证,通俗点就是用户名密码验证
2.授权(Authorization)是对资源的授权,k8s中的资源无非是容器,最终其实就是容器的计算,网络,存储资源,当一个请求经过认证后,需要访问某一个资源(比如创建一个pod),授权检查会根据授权规则判定该资源(比如某namespace下的pod)是否是该客户可访问的。
3.准入(Admission Control)机制:
准入控制器(Admission Controller)位于 API Server 中,在对象被持久化之前,准入控制器拦截对 API Server 的请求,一般用来做身份验证和授权。其中包含两个特殊的控制器:
MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook。分别作为配置的变异和验证准入控制 webhook。
变更(Mutating)准入控制:修改请求的对象
验证(Validating)准入控制:验证请求的对象
准入控制器是在 API Server 的启动参数配置的。一个准入控制器可能属于以上两者中的一种,也可能两者都属于。当请求到达 API Server 的时候首先执行变更准入控制,然后再执行验证准入控制。
我们在部署 Kubernetes 集群的时候都会默认开启一系列准入控制器,如果没有设置这些准入控制器的话可以说你的 Kubernetes 集群就是在裸奔,应该只有集群管理员可以修改集群的准入控制器。
例如我会默认开启如下的准入控制器。
–admission-control=ServiceAccount,NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota,MutatingAdmissionWebhook,ValidatingAdmissionWebhook
k8s的整体架构也是一个微服务的架构,所有的请求都是通过一个GateWay,也就是kube-apiserver这个组件(对外提供REST服务),k8s中客户端有两类,一种是普通用户,一种是集群内的Pod,这两种客户端的认证机制略有不同,但无论是哪一种,都需要依次经过认证,授权,准入这三个机制。
1、认证
1、认证支持多种插件
(1)令牌(token)认证:
双方有一个共享密钥,服务器上先创建一个密码下来,客户端登陆的时候拿这个密码登陆即可,这个就是对称密钥认证方式;k8s提供了一个restful风格的接口,它的所有服务都是通过http协议提供的,因此认证信息只能经由http协议的认证首部进行传递,这种认证首部进行传递通常叫做令牌;
(2)ssl认证:
对于k8s访问来讲,ssl认证能让客户端确认服务器的认证身份,我们在跟服务器通信的时候,需要服务器发过来一个证书,我们需要确认这个证书是不是ca签署的,如果是我们认可的ca签署的,里面的subj信息与我们访问的目标主机信息保持一致,没有问题,那么我们就认为服务器的身份得到认证了,k8s中最重要的是服务器还需要认证客户端的信息,kubectl也应该有一个证书,这个证书也是server所认可的ca签署的证书,双方需要互相认证,实现加密通信,这就是ssl认证。
2、kubernetes上的账号
客户端对apiserver发起请求,apiserver要识别这个用户是否有请求的权限,要识别用户本身能否通过apiserver执行相应的操作,那么需要哪些信息才能识别用户信息来完成对用户的相关的访问控制呢?
kubectl explain pods.spec可以看到有一个字段ServiceAccountName(服务账号名称),这个就是我们pod连接apiserver时使用的账号,因此整个kubernetes集群中的账号有两类,ServiceAccount(服务账号),User account(用户账号)
User account:实实在在现实中的人,人可以登陆的账号,客户端想要对apiserver发起请求,apiserver要识别这个客户端是否有请求的权限,那么不同的用户就会有不同的权限,靠用户账号表示,叫做username
ServiceAccount:方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的,是kubernetes中的一种资源
sa账号:登陆dashboard使用的账号
user account:这个是登陆k8s物理机器的用户
1.ServiceAccount
Service account是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的。它与User account不同,User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API而设计;User account是跨namespace的,而service account则是仅局限它所在的namespace;每个namespace都会自动创建一个default service account;
开启ServiceAccount Admission Controller后
1)每个Pod在创建后都会自动设置spec.serviceAccount为default(除非指定了其他ServiceAccout)
2)验证Pod引用的service account已经存在,否则拒绝创建;
当创建 pod 的时候,如果没有指定一个 serviceaccount,系统会自动在与该pod 相同的 namespace 下为其指派一个default service account。这是pod和apiserver之间进行通信的账号,如下:
1 |
|
从上面可以看到每个Pod无论定义与否都会有个存储卷,这个存储卷为default-token-***。pod和apiserver的认证信息通过secret进行定义,由于认证信息属于敏感信息,所以需要保存在secret资源当中,并以存储卷的方式挂载到Pod当中。从而让Pod内运行的应用通过对应的secret中的信息来连接apiserver,并完成认证。每个 namespace 中都有一个默认的叫做 default 的 serviceaccount 资源。查看名称空间内的secret,也可以看到对应的default-token。让当前名称空间中所有的pod在连接apiserver时可以使用的预制认证信息,从而保证pod之间的通信。
1 |
|
默认的service account 仅仅只能获取当前Pod自身的相关属性,无法观察到其他名称空间Pod的相关属性信息。如果想要扩展Pod,假设有一个Pod需要用于管理其他Pod或者是其他资源对象,是无法通过自身的名称空间的serviceaccount进行获取其他Pod的相关属性信息的,此时就需要进行手动创建一个serviceaccount,并在创建Pod时进行定义。那么serviceaccount该如何进行定义呢?实际上,service accout也属于一个k8s资源,serviceAccount也属于标准的k8s资源,可以创建一个serviceAccount,创建之后由我们创建的pod使用serviceAccountName去加载自己定义的serviceAccount就可以了,如下:
1 |
|
可以看到已经创建了test的serviceacount
kubectl describe sa test 查看test这个账号的详细信息
上面可以看到生成了一个test-token-hnc57的secret和test-token-hnc57的token
kubectl get secret 显示如下:
kubectl describe secret test-token-hnc57 显示如下:
上面可以看到生成了test-token-hnc57的token详细信息,这个token就是sa连接apiserver的认证信息,这个token也是登陆k8s dashboard的token,这些是一个认证信息,能够登陆k8s,能认证到k8s,但是不能做别的事情,不代表权限,想要做其他事情,需要授权
2、kubeconfig文件
在K8S集群当中,每一个用户对资源的访问都是需要通过apiserver进行通信认证才能进行访问的,那么在此机制当中,对资源的访问可以是token,也可以是通过配置文件的方式进行保存和使用认证信息,可以通过kubectl config进行查看配置,如下:
1 |
|
在上面的配置文件当中,定义了集群、上下文以及用户。其中Config也是K8S的标准资源之一,在该配置文件当中定义了一个集群列表,指定的集群可以有多个;用户列表也可以有多个,指明集群中的用户;而在上下文列表当中,是进行定义可以使用哪个用户对哪个集群进行访问,以及当前使用的上下文是什么。
2、授权
如果用户通过认证,什么权限都没有,需要一些后续的授权操作,如对资源的增删改查等,kubernetes1.6之后开始有RBAC(基于角色的访问控制机制)授权检查机制。
Kubernetes的授权是基于插件形成的,其常用的授权插件有以下几种:
1)Node(节点认证)
2)ABAC(基于属性的访问控制)
3)RBAC(基于角色的访问控制)
4)Webhook(基于http回调机制的访问控制)
什么是RBAC(基于角色的访问控制)?
让一个用户(Users)扮演一个角色(Role),角色拥有权限,从而让用户拥有这样的权限,随后在授权机制当中,只需要将权限授予某个角色,此时用户将获取对应角色的权限,从而实现角色的访问控制。如图:
在k8s的授权机制当中,采用RBAC的方式进行授权,其工作逻辑是,把对对象的操作权限定义到一个角色当中,再将用户绑定到该角色,从而使用户得到对应角色的权限。如果通过rolebinding绑定role,只能对rolebingding所在的名称空间的资源有权限,上图user1这个用户绑定到role1上,只对role1这个名称空间的资源有权限,对其他名称空间资源没有权限,属于名称空间级别的;
另外,k8s为此还有一种集群级别的授权机制,就是定义一个集群角色(ClusterRole),对集群内的所有资源都有可操作的权限,从而将User2通过ClusterRoleBinding到ClusterRole,从而使User2拥有集群的操作权限。
Role、RoleBinding、ClusterRole和ClusterRoleBinding的关系如下图:
通过上图可以看到,可以通过rolebinding绑定role,rolebinding绑定clusterrole,clusterrolebinding绑定clusterrole。
上面我们说了两个角色绑定:
(1)用户通过rolebinding绑定role
(2)用户通过clusterrolebinding绑定clusterrole
还有一种:rolebinding绑定clusterrole
rolebinding绑定clusterrole的好处:
假如有6个名称空间,每个名称空间的用户都需要对自己的名称空间有管理员权限,那么需要定义6个role和rolebinding,然后依次绑定,如果名称空间更多,我们需要定义更多的role,这个是很麻烦的,所以我们引入clusterrole,定义一个clusterrole,对clusterrole授予所有权限,然后用户通过rolebinding绑定到clusterrole,就会拥有自己名称空间的管理员权限了
注:RoleBinding仅仅对当前名称空间有对应的权限。
3、准入控制
一般而言,准入控制只是用来定义我们授权检查完成之后的后续的其他安全检查操作的,进一步补充了授权机制,由多个插件组合实行,一般而言在创建,删除,修改或者做代理时做补充;
Kubernetes的Admission Control实际上是一个准入控制器(Admission Controller)插件列表,发送到APIServer的请求都需要经过这个列表中的每个准入控制器插件的检查,如果某一个控制器插件准入失败,就准入失败。
控制器插件如下:
AlwaysAdmit:允许所有请求通过
AlwaysPullImages:在启动容器之前总是去下载镜像,相当于每当容器启动前做一次用于是否有权使用该容器镜像的检查
AlwaysDeny:禁止所有请求通过,用于测试
DenyEscalatingExec:拒绝exec和attach命令到有升级特权的Pod的终端用户访问。如果集中包含升级特权的容器,而要限制终端用户在这些容器中执行命令的能力,推荐使用此插件
ImagePolicyWebhook
ServiceAccount:这个插件实现了serviceAccounts等等自动化,如果使用ServiceAccount对象,强烈推荐使用这个插件
SecurityContextDeny:将Pod定义中定义了的SecurityContext选项全部失效。SecurityContext包含在容器中定义了操作系统级别的安全选型如fsGroup,selinux等选项
ResourceQuota:用于namespace上的配额管理,它会观察进入的请求,确保在namespace上的配额不超标。推荐将这个插件放到准入控制器列表的最后一个。ResourceQuota准入控制器既可以限制某个namespace中创建资源的数量,又可以限制某个namespace中被Pod请求的资源总量。ResourceQuota准入控制器和ResourceQuota资源对象一起可以实现资源配额管理。
LimitRanger:用于Pod和容器上的配额管理,它会观察进入的请求,确保Pod和容器上的配额不会超标。准入控制器LimitRanger和资源对象LimitRange一起实现资源限制管理
NamespaceLifecycle:当一个请求是在一个不存在的namespace下创建资源对象时,该请求会被拒绝。当删除一个namespace时,将会删除该namespace下的所有资源对象
DefaultStorageClass
DefaultTolerationSeconds
PodSecurityPolicy
当Kubernetes版本>=1.6.0,官方建议使用这些插件:
–admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds
当Kubernetes版本>=1.4.0,官方建议使用这些插件:
–admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota
以上是标准的准入插件,如果是自己定制的话,k8s1.7版 出了两个alpha features, Initializers 和 External Admission Webhooks
2、ServiceAccount介绍
kubernetes中账户区分为:User Accounts(用户账户) 和 Service Accounts(服务账户) 两种:
UserAccount是给kubernetes集群外部用户使用的,例如运维或者集群管理人员,,kubeadm安装的k8s,默认用户账号是kubernetes-admin;
k8s客户端(一般用:kubectl) ——>API Server
APIServer需要对客户端做认证,使用kubeadm安装的K8s,会在用户家目录下创建一个认证配置文件 .kube/config 这里面保存了客户端访问API Server的密钥相关信息,这样当用kubectl访问k8s时,它就会自动读取该配置文件,向API Server发起认证,然后完成操作请求。
用户名称可以在kubeconfig中查看
[root@xuegod63~]# cd ~/.kube/
[root@xuegod63 .kube]# ls
cache config http-cache
[root@xuegod63 .kube]# cat config
…
users:
- name: kubernetes-admin
ServiceAccount是Pod使用的账号,Pod容器的进程需要访问API Server时用的就是ServiceAccount账户;ServiceAccount仅局限它所在的namespace,每个namespace创建时都会自动创建一个default service account;创建Pod时,如果没有指定Service Account,Pod则会使用default Service Account。
3、RBAC认证授权策略
RBAC介绍
在Kubernetes中,所有资源对象都是通过API进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现,上面的Service Account其实就是APIServer的认证过程,而授权的机制是通过RBAC:基于角色的访问控制实现。
RBAC有四个资源对象,分别是Role、ClusterRole、RoleBinding、ClusterRoleBinding
1、role:角色
一组权限的集合,在一个命名空间中,可以用其来定义一个角色,只能对命名空间内的资源进行授权。如果是集群级别的资源,则需要使用ClusterRole。例如:定义一个角色用来读取Pod的权限
1 |
|
rules中的参数说明:
1、apiGroups:支持的API组列表,例如:”apiVersion: batch/v1”等
2、resources:支持的资源对象列表,例如pods、deplayments、jobs等
3、resourceNames: 指定resource的名称(通过 resourceNames
列表按名称引用资源,例如一个叫my-configmap的 ConfigMap)
4、verbs:对资源对象的操作方法列表。
2、ClusterRole:集群角色
具有和角色一致的命名空间资源的管理能力,还可用于以下特殊元素的授权
1、集群范围的资源,例如Node
2、非资源型的路径,例如:/healthz
3、包含全部命名空间的资源,例如Pods
例如:定义一个集群角色可让用户访问任意secrets
1 |
|
3、RoleBinding:角色绑定、ClusterRolebinding:集群角色绑定
角色绑定和集群角色绑定用于把一个角色绑定在一个目标上,可以是User,Group,Service Account,使用RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权。
例如:将在rbac命名空间中把pod-read角色授予用户es
1 |
|
RoleBinding也可以引用ClusterRole,对属于同一命名空间内的ClusterRole定义的资源主体进行授权
例如:es能获取到集群中所有的资源信息
1 |
|
集群角色绑定的角色只能是集群角色,用于进行集群级别或对所有命名空间都生效的授权
例如:允许manager组的用户读取所有namaspace的secrets
1 |
|
4、资源的引用方式
多数资源可以用其名称的字符串表示,也就是Endpoint中的URL相对路径,例如pod中的日志是GET /api/v1/namaspaces/{namespace}/pods/{podname}/log
如果需要在一个RBAC对象中体现上下级资源,就需要使用“/”分割资源和下级资源。
例如:若想授权让某个主体同时能够读取Pod和Pod log,则可以配置 resources为一个数组
1 |
|
资源还可以通过名称(ResourceName)进行引用,在指定ResourceName后,使用get、delete、update、patch请求,就会被限制在这个资源实例范围内
例如,下面的声明让一个主体只能对名为my-configmap的Configmap进行get和update操作:
1 |
|
5、常见角色实例
1、允许读取核心API组的Pod资源
1 |
|
2、允许读写extensions和apps两个API族中的deployment资源rules
1 |
|
3、允许读取Pod以及读写job信息
1 |
|
4、允许读取一个名为my-config的ConfigMap(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap)
1 |
|
5、读取核心组的Node资源(Node属于集群级的资源,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定)
1 |
|
6、允许对非资源端点“/healthz”及其所有子路径进行GET和POST操作(必须使用ClusterRole和ClusterRoleBinding)
1 |
|
6、常见的角色绑定示例
1、用户名alice
1 |
|
2、组名alice
1 |
|
3、kube-system命名空间中默认Service Account
1 |
|
4、qa命名空间中的所有Service Account
1 |
|
5、所有Service Account
1 |
|
6、所有认证用户
1 |
|
7、所有未认证用户
1 |
|
8、全部用户
1 |
|
7、对Service Account的授权管理
Service Account也是一种账号,是给运行在Pod里的进程提供了必要的身份证明。需要在Pod定义中指明引用的Service Account,这样就可以对Pod的进行赋权操作。例如:pod内可获取rbac命名空间的所有Pod资源,pod-reader-sc的Service Account是绑定了名为pod-read的Role
1 |
|
默认的RBAC策略为控制平台组件、节点和控制器授予有限范围的权限,但是除kube-system外的Service Account是没有任何权限的。
(1)为一个应用专属的Service Account赋权
此应用需要在Pod的spec中指定一个serviceAccountName,用于API、Application Manifest、kubectl create serviceaccount等创建Service Account的命令。
例如为my-namespace中的my-sa Service Account授予只读权限
1 |
|
(2)为一个命名空间中名为default的Service Account授权
如果一个应用没有指定 serviceAccountName,则会使用名为default的Service Account。注意,赋予Service Account “default”的权限会让所有没有指定serviceAccountName的Pod都具有这些权限
例如,在my-namespace命名空间中为Service Account“default”授予只读权限:
1 |
|
另外,许多系统级Add-Ons都需要在kube-system命名空间中运行,要让这些Add-Ons能够使用超级用户权限,则可以把cluster-admin权限赋予kube-system命名空间中名为default的Service Account,这一操作意味着kube-system命名空间包含了通向API超级用户的捷径。
1 |
|
(3)为命名空间中所有Service Account都授予一个角色
如果希望在一个命名空间中,任何Service Account应用都具有一个角色,则可以为这一命名空间的Service Account群组进行授权
1 |
|
(4)为集群范围内所有Service Account都授予一个低权限角色
如果不想为每个命名空间管理授权,则可以把一个集群级别的角色赋给所有Service Account。
1 |
|
(5)为所有Service Account授予超级用户权限
1 |
|
8、使用kubectl命令行工具常见资源对象
1、在命名空间rbac中为用户es授权admin ClusterRole
1 |
|
2、在命名空间rbac中为名为myapp的Service Account授予view ClusterRole
1 |
|
3、在全集群范围内为用户root授予cluster-admin ClusterRole
1 |
|
4、在全集群范围内为名为myapp的Service Account授予view ClusterRole
1 |
|
yaml文件进行rbac授权:https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/
9、限制不同的用户操作k8s资源
1、新建一个用户
生成一个私钥
1 |
|
生成一个证书请求文件
1 |
|
生成一个证书
1 |
|
把zy这个用户添加到kubernetes集群中,可以用来认证apiserver的连接
1 |
|
在配置文件中新增zy这个账号
1 |
|
切换账号到zy,默认没有任何权限
1 |
|
把zy这个用户通过rolebinding绑定到clusterrole上
1 |
|
切换回zy用户,测试是否有权限
1 |
|
新建linux普通用户zy,测试
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!