三、LDAP + Dex + Kubernetes 权限管控完整关联关系与流程详解整个权限管理流程相当的经典呀ex、kubectl、kubectl-login、ldap、api-service的关联关系,和整个权限校验的流程
组件关联关系
LDAP:存储用户和组信息的目录服务。在这里,我们使用OpenLDAP。
Dex:一个身份认证服务,支持OIDC协议。它连接LDAP,作为Kubernetes的OIDC身份提供商。
Kubernetes API Server:集群的入口,负责验证请求。它配置了OIDC身份提供商(Dex)的信息。
kubectl:Kubernetes命令行工具,用户通过它来与API Server交互。
kubectl-oidc-login:kubectl的一个插件,用于处理OIDC认证流程,从Dex获取id_token。
权限校验流程
整个流程可以分为两个主要部分:认证(Authentication)和授权(Authorization)。
认证流程(Authentication)
用户使用kubectl命令,例如kubectl get pods。
kubectl检查kubeconfig,发现当前用户使用exec插件进行认证(配置了oidc-login)。
kubectl执行oidc-login插件,该插件启动一个本地服务器(例如在18000端口)并打开浏览器(或跳过浏览器),向Dex发起认证请求。
用户被重定向到Dex的登录页面,输入LDAP凭据(用户名和密码)。
Dex验证用户凭据(通过LDAP),成功后返回授权码到oidc-login插件启动的本地服务器。
oidc-login插件使用授权码向Dex交换id_token。
oidc-login插件将id_token输出给kubectl,kubectl使用这个id_token作为Bearer Token发送给API Server。
API Server收到请求,其中包含Bearer Token。它根据配置的OIDC参数(issuer-url, client-id等)验证Token的签名、有效期、颁发者等信息。同时,它从Token中提取声明(claims),例如用户名(email)和组(groups)。
认证成功,API Server将请求中的用户信息(用户名和组)传递给授权阶段。
授权流程(Authorization)
API Server使用认证阶段传递过来的用户信息,检查该用户是否有权限执行请求的操作。
API Server根据配置的RBAC规则(Role、ClusterRole、RoleBinding、ClusterRoleBinding)进行判断。
如果用户被授权,则请求被处理;否则返回错误。
关键点
Dex 作为OIDC身份提供商,连接LDAP,将LDAP中的用户和组信息通过OIDC协议传递给API Server。
kubectl-oidc-login 插件处理OIDC认证流程,使得kubectl能够获取id_token。
API Server 验证id_token,并提取用户信息(用户名和组)用于RBAC授权。
注意事项
时间同步:OIDC协议中Token的有效期验证需要各组件时间同步,否则会导致认证失败。
网络连通性:确保kubectl所在机器可以访问Dex,API Server可以访问Dex(获取公钥验证签名)。
配置一致性:确保Dex的issuer、client-id等配置与API Server的OIDC配置一致。
安全:生产环境建议使用HTTPS,本文档中使用HTTP仅用于测试。
验证流程
验证LDAP中的用户和组信息。
验证Dex服务是否正常运行,并且可以正确连接LDAP。
验证API Server的OIDC配置是否正确。
验证kubectl-oidc-login插件是否可以成功获取id_token。
验证RBAC权限是否正确绑定。
常见问题
时间不同步导致Token验证失败。
网络问题导致组件之间无法通信。
配置错误,例如issuer-url、client-id不匹配。
RBAC配置错误,导致权限不足。
总结
整个流程通过OIDC协议将LDAP中的用户身份传递到Kubernetes集群,实现了基于LDAP的统一认证。然后通过Kubernetes RBAC进行授权管理。正确配置各组件并确保它们之间的关联关系是成功集成的关键。
LDAP + Dex + Kubernetes 权限管控完整关联关系与流程详解
🎯 核心组件关联关系
graph TB
subgraph "认证与权限管控体系"
A[LDAP] -->|1. 存储用户/组| B[Dex]
B -->|2. 提供OIDC认证| C[Kubernetes API Server]
B -->|3. 返回Token| D[kubectl + oidc-login]
D -->|4. 携带Token请求| C
C -->|5. 验证Token| B
C -->|6. RBAC授权| E[Kubernetes资源]
F[用户] -->|7. LDAP认证| A
D -->|8. 发起认证| B
end
subgraph "配置与通信"
G[Dex Config] --> B
H[API Server OIDC配置] --> C
I[kubeconfig] --> D
J[RBAC配置] --> C
end
🔄 完整权限校验流程
流程图
用户认证流程 (Authentication Flow):
1. 用户执行 kubectl 命令
2. kubectl 调用 oidc-login 插件
3. oidc-login 重定向到 Dex
4. Dex 查询 LDAP 验证用户
5. LDAP 返回用户/组信息
6. Dex 生成 OIDC Token
7. Token 返回给 kubectl
8. kubectl 携带 Token 请求 API Server
9. API Server 验证 Token
10. Token 验证通过,提取用户信息
授权流程 (Authorization Flow):
11. API Server 检查 RBAC
12. RBAC 匹配用户/组权限
13. 权限验证通过
14. 执行请求操作
15. 返回结果
📊 详细组件关系矩阵
|
组件 |
角色 |
关联组件 |
通信协议 |
关键配置 |
|---|---|---|---|---|
|
LDAP |
用户存储 |
Dex |
LDAP |
host, bindDN, baseDN |
|
Dex |
OIDC 提供商 |
LDAP, API Server, kubectl |
HTTP/HTTPS, OIDC |
issuer, client-id, LDAP connector |
|
kubectl-oidc-login |
认证插件 |
kubectl, Dex |
HTTP, OIDC |
issuer-url, client-id, client-secret |
|
kubectl |
客户端工具 |
oidc-login, API Server |
HTTPS, Bearer Token |
kubeconfig exec 配置 |
|
API Server |
集群入口 |
Dex, kubectl |
HTTPS, OIDC |
oidc-issuer-url, oidc-client-id |
|
RBAC |
权限控制 |
API Server |
内部 |
ClusterRole, RoleBinding |
🔍 分步详细流程
步骤1:用户启动认证
# 用户执行
kubectl get pods
# kubectl 检查 kubeconfig
# 发现配置了 exec 插件
apiVersion: v1
kind: Config
users:
- name: alice
user:
exec:
command: kubectl
args:
- oidc-login
- get-token
- --oidc-issuer-url=http://192.168.175.182:32000
步骤2:oidc-login 启动认证流程
# oidc-login 执行
1. 启动本地服务器 (0.0.0.0:18000)
2. 构造认证 URL:
http://192.168.175.182:32000/auth?
client_id=kubernetes&
redirect_uri=http://localhost:18000&
response_type=code&
scope=openid+email+groups
3. 显示 URL 让用户访问
步骤3:Dex 处理认证请求
Dex 收到请求:
1. 验证 client_id 和 redirect_uri
2. 显示登录页面
3. 用户输入 LDAP 凭据
4. Dex 连接 LDAP 验证:
LDAP 查询: (&(objectClass=inetOrgPerson)(uid=alice))
5. LDAP 返回用户信息:
- DN: uid=alice,ou=users,dc=example,dc=com
- 组: developers, k8s-admins
6. Dex 生成授权码
7. 重定向到 redirect_uri
步骤4:获取 Token
# oidc-login 接收授权码
# 调用 Dex 的 token 端点
POST http://192.168.175.182:32000/token
参数:
grant_type=authorization_code
code={授权码}
redirect_uri=http://localhost:18000
client_id=kubernetes
client_secret=ZXhhbXBsZS1hcHAtc2VjcmV0
# Dex 返回
{
"id_token": "eyJhbGciOiJSUzI1Ni...",
"access_token": "...",
"token_type": "Bearer"
}
步骤5:Token 内容解析
{
"iss": "http://192.168.175.182:32000",
"aud": "kubernetes",
"exp": 1772984228,
"iat": 1772980628,
"email": "alice@example.com",
"groups": ["developers", "k8s-admins"],
"sub": "Cgtib2JAZXhhbXBsZS5jb20"
}
步骤6:API Server 验证 Token
// API Server 内部流程
func authenticateToken(token string) {
// 1. 解码 Token
claims := decodeJWT(token)
// 2. 验证签名
verifySignature(claims, dexPublicKey)
// 3. 验证 Issuer
if claims.iss != "http://192.168.175.182:32000" {
return error
}
// 4. 验证 Audience
if claims.aud != "kubernetes" {
return error
}
// 5. 验证有效期
if time.Now() < claims.iat || time.Now() > claims.exp {
return error
}
// 6. 提取用户信息
username := claims.email
groups := claims.groups
return UserInfo{username, groups}
}
步骤7:RBAC 授权检查
// API Server 授权流程
func authorize(user UserInfo, request Action) bool {
// 1. 查找匹配的 RoleBinding/ClusterRoleBinding
bindings := findBindingsForUser(user)
// 2. 检查每个绑定的权限
for _, binding := range bindings {
role := getRole(binding.roleRef)
if canAccess(role, request) {
return true
}
}
return false
}
步骤8:权限匹配示例
# 用户: alice
# 组: ["developers", "k8s-admins"]
# ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: developers-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: developer
subjects:
- kind: Group
name: "developers" # ✅ 匹配
apiGroup: rbac.authorization.k8s.io
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: admins-binding
namespace: development
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: Group
name: "k8s-admins" # ✅ 匹配
apiGroup: rbac.authorization.k8s.io
📈 完整的请求响应流
HTTP 请求流
1. kubectl → API Server
GET /api/v1/namespaces/development/pods
Authorization: Bearer eyJhbGciOiJSUzI1Ni...
2. API Server → Dex (公钥端点)
GET /keys
(获取公钥验证签名)
3. API Server 内部处理
- 验证 Token
- 提取用户/组
- 检查 RBAC
- 执行业务逻辑
4. API Server → kubectl
200 OK
{"items": [...]}
认证流程图
sequenceDiagram
participant U as User
participant K as kubectl
participant O as oidc-login
participant D as Dex
participant L as LDAP
participant A as API Server
participant R as RBAC
U->>K: kubectl get pods
K->>O: 调用插件获取Token
O->>D: 启动认证流程
D->>U: 显示登录页面
U->>D: 输入LDAP凭据
D->>L: 验证用户
L-->>D: 返回用户/组
D-->>O: 返回授权码
O->>D: 用授权码换Token
D-->>O: 返回id_token
O-->>K: 返回Token
K->>A: 携带Token请求
A->>D: 验证Token(可选)
D-->>A: 验证结果
A->>R: 检查RBAC权限
R-->>A: 授权结果
A-->>K: 返回API响应
K-->>U: 显示结果
⚙️ 各组件配置关联
配置关联矩阵
|
配置项 |
Dex |
API Server |
kubectl |
必须一致 |
说明 |
|---|---|---|---|---|---|
|
Issuer URL |
✅ |
✅ |
✅ |
✅ |
身份提供商地址 |
|
Client ID |
✅ |
✅ |
✅ |
✅ |
客户端标识 |
|
Client Secret |
✅ |
❌ |
✅ |
❌ |
客户端密钥,仅认证用 |
|
Redirect URI |
✅ |
❌ |
✅ |
匹配 |
回调地址 |
|
Username Claim |
❌ |
✅ |
❌ |
匹配 |
Token 中用户名字段 |
|
Groups Claim |
❌ |
✅ |
❌ |
匹配 |
Token 中组字段 |
|
LDAP 连接 |
✅ |
❌ |
❌ |
- |
LDAP 服务器配置 |
|
Scope |
❌ |
❌ |
✅ |
包含 |
请求的权限范围 |
配置验证脚本
#!/bin/bash
# verify-config-consistency.sh
echo "=== 配置一致性验证 ==="
echo ""
# 1. 提取各组件配置
echo "1. Issuer URL 验证:"
DEX_ISSUER=$(curl -s http://192.168.175.182:32000/.well-known/openid-configuration 2>/dev/null | jq -r .issuer)
APISERVER_ISSUER=$(sudo ps aux | grep kube-apiserver | grep -o "oidc-issuer-url=[^ ]*" | cut -d= -f2)
KUBECONFIG_ISSUER=$(grep -o "issuer-url=[^ ]*" kubeconfig-alice.yaml | head -1 | cut -d= -f2)
echo " Dex: $DEX_ISSUER"
echo " API Server: $APISERVER_ISSUER"
echo " kubeconfig: $KUBECONFIG_ISSUER"
echo " 状态: $([ "$DEX_ISSUER" = "$APISERVER_ISSUER" ] && [ "$APISERVER_ISSUER" = "$KUBECONFIG_ISSUER" ] && echo "✅ 一致" || echo "❌ 不一致")"
echo ""
# 2. Client ID 验证
echo "2. Client ID 验证:"
DEX_CLIENT_ID=$(kubectl get configmap dex-config -n dex -o yaml | grep -A5 "staticClients:" | grep "id:" | head -1 | awk '{print $2}')
APISERVER_CLIENT_ID=$(sudo ps aux | grep kube-apiserver | grep -o "oidc-client-id=[^ ]*" | cut -d= -f2)
KUBECONFIG_CLIENT_ID=$(grep -o "client-id=[^ ]*" kubeconfig-alice.yaml | head -1 | cut -d= -f2)
echo " Dex: $DEX_CLIENT_ID"
echo " API Server: $APISERVER_CLIENT_ID"
echo " kubeconfig: $KUBECONFIG_CLIENT_ID"
echo " 状态: $([ "$DEX_CLIENT_ID" = "$APISERVER_CLIENT_ID" ] && [ "$APISERVER_CLIENT_ID" = "$KUBECONFIG_CLIENT_ID" ] && echo "✅ 一致" || echo "❌ 不一致")"
echo ""
# 3. 声明映射验证
echo "3. 声明映射验证:"
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)"
echo ""
echo " kubeconfig scope:"
grep -o "extra-scope=[^ ]*" kubeconfig-alice.yaml
echo ""
echo " Dex LDAP 配置:"
kubectl get configmap dex-config -n dex -o yaml | grep -A3 "userSearch:"
echo ""
🔧 故障排查流程
认证失败排查
#!/bin/bash
# troubleshoot-auth-flow.sh
echo "=== 认证流程故障排查 ==="
echo ""
# 1. 检查网络连通性
echo "1. 网络连通性:"
echo " kubectl → Dex:"
curl -v http://192.168.175.182:32000/healthz 2>&1 | grep -E "Connected|HTTP"
echo ""
echo " API Server → Dex:"
kubectl run -it --rm --image=busybox test -- nc -zv 192.168.175.182 32000
echo ""
# 2. 检查 Token 获取
echo "2. Token 获取测试:"
rm -rf ~/.kube/cache/
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 | head -20
echo ""
# 3. 检查 Token 有效性
echo "3. 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
echo "✅ 获取到 Token,长度: ${#TOKEN}"
echo " 解码 Token 内容:"
echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null | jq '{iss, aud, email, groups}' 2>/dev/null
else
echo "❌ 无法获取 Token"
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)
echo " HTTP 状态码: $RESPONSE"
case $RESPONSE in
200) echo " ✅ Token 有效且有权限" ;;
403) echo " ✅ Token 有效但无权限" ;;
401) echo " ❌ Token 无效" ;;
*) echo " ⚠️ 其他错误: $RESPONSE" ;;
esac
fi
权限失败排查
#!/bin/bash
# troubleshoot-permission.sh
echo "=== 权限故障排查 ==="
echo ""
# 1. 获取当前用户信息
echo "1. 获取当前用户信息:"
TOKEN=$(kubectl config view --raw -o jsonpath='{.users[?(@.name=="alice")].user.exec.args[0]}' 2>/dev/null | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
if [ -z "$TOKEN" ]; then
# 尝试手动获取
TOKEN=$(./get-token-manual.sh 2>&1 | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
fi
if [ -n "$TOKEN" ]; then
echo "✅ 获取到 Token"
PAYLOAD=$(echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null)
echo " 用户名: $(echo "$PAYLOAD" | jq -r '.email' 2>/dev/null)"
echo " 用户组: $(echo "$PAYLOAD" | jq -r '.groups | join(", ")' 2>/dev/null)"
else
echo "❌ 无法获取 Token"
exit 1
fi
echo ""
# 2. 检查 RBAC 绑定
echo "2. 检查 RBAC 绑定:"
USER_GROUPS=$(echo "$PAYLOAD" | jq -r '.groups | join("|")' 2>/dev/null)
echo " 用户组: $USER_GROUPS"
echo ""
echo " 匹配的 ClusterRoleBinding:"
kubectl get clusterrolebindings -o yaml | grep -B5 -A5 "name: \"$(echo "$USER_GROUPS" | cut -d'|' -f1)\"" || echo " 未找到匹配"
echo ""
# 3. 检查权限
echo "3. 检查具体权限:"
kubectl --token="$TOKEN" auth can-i --list
📊 状态监控指标
关键监控点
|
指标 |
检查方法 |
正常值 |
异常处理 |
|---|---|---|---|
|
Dex 健康 |
|
HTTP 200 |
重启 Dex |
|
LDAP 连接 |
|
成功响应 |
检查网络/证书 |
|
Token 获取 |
|
成功返回 Token |
检查配置 |
|
API Server 验证 |
|
200/403 |
检查 OIDC 配置 |
|
时间同步 |
|
偏差 < 5s |
同步时间 |
|
网络延迟 |
|
< 100ms |
检查网络 |
监控脚本
#!/bin/bash
# monitor-health.sh
echo "=== 系统健康检查 ==="
echo "时间: $(date)"
echo ""
# 检查点数组
declare -A CHECKS=(
["Dex健康"]="curl -s http://192.168.175.182:32000/healthz"
["LDAP连接"]="kubectl exec -n ldap deployment/openldap -- ldapwhoami -x -H ldap://localhost 2>&1 | grep -q anonymous && echo OK"
["API Server"]="curl -k -s https://192.168.175.181:6443/healthz"
["时间同步"]="date && kubectl exec -n dex deployment/dex -- date"
["Token测试"]="timeout 10 kubectl oidc-login get-token --skip-open-browser 2>&1 | grep -q token && echo OK"
)
for CHECK in "${!CHECKS[@]}"; do
echo -n "$CHECK: "
eval "${CHECKS[$CHECK]}" 2>&1 | head -1
done
🎯 总结:完整的关联与流程
五大核心关系
-
LDAP ↔ Dex:用户存储与认证
-
Dex 查询 LDAP 验证用户
-
LDAP 返回用户和组信息
-
通过 LDAP connector 配置连接
-
-
Dex ↔ kubectl-oidc-login:OIDC 认证流程
-
kubectl-oidc-login 启动认证
-
Dex 处理认证请求
-
Dex 返回 Token
-
通过 OIDC 协议通信
-
-
Dex ↔ API Server:Token 验证
-
API Server 验证 Token 签名
-
验证 Token 的 iss/aud/exp
-
通过公钥端点获取验证密钥
-
-
kubectl ↔ API Server:API 请求
-
kubectl 携带 Token 请求
-
API Server 处理业务逻辑
-
通过 HTTPS + Bearer Token
-
-
RBAC ↔ API Server:权限控制
-
API Server 检查 RBAC
-
匹配用户/组与权限
-
决定是否允许操作
-
关键成功因素
-
配置一致性:Issuer、Client ID 必须一致
-
时间同步:所有系统时间偏差 < 5秒
-
网络连通:组件间网络可达
-
声明匹配:Token 声明与 RBAC 配置匹配
-
证书/签名:Token 签名验证正确
故障树
认证失败
├── 网络问题
│ ├── Dex 不可达
│ ├── LDAP 不可达
│ └── 端口未开放
├── 配置问题
│ ├── Issuer 不匹配
│ ├── Client ID 不匹配
│ └── 声明配置错误
├── 时间问题
│ ├── 系统时间不同步
│ └── Token 过期
└── 证书问题
├── 签名验证失败
└── 证书不信任
权限失败
├── RBAC 配置
│ ├── 组名不匹配
│ ├── 权限不足
│ └── 绑定错误
└── Token 问题
├── 组声明缺失
└── 声明名错误
通过理解这些关联关系和完整流程,可以更好地设计、部署和排查基于 LDAP + Dex 的 Kubernetes 认证授权系统。
posted on 2026-03-09 16:39 luzhouxiaoshuai 阅读(36) 评论(0) 收藏 举报
浙公网安备 33010602011771号