· 认证(Authentication)是识别用户的过程,这个过程需要知道用户到底是谁;
· 而授权(Authorization)是识别已认证用户访问权限的过程,这个过程判断用户是否具有某些权限;
· 准入控制(Admission Control)是最后的关卡,它会在请求通过认证和鉴权之后、对象被持久化之前拦截到达 API 服务器的请求,其通过一组控制逻辑对对象的操作进行验证和变更等操作。
一.
认证Authentication
那么,这个Token是怎么生成的呢?
该Token是动态生成的,是由kube-controller-manager进程调用API Server的私钥(/etc/kubernetes/manifests/kube-controller-manager.yaml配置文件--service-account-private-key-file参数指定的文件)签名生成的一个JWT格式的Token。API Server接收到客户端发来的Token后,会再次用私钥(/etc/kubernetes/manifests/kube-controller-manager.yaml配置文件--service-account-private-key-file参数指定的文件)对该Token进行校验。
我们查看所有的ServiceAccount,发现在每个命名空间下都存在一个名为default的默认ServiceAccount对象。
在这个Service Account里面有一个名为Secrets的可以作为Volume被挂载到Pod里的Secret,Pod启动时,这个Secrets会自动被挂载到Pod的指定目录下,用来协助完成Pod中的进程访问API Server时的身份鉴权。
一个Service Account可以包含多个secret,名为secrets的secret用于访问API Server的secret,也被称为ServiceAccountSecret;名为imagePullSecrets的secret用于下载容器镜像时的认证,但是由于镜像库通常运行在Insecure模式下,所以这个secret为空;用户还可以自定义其他的secret。
如果一个Pod在定义时没有指定spec.serviceAccountName属性,则系统会自动将其赋值为default,即大家都使用同一个命名空间中的默认Service Account。如果某个Pod需要使用非default的Service Account,则需要在定义时指定spec.serviceAccountName为"服务账户名"。
Service Account的正常工作离不开以下准入控制器:
Service Account准入控制器
Token准入控制器
关于准入控制器,我们会后文章最后进行讲解。
注意:由于 Service Account 的 token 存储在 secret 中,所以具有对这些 secret 的读取权限的任何用户都可以作为 Service Account 进行身份验证。授予 Service Account 权限和读取 secret 功能时要谨慎。
2
普通用户
普通用户就是个人用户,比如某个研发人员或外部应用的账号。但是K8s并没有相应的资源对象或者API来支持常规的个人用户。拥有K8s集群的CA证书签名的有效证书,个人用户就可以访问K8s集群了。在这种情况下,证书中的subject会被API Server服务解析成一个用户。比如,证书中的subject的内容为:O=yunwei,CN=lisi。其中CN(Common Name)lisi会被解析为用户,而O(Organization Name)yunwei会被解析为用户所在的组。
K8s中内置的用户
K8s内置了一组系统级别的用户,以“system:”开头,如下:
· system:kube-controller-manager:绑定了名为system:kube-controller-manager的ClusterRole,允许访问控制器管理器组件所需要的资源。
· system:kube-scheduler:绑定了名为system:kube-scheduler的ClusterRole,允许访问 scheduler组件所需要的资源。
· system:kube-proxy:绑定了名为system:node-proxier的ClusterRole,允许访问 kube-proxy 组件所需要的资源。
· system:anonymous:绑定了名为kubeadm:bootstrap-signer-clusterinfo的Role,当一个请求没有携带任何的认证信息时,它会自动获得该用户名。
执行如下命令然后查看Users列即可查看K8s默认创建的User。
kubectl get clusterrolebinding -A -o widekubectl get rolebinding -A -o wide
3
Anonymous
当一个请求没有携带任何的认证信息时,它会自动获得用户名:system:anonymous和用户组 system:unauthenticated,我们可以配置分配特定的权限给这种匿名用户,适用于想要公开一些不敏感的资源等场景。
4
K8s中的Group
同外部用户一样,Group 也是一种外部的概念,在X509客户端证书认证的方式中,Group 名字就是证书的组织名O(Orgnization)。
K8s中内置的组
K8s内置了一组系统级别的组,以“system:”开头,如下:
· system:authenticated:认证成功后的用户自动加入的一个组,用于快捷引用所有正常通过认证的用户账号,该组包含在所有已验证用户的组列表中。绑定了名为system:discovery的ClusterRole。
· system:unauthenticated:未能通过任何一个授权插件检验的账号,即未通过认证测 试的用户所属的组 。绑定了名为system:public-info-viewer的ClusterRole。
· system:serviceaccounts:当前集群上的所有 Service Account 对象。绑定了名为system:service-account-issuer-discovery的ClusterRole。
· system:serviceaccounts:<namespace>:特定命名空间内的所有service account="" 对象。<="" span="">
· system:masters:绑定了名为cluster-admin的ClusterRole。
· system:nodes:绑定了名为system:certificates.k8s.io:certificatesigningrequests:selfnodeclient的ClusterRole。
· system:monitoring:绑定了名为system:monitoring的ClusterRole。
·system:bootstrappers:kubeadm:default-node-token
执行如下命令然后查看Groups列即可查看K8s默认创建的Group。
kubectl get clusterrolebinding -A -o widekubectl get rolebinding -A -o wide
2
HTTPS证书认证
K8s需要PKI(public key infrastructure,公钥基础设施)证书来基于TLS的安全的认证。如果是使用kubeadm来初始化的集群,则kubeadm会帮助你自动生成集群所需要的各类证书。kubeadm会将证书放置在/etc/kubernetes/pki目录下,而包含管理员证书的配置文件admin.conf会放置到/etc/kubernetes目录下。
k8s使用x509证书中CN(Common Name)以及O(Organization)字段对应k8s中的user和group,将Authentication和RBAC Authorization结合到了一起,巧妙地将Control Plane中的各个核心User和Group、与操作权限(ClusterRole)进行了集群绑定(ClusterRoleBinding)。
3
HTTP Bear Token认证
这种认证采用的数据结构是由JWT Token类型的,一般的形式是在HTTP Authroziation头部添加Bear Token,每个Bearer Token都对应一个用户名。客户端发起API调用请求时,API Server就能识别用户身份了。比如pod所对应的Service Account采用的就是这种形式,Token采用的是RS256非对称加密算法进行加密。
#使用Bear Token进行认证kubectl --insecure-skip-tls-verify -s https://172.16.200.70:6443 --token="xxxx" get cs
#使用Bear Token进行认证curl --header "Authorization: Token" -X GET https://172.16.200.70:6443/api -k
1
RBAC授权
基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对计算机或网络资源的访问的方法。RBAC 鉴权机制使用 rbac.authorization.k8s.io API 组来驱动鉴权决定, 允许你通过 K8s API 动态配置策略。RBAC在K8s 1.8版本时升级为GA稳定版本,并作为kubeadm安装方式下的默认授权选项。
RBAC具有如下优势:
对集群中的资源和非资源权限均有完整的覆盖。
RBAC的权限配置通过几个API对象即可完成,同其他API对象一样,可以用kubectl或API进行操作。
可以在运行时进行调整,无须重新启动API Server。
在RBAC授权中,有如下概念:
subject主体
· User
· Group
· ServiceAccount
角色
· Role:授予特定命名空间的访问权限
· ClusterRole:授予集群的访问权限
角色绑定
· RoleBinding:将特定命名空间的角色绑定到subject主体
· ClusterRoleBinding:将集群角色绑定到subject主体
资源:也就是K8s中的各种资源对象,如pod、service、secret等。
最后就是将主体与角色进行绑定,以获得特定的权限,如下图所示:
在RBAC管理体系中,K8s引入了4个资源对象:Role、ClusterRole、RoleBinding和ClusterRoleBinding。同其他API资源对象一样,用户可以使用kubectl或者API调用等方式操作这些资源对象。
1
Role和ClusterRole
Role 或 ClusterRole 中包含一组代表相关权限的规则,这些规则设置的权限都是许可形式的,不可以设置拒绝形式的规则。Role设置的权限将会局限于命名空间范围内,在你创建 Role 时,你必须指定该 Role 所属的名字空间。如果需要在集群级别设置权限,就需要使用ClusterRole了。
Role示例
以下是一个Role的yaml定义:
kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata: namespace: test name: test-rolerules:- apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch", "delete"]
上述定义的Role的name是test-role,这个Role的权限是可以对所有apiGroups下面的资源名为“pods”的资源进行get、list、watch和delete的操作。但是需要注意的是限定在test的命名空间范围内。
Role资源对象主要通过rules字段来描述它的功能,rules字段是rule的列表,每个rule是一组作用于不同apiGroup资源上的一组操作的集合,每一个rule包含如下几个关键字段:
· apiGroups:api组,比如当我们使用kubectl api-resources来查询集群所支持的api资源时,会发现如“apps/v1”这样的vesion,它的结构是apiVersion: $GROUP_NAME/$VERSION,所以,这里的api组就是apps。
· resouces:和Role绑定的资源名称,如node、pod、secret等资源对象。
· verbs:和Role绑定的动作,比如get、list、watch、delete、update、create、patch等。
ClusterRole示例
从命名上来看,ClusterRole的处理范围要比Role大,因为Role的范围是namespace,而ClusterRole的范围是Cluster。
ClusterRole主要适用以下场景:
· 对集群范围内资源的授权,例如Node。
· 对非资源型的授权,例如healthz。
· 对包含全部namespace资源的授权,例如pods(用于kubectl get pods -A这样的操作授权)。
· 对某个命名空间中多种权限的一次性授权。
下面是一个ClusterRole的yaml定义:
kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata: name: test-ClusterRolerules:- apiGroups: [""] resources: ["secrets"] verbs: ["get", "list", "watch"]
上述ClusterRole定义的是一个name为test-ClusterRole,拥有对所有apiGroup下的资源类型为secrets的资源进行get、list、watch的操作,并且他没有限定namespace。
Role和ClusterRole的rules可配置参数
apiGroups
"","apps", "autoscaling", "batch"
resources
"services", "endpoints", "pods","secrets","configmaps","crontabs","deployments","jobs","nodes","rolebindings","clusterroles","daemonsets","replicasets","statefulsets","horizontalpodautoscalers","replicationcontrollers","cronjobs"
verbs
"get", "list", "watch", "create", "update", "patch", "delete", "exec"
2
RoleBinding和
ClusterRoleBinding
角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组用户。 它包含若干主体(用户、组或服务账户)的列表和对这些主体所获得的角色的引用。 RoleBinding 在指定的名字空间中执行授权,而 ClusterRoleBinding 在集群范围执行授权。
RoleBinding示例
一个RoleBinding可以引用同一命名空间中的任何Role,也可以引用ClusterRole并将该ClusterRole绑定到RoleBinding所在的名字空间。
下面这个RoleBingding的例子是将上面我们定义的test-role与用户test进行绑定,作用的命名空间为test。
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: test-rolebinding namespace: test labels: roleBinding: test-rolebinding annotation:subjects:- kind: User name: test apiGroup: rbac.authorization.k8s.ioroleRef: kind: Role name: test-role apiGroup: rbac.authorization.k8s.io
RoleBinding有两个比较重要的根节点,一个是subjects,描述了需要绑定的主体,有user、group和service account;另一个是roleRef,描述了要绑定的Role。
RoleBinding本身会被namespace所影响,用于某个namespace内的授权,如果它与Role进行绑定,就需要保持一致的namespace;
RoleBinding除了能够和Role绑定,也能和ClusterRole绑定,这个操作的含义是:对目标主体在其所在的命名空间授予在ClusterRole中定义的权限。如下将集群角色test-ClusterRole与用户test进行绑定,虽然test-ClusterRole是一个集群角色,但因为RoleBinding的作用范围为命名空间test,所以用户test只能读取命名空间test中的secret资源对象,而不能读取其他命名空间中的secret资源对象。
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: rolebinding-with-clusterole namespace: testsubjects:- kind: User name: test apiGroup: rbac.authorization.k8s.ioroleRef: kind: ClusterRole name: test-ClusterRole apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding示例
ClusterRoleBinding用于进行集群级别或者对所有命名空间都生效的授权。下面的例子允许test组的用户读取任意命名空间中的secret资源对象:
kubectl get clusterrolebinding -A -o widekubectl get rolebinding -A -o wide0
在集群角色绑定(ClusterRoleBinding)中引用的角色只能是集群级别的角色(ClusterRole),而不能是命名空间级别的Role。
一旦通过创建RoleBinding或ClusterRoleBinding与某个Role或ClusterRole完成了绑定,用户就无法修改与之绑定的Role或ClusterRole了。只有删除了RoleBinding或ClusterRoleBinding,才能修改Role或ClusterRole。Kubernetes限制roleRef字段中的内容不可更改,主要有以下两个原因。
· 从逻辑上来说,与一个新的Role进行绑定实际上是一次全新的授权操作。通过删除或重建的方式更改绑定的Role,可以确保给主体授予新角色的权限(而不是在不验证所有现有主体的情况下去修改roleRef)。
· 使roleRef不变,可以授予某个用户对现有绑定对象(Bindingobject)的更新(update)权限,以便其管理授权主体(subject),同时禁止更改角色中的权限设置。
2
Node授权
Node授权策略用于对kubelet发出的请求进行访问控制,与用户的应用授权无关,属于K8s自身安全的增强功能。简单来说,就是限制每个Node只访问它自身运行的Pod及相关的Service、Endpoints等信息;也只能受限于修改自身Node的一些信息,比如Label;也不能操作其他Node上的资源。而之前用RBAC这种通用权限模型其实并不能满足Node这种特殊的安全要求,所以将其剥离出来定义为新的Node授权策略。Node授权可以与NodeRestriction准入控制插件相结合使用来进行Node隔离。
Node授权器允许kubelet执行的API操作包括:
读取:
· services
· endpoints
· nodes
· pods
· 与绑定到 kubelet 节点的 Pod 相关的 Secret、ConfigMap、PersistentVolumeClaim 和持久卷
写入:
· Node和Node状态(启用NodeRestriction准入插件限制kubelet仅修改当前的Node)
· Pod和Pod状态(启用NodeRestriction准入插件限制kubelet仅修改与当前绑定的pod)
· 事件
身份认证与鉴权相关的操作:
· 对于基于 TLS 的启动引导过程时使用的 certificationsigningrequests API 的读/写权限
· 为委派的身份验证/鉴权检查创建 TokenReview 和 SubjectAccessReview 的能力
在K8s 1.6中,使用RBAC授权模式时,system:node群集角色(role)自动绑定到该system:nodes组。
在K8s 1.7中,由于Node授权器实现了相同的目的,因此不再支持system:nodes组与system:node角色的自动绑定,从而有利于对secret 和configmap访问的附加限制。
在K8s 1.8中,将不会创建binding。
使用RBAC时,将继续创建system:node集群角色,以便兼容使用deployment将其他users或groups绑定到集群角色的方法。
三
准入控制Admission Control
如果想关闭准入控制器的话,可以使用disable-admission-plugins 参数标志,该参数会将传入的(以逗号分隔的) 准入控制插件列表禁用,即使是默认启用的插件也会被禁用。
如下,下面的参数标准禁用 PodNodeSelector 和 AlwaysDeny准入控制插件。
kubectl get clusterrolebinding -A -o widekubectl get rolebinding -A -o wide1
除了静态编译的Admission插件,也可以通过Webhook方式对接外部的AdmissionWebhook服务,实现与Admission插件一样的功能。但Webhook方式更加灵活,能够在API Server运行时修改和配置动态更新控制策略。
不过,相对于Admission Control插件来说,使用Admission Webhook要复杂得多,除了需要开发一个Admission Webhook Server实现HTTP回调的逻辑,还需要创建一个对应的ValidatingWebhookConfiguration资源对象配置文件,如果Admission Webhook需要与API Server进行认证,则还需要创建对应的AdmissionConfiguration配置文件。
1
NodeRestriction准入控制器
该准入控制器插件限制了kubelet 可以修改的 Node 和 Pod 对象。 为了受到这个准入控制器的限制,kubelet 必须使用在 system:nodes 组中的凭证, 并使用 system:node: 形式的用户名。 这样,kubelet 只可修改自己的 Node API 对象,只能修改绑定到自身节点的 Pod 对象。
并且该准入控制器插件不允许 kubelet 更新或删除 Node API 对象的污点。
NodeRestriction 准入控制器插件可防止 kubelet 删除其 Node API 对象, 并对前缀为 kubernetes.io/ 或 k8s.io/ 的标签的修改对 kubelet 作如下限制:
· 禁止 kubelet 添加、删除或更新前缀为 node-restriction.kubernetes.io/ 的标签。 这类前缀的标签时保留给管理员的,用以为 Node 对象设置标签以隔离工作负载,而不允许 kubelet 修改带有该前缀的标签。
· 允许 kubelet 添加、删除、更新以下标签:
kubernetes.io/hostname
kubernetes.io/arch
kubernetes.io/os
beta.kubernetes.io/instance-type
node.kubernetes.io/instance-type
failure-domain.beta.kubernetes.io/region (已弃用)
failure-domain.beta.kubernetes.io/zone (已弃用)
topology.kubernetes.io/region
topology.kubernetes.io/zone
kubelet.kubernetes.io/ 为前缀的标签
node.kubernetes.io/ 为前缀的标签
以 kubernetes.io 或 k8s.io 为前缀的所有其他标签都限制 kubelet 使用,并且将来可能会被 NodeRestriction 准入插件允许或禁止。将来的版本可能会增加其他限制,以确保 kubelet 具有正常运行所需的最小权限集。
2
Service Account准入控制器
Service Account准入控制器实现了ServiceAccount 的自动化,如果你打算使用 K8s 的 ServiceAccount 对象,强烈推荐为 K8s 项目启用此准入控制器。
Service Account 准入控制器的工作相对简单,它会监听Service Account和Namespace这两种资源对象的事件,如果在一个Namespace中没有默认的Service Account,那么它会为该Namespace创建一个默认的ServiceAccount对象,这就是在每个Namespace下都有一个名为default的Service Account的原因。
针对Pod新增或修改的请求,Service Account准入控制器会验证Pod里的Service Account是否合法,并做出如下控制操作:
· 如果Pod的spec.ServiceAccount没有被设置,则Service Account 准入控制器将为其添加名称为default的ServiceAccout。
· 如果Pod的spec.ServiceAccount指定了不存在的Service Account,则该Pod操作会被拒绝。
·如果服务账号的 automountServiceAccountToken 字段或 Pod 的automountServiceAccountToken 字段都未显式设置为 false:
· 准入控制器变更新来的 Pod,添加一个包含 API 访问令牌的额外卷。
· 准入控制器将 volumeMount 添加到 Pod 中的每个容器, 忽略已为 /var/run/secrets/kubernetes.io/serviceaccount路径定义的卷挂载的所有容器。 对于 Linux 容器,此卷挂载在 /var/run/secrets/kubernetes.io/serviceaccount; 在 Windows 节点上,此卷挂载在等价的路径上。
· 如果新来 Pod 的规约已包含任何 imagePullSecrets,则准入控制器添加 imagePullSecrets, 并从 ServiceAccount 进行复制。
在K8s 1.6版本以后,我们可以禁止自动创建ServiceAccount对应的Secret了,在ServiceAccount的yaml文件中增加automountServiceAccountToken:false属性即可,同时可以在某个Pod的yaml文件中增加此属性,以实现同样的效果。
3
Token准入控制器
Token准入控制器作为 kube-controller-manager 的一部分运行,以异步的形式工作。
其职责包括:
· 监测 ServiceAccount 的删除并删除所有相应的服务账号令牌 Secret。
· 监测服务账号令牌 Secret 的添加,保证相应的 ServiceAccount 存在。如果发现在新建的Service Account里没有对应的Secret,则会用私钥文件(--service-account-private-key-file参数标志指定的文件,默认为/etc/kubernetes/pki/sa.key)签名生成一个Token,并用该Token、API Server的CA证书(/etc/kubernetes/pki/ca.crt)等信息生成一个secret对象,然后放入刚才的Service Account中。而/etc/kubernetes/pki/sa.pub公钥文件用于API Server在身份认证过程中校验Token。
· 监测服务账号令牌 Secret 的删除,如有需要,从相应的 ServiceAccount 中删除Secret,确保与对应的Service Account的关联关系正确。
非常感谢您读到现在,由于作者的水平有限,编写时间仓促,文章中难免会出现一些错误或者描述不准确的地方,恳请各位师傅们批评指正。
如果你想一起学习内网渗透、域渗透、云安全、红队攻防的话,可以加入下面的知识星球一起学习交流。
参考:
用户认证:
https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/authentication/
使用 RBAC 鉴权:
https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/rbac/#core-component-roles
使用 Node 鉴权:
https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/node/
kubernetes集群安全机制:
https://zhuanlan.zhihu.com/p/468010077
Kubernetes 集群权限管理RBAC:
https://blog.csdn.net/qq_34556414/article/details/112909522
Kubernetes 中的用户与身份认证授权:
https://www.kancloud.cn/chriswenwu/g_k8s/1006520
- END -
还没有评论,来说两句吧...