K8S学习之用户认证及鉴权

  • 用户认证
  • 名词解释
  • 身份认证策略
  • 服务账号令牌
  • OpenID Connect(OIDC)令牌
  • 创建一个可以访问所有 namespace 的ServiceAccount
  • 新建 ServiceAccount 对象
  • 新建 ClusterRole 对象
  • 新建 ClusterRoleBinding 对象
  • 验证登录Dashboard
  • 鉴权
  • 参考链接


用户认证

名词解释

  • 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 请求的身份。
  • 至少两种身份认证方法
  1. 针对服务账号使用服务账号令牌
  2. 至少另外一种方法对用户的身份进行认证

当集群中启用了多个身份认证模块时,第一个成功地对请求完成身份认证的模块会 直接做出评估决定。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执行流程图
  1. 登录到你的身份服务(Identity Provider)
  2. 你的身份服务将为你提供 access_token、id_token 和 refresh_token
  3. 在使用 kubectl 时,将 id_token 设置为 --token 标志值,或者将其直接添加到 kubeconfig 中
  4. kubectl 将你的 id_token 放到一个称作 Authorization 的头部,发送给 API 服务器
  5. API 服务器将负责通过检查配置中引用的证书来确认 JWT 的签名是合法的
  6. 检查确认 id_token 尚未过期
  7. 确认用户有权限执行操作
  8. 鉴权成功之后,API 服务器向 kubectl 返回响应
  9. 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。

参考链接