k8s☞14认证授权

阅读量: zyh 2020-10-15 16:35:23
Categories: > Tags:

基础

流程介绍

这里是一个认证的一个基本流程:

image-20201016114248549

即: kubectl => 用户认证 => 用户授权 => 入口控制 -> 资源对象

用户认证:检查递交信息包含的证书,用户名。确定是否是正常用户。

用户授权:给用户授权权限策略,授权方式有多种:ABAC mode, RBAC Mode, and Webhook mode。确定是否有权限。

入口控制器:具有特殊功能的过滤器,他们会把请求拦截下来,如果请求违反了过滤器的配置,则请求会被拒绝。确定是否有更精细的粒度控制。

以上三阶段都是通过插件实现的。当某个阶段的某个插件授权通过后,就不会再需要此阶段的其它插件进行校验。

用户认证

令牌认证

kubectl 通过提交令牌给用户认证

TSL认证

kubectl 和 Api server 双向认证

username/password认证

一般不用这种方式

RBAC

https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/

RBAC授权是目前比较常见的方式。通过角色(规则体),用户(实体),用户绑定角色的方式,赋予用户权限。

通过kubeadm安装的集群,默认就是RBAC授权机制。

涉及到的基本对象:

角色

角色分两种,一种是命名空间级别的 Role,一种是集群级别的 ClusterRole。

用于授权对xxx资源有xxx操作权限。

# role
## https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/role-v1/
## 拥有 dev 命名空间里 "deployments", "replicasets", "pods" 资源的增删改查权限。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: dev
rules:
- apiGroups: ["", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # 也可以使用['*']
# clusterrole
## https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/cluster-role-v1/
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: filebeat
  labels:
    app: filebeat
rules:
- apiGroups: [""] # "" indicates the core API group
  resources:
  - namespaces
  - pods
  - nodes
  verbs:
  - get
  - watch
  - list

用户

从使用者角度来看的时候,k8s把用户分为普通用户服务用户。普通用户对外(也就是上图里的Human),服务用户对内(也就是上图里的Pod)。

💥请记住,k8s并没有普通用户的实体对象,也就是说通过kubectl get user是没有这个对象的。因此,只要你递交的用户拥有k8s集群内部CA所签发的证书,那么这个用户就会被rbac子系统认为是有效的。

普通用户

创建普通用户所需的证书

https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#normal-user

  1. 创建私钥key,通过私钥发起证书请求,生成请求文件csr

    创建私钥会让你填写一些属性,这里有两个属性特别重要,分别是属性CN(填写用户名)和属性O(填写用户组)

    例如创建用户zyh,群组it

    openssl genrsa -out zyh.key 2048
    openssl req -new -key zyh.key -out zyh.csr -subj "/CN=zyh/O=it"
    
  2. 构建k8s的 CertificateSigningRequest 证书请求对象

    • 先将 csr 文件进行base64编码
    RequestStr=`cat zyh.csr | base64 | tr -d "\n"`
    
    • 将编码后的内容写入 CertificateSigningRequest 对象的 request 字段
    cat <<EOF | kubectl apply -f -
    apiVersion: certificates.k8s.io/v1
    kind: CertificateSigningRequest
    metadata:
      name: zyh
    spec:
      groups:
      - system:authenticated
      request: ${RequestStr}
      signerName: kubernetes.io/kube-apiserver-client
      usages:
      - client auth
    EOF
    

    ⭐️usages字段必须是client auth

    ⭐️需要注意的是,证书签发默认只有1年有效期

    🌟确保当前 csr 没有重名申请

  3. 批准证书请求,并获取证书

    批准CertificateSigningRequest对象的证书请求:

    kubectl get csr
    kubectl certificate approve zyh
    

    获取批准后的颁发的证书:

    kubectl get csr zyh -o jsonpath='{.status.certificate}' | base64 --decode > zyh.crt
    

    ⭐️检查证书有效期:​openssl x509 -in zyh.crt -noout -dates

    至此,一个普通用户就创建完毕了。但是它没有任何权限,需要随后声明绑定对象,将角色和用户关联。

服务用户

流程

https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#service-account-automation

服务用户对象,即ServiceAccount。

例如,下面的SA对象通过imagePullSecrets附加了额外的secret授权信息myregistrykey,使得Pod可以拉取镜像。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: default
secrets:
- name: default-token-uudge # 这是默认服务账户的Token
imagePullSecrets:
- name: myregistrykey  # 这是Secret对象的key,存储着拉取镜像的用户密码

创建服务用户

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin
  namespace: kube-system
  labels:
    app: filebeat

创建完毕后,对应的 secret.namespace 会生成一个新的对象:<sa_name>-token-$RANDOM,用来进行资源对象的认证,请注意这里是认证,不是授权。也就是说通过了认证但没权限访问资源。

用户绑定角色

普通用户绑定

绑定创建。位于 dev 命名空间的 rolebinding 对象

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-rolebinding
  namespace: dev
subjects:
- kind: User
  name: zyh
  apiGroup: ""
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io  # 留空字符串也可以,则使用当前的apiGroup

通过上述创建过程,你可以发现用户创建和用户授权两个阶段是分离的。也就是说,你可以创建多个用户,然后用同一个角色绑定多个用户。

服务用户绑定

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: filebeat
subjects:
- kind: ServiceAccount
  name: filebeat
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: filebeat
  apiGroup: rbac.authorization.k8s.io

用户调用

普通用户

  1. 添加用户证书到kubectl配置

    kubectl config set-credentials zyh --client-key=zyh.key --client-certificate=zyh.crt --embed-certs=true
    
  2. 设置用户上下文,方便进行用户切换

    kubectl config set-context zyh --cluster=kubernetes --user=zyh
    

    –cluster 指定要访问集群的名称

  3. 通过用户上下文进行用户切换

    kubectl config use-context zyh
    

用户的有效期,取决于你证书的有效期。

  1. 测试权限

    kubectl get pod -n dev
    ===
    No resources found in developer namespace.
    
    kubectl get svc -n dev
    ===
    Error from server (Forbidden): services is forbidden: User "zyh" cannot list resource "services" in API group "" in the namespace "developer"
    

服务用户

Pod通过spec.serviceAccountName显式指定一个SA

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: k8s-pod-logs
  namespace: kube-system
spec:
  selector:
    matchLabels:
      project: k8s-pod-logs
      app: filebeat
  template:
    metadata:
      labels:
        project: k8s-pod-logs
        app: filebeat
    spec:
      serviceAccountName: filebeat

对象总结

role 和 rolebinding 是 namespace 级别对象,clusterrole 和 clusterrolebinding 是集群级别对象。

  1. 授权某个用户单命名空间或者集群权限。
  1. 授权某个用户多个命名空间的权限。

当你把 user 替换为 group 的时候,将会授权某个组

当你把 user 替换为 serviceaccount 的时候,将会授权调用 spec.serviceAccountName 的 pod