在CCE中使用Dex进行OIDC身份验证
Dex是一个开源的OpenID Connect(OIDC)身份提供商,在Kubernetes中使用Dex可以为集群提供灵活的身份认证和联邦身份管理能力。Dex充当中间层,将多种身份源(如LDAP、GitHub、SAML等)转换为标准的OIDC协议,供Kubernetes和其他应用使用。
OIDC是一种基于OAuth 2.0协议的认证方式,在使用访问令牌(Access Token)之外还会返回一个ID Token(ID 令牌)。ID Token是一个由服务器签名的JWT(JSON Web Token)令牌,包含用户的邮箱地址等预知字段。Kubernetes可以根据ID Token中包含的用户信息进行RBAC授权,从而实现第三方身份源与Kubernetes权限的转换,详情请参见OpenID Connect(OIDC)令牌。
典型应用场景如下:
- 企业LDAP/AD集成:企业内部已有LDAP,希望Kubernetes直接继承现有用户体系。
- 多集群统一认证:多个Kubernetes集群共享同一个Dex实例,实现统一登录。
- 统一身份联邦:多团队协作时,将不同来源的用户身份认证(如GitHub、Gitlab等)通过Dex统一转换为OIDC协议,并获取 Kubernetes可识别的OIDC Token。
本文演示使用LDAP OAuth账户的方式完成CCE OIDC的认证。
方案原理
在Kubernetes集群中使用Dex进行OIDC身份验证时,主要包含Dex和dex-k8s-authenticator两个组件:
- Dex充当其他身份提供商的门户,负责将身份验证请求推送到LDAP服务器、SAML提供商或其他网络身份提供商(如 GitHub、Gitlab等)。
- dex-k8s-authenticator是一个web-app,它可以与Dex进行交互并获取Dex生成的token,然后提供创建和修改kubeconfig文件的命令。用户执行这些生成的命令后可以完成kubeconfig文件配置。

使用Dex登录验证的流程如下所示:
- 用户访问登录页面。
- 系统会将登录请求重定向到Dex进行身份登录验证。
- Dex将身份验证请求转发给第三方身份认证服务(Identity Provider)。
- 如果用户的凭证通过了第三方身份认证服务的验证,身份认证服务将返回id_token。
- 用户在使用kubectl时,将id_token设置为--token标志的值,或者将其直接添加到kubeconfig中进行使用。
- kubectl将id_token放在HTTP请求的Authorization头部,并发起请求到Kubernetes API服务器。
- API服务器接收到请求后,会验证Authorization头部中的JWT签名,以确认其有效性。
- API服务器会与Dex通信以验证id_token是否已经被授权。
- Dex确认该用户已授权,并返回验证结果。
- 鉴权成功之后,API服务器向kubectl返回响应。
- 最后,kubectl将API服务器的响应以可读的形式呈现给用户。
准备工作
- 创建CCE集群:在华为云控制台创建一个CCE集群,且集群版本要求v1.30及以上,详情请参见购买Standard/Turbo集群。
- 准备kubectl及Helm工具:在集群所在VPC内准备一台可访问公网的虚拟机,安装kubectl连接集群,并安装Helm v3。
- 创建ELB并绑定公网IP:创建一个ELB实例,并绑定一个公网IP,具体操作请参见购买独享型负载均衡器。
- 准备域名:
- 公网域名1:dex.k8s.example.com,此域名为dex服务的访问域名地址。
- 公网域名2:login.k8s.example.com,此域名为dex-k8s-authenticator服务的域名地址。
- 配置DNS A记录:为上述两个域名配置DNS公网解析,具体操作请参见配置公网域名解析。如果仅使用内网访问该域名则可以通过节点host进行配置。
- 安装Nginx Ingress插件:选择步骤3中创建的ELB实例,详情请参见NGINX Ingress控制器。
- 已有LDAP服务:确保LDAP服务已部署,并创建好用户组和用户。
- (可选)节点子网配置SNAT:如果Dex部署在其他集群,需要为集群所在VPC和节点所在子网创建公网NAT网关,允许kube-apiserver访问公网。具体操作请参见购买公网NAT网关。
步骤一:创建密钥(已有证书请忽略)
- 登录已安装kubectl和Helm的虚拟机。
- 创建Dex自签证书。如果通过HTTPS访问Dex需要证书认证,因此需要先自签名服务器证书和CA证书。
创建create_cert.sh脚本文件,文件内容如下:
#!/bin/bash mkdir -p ssl cat << EOF > ssl/req.cnf [req] req_extensions = v3_req distinguished_name = req_distinguished_name [req_distinguished_name] [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = *.k8s.example.com # 所有k8s.example.com后缀的域名都是此证书的信任范围 EOF openssl genrsa -out ssl/ca-key.pem 2048 openssl req -x509 -new -nodes -key ssl/ca-key.pem -days 3650 -out ssl/ca.pem -subj "/CN=kube-ca" openssl genrsa -out ssl/key.pem 2048 openssl req -new -key ssl/key.pem -out ssl/csr.pem -subj "/CN=kube-ca" -config ssl/req.cnf openssl x509 -req -in ssl/csr.pem -CA ssl/ca.pem -CAkey ssl/ca-key.pem -CAcreateserial -out ssl/cert.pem -days 3650 -extensions v3_req -extfile ssl/req.cnf
执行脚本:
chmod +x create_cert.sh ./create_cert.sh
- 生成服务器证书Secret,访问 dex.k8s.example.com 和 login.k8s.example.com 需要使用该密钥。本示例中密钥名称为dex.example.com.tls。
kubectl create ns dex cd ssl; mv key.pem tls.key; mv cert.pem tls.crt kubectl create secret tls -n dex dex.example.com.tls \ --cert=tls.crt\ --key=tls.key
步骤二:部署Dex应用
使用Helm部署Dex应用,操作详情请参见通过Dex进行Kubernetes身份验证。
- 登录已安装kubectl和Helm的虚拟机,添加Helm仓库。
helm repo add dex https://charts.dexidp.io helm repo update
- 创建dex-values.yaml文件,用于自定义配置Dex参数,该文件中定义了Dex的访问方式和Dex中注册的LDAP后端服务。
文件示例如下:
tls: enabled: true clientCA: "" ingress: enabled: true className: nginx # 创建Nginx Ingress hosts: - host: dex.k8s.example.com # Dex的访问域名 paths: - path: / pathType: ImplementationSpecific tls: - secretName: dex.example.com.tls # 步骤一中创建Dex的访问密钥 hosts: - dex.k8s.example.com # Dex的访问域名 config: issuer: https://dex.k8s.example.com # Dex的访问域名,访问地址也可以填http storage: type: kubernetes config: inCluster: true oauth2: responseTypes: ["code", "token", "id_token"] skipApprovalScreen: true connectors: - type: ldap id: ldap name: LDAP config: host: xxx.xxx.xxx.xxx:389 # ldap server insecureNoSSL: true insecureSkipVerify: true bindDN: CN=admin,DC=example,DC=com # 管理员DN(Distinguished Name),是LDAP目录中的唯一标识符 bindPW: "*****" # 请设置管理员密码 userSearch: # 查询LDAP中的用户信息映射到Dex中 baseDN: dc=example,dc=com filter: "(objectClass=posixAccount)" username: uid # 用户登录名 idAttr: DN # 本示例中将LDAP记录中的DN映射到Dex emailAttr: mail # 本示例中将LDAP记录中的mail字段映射到Dex nameAttr: cn # 本示例中将LDAP记录中的cn字段映射到Dex groupSearch: baseDN: dc=example,dc=com filter: "(objectClass=posixGroup)" userMatchers: - userAttr: uid groupAttr: memberUid nameAttr: cn staticClients: - id: kubernetes # 注册客户端ID secret: ***** # 设置客户端密码 name: "kubernetes" redirectURIs: - https://login.k8s.example.com/callback # dex-k8s-authenticator的访问域名
更多参数配置请参考官方示例:
- 根据自定义配置安装Dex。
helm install dex dex/dex --namespace dex --create-namespace --version 0.19.1 --values dex-values.yaml
执行以下命令查看已安装的模板实例。
helm list
步骤三:配置集群内域名解析
- 登录CCE控制台,单击集群名称进入集群。
- 在左侧导航栏中选择“插件中心”,在CoreDNS 域名解析下单击“编辑”,进入插件详情页。
- 在“参数配置”下编辑“扩展参数配置”,在plugins字段添加以下内容,增加Dex服务域名解析。
{ "configBlock": "10.247.82.158 dex.k8s.example.com\nfallthrough", "name": "hosts" }
其中IP 10.247.82.158为nginx-ingress-controller Service的ClusterIP。
- 单击“确定”。
步骤四:部署dex-k8s-authenticator应用
- 添加Helm仓库。
helm repo add skm https://charts.sagikazarmark.dev helm repo update
- 创建authen-values.yaml文件,用于自定义配置dex-k8s-authenticator参数。配置示例详情请参见https://github.com/mintel/dex-k8s-authenticator/blob/master/docs/config.md。
config: clusters: - name: Hello-CCE short_description: "Your cluster" description: "Your cluster" issuer: https://dex.k8s.example.com # Dex的访问域名 client_id: kubernetes # 对应步骤二中Dex config中的client_id client_secret: ***** # 对应步骤二中Dex config中的client_secret redirect_uri: https://login.k8s.example.com/callback # dex-k8s-authenticator的访问域名 k8s_master_uri: https://192.168.0.158:5443 # 集群API Server访问地址 #集群的CA证书 k8s_ca_pem: | -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- # 如果Dex访问为https, 需要提供Dex域名的CA证书 trusted_root_ca: | -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- ingress: enabled: true className: nginx hosts: - host: login.k8s.example.com # 修改为dex-k8s-authenticator的访问域名 paths: - path: / pathType: ImplementationSpecific tls: - secretName: dex.example.com.tls # 步骤一中创建Dex的访问密钥 hosts: - login.k8s.example.com # 修改为dex-k8s-authenticator的访问域名
- 根据自定义配置安装dex-k8s-authenticator。
helm install dex-k8s-authenticator skm/dex-k8s-authenticator --namespace dex --version 0.0.3 --values authen-values.yaml
步骤五:修改APIserver启动参数
- 登录CCE控制台,单击集群名称进入集群。
- 在集群控制台左侧导航栏中选择“配置中心”。
- 切换至“集群访问配置”页签,启用OIDC,并配置kube-apiserver使用OIDC所需的参数。
参数
说明
示例
发布者URL (oidc-issuer-url)
提供OpenID Connect认证服务的URL,必须是HTTPS协议。
https://dex.k8s.example.com
客户端ID (oidc-client-id)
OpenID Connect认证服务中注册的客户端ID,例如步骤二中注册的客户端ID为kubernetes。
kubernetes
注册用户名 (oidc-username-claim)
指定JWT令牌中的字段,获取该字段的值作为用户名。默认值为sub,这通常是最终用户的唯一标识符,您也可以选择其他字段,如email或name。
后续可以在集群中根据用户名授予Kubernetes权限,参见步骤六:为第三方用户授予Kubernetes权限。
email
该参数值设置为email,表示将JWT中email字段的值,即电子邮件地址作为用户名。
注册组 (oidc-groups-claim)
指定JWT令牌中的字段,获取该字段的值作为用户组,表示用户组的字段名称通常为groups。后续可以根据用户组授予Kubernetes权限,参见步骤六:为第三方用户授予Kubernetes权限。
groups
该参数值设置为groups,表示将JWT中groups字段的值作为用户组。
认证CA证书 (oidc-ca-pem)
PEM格式的CA证书,用于签署身份提供商的Web证书。
步骤一中Dex域名的CA证书
- 单击“确认配置”。
步骤六:为第三方用户授予Kubernetes权限
由于Dex只是对用户进行认证,并没有Kubernetes授权,所以需要为经过Dex认证的用户添加Kubernetes权限。
本示例中,根据步骤五中设置的注册组groups进行授权,即对认证返回的JWT中的用户组授予Kubernetes权限(本示例中用户组名称为CCE)。如果登录用户属于该用户组,则具有相应的Kubernetes权限。配置ClusterRoleBinding和ClusterRole的示例如下,您可以根据自己的实际需求分配对应的权限:
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: cce-admin
subjects:
- kind: Group
name: "CCE" # CCE用户组是LDAP中用户所属用户组,为该用户组中的用户授权Kubernetes权限
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
步骤七:登录测试
- 在浏览器中打开dex-k8s-authenticator域名,本示例中为login.k8s.example.com。
- 输入LDAP中CCE用户组下的用户账号密码。
- 登录成功后,dex-k8s-authenticator会提供可执行的命令,帮助用户配置kubeconfig,请按照页面指导执行命令。
- 执行以上命令,完成kubeconfig配置后,使用kubectl访问Kubernetes资源进行测试。