三、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 健康​

curl /healthz

HTTP 200

重启 Dex

LDAP 连接​

ldapwhoami

成功响应

检查网络/证书

Token 获取​

kubectl get-token

成功返回 Token

检查配置

API Server 验证​

curl with Token

200/403

检查 OIDC 配置

时间同步​

date

偏差 < 5s

同步时间

网络延迟​

ping/nc

< 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

🎯 总结:完整的关联与流程

五大核心关系

  1. LDAP ↔ Dex:用户存储与认证

    • Dex 查询 LDAP 验证用户

    • LDAP 返回用户和组信息

    • 通过 LDAP connector 配置连接

  2. Dex ↔ kubectl-oidc-login:OIDC 认证流程

    • kubectl-oidc-login 启动认证

    • Dex 处理认证请求

    • Dex 返回 Token

    • 通过 OIDC 协议通信

  3. Dex ↔ API Server:Token 验证

    • API Server 验证 Token 签名

    • 验证 Token 的 iss/aud/exp

    • 通过公钥端点获取验证密钥

  4. kubectl ↔ API Server:API 请求

    • kubectl 携带 Token 请求

    • API Server 处理业务逻辑

    • 通过 HTTPS + Bearer Token

  5. RBAC ↔ API Server:权限控制

    • API Server 检查 RBAC

    • 匹配用户/组与权限

    • 决定是否允许操作

关键成功因素

  1. 配置一致性:Issuer、Client ID 必须一致

  2. 时间同步:所有系统时间偏差 < 5秒

  3. 网络连通:组件间网络可达

  4. 声明匹配:Token 声明与 RBAC 配置匹配

  5. 证书/签名:Token 签名验证正确

故障树

认证失败
├── 网络问题
│   ├── Dex 不可达
│   ├── LDAP 不可达
│   └── 端口未开放
├── 配置问题
│   ├── Issuer 不匹配
│   ├── Client ID 不匹配
│   └── 声明配置错误
├── 时间问题
│   ├── 系统时间不同步
│   └── Token 过期
└── 证书问题
    ├── 签名验证失败
    └── 证书不信任

权限失败
├── RBAC 配置
│   ├── 组名不匹配
│   ├── 权限不足
│   └── 绑定错误
└── Token 问题
    ├── 组声明缺失
    └── 声明名错误

通过理解这些关联关系和完整流程,可以更好地设计、部署和排查基于 LDAP + Dex 的 Kubernetes 认证授权系统。

posted on 2026-03-09 16:39  luzhouxiaoshuai  阅读(36)  评论(0)    收藏  举报

导航