美文网首页
kubernetes 权限控制篇

kubernetes 权限控制篇

作者: 一瓶多先生 | 来源:发表于2020-10-27 12:04 被阅读0次

    kubernets集群中使用了多种的认证方式, 涉及到的关键词有:api-server,认证,授权,准入控制,RBAC,Service Account,客户端证书认证,Kubernetes 用户,Token 认证等等。

    因为集群中所有的组件全部使用HTTP RESTFUL与kube-apiserver进行通信, 所有的client与kube-apiserver通信的过程中都会经过:

    • 认证: 检查用户是否合法
    • 授权: 检查请求的行为是否具有权限
    • 准入机制: 检查请求的内容是否符合k8s的规范或要求
    + - - - - - - - - - - +     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
    ' Client              '     ' kube-apiserver                                                     '
    '                     '     '                                                                    '
    ' +-----------------+ '     ' +----------------+     +---------------+     +-------------------+ '     +------+
    ' |      User       | ' --> ' | Authentication | --> | Authorization | --> | Admission Control | ' --> | etcd |
    ' +-----------------+ '     ' +----------------+     +---------------+     +-------------------+ '     +------+
    '                     '     '                                                                    '
    '                     '     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
    ' +-----------------+ '
    ' | service-account | '
    ' +-----------------+ '
    '                     '
    + - - - - - - - - - - +
    

    Authentication

    认证阶段的工作是识别用户身份,支持的认证方式有很多,比如:HTTP Base,HTTP token,TLS,Service Account,OpenID Connect 等,API Server 启动时可以同时指定多种认证方式,会逐个使用这些方法对客户请求认证,只要通过任意一种认证方式,API Server 就会认为 Authentication 成功。

    kubernetes中的用户有两种:

    • service-account
    • 普通用户

    要特别说的是普通用户在k8s中没有具体的api管理用户都是通过外部方式进行管理

    认证方式:

    • X509 Client Certs: 客户端证书模式需要在 kubectl 命令中加入 --client-ca-file=<SOMEFILE> 参数,指明证书所在位置。这是k8s默认的方式
    • bearer tokens: 在 HTTP 请求头中加入 Authorization: Bearer <TOKEN>。 主要适用JWT的认证方式
    - Bootstrap Tokens: 与 bearer tokens 一致,但 TOKEN 格式为 [a-z0-9]{6}.[a-z0-9]{16}。该方式称为 dynamically-managed Bearer token,以 secret 的方式保存在 kube-system namespace 中,可以被动态的创建和管理。同时,启用这种方式还需要在 APIServer 中打开 --enable-bootstrap-token-auth。
    
    - Basic Token认证方式, 通过--token-auth-file=<SOMEFILE> 参数指明 bearer tokens 所在位置。
    
    - Service Account Tokens: 该方式通常被 pod 所使用,在 PodSpec 中指明 ServiceAccount 来访问 ApiServer。
    
    - OpenID Connect Tokens
    
    - Webhook Token Authentication
    
    • Basic auth: 以参数 --basic-auth-file=<SOMEFILE> 指明 basic auth file 的位置。这个 basic auth file 以 csv 文件的形式存在,里面至少包含三个信息:password、username、user id,同时该模式在使用时需要在请求头中加入 Authorization: Basic BASE64ENCODED(USER:PASSWORD) 。

    01.X509证书认证

    建立完整TLS加密通信,需要有一个CA认证机构,会向客户端下发根证书、服务端证书以及签名私钥给客户端。ca.pem & ca-key.pem & ca.csr组成了一个自签名的CA机构。

    我们把这种方式也称之为双向认证, 在所有的认证中也是最严格的认证。 需要kube-apiserver启动时指定:

    • client-ca-file: 指定CA根证书文件为/etc/kubernetes/pki/ca.pem,内置CA公钥用于验证某证书是否是CA签发的证书
    • tls-private-key-file: 指定ApiServer私钥文件为/etc/kubernetes/pki/apiserver-key.pem
    • tls-cert-file:指定ApiServer证书文件为/etc/kubernetes/pki/apiserver.pem

    0101.kubeconfig文件详解

    其中client-ca-file中指定的CA根证书会在类似kube-controller-manager的组件通信时验证证书是否为该CA根证书签发, 目前组件访问kube-apiserver主要是通过kubeconfig的方式, kubeconfig的文件中包含根CA、根CA签发的证书的公钥和私钥, 我们以kube-scheduler的kubeconfig为例进行说明, 下面为kube-scheduler.kubeconfig

    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority-data: CA证书的base64格式
        server: https://apiserver-p001.svc.gxd88.cn:6443
      name: kubernetes
    contexts:
    - context:
        cluster: kubernetes
        user: system:kube-scheduler
      name: default
    current-context: default
    kind: Config
    preferences: {}
    users:
    - name: system:kube-scheduler
      user:
        client-certificate-data: CA证书签发的证书公钥
        client-key-data:  CA证书签发证书私钥
    

    可以看出文件分为三大部分:clusters、contexts、users

    • clusters 部分
      定义集群信息,包括 api-server 地址certificate-authority-data, 其中certificate-authority-data用于服务端证书认证的自签名 CA 根证书

    • contexts 部分
      集群信息和用户的绑定,kubectl 通过上下文提供的信息连接集群。

    • users 部分
      多种用户类型,默认是客户端证书(x.509 标准的证书)和证书私钥,也可以是 ServiceAccount Token。这里重点说下前者:

      • client-certificate-data: base64 加密后的客户端证书;
      • client-key-data: base64 加密后的证书私钥;

    一个请求在通过 api-server 的认证后,api-server 会从收到客户端证书中取用户信息,然后用于后面的授权,这里所说的用户并不是服务账号,而是客户端证书里面的 Subject 信息:O 代表用户组,CN 代表用户名。

    每个组件对应的CN和O

    组件 Common Name Organization
    Kube-apiserver kubernetes
    kube-scheduler System:kube-scheduler
    Kube-controller-manager system:kube-controller-manager
    Kubelet System:node:${node_name} system:nodes
    Kube-proxy system:kube-proxy
    kubectl admin

    0102.双向认证的流程

    当组件kube-scheduler访问kube-apiserver时是双向认证, 流程如下

    1. kube-scheduler发送请求到kube-apiserver
    2. kube-apiserver将tls-cert-file配置的公钥发送给kube-scheduler
    3. kube-scheduler使用kubeconfig中的certificate-authority-data验证证书是否合法
    4. 如果证书合法kube-scheduler发送kubeconfig中的client-certificate-data给kube-apiserver
    5. kube-apiserver使用client-ca-file验证证书是否合法
    6. 如果证书全部合法可以进行通信
        3.使用certificate-authority-data验证证书                              5.client-ca-file验证证书
      +------------------------------------+                              +----------------------+
      v                                    |                              v                      |
    +----------------------------------------+  1.HTTPS Request           +--------------------------+
    |                                        | -------------------------> |                          |
    |                                        |                            |                          |
    |                                        |  2.tls-cert-file           |                          |
    |                                        | <-------------------       |                          |
    |             kube-scheduler             |                            |      kube-apiserver      |
    |                                        |  4.client-certificate-data |                          |
    |                                        | ------------------->       |                          |
    |                                        |                            |                          |
    |                                        |  6.通信                     |                          |
    |                                        | <-------------------       |                          |
    +----------------------------------------+                            +--------------------------+
    

    02.Static Token File

    kube-apiserver启动时需要使用--token-auth-file=bootstrap-token.csv

    客户端请求的时候需要在http header中加入:”Authorization: Bearer THETOKEN”,如下实例:

    curl -k --header "Authorization: Bearer e5fc5f662ea596befbe5ababc731a5c3" https://127.0.0.1:6443/api
    {
      "kind": "APIVersions",
      "versions": [
        "v1"
      ],
      "serverAddressByClientCIDRs": [
        {
          "clientCIDR": "0.0.0.0/0",
          "serverAddress": "10.40.61.116:6443"
        }
      ]
    }
    

    或者使用kubectl:

    kubectl --server=https://127.0.0.1:6443 \
    --token=e5fc5f662ea596befbe5ababc731a5c3 \
    --insecure-skip-tls-verify=true \
    cluster-info
    

    03.Bootstrap Tokens认证

    Bootstrap Token 和 Static Token的区别是Bootstrap Token在 k8s 中动态的管理一种type为bootstrap token的token,这些token作为secret放在kube-system namespace中。controller-manager中的tokencleaner controller会在bootstrap token 过期时进行删除。

    生成Bootstrap Token:

    $ echo "$(head -c 6 /dev/urandom | md5sum | head -c 6)"."$(head -c 16 /dev/urandom | md5sum | head -c 16)"
    
    f455f5.db29ddb7b7d01ab9
    

    这个 f455f5.db29ddb7b7d01ab9 就是生成的 Bootstrap Token,保存好 token,因为后续要用;关于这个 token 解释如下:

    Token 必须满足 [a-z0-9]{6}.[a-z0-9]{16} 格式;以 . 分割,前面的部分被称作 Token ID,Token ID 并不是 “机密信息”,它可以暴露出去;相对的后面的部分称为 Token Secret,它应该是保密的

    创建 Bootstrap Token Secret:

    对于 Kubernetes 来说 Bootstrap Token Secret 也仅仅是一个特殊的 Secret 而已;对于这个特殊的 Secret 样例 yaml 配置如下:

    apiVersion: v1
    kind: Secret
    metadata:
      # Name MUST be of form "bootstrap-token-<token id>"
      name: bootstrap-token-07401b
      namespace: kube-system
    
    # Type MUST be 'bootstrap.kubernetes.io/token'
    type: bootstrap.kubernetes.io/token
    stringData:
      # Human readable description. Optional.
      description: "The default bootstrap token generated by 'kubeadm init'."
    
      # Token ID and secret. Required.
      token-id: f455f5
      token-secret: db29ddb7b7d01ab9
    
      # Expiration. Optional.
      expiration: 2200-01-01T00:00:11Z
    
      # Allowed usages.
      usage-bootstrap-authentication: "true"
      usage-bootstrap-signing: "true"
    
      # Extra groups to authenticate the token as. Must start with "system:bootstrappers:"
      auth-extra-groups: system:bootstrappers:worker,system:bootstrappers:ingress
      
    

    需要注意几点:

    作为 Bootstrap Token Secret 的 type 必须为 bootstrap.kubernetes.io/token,name 必须为 bootstrap-token-<token id> (Token ID 就是上一步创建的 Token 前一部分)
    usage-bootstrap-authentication、usage-bootstrap-signing 必须存才且设置为 true
    expiration 字段是可选的,如果设置则 Secret 到期后将由 Controller Manager 中的 tokencleaner 自动清理
    auth-extra-groups 也是可选的,令牌的扩展认证组,组必须以 system:bootstrappers: 开头
    最后使用kubectl create -f bootstrap.secret.yaml创建即可

    04.Service Account Tokens

    Service Account Token 是一种比较特殊的认证机制,适用于上文中提到的pod内部服务需要访问apiserver的认证情况,默认enabled。

    apiserver 的启动配置参数有--service-account-key-file=/srv/kubernetes/pki/service-account.pem,用于检验 ServiceAccount 的 token, 如果没有指明文件,默认使用–tls-private-key-file的值,即API Server的私钥。

    controller-manager的启动配置参数--service-account-private-key-file=/srv/kubernetes/pki/service-account-key.pem该文件是PEM 编码的 X509 RSA,用于签署 Service Account Token。

    特别说明:

    apiserver 和 controller-manager中指定的key可以是同一个文件, 可以直接使用如下命令生成

    openssl genrsa -out private.key 4096
    

    0401.资源说明

    service accout本身是作为一种资源在k8s集群中,我们可以通过命令行获取

    $ kubectl get serviceaccount --all-namespaces | grep default
    default           default                              1         8d
    kube-node-lease   default                              1         8d
    kube-public       default                              1         8d
    kube-system       default                              1         8d
    

    默认的情况下k8s会在集群中的所有namespace创建一个default的serviceaccount,并且这个serviceaccount关联一个default-token-xxxx这样的token

    查看serviceaccout和token的对应关系:

    kubectl get serviceaccount default -n kube-system   -o yaml
    apiVersion: v1
    imagePullSecrets:
    - name: wcr-secret
    kind: ServiceAccount
    metadata:
      creationTimestamp: "2018-06-19T09:03:28Z"
      name: default
      namespace: kube-system
      resourceVersion: "116579"
      selfLink: /api/v1/namespaces/kube-system/serviceaccounts/default
      uid: a1eec26f-739f-11e8-bd8f-00163e0ed17a
    secrets:
    - name: default
    - name: default-token-xl2hw
    

    查看default-token的具体内容:

    kubectl get secret  default-token-xl2hw -n kube-system   -o yaml
    apiVersion: v1
    data:
      ca.crt: xxxx
      namespace: xxxx
      token:xxxx
    kind: Secret
    metadata:
      creationTimestamp: "2018-06-19T09:03:28Z"
      name: default-token-xl2hw
      namespace: kube-system
      resourceVersion: "234"
      selfLink: /api/v1/namespaces/kube-system/secrets/default-token-xl2hw
      uid: a1f3334f-739f-11e8-bd8f-00163e0ed17a
    type: kubernetes.io/service-account-token
    

    可以看到default-token-xl2hw资源包含的数据有三部分:

    • ca.crt,这是API Server的CA公钥证书,用于Pod中的Process对API Server的服务端数字证书进行校验时使用的;

    • namespace,这是Secret所在namespace的值的base64编码:# echo -n “kube-system”|base64 => “a3ViZS1zeXN0ZW0=”

    • token:该token就是由service-account-key-file的值签署(sign)生成。

    这种认证方式主要由k8s集群自己管理,用户用到的情况比较少。我们创建一个pod时,默认就会将该namespace对应的默认service account token mount到Pod中,所以无需我们操作便可以直接与apiserver通信

    05.OpenID Connect Tokens

    如果集群需要根据用所属的部门或者职能进行权限划分最好使用OpenID的方式进行访问授权。

    相关文章

      网友评论

          本文标题:kubernetes 权限控制篇

          本文链接:https://www.haomeiwen.com/subject/whlpmktx.html