K8S学习之用户认证及鉴权
用户认证
名词解释
-
RBAC
RBAC只是Kubernetes中安全认证的一种方式,基于角色访问控制(RBAC)子系统会确定用户是否有权针对某资源执行特定的操作。
-
匿名用户
集群内外的每个进程在向 API 服务器发起 请求时都必须通过身份认证,否则会被视作匿名用户。
这里的进程可以是在某工作站上 输入 kubectl 命令的操作人员,也可以是节点上的 kubelet 组件,还可以是控制面 的成员。
-
Service Account
服务帐号,通过Kubernetes API 来管理的一些用户帐号,和 namespace 进行关联的,适用于集群内部运行的应用程序,需要通过 API 来完成权限认证,所以在集群内部进行权限操作,我们都需要使用到 ServiceAccount。
-
ClusterRoleBinding
集群角色绑定,简单来说就是把声明的 Subject 和我们的 Role 进行绑定的过程(给某个用户绑定上操作的权限),ClusterRoleBinding 会影响到所有的 namespace。
身份认证策略
-
认证方式
Kubernetes 使用身份认证插件利用客户端证书、持有者令牌(Bearer Token)、身份认证代理(Proxy) 或者 HTTP 基本认证机制来认证 API 请求的身份。
-
至少两种身份认证方法
-
针对服务账号使用服务账号令牌
-
至少另外一种方法对用户的身份进行认证
当集群中启用了多个身份认证模块时,第一个成功地对请求完成身份认证的模块会 直接做出评估决定。API 服务器并不保证身份认证模块的运行顺序。
-
服务账号令牌
-
内容介绍
服务账号(Service Account)是一种自动被启用的用户认证机制,使用经过签名的持有者令牌来验证请求。该插件可接受两个可选参数:
–service-account-key-file 一个包含用来为持有者令牌签名的 PEM 编码密钥。 若未指定,则使用 API 服务器的 TLS 私钥。
–service-account-lookup 如果启用,则从 API 删除的令牌会被回收。
-
关联方式
服务账号通常由 API 服务器自动创建并通过 ServiceAccount 准入控制器 关联到集群中运行的 Pod 上。持有者令牌会挂载到 Pod 中可预知的位置,允许集群内进程与 API 服务器通信。 服务账号也可以使用 Pod 规约的 serviceAccountName 字段显式地关联到 Pod 上。
注意事项: serviceAccountName 通常会被忽略,因为关联关系是自动建立的
-
常用命令
# 创建服务账户(此命令会在当前的名称空间中生成一个 服务账号和一个与之关联的 Secret) kubectl create serviceaccount 服务账户名称 # 查看服务账户信息 kubectl get serviceaccounts 服务账户名称 -n 命名空间 -o yaml # 查看创建的Secret ## 所创建的 Secret 中会保存 API 服务器的公开的 CA 证书和一个已签名的 JSON Web 令牌(JWT)。 ## 说明: 字段值是按 Base64 编码的,这是因为 Secret 数据总是采用 Base64 编码来存储。 kubectl get secret secret名称 -n 命名空间 -o yaml
-
使用说明
已签名的 JWT 可以用作持有者令牌,并将被认证为所给的服务账号。通常,这些 Secret 数据会被挂载到 Pod 中以便集群内访问 API 服务器时使用, 不过也可以在集群外部使用。
注意实现:由于服务账号令牌保存在 Secret 对象中,任何能够读取这些 Secret 的用户 都可以被认证为对应的服务账号。在为用户授予访问服务账号的权限时,以及对 Secret 的读权限时,要格外小心。
OpenID Connect(OIDC)令牌
-
内容介绍
协议对 OAuth2 的主要扩充体现在有一个附加字段会和访问令牌一起返回, 这一字段称作 ID Token(ID 令牌)。 ID 令牌是一种由服务器签名的 JSON Web 令牌(JWT),其中包含一些可预知的字段, 例如用户的邮箱地址。
要识别用户,身份认证组件使用 OAuth2 令牌响应 中的 id_token(而非 access_token)作为持有者令牌。
-
kubectl执行流程图
-
登录到你的身份服务(Identity Provider)
-
你的身份服务将为你提供 access_token、id_token 和 refresh_token
-
在使用 kubectl 时,将 id_token 设置为 --token 标志值,或者将其直接添加到 kubeconfig 中
-
kubectl 将你的 id_token 放到一个称作 Authorization 的头部,发送给 API 服务器
-
API 服务器将负责通过检查配置中引用的证书来确认 JWT 的签名是合法的
-
检查确认 id_token 尚未过期
-
确认用户有权限执行操作
-
鉴权成功之后,API 服务器向 kubectl 返回响应
-
kubectl 向用户提供反馈信息
-
创建一个可以访问所有 namespace 的ServiceAccount
-
内容介绍
创建一个新的 ServiceAccount,需要他操作的权限作用于所有的 namespace,这个时候我们就需要使用到 ClusterRole 和 ClusterRoleBinding 这两种资源对象了。
新建 ServiceAccount 对象
-
k8s-monitor.yaml样例文件
apiVersion: v1 kind: ServiceAccount metadata: name: k8s-monitor namespace: k8s-test
-
常用命令
# 创建ServiceAccount kubectl create -f k8s-monitor.yaml
新建 ClusterRole 对象
- k8s-admin.yaml样例文件
# 下面示例中的 ClusterRole 定义可用于授予用户对某一特定命名空间,或者所有命名空间中的 secret(取决于其 绑定 方式)的管理权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
cattle.io/creator: nbsp-admin
name: k8s-admin
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
- nonResourceURLs:
- '*'
verbs:
- '*'
新建 ClusterRoleBinding 对象
-
内容介绍
我们没有为这个资源对象声明 namespace,因为这是一个 ClusterRoleBinding 资源对象,是作用于整个集群的。
这里我们新建了一个 ClusterRole 对象,也可以不单独新建,而是使用的 cluster-admin 这个对象,这是Kubernetes集群内置的 ClusterRole 对象
cluster-admin 这个集群角色是拥有最高权限的集群角色,所以一般需要谨慎使用该集群角色。
-
k8s-admin-bindings-k8s-monitor.yaml样例文件
# 下面示例中定义的 ClusterRoleBinding 对象在所有命名空间中将 “k8s-admin” 角色授予 k8s-test 命名空间下的服务账户(Service Accounts)k8s-monitor。
# 允许在 k8s-test 命名空间下的服务账户(Service Accounts)中的 k8s-monitor 用户 可以读取集群中任何命名空间中的 secret
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: k8s-admin-bindings-k8s-monitor
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: k8s-admin
subjects:
- kind: ServiceAccount # 角色绑定主体可以是用户组(Group)、用户(User)或者服务账户(Service Accounts)
name: k8s-monitor
namespace: k8s-test # k8s-test 命名空间中的 k8s-monitor 服务账户
- 常用命令
# 查看系统内置的一些集群角色
kubectl get clusterrole
# 查看系统内置的集群角色绑定
kubectl get clusterrolebinding
# 创建ClusterRoleBinding对象
kubectl create -f k8s-admin-bindings-k8s-monitor.yaml
验证登录Dashboard
-
内容介绍
创建完成后同样使用 ServiceAccount 对应的 token 去登录 Dashboard 验证下
-
常用命令
# 获取secret kubectl get secret -n k8s-test | grep k8s-monitor k8s-monitor-token-dg56n kubernetes.io/service-account-token 3 47m # 获取对应base64后的字符串 kubectl get secret k8s-monitor-token-dg56n -o jsonpath={.data.token} -n k8s-test | base64 -d ## 会生成一串很长的base64后的字符串 eyJhbGciOiJSUzI1NiIsImtpZCI6ImdmYTFEaEZPZXE4QnpoeXdkTHEtLW9fMWlrNGVqaXQwZGJzWUtucG1YUEUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrOHMtdGVzdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJiamNhLWs4cy1tb25pdG9yLXRva2VuLWRnNTZuIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImJqY2EtazhzLW1vbml0b3IiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJlZmJkY2RlNi01ODE0LTQwNWUtODljMi03MzRjNGYwY2Q1YjEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6azhzLXRlc3Q6YmpjYS1rOHMtbW9uaXRvciJ9.kl0tuYHxdDQRkVIVCafFt6M-5xs-Zbr1WdTqcjUIeOrP0TnXJwJYRLT04MuViDowff2AyIQWseAriSyHs5SDnrqnFZD9ziaaeVlEjxPsbKQoVKowq639dR8mTGo4-WndN56CXTJbKMmBQcejDKdETQklLJ0INKWGS0fboYokzWNtlPzdh904D3M20GBYxwu8FiRufEoOY7CipdYCxIVwXPYP_eCcEY-xkvcFnDoQ253TvMZoKpu48Ll-88UEGpC0wvFucvfp3Bk9jqohFPlEhSo_r6qg-Izf8Mfksyki_A62BNPhf2VmqY7FVnM5LukHlRDZMjnhg8z3OBrP3RhwEA
鉴权
-
概述
在 Kubernetes 中,你必须在鉴权(授予访问权限)之前进行身份验证(登录)。
Kubernetes 期望请求中存在 REST API 常见的属性。 这意味着 Kubernetes 鉴权适用于现有的组织范围或云提供商范围的访问控制系统, 除了 Kubernetes API 之外,它还可以处理其他 API。
参考链接
-
用户认证
https://kubernetes.io/zh/docs/reference/access-authn-authz/authentication/
-
鉴权概述
https://kubernetes.io/zh/docs/reference/access-authn-authz/authorization/
-
使用 RBAC 鉴权
https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/
-
Kubernetes RBAC 详解
https://www.qikqiak.com/post/use-rbac-in-k8s/