四、LDAP + Dex + Kubernetes 权限管控完整关联关系与流程详解整个权限管理流程相当的经典呀ex、kubectl、kubectl-login、ldap、api-service的关联关系,和整个权限校验的流程
我们有两个配置文件:一个是kubeconfig中的exec配置,另一个是API Server的OIDC配置。它们分别用于客户端和服务器端的OIDC认证流程。
下面我们分别解释这两个配置的含义,并说明它们之间的关联和注意事项。
kubeconfig中的exec配置(客户端):
这个配置告诉kubectl如何使用OIDC获取令牌。
当kubectl需要与API Server通信时,它会执行这个命令来获取一个ID令牌。
API Server的OIDC配置(服务器端):
这个配置告诉API Server如何验证客户端(kubectl)提供的ID令牌。
关联关系:
客户端通过exec配置从Dex(OIDC提供商)获取ID令牌,然后将其作为Bearer Token发送给API Server。
API Server使用其OIDC配置来验证这个令牌的有效性(例如,检查签发者、客户端ID、签名等)。
下面详细说明每个参数的含义和注意事项。
一、kubeconfig exec配置参数:
apiVersion: client.authentication.k8s.io/v1beta1 # 客户端认证API版本
command: kubectl # 执行的命令,这里是kubectl,实际上我们安装了kubectl-oidc-login插件
args:
- oidc-login
- get-token
- --oidc-issuer-url=http://192.168.175.182:32000 # Dex的地址,必须与API Server配置中的issuer一致
- --oidc-client-id=kubernetes # 客户端ID,必须与API Server配置中的client-id一致
- --oidc-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0 # 客户端密钥,在Dex中注册的客户端密钥
- --oidc-extra-scope=email # 请求的额外scope,这里要求返回email声明
- --oidc-extra-scope=groups # 请求groups声明,用于RBAC分组
- --skip-open-browser # 不自动打开浏览器,适用于无浏览器环境
- --listen-address=0.0.0.0:18000 # 监听地址,用于接收授权码回调
二、API Server OIDC配置参数:
- --oidc-issuer-url=http://192.168.175.182:32000 # 必须与Dex的issuer一致,且必须与客户端issuer相同
- --oidc-client-id=kubernetes # 必须与客户端配置的client-id相同
- --oidc-username-claim=email # 使用token中的email声明作为用户名
- --oidc-groups-claim=groups # 使用token中的groups声明作为组
- --oidc-signing-algs=RS256 # 指定签名算法,Dex默认使用RS256
注意事项:
issuer-url必须完全一致,包括协议、主机和端口。通常Dex的issuer会在其配置中指定,并且必须与API Server和客户端配置相同。
client-id必须一致。在Dex中注册的客户端ID,必须同时配置在API Server和kubeconfig中。
客户端密钥(client-secret)只在客户端使用,用于从Dex获取令牌,API Server不需要知道这个密钥。
API Server配置中的username-claim和groups-claim必须与令牌中的声明对应。在Dex中,我们配置了返回email和groups声明。
签名算法必须一致。Dex使用的签名算法是RS256,所以API Server也要指定RS256。
时间同步:由于令牌有有效期,所有组件(Dex、API Server、客户端)的时间必须同步,否则会导致令牌验证失败。
网络连通性:API Server必须能够访问Dex的issuer-url,以获取公钥来验证令牌签名。注意,这里使用的是http,所以不需要CA证书。
回调地址:在Dex的客户端配置中,redirectURIs必须包含kubectl-oidc-login使用的回调地址。默认情况下,kubectl-oidc-login会使用http://localhost:8000
和http://localhost:18000
等。如果使用--listen-address指定了其他地址,则需要相应调整。
安全考虑:使用http协议仅适用于测试环境。生产环境应使用https,并配置正确的证书。在API Server配置中,如果需要使用https,可能需要通过--oidc-ca-file指定CA证书。
在API Server配置中,还可以添加其他参数,例如--oidc-username-prefix和--oidc-groups-prefix,用于在用户名和组前添加前缀,以避免冲突。
如果Dex和API Server之间使用http,而API Server在启动时使用了--oidc-ca-file,那么可能会导致验证失败,因为CA证书不匹配。所以,如果使用自签名证书,必须确保API Server信任该CA。
在kubeconfig中,--skip-open-browser和--listen-address适用于无浏览器环境,例如SSH连接。如果有浏览器,可以去掉--skip-open-browser,让kubectl自动打开浏览器。
如果遇到权限问题,请检查Dex返回的令牌中是否包含了正确的groups声明,以及RBAC配置中是否使用了相同的组名。
如果遇到令牌无效或过期,请检查时间同步,并确保令牌没有过期。
调试技巧:可以通过手动获取令牌并解码来检查声明,或者查看API Server的日志来获取更详细的错误信息。
下面是一个手动获取令牌并解码的例子:
获取令牌:
kubectl oidc-login get-token \
--oidc-issuer-url=http://192.168.175.182:32000 \
--oidc-client-id=kubernetes \
--oidc-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0 \
--skip-open-browser
解码令牌(假设令牌为$TOKEN):
echo $TOKEN | cut -d'.' -f2 | base64 -d | jq .
通过查看解码后的令牌,确保有email和groups声明,并且其值与预期一致。
总结:确保客户端和服务器端的配置匹配,特别是issuer、client-id、声明和签名算法。同时,确保网络、时间和安全配置正确
kubeconfig exec 配置与 API Server OIDC 配置的关联关系详解
📊 配置对比表
|
配置位置 |
参数 |
客户端 (kubeconfig) |
服务端 (API Server) |
必须一致 |
|---|---|---|---|---|
|
Issuer URL |
身份提供商地址 |
|
|
✅ 是 |
|
Client ID |
客户端标识 |
|
|
✅ 是 |
|
Client Secret |
客户端密钥 |
|
不需要 |
❌ 否 |
|
用户名声明 |
识别用户的字段 |
不配置 |
|
- |
|
组声明 |
识别用户组的字段 |
不配置 |
|
- |
|
签名算法 |
Token 签名算法 |
自动协商 |
|
建议一致 |
|
Scope |
请求的权限范围 |
|
不需要 |
- |
🔍 详细解析
1. 客户端配置 (kubeconfig)
- name: alice
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: kubectl
args:
- oidc-login
- get-token
- --oidc-issuer-url=http://192.168.175.182:32000
- --oidc-client-id=kubernetes
- --oidc-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0
- --oidc-extra-scope=email
- --oidc-extra-scope=groups
- --skip-open-browser
- --listen-address=0.0.0.0:18000
参数含义:
|
参数 |
含义 |
作用 |
|---|---|---|
|
|
Dex 服务的 URL |
告诉 kubectl 从哪里获取 Token |
|
|
在 Dex 中注册的客户端 ID |
标识哪个应用在请求 Token |
|
|
客户端密钥 |
证明客户端身份,防止滥用 |
|
|
请求的权限范围 |
控制返回 Token 中包含的信息 |
|
|
不自动打开浏览器 |
适用于无 GUI 环境 |
|
|
回调监听地址 |
接收 Dex 回调授权码 |
流程说明:
kubectl 启动 → 执行 exec 命令 → 连接到 Dex → 用户认证 → 返回 Token → kubectl 使用 Token
2. 服务端配置 (API Server)
# OIDC 配置
- --oidc-issuer-url=http://192.168.175.182:32000
- --oidc-client-id=kubernetes
- --oidc-username-claim=email
- --oidc-groups-claim=groups
- --oidc-signing-algs=RS256
参数含义:
|
参数 |
含义 |
作用 |
|---|---|---|
|
|
Dex 服务的 URL |
验证 Token 的签发者是否正确 |
|
|
客户端 ID |
验证 Token 的目标受众是否正确 |
|
|
用户名字段 |
从 Token 的哪个字段提取用户名 |
|
|
组字段 |
从 Token 的哪个字段提取用户组 |
|
|
签名算法 |
指定可接受的 Token 签名算法 |
验证流程:
API Server 收到请求 → 检查 Token → 验证签发者 → 验证客户端 → 提取用户信息 → 应用 RBAC
🔗 二者关联关系详解
关联 1:Issuer URL
# 客户端
--oidc-issuer-url=http://192.168.175.182:32000
# 服务端
--oidc-issuer-url=http://192.168.175.182:32000
必须完全一致,包括:
-
协议 (
http或https) -
主机名 (
192.168.175.182) -
端口 (
32000) -
路径(如果有)
验证方法:
# 检查客户端配置的 issuer
grep -o "issuer-url=[^ ]*" kubeconfig-alice.yaml
# 检查 API Server 配置的 issuer
sudo ps aux | grep kube-apiserver | grep -o "oidc-issuer-url=[^ ]*"
# 检查 Dex 实际的 issuer
curl -s http://192.168.175.182:32000/.well-known/openid-configuration | jq -r .issuer
关联 2:Client ID
# 客户端
--oidc-client-id=kubernetes
# 服务端
--oidc-client-id=kubernetes
必须完全一致,这是双向验证:
-
客户端:告诉 Dex 我是谁
-
服务端:验证 Token 是不是发给我的
验证方法:
# 检查 Dex 客户端配置
kubectl get configmap dex-config -n dex -o yaml | grep -A5 "staticClients:"
# 检查 API Server 配置
sudo ps aux | grep kube-apiserver | grep -o "oidc-client-id=[^ ]*"
关联 3:Token 声明映射
# 客户端:请求的 scope
--oidc-extra-scope=email
--oidc-extra-scope=groups
# 服务端:使用的声明
--oidc-username-claim=email
--oidc-groups-claim=groups
关联关系:
-
客户端通过
--oidc-extra-scope请求特定信息 -
Dex 在 Token 中包含这些信息
-
API Server 通过
--oidc-username-claim和--oidc-groups-claim找到这些信息
验证 Token 内容:
# 获取 Token
TOKEN=$(kubectl oidc-login get-token \
--oidc-issuer-url=http://192.168.175.182:32000 \
--oidc-client-id=kubernetes \
--oidc-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0 \
--skip-open-browser 2>&1 | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
# 解码 Token
echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null | jq '.'
输出示例:
{
"iss": "http://192.168.175.182:32000",
"sub": "Cgtib2JAZXhhbXBsZS5jb20",
"aud": "kubernetes",
"email": "alice@example.com",
"groups": ["developers", "k8s-admins"]
}
关联 4:签名算法
# 客户端:通常自动协商
# 服务端:明确指定
--oidc-signing-algs=RS256
验证方法:
# 检查 Dex 支持的算法
curl -s http://192.168.175.182:32000/.well-known/openid-configuration | jq -r '.id_token_signing_alg_values_supported[]'
# 检查 API Server 配置
sudo ps aux | grep kube-apiserver | grep -o "oidc-signing-algs=[^ ]*"
⚠️ 必须注意的关键点
1. 时间同步问题
# 检查所有系统时间
date
kubectl exec -n dex deployment/dex -- date
ssh 192.168.175.181 date
# 时间差必须小于 5 秒
问题现象:
-
Token 验证失败:"Token is expired" 或 "Token not yet valid"
-
即使 Token 刚获取也无法使用
解决方案:
# 所有节点同步时间
sudo ntpdate pool.ntp.org
sudo hwclock --systohc
2. 网络连通性
# 客户端必须能访问 Dex
curl -v http://192.168.175.182:32000/healthz
# API Server 必须能访问 Dex
kubectl run -it --rm --image=busybox test -- nc -zv 192.168.175.182 32000
问题现象:
-
客户端无法获取 Token
-
API Server 无法验证 Token
3. 客户端 Secret 安全
# 在 kubeconfig 中
--oidc-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0
注意:
-
客户端 Secret 仅在客户端使用
-
API Server 不需要知道这个 Secret
-
不要将 Secret 硬编码在公共配置中
安全建议:
# 使用环境变量
export DEX_CLIENT_SECRET=ZXhhbXBsZS1hcHAtc2VjcmV0
# 在 kubeconfig 中引用
args:
- --oidc-client-secret=${DEX_CLIENT_SECRET}
4. 回调地址配置
# Dex 配置中必须有相应的 redirectURIs
redirectURIs:
- 'http://localhost:8000'
- 'http://localhost:18000'
验证:
# 检查 Dex 客户端配置
kubectl get configmap dex-config -n dex -o yaml | grep -A10 "redirectURIs:"
5. 声明名称匹配
# API Server 配置
--oidc-username-claim=email
--oidc-groups-claim=groups
# Token 中必须包含这些字段
# 错误的声明名会导致 RBAC 失效
验证脚本:
#!/bin/bash
# verify-claims.sh
echo "=== 验证声明映射 ==="
echo ""
# 获取 Token
TOKEN=$(kubectl oidc-login get-token \
--oidc-issuer-url=http://192.168.175.182:32000 \
--oidc-client-id=kubernetes \
--oidc-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0 \
--skip-open-browser 2>&1 | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
if [ -n "$TOKEN" ]; then
PAYLOAD=$(echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null)
echo "Token 中的声明:"
echo "$PAYLOAD" | jq -r 'keys[]' | sort
echo ""
echo "关键声明值:"
echo " email: $(echo "$PAYLOAD" | jq -r '.email // "未找到"')"
echo " groups: $(echo "$PAYLOAD" | jq -r '.groups // "未找到" | join(", ")')"
echo ""
# 检查 API Server 配置
echo "API Server 配置:"
echo " username-claim: $(sudo ps aux | grep kube-apiserver | grep -o 'username-claim=[^ ]*' | cut -d= -f2)"
echo " groups-claim: $(sudo ps aux | grep kube-apiserver | grep -o 'groups-claim=[^ ]*' | cut -d= -f2)"
fi
🔧 调试和验证脚本
完整验证脚本
#!/bin/bash
# verify-oidc-integration.sh
echo "=== OIDC 集成完整性验证 ==="
echo ""
# 1. 检查配置一致性
echo "1. 配置一致性检查:"
echo " Issuer URL:"
echo " kubeconfig: $(grep -o "issuer-url=[^ ]*" kubeconfig-alice.yaml | head -1)"
echo " API Server: $(sudo ps aux | grep kube-apiserver | grep -o 'oidc-issuer-url=[^ ]*' | head -1)"
echo " Dex: $(curl -s http://192.168.175.182:32000/.well-known/openid-configuration 2>/dev/null | jq -r .issuer 2>/dev/null || echo '无法获取')"
echo ""
echo " Client ID:"
echo " kubeconfig: $(grep -o "client-id=[^ ]*" kubeconfig-alice.yaml | head -1)"
echo " API Server: $(sudo ps aux | grep kube-apiserver | grep -o 'oidc-client-id=[^ ]*' | head -1)"
echo ""
# 2. 获取测试 Token
echo "2. 测试 Token 获取:"
rm -rf ~/.kube/cache/
TOKEN_RESPONSE=$(kubectl oidc-login get-token \
--oidc-issuer-url=http://192.168.175.182:32000 \
--oidc-client-id=kubernetes \
--oidc-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0 \
--skip-open-browser \
--listen-address=0.0.0.0:18000 2>&1)
if echo "$TOKEN_RESPONSE" | grep -q "token"; then
echo "✅ Token 获取成功"
TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
else
echo "❌ Token 获取失败"
echo "错误信息: $TOKEN_RESPONSE"
exit 1
fi
echo ""
# 3. 验证 Token
echo "3. Token 验证:"
if [ -n "$TOKEN" ]; then
# 解码 Token
PAYLOAD=$(echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null 2>/dev/null)
if [ -n "$PAYLOAD" ]; then
echo "✅ Token 格式正确"
echo " Issuer: $(echo "$PAYLOAD" | jq -r '.iss' 2>/dev/null)"
echo " Audience: $(echo "$PAYLOAD" | jq -r '.aud' 2>/dev/null)"
echo " Email: $(echo "$PAYLOAD" | jq -r '.email' 2>/dev/null)"
echo " Groups: $(echo "$PAYLOAD" | jq -r '.groups | join(", ")' 2>/dev/null)"
else
echo "❌ Token 解码失败"
fi
fi
echo ""
# 4. 测试 API Server 验证
echo "4. API Server 验证测试:"
if [ -n "$TOKEN" ]; then
RESPONSE=$(curl -k -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
https://192.168.175.181:6443/api/v1/namespaces/default/pods)
if [ "$RESPONSE" = "200" ] || [ "$RESPONSE" = "403" ]; then
echo "✅ API Server 接受 Token (HTTP $RESPONSE)"
echo " 200: 有权限,403: 无权限但 Token 有效"
else
echo "❌ API Server 拒绝 Token (HTTP $RESPONSE)"
fi
fi
📊 配置映射关系总结
完整 OIDC 流程
┌─────────────┐ 获取 Token ┌─────────────┐
│ kubectl ├─────────────────►│ Dex │
│ (客户端) │◄─────────────────┤ (OIDC服务) │
└──────┬──────┘ 返回 Token └─────────────┘
│
│ 发送请求 + Token
▼
┌─────────────┐ 验证 Token ┌─────────────┐
│ API Server ├─────────────────►│ Dex │
│ (服务端) │◄─────────────────┤ (获取公钥) │
└─────────────┘ 验证结果 └─────────────┘
配置对应关系
|
步骤 |
客户端配置 |
服务端配置 |
必须一致 |
|---|---|---|---|
|
1. 标识身份提供商 |
|
|
✅ |
|
2. 标识客户端 |
|
|
✅ |
|
3. 证明客户端身份 |
|
不需要 |
❌ |
|
4. 请求用户信息 |
|
不需要 |
❌ |
|
5. 提取用户信息 |
不需要 |
|
- |
|
6. 提取组信息 |
不需要 |
|
- |
|
7. 验证签名 |
自动协商 |
|
建议 |
✅ 最佳实践检查清单
部署前检查
-
[ ] Issuer URL 完全一致(协议、主机、端口)
-
[ ] Client ID 完全一致
-
[ ] Dex 客户端配置包含正确的 redirectURIs
-
[ ] Token 中包含 API Server 配置的声明字段
-
[ ] 所有系统时间同步(偏差 < 5 秒)
-
[ ] 网络连通性正常
-
[ ] 使用正确的签名算法
部署后验证
-
[ ] kubectl 可以成功获取 Token
-
[ ] Token 可以被正确解码
-
[ ] Token 中包含正确的声明
-
[ ] API Server 接受 Token
-
[ ] RBAC 权限正确应用
-
[ ] 日志无错误信息
问题排查顺序
-
网络连通性:客户端 → Dex,API Server → Dex
-
时间同步:所有节点时间偏差
-
配置一致性:Issuer URL 和 Client ID
-
声明匹配:Token 内容与 API Server 配置
-
RBAC 配置:组名匹配和权限绑定
-
日志分析:Dex、API Server、kubectl 日志
通过确保这些配置的正确性和一致性,可以建立可靠的 OIDC 认证流程。
posted on 2026-03-09 16:42 luzhouxiaoshuai 阅读(18) 评论(0) 收藏 举报
浙公网安备 33010602011771号