目录
认证Authentication
1.认证主体
(1) Service Account
(2)普通用户
1)K8s中内置的用户
(3)Anonymous
(4)K8s中的Group
1)K8s中内置的组
2.HTTPS证书认证
3.HTTP Bear Token认证
授权Authorization
1.RBAC授权
(1)Role和ClusterRole
1)Role示例
2)ClusterRole示例
3)Role和ClusterRole的rules可配置参数
(2)RoleBinding和ClusterRoleBinding
1)RoleBinding示例
2)ClusterRoleBinding示例
2.Node授权
准入控制Admission Control
1.NodeRestriction准入控制器
2.Service Account准入控制器
3.Token准入控制器
我们在请求API Server的时候,会经历哪些步骤呢?总得来说,有如下步骤:
· 认证(Authentication)是识别用户的过程,这个过程需要知道用户到底是谁;
· 而授权(Authorization)是识别已认证用户访问权限的过程,这个过程判断用户是否具有某些权限;
· 准入控制(Admission Control)是最后的关卡,它会在请求通过认证和鉴权之后、对象被持久化之前拦截到达 API 服务器的请求,其通过一组控制逻辑对对象的操作进行验证和变更等操作。
一.
认证Authentication
在认证方面,K8s提供了如下的认证方式:
HTTPS证书认证:
基于CA根证书签名的双向数字认证方式,比如k8s运维人员通过kubectl访问API Server或node节点上的kubelet进程与API Server进程交互都是使用的证书认证;kubectl默认的配置文件保存路径为~/.kube/config,而kubelet默认的配置文件保存路径为/etc/kubernetes/kubelet.conf。
HTTP Bear Token认证:
通过一个Bear Token识别合法用户,比如pod与API Server交互这种认证方式,pod以Service Account的身份去运行,一个Service Account对应着一个Secret,而Secret中保存着Bear Token,pod中Bear Token默认的保存路径为/var/run/secrets/kubernetes.io/serviceaccount/token,是jwt格式的字符串。
OpenID Connect Token第三方认证:
通过第三方OIDC协议进行认证。
Webhook Token认证:通过外部Webhook服务进行认证。
Authentication Proxy认证:通过认证代理进程序行认证。
在身份认证阶段,最重要的就是辨别用户的身份了,API Server需要从请求中获取有关于用户身份的信息。通常用户身份信息可以通过User或Group来定义,但是K8s中并没有相关的定义,所以无法通过API Server对User或Group进行管理。K8s认为User、Group这类信息由外部系统来管理,自己并不负责管理和设计,这样做的好处在于可以避免重复定义用户模型,更方便第三方用户权限平台进行对接。
当向API Server发送请求时,认证插件将以下属性与请求者相关联:
用户名:标识最终用户的字符串,在证书中也就是subject字段所对应的CN。
组:一组将用户和常规用户组相关联的字符串,在证书中也就是subject字段所对应的O。自 Kubernetes 1.4 开始,客户端证书还可以通过证书的 organization 字段标明用户的组成员信息。 要包含用户的多个组成员信息,可以在证书中包含多个 organization 字段。
UID:标识最终用户的字符串,比用户名更加一致且唯一。
额外字段:包含其他有用认证信息的字符串列表的映射。
所有的值对身份认证系统都是不透明的,并只有在由authorizer授权者解释时才具有重要意义。您可以一次性启用多种身份验证方式。通常使用至少两种认证方式。
当启用了多个认证模块时,第一个认证模块成功认证后将不会进行第二个模块的认证。API Server不会保证认证的顺序。
与其他身份验证协议(LDAP、SAML、Kerberos、x509 方案等)的集成可以使用身份验证代理或身份验证 webhook来实现。
1
认证主体
K8s集群中包含两类用户:
· 一类是由K8s管理的 Service Account;
· 另一类是普通用户。
为什么K8s中会有Service Account和普通用户这两种形式呢?因为与API Server服务交互实际上有两种类型东西,一种是真实的人类用户,另一类就是程序。因此,真实的人类用户对应的就是普通用户账号,而程序对应的就是Service Account了。
API Server请求被绑定到Service Account或普通用户上,或者作为匿名请求对待。这意味着集群内部或外部的每个进程,无论是在服务器上输入 kubectl 的用户、节点上的 kubelet或web控制面板的成员,都必须在向 API Server 发出请求时进行身份验证,否则被视为匿名用户。
1
Service Account
Service Account是由 K8s API管理的帐户,它不是给K8s集群的用户(系统管理员、运维人员、租户用户等)使用的,而是给运行在Pod里的进程用的,它为Pod里的进程提供了必要的身份证明。Service Account都绑定到了特定的 namespace,并由 API Server 自动创建或者通过 API 调用手动创建。一个Pod必须要以某一个Service Account的身份去运行,一个Service Account对应着一个Secret,一个Secret保存着一个Token和公钥文件,从而允许 pod 与API Server之间的调用。Secret从属于Service Account资源对象,属于Service Account的一部分,在一个Service Account对象里面可以包括多个不同的Secret对象,分别用于不同目的的认证活动。
我们进入pod中,查找/var/run/secrets/kubernetes.io/serviceaccount下的token文件,即可看到该pod对应服务账户的Token,该Token是jwt格式的字符串,如图所示:
那么,这个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 wide
kubectl 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 wide
kubectl 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
二
授权Authorization
当用户认证通过后,下一步就是授权操作了。API Server服务目前支持以下几种授权策略:
· AlwaysDeny:表示拒绝所有请求,一般用于测试。
· AlwaysAllow:允许接收所有请求。如果集群不需要授权流程,则可以采用该策略。但是为了安全,千万不要采用该策略!
·ABAC(Attribute-Based Access Control):基于属性的访问控制。表示使用用户配置的授权规则对用户请求进行匹配和控制,它是K8s 1.6之前的默认策略,现在已经被RBAC代替。
· RBAC(Role-Based Access Control):基于角色的访问控制,它是目前K8s默认的授权策略。如果RBAC仍然不满足某些特定需求,则用户还可以自行编写授权逻辑并通过Webhook方式注册为Kubernetes的授权服务,以实现更加复杂的授权规则。
· Node:是一种特殊授权模式,用于对kubelet发出的请求进行访问控制。
Webhook:通过调用外部REST服务对用户进行授权。
通过API Server的配置文件/etc/kubernetes/manifests/kube-apiserver.yaml的参数--authorization-mode可配置多种授权策略,用逗号分隔即可。在通常情况下,我们会设置授权策略为Node,RBAC,如图所示。API Server在收到请求后,会读取该请求中的数据,生成一个访问策略对象,然后API Server会将这个访问策略对象和配置的授权模式逐条进行匹配,第一个被满足或拒绝的授权策略决定了该请求的授权结果,如果匹配的结果是禁止访问,则API Server会终止API调用流程,并返回客户端的错误调用码。
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: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: test
name: test-role
rules:
- 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: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: test-ClusterRole
rules:
- 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/v1
kind: RoleBinding
metadata:
name: test-rolebinding
namespace: test
labels:
roleBinding: test-rolebinding
annotation:
subjects:
- kind: User
name: test
apiGroup: rbac.authorization.k8s.io
roleRef:
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/v1
kind: RoleBinding
metadata:
name: rolebinding-with-clusterole
namespace: test
subjects:
- kind: User
name: test
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: test-ClusterRole
apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding示例
ClusterRoleBinding用于进行集群级别或者对所有命名空间都生效的授权。下面的例子允许test组的用户读取任意命名空间中的secret资源对象:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: test-ClusterRoleBinding
subjects:
- kind: Group
name: test
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: test-ClusterRole
apiGroup: rbac.authorization.k8s.io
在集群角色绑定(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
客户端的请求通过认证Authentication和授权Authorization后,会进入到准入控制AdmissionControl关卡。准入控制可以执行验证Validating和变更Mutating等操作。准入控制器限制创建、删除、修改对象的请求,也可以阻止自定义动作,但是准入控制器不会也不能阻止get、watch、list对象的请求。
准入控制过程分为两个阶段。第一阶段,运行变更准入控制器。第二阶段,运行验证准入控制器。 某些准入控制器既可以是变更准入控制器又可以是验证准入控制器。如果两个阶段之一的任何一个控制器拒绝了某请求,则整个请求将立即被拒绝,并向最终用户返回错误。最后,除了对对象进行变更外,准入控制器还可能有其它的作用,比如将相关资源作为请求处理的一部分进行变更。 增加配额用量就是一个典型的示例,说明了这样做的必要性。 此类用法都需要相应的回收或回调过程,因为任一准入控制器都无法确定某个请求能否通过所有其它准入控制器。
那么可能很多人会问了,为什么需要准入控制呢?
原因在于K8s 的若干重要功能(如创建、删除等高危操作)都要求启用一个准入控制器,以便正确地支持该特性。 因此,没有正确配置准入控制器的 K8s API 服务器是不完整的,它无法支持你所期望的所有特性。
那么如何启用一个准入控制器呢?
在K8s 1.9及之前的版本中使用的参数是--admission-control,其中的内容是顺序相关的;在Kubernetes1.10及之后的版本中使用的参数是--enable-admission-plugins,该参数标志接受一个准入控制插件列表(以逗号分隔的), 这些准入控制插件会在集群修改对象之前被调用,发送给API Server的任何请求都需要通过列表中每个准入控制器的检查,检查与准入控制器的顺序无关。
如下,下面的参数标准启用 NodeRestriction、NamespaceLifecycle 和 LimitRanger 准入控制插件:
- --enable-admission-plugins=NodeRestriction,NamespaceLifecycle,LimitRanger
如果想关闭准入控制器的话,可以使用disable-admission-plugins 参数标志,该参数会将传入的(以逗号分隔的) 准入控制插件列表禁用,即使是默认启用的插件也会被禁用。
如下,下面的参数标准禁用 PodNodeSelector 和 AlwaysDeny准入控制插件。
--disable-admission-plugins=PodNodeSelector,AlwaysDeny ...
除了静态编译的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 -