Kubernetes 没有用户以及用户组

Kubernetes 的 RBAC 模型授权对象(Subject)是用户(User)或者用户组(Group),即使ServiceAccount 也会当作为一个虚拟 User。

通过 Kubernetes 找不到真正的用户以及用户组信息,甚至连对应的 User Resource 以及 Group Resource 都没有,所以有时候在写 rolebingding 的时候会觉得很奇怪,Subjects 需要填 User 或者Group,可是 Kubernetes 却没有办法列出可信任的 User 列表以及 Group 列表。

换句话说 Kubernetes 并没有提供用户管理和身份认证功能,除了 Service Account 外,所有的用户信息都依赖外部的用户管理系统来存储,因此通过 api-serever 根本无法列出 User 和 Group。

这样做的好处也显而易见,用户账户信息与 Kubernetes 集群松耦合,便于集成企业已有的身份认证系统,如 AD、LADP、Keycloak 等。

前置条件

《Docker 安装 Keycloak,配置 SSL/TLS》
《Kubernetes 安装 Keycloak 以及配置SSL》

Keycloak 认证信息配置

登录keycloak管理页面创建一个realm以及client,名称都为int32bit-kubernetes。其中realm类似namespace概念,实现了多租户模型,client对应一个认证主体,所有使用keycloak认证的都需要创建一个对应的client。

创建 realm 和 client

image.png

配置 secret

每个 client 会对应有一个 secret,这二者关系就是 access key 和 access secret 关系

image.png
设置 Access Type 后,注意保存此修改
image.png

创建 Role 和 User

打开 Keycloak Web 管理界面

  1. 在 Roles 中创建两个 role 分别为 int32bit-kubernetes-cluster-adminint32bit-kubernetes-readonly

image.png

  1. 在 Users 中创建两个用户 k8s-admink8s-readonlly

image.png

  1. k8s-admin 关联 int32bit-kubernetes-cluster-admin role,k8s-readonlly 关联 int32bit-kubernetes-readonly role。

image.png
image.png

  1. 为了支持 Kubernetes 的 Group 认证,需要在 client 中添加 mappers 字段 groups

    这里之所以映射 User Realm Role,而不是 Group MemberShip,是因为 Group 会在 id_token 中添加前缀 /,如 /test-group1, /test-group2,这个暂时没想到怎么处理,或许有更好的办法。 更新:《Keycloak User Groups 实现 K8s RBAC》

image.png
image.png

设置 User Password

image.png

获取 Token

  1. curl -sSLk \
  2. -d "client_id=int32bit-kubernetes" \
  3. -d "client_secret=5ef28ad1-5ed5-4227-99ca-4ac13390edc6" \
  4. -d "response_type=code token" \
  5. -d "grant_type=password" \
  6. -d "username=k8s-admin" \
  7. -d "password=k8s-admin" \
  8. -d "scope=openid" \
  9. https://192.168.56.10:8443/auth/realms/int32bit-kubernetes/protocol/openid-connect/token

image.png
其中返回的 id_token,在后面 Kubernetes 对接中非常重要,它也是一个 JWT Token,解码后的内容如下:

你可以打开 https://jwt.io,对 id_token 进行解码

其中,JWT Token 包含了 Groups 信息

"groups": [
    "int32bit-kubernetes-cluster-admin"
 ],
{
  "exp": 1636781925,
  "iat": 1636781625,
  "auth_time": 0,
  "jti": "7d1825d9-d28f-479c-9931-cf7ad12aaf7e",
  "iss": "https://192.168.56.10:8443/auth/realms/int32bit-kubernetes",
  "aud": "int32bit-kubernetes",
  "sub": "2bffc6a7-1b0b-493c-b29b-cf55f7b922f8",
  "typ": "ID",
  "azp": "int32bit-kubernetes",
  "session_state": "52aaabff-4bdc-4157-b387-0f72ce624b62",
  "at_hash": "J4608t81sDbP3A3tWpk3BA",
  "acr": "1",
  "sid": "52aaabff-4bdc-4157-b387-0f72ce624b62",
  "email_verified": false,
  "groups": [
    "int32bit-kubernetes-cluster-admin"
  ],
  "preferred_username": "k8s-admin"
}

Kubernetes 集成 keycloak 认证

在 api-server 中增加如下命令行启动参数

注意:--oidc-issuer-url 需要使用 https 协议

- --oidc-issuer-url=https://192.168.56.10:8443/auth/realms/int32bit-kubernetes
- --oidc-client-id=int32bit-kubernetes
- --oidc-username-claim=preferred_username
- --oidc-username-prefix=-
- --oidc-groups-claim=groups
- --oidc-ca-file=/etc/kubernetes/pki/keycloak.crt

相对应的在 Kubernetes 创建两个 clusterrolebinging

cluster-admin

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:masters
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: int32bit-kubernetes-cluster-admin

cluster-readonly

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-readonly
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: view
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: int32bit-kubernetes-readonly

使用 OpenId Connect 认证

生成config文件:

kubectl config set-credentials oidc \
   --auth-provider=oidc \
   --auth-provider-arg=idp-issuer-url=https://192.168.56.10:8443/auth/realms/int32bit-kubernetes \
   --auth-provider-arg=client-id=int32bit-kubernetes \
   --auth-provider-arg=client-secret=5ef28ad1-5ed5-4227-99ca-4ac13390edc6

为了便于登录,下载 kube-login插件

kubectl krew install oidc-login

如果你没有安装 kubectl krew:《Install kubectl krew》
切换到 oidc 用户

kubectl config set-context --current --user=oidc

此时可以直接通过如下命令进行登录

kubectl oidc-login --username username --password password

你可能会遇到一个错误,这是自签证书的原因

[root@master kubernetes]# kubectl oidc-login --username k8s-admin --password k8s-admin
NOTE: You can use the credential plugin mode for better user experience.
Kubectl automatically runs kubelogin and you do not need to run kubelogin explicitly.
See https://github.com/int128/kubelogin for more.
error: login: authentication error: oidc error: oidc discovery error: Get "https://192.168.56.10:8443/auth/realms/int32bit-kubernetes/.well-known/openid-configuration": x509: certificate signed by unknown authority

使用 --insecure-skip-tls-verify=true 跳过验证

kubectl oidc-login --username k8s-admin --password k8s-admin --insecure-skip-tls-verify=true