Kubernetes VIM OpenID Token Auth 使用指南

概述

Kubernetes 有多种认证策略。本文档描述了 Tacker 如何使用 OpenID token 与 Kubernetes 进行认证。

Kubernetes 的 OpenID token 认证依赖于外部 OpenID 提供者,并且 Keycloak 在本文档中充当 OpenID 提供者。

准备工作

先决条件

应安装以下软件包

  • Kubernetes

  • Docker

启动 Keycloak

创建 CSR 配置文件 csr.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]
IP.1 = 127.0.0.1
IP.2 = 192.168.2.33 # Host IP

为 Keycloak 生成 SSL 证书

#!/bin/bash

req_conf=csr.cnf
ssl_dir=/etc/keycloak/ssl
key_file=$ssl_dir/keycloak.key
csr_file=$ssl_dir/keycloak.csr
crt_file=$ssl_dir/keycloak.crt

k8s_ssl_dir=/etc/kubernetes/pki
k8s_ca_crt=$k8s_ssl_dir/ca.crt
k8s_ca_key=$k8s_ssl_dir/ca.key

# make a directory for storing certificate
mkdir -p $ssl_dir

# generate private key
openssl genrsa -out $key_file 2048

# generate certificate signing request
openssl req -new -key $key_file -out $csr_file -subj "/CN=Keycloak" \
-config $req_conf

# use Kubernetes's CA for issuing certificate
openssl x509 -req -in $csr_file -CA $k8s_ca_crt -CAkey $k8s_ca_key \
-CAcreateserial -out $crt_file -days 365 -extensions v3_req \
-extfile $req_conf

# add executeable permission to key file
chmod 755 $key_file

使用 docker 启动 Keycloak 容器

$ docker run -d \
  --net=host \
  -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \
  -e KC_HTTP_PORT=8080 -e KC_HTTPS_PORT=8443 \
  -e KC_HTTPS_CERTIFICATE_FILE=/opt/keycloak/conf/keycloak.crt \
  -e KC_HTTPS_CERTIFICATE_KEY_FILE=/opt/keycloak/conf/keycloak.key \
  -v /etc/keycloak/ssl:/opt/keycloak/conf \
  quay.io/keycloak/keycloak:18.0.2 \
  start-dev

设置 Keycloak

登录到管理控制台

创建一个 realm

  • 点击 添加 realm

  • 名称 中填写 oidc

  • 点击 创建

创建一个用户

  • 点击菜单中的 用户

  • 点击 添加用户

  • 用户名 中填写 end-user

  • 点击 保存

设置用户凭据

  • 点击 凭据

  • 使用以下值填写表单

    • 密码 : end-user

    • 确认密码 : end-user

  • 关闭临时

  • 点击 保存

设置用户属性

  • 点击 属性

  • 使用以下值填写表单

    • : name

    • : end-user

  • 点击 添加

  • 点击 保存

创建一个客户端

  • 点击菜单中的 客户端

  • 点击 创建

  • 客户端 ID 中填写 tacker

  • 点击 保存

设置客户端类型和有效的重定向 URI

  • 点击 设置

  • 访问类型 选择为 confidential

  • 有效的重定向 URI 中填写 http://*

  • 点击 保存

设置客户端映射器

  • 点击 映射器

  • 点击 创建

  • 映射器类型 选择为 用户属性

  • 使用以下值填写表单

    • 名称 : name

    • 用户属性 : name

    • Token Claim 名称 : name

  • Claim JSON 类型 选择为 String

  • 点击 保存

查看客户端密钥

  • 点击 凭据 并查看密钥。

设置 Kubernetes

将 oidc 相关启动参数添加到 kube-apiserver 清单文件中。

$ cat /etc/kubernetes/manifests/kube-apiserver.yaml

spec:
  containers:
  - command:
    - kube-apiserver
    - --oidc-issuer-url=https://192.168.2.33:8443/realms/oidc
    - --oidc-client-id=tacker
    - --oidc-username-claim=name
    - --oidc-username-prefix=-
    - --oidc-ca-file=/etc/kubernetes/ssl/ca.crt

注意

修改 kube-apiserver 清单文件后,kube-apiserver 将被重启。

创建一个集群角色绑定,以授予最终用户操作 Kubernetes 资源的权限。

  • 创建集群角色绑定文件 cluster_role_binding.yaml

    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: oidc-cluster-admin-binding
    roleRef:
      kind: ClusterRole
      name: cluster-admin
      apiGroup: rbac.authorization.k8s.io
    subjects:
    - kind: User
      name: end-user
    
  • 创建集群角色绑定

    $ kubectl create -f cluster_role_binding.yaml
    

验证

从 Keycloak 获取 token 端点

$ curl -ks -X GET https://192.168.2.33:8443/realms/oidc/.well-known/openid-configuration | jq -r .token_endpoint

结果

https://192.168.2.33:8443/realms/oidc/protocol/openid-connect/token

从 Keycloak 获取 OpenID token

$ ID_TOKEN=$(curl -ks -X POST https://192.168.2.33:8443/realms/oidc/protocol/openid-connect/token \
  -d grant_type=password -d scope=openid -d username=end-user -d password=end-user \
  -d client_id=tacker -d client_secret=A93HfOUpySm6BjPug9PJdJumjEGUJMhc | jq -r .id_token)
$ echo $ID_TOKEN

结果

eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxbC1RMy1KanQ1eHVrNzhYbUVkZDU2Mko4YXRRVF95MU1zS0JDUTBBcklnIn0.eyJleHAiOjE2NjAxMjExNTUsImlhdCI6MTY2MDEyMDg1NSwiYXV0aF90aW1lIjowLCJqdGkiOiIwZjdkNDE2My05Njk1LTQ3MGMtYmE1OC02MWI4NDM4YTU4MzQiLCJpc3MiOiJodHRwczovLzE5Mi4xNjguMi4zMzo4NDQzL3JlYWxtcy9vaWRjIiwiYXVkIjoidGFja2VyIiwic3ViIjoiOGZlZDVhYzctZDY4OS00NWM1LWE5NmQtYTlmN2M3Y2QxZTJjIiwidHlwIjoiSUQiLCJhenAiOiJ0YWNrZXIiLCJzZXNzaW9uX3N0YXRlIjoiNzhiYzhmNDEtMjc4NC00YTU5LWJjOTUtNjNkZDM5YTQ5NjNiIiwiYXRfaGFzaCI6Ik9WczJ3Q29VclU0QWxZaml0dGNQLXciLCJhY3IiOiIxIiwic2lkIjoiNzhiYzhmNDEtMjc4NC00YTU5LWJjOTUtNjNkZDM5YTQ5NjNiIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJlbmQtdXNlciJ9.SAncMlpRCLY8JlRUZ7YwirmYs5Qc-5qrvJYmyCZSiRgHyn-7cuqNan3vyVGO46Iv9Da51_Im3L5HaVJTcReeCZ2fhuzgei3yOquPugcfaqKKZEujA042Cc0pFTLS_dPl1xX3XINEcN4nGYGhGtLi8CBH0iANi-IY_VEdxogTyc9MlKgjP9Ca8eYNUPhop49GwLC-ph5vMShS9O834ywtQargb51zokQsoXAYrGBJMTWr37uMxP7UWXpYAQa82OyX3fElpueurd5WGEzGT1AhN1Ad4uIAxgD6dxFsiQYOHRSH-sByV0IwMdZoqIm4GFS6NHLj5usr6PSA5U9QpgCI7Q

使用 OpenID token 从 Kubernetes 获取所有命名空间

curl -ks -H "Authorization: Bearer $ID_TOKEN" https://192.168.2.33:6443/api/v1/namespaces

结果

{
  "kind": "NamespaceList",
  "apiVersion": "v1",
  ...omit...

查看证书

查看 Kubernetes CA 证书

$ cat /etc/kubernetes/pki/ca.crt
-----BEGIN CERTIFICATE-----
MIICwjCCAaqgAwIBAgIBADANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwdrdWJl
LWNhMB4XDTIwMDgyNjA5MzIzMVoXDTMwMDgyNDA5MzIzMVowEjEQMA4GA1UEAxMH
a3ViZS1jYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALxkeE16lPAd
pfJj5GJMvZJFcX/CD6EB/LUoKwGmqVoOUQPd3b/NGy+qm+3bO9EU73epUPsVaWk2
Lr+Z1ua7u+iib/OMsfsSXMZ5OEPgd8ilrTGhXOH8jDkif9w1NtooJxYSRcHEwxVo
+aXdIJhqKdw16NVP/elS9KODFdRZDfQ6vU5oHSg3gO49kgv7CaxFdkF7QEHbchsJ
0S1nWMPAlUhA5b8IAx0+ecPlMYUGyGQIQgjgtHgeawJebH3PWy32UqfPhkLPzxsy
TSxk6akiXJTg6mYelscuxPLSe9UqNvHRIUoad3VnkF3+0CJ1z0qvfWIrzX3w92/p
YsDBZiP6vi8CAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB/wQFMAMB
Af8wDQYJKoZIhvcNAQELBQADggEBAIbv2ulEcQi019jKz4REy7ZyH8+ExIUBBuIz
InAkfxNNxV83GkdyA9amk+LDoF/IFLMltAMM4b033ZKO5RPrHoDKO+xCA0yegYqU
BViaUiEXIvi/CcDpT9uh2aNO8wX5T/B0WCLfWFyiK+rr9qcosFYxWSdU0kFeg+Ln
YAaeFY65ZWpCCyljGpr2Vv11MAq1Tws8rEs3rg601SdKhBmkgcTAcCzHWBXR1P8K
rfzd6h01HhIomWzM9xrP2/2KlYRvExDLpp9qwOdMSanrszPDuMs52okXgfWnEqlB
2ZrqgOcTmyFzFh9h2dj1DJWvCvExybRmzWK1e8JMzTb40MEApyY=
-----END CERTIFICATE-----

查看 Keycloak 证书

$ cat /etc/keycloak/ssl/keycloak.crt
-----BEGIN CERTIFICATE-----
MIIC7TCCAdWgAwIBAgIUQK2k5uNvlRLx43LI/t3a2/A/3iQwDQYJKoZIhvcNAQEL
BQAwFTETMBEGA1UEAxMKa3ViZXJuZXRlczAeFw0yMjA4MDQwNjIwNTFaFw0yMzA4
MDQwNjIwNTFaMBMxETAPBgNVBAMMCEtleWNsb2FrMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAni7HWLn2IpUImGO1sbBf/XuqATkXSeIIRuQuFymwYPoX
BP7RowzrbfF9KUwdIKlz9IXjqb1hplumiqNy1Sc7MmrTY9Fj87MNAMlnCIvyWkjE
XVXWxGef49mqc85P2K1iuAsr2R7sDrv7SC0ch+lHclOjGDmCjKOk8qF3kD1LATWg
zf42aXb4nNF9kyIOPEbI+jX4PWhAQpEz5nIG+xIRjTHGfacjpeg0+XOK21wLAuQB
fqebJ6GxX4OzB37ZtLLgrKyBYWaWuYkWbexVRM3wEvQu8ENkvhV017iPuPHSxNWx
Y8z072XMs9j8XRQD65EVqObXyizotPRJF4slEJ9qMQIDAQABozcwNTAJBgNVHRME
AjAAMAsGA1UdDwQEAwIF4DAbBgNVHREEFDAShwR/AAABhwTAqAIhhwQKCgCMMA0G
CSqGSIb3DQEBCwUAA4IBAQBebjmNHd8sJXjvPQc3uY/3KSDpk9AYfYzhUZvcvLNg
z0llFqXHaFlMqHTsz1tOH4Ns4PDKKoRT0JIKC1FkvjzqgL+X2jWFS0NRoNyd3W3B
yHLEL7MdQqDR+tZX02EGfaGXjuy8GHIU4J2hXhohmpn6ntfiRONfY8jaEjIecPFS
IwZWXNhsDESa1zuDe0PatES/Ati8bAUpN2rb/7rsE/AeM5GXpQfOKV0XxdIeBZ82
Vf5cUDWPipvq2Q9KS+yrTvEObGtA6gKhQ4bpz3MieU3N8AtQpEKtROH7mJWMHyl2
roD1k8KeJlfvR/XcVTGFcgIdNLfKIdd99Xfi4gSaIKuw
-----END CERTIFICATE-----

使用 OpenID token 部署 CNF

请参考 CNF 使用指南 使用 OpenID token 部署 CNF。