四、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​

身份提供商地址

--oidc-issuer-url

--oidc-issuer-url

✅ 是

Client ID​

客户端标识

--oidc-client-id

--oidc-client-id

✅ 是

Client Secret​

客户端密钥

--oidc-client-secret

不需要

❌ 否

用户名声明​

识别用户的字段

不配置

--oidc-username-claim

-

组声明​

识别用户组的字段

不配置

--oidc-groups-claim

-

签名算法​

Token 签名算法

自动协商

--oidc-signing-algs

建议一致

Scope​

请求的权限范围

--oidc-extra-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

参数含义:

参数

含义

作用

--oidc-issuer-url​

Dex 服务的 URL

告诉 kubectl 从哪里获取 Token

--oidc-client-id​

在 Dex 中注册的客户端 ID

标识哪个应用在请求 Token

--oidc-client-secret​

客户端密钥

证明客户端身份,防止滥用

--oidc-extra-scope​

请求的权限范围

控制返回 Token 中包含的信息

--skip-open-browser​

不自动打开浏览器

适用于无 GUI 环境

--listen-address​

回调监听地址

接收 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

参数含义:

参数

含义

作用

--oidc-issuer-url​

Dex 服务的 URL

验证 Token 的签发者是否正确

--oidc-client-id​

客户端 ID

验证 Token 的目标受众是否正确

--oidc-username-claim​

用户名字段

从 Token 的哪个字段提取用户名

--oidc-groups-claim​

组字段

从 Token 的哪个字段提取用户组

--oidc-signing-algs​

签名算法

指定可接受的 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. 标识身份提供商​

--oidc-issuer-url

--oidc-issuer-url

✅

2. 标识客户端​

--oidc-client-id

--oidc-client-id

✅

3. 证明客户端身份​

--oidc-client-secret

不需要

❌

4. 请求用户信息​

--oidc-extra-scope

不需要

❌

5. 提取用户信息​

不需要

--oidc-username-claim

-

6. 提取组信息​

不需要

--oidc-groups-claim

-

7. 验证签名​

自动协商

--oidc-signing-algs

建议


✅ 最佳实践检查清单

部署前检查

  • [ ] Issuer URL 完全一致(协议、主机、端口)

  • [ ] Client ID 完全一致

  • [ ] Dex 客户端配置包含正确的 redirectURIs

  • [ ] Token 中包含 API Server 配置的声明字段

  • [ ] 所有系统时间同步(偏差 < 5 秒)

  • [ ] 网络连通性正常

  • [ ] 使用正确的签名算法

部署后验证

  • [ ] kubectl 可以成功获取 Token

  • [ ] Token 可以被正确解码

  • [ ] Token 中包含正确的声明

  • [ ] API Server 接受 Token

  • [ ] RBAC 权限正确应用

  • [ ] 日志无错误信息

问题排查顺序

  1. 网络连通性:客户端 → Dex,API Server → Dex

  2. 时间同步:所有节点时间偏差

  3. 配置一致性:Issuer URL 和 Client ID

  4. 声明匹配:Token 内容与 API Server 配置

  5. RBAC 配置:组名匹配和权限绑定

  6. 日志分析:Dex、API Server、kubectl 日志

通过确保这些配置的正确性和一致性,可以建立可靠的 OIDC 认证流程。

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

导航