A small tutorial on how to use Keycloak can connect Kubernetes with your LDAP server and configure the import of users and groups. This will allow you to configure RBAC for your users and use auth-proxy to protect the Kubernetes Dashboard and other applications that do not know how to authorize themselves.
Suppose you already have an LDAP server. This could be Active Directory, FreeIPA, OpenLDAP, or anything else. If you do not have an LDAP server, then in principle you can create users directly in the Keycloak interface, or use public oidc providers (Google, Github, Gitlab), the result will be almost the same.
First of all, we install Keycloak itself, the installation can be performed separately, and immediately into the Kubernetes cluster, as a rule, if you have several Kubernetes clusters, it would be easier to install it separately. On the other hand, you can always use the official helm-chart and set it directly in your cluster.
To store Keycloak data you need a database. The default is h2
(all data is stored locally), but it is also possible to use postgres
, mysql
or mariadb
.
If you decided to install Keycloak separately, you will find more detailed instructions in the official documentation .
First of all, create a new realm. Realm is the space of our application. Each application can have its realm with different users and authorization settings. The master realm is used by Keycloak itself and using it for something else is wrong.
Click Add realm
Option | Value |
---|---|
Name | kubernetes |
Display name | Kubernetes |
HTML Display Name | <img src="https://kubernetes.io/images/nav_logo.svg" width="400" \> |
Kubernetes by default checks whether the user has confirmed email or not. Since we use our own LDAP server, this check will almost always return false
. Let's turn off the view of this parameter in Kubernetes:
Client scopes -> Email -> Mappers -> Email verified (Delete)
Now let's set up the federation, for this we go to:
User federation -> Add provider ... -> ldap
I will give an example of settings for FreeIPA:
Option | Value |
---|---|
Console Display Name | freeipa.example.org |
Vendor | Red Hat Directory Server |
UUID LDAP attribute | ipauniqueid |
Connection URL | ldaps://freeipa.example.org |
Users DN | cn=users,cn=accounts,dc=example,dc=org |
Bind DN | uid=keycloak-svc,cn=users,cn=accounts,dc=example,dc=org |
Bind credential | <password> |
Allow Kerberos authentication: | on |
Kerberos Realm: | EXAMPLE.ORG |
Server Principal: | HTTP/freeipa.example.org@EXAMPLE.ORG |
KeyTab: | /etc/krb5.keytab |
The user keycloak-svc
must be created in advance on our LDAP server.
In the case of Active Directory, simply select Vendor: Active Directory and the necessary settings will be substituted into the form automatically.
Click Save
Now let's go:
User federation -> freeipa.example.org -> Mappers -> First Name
Option | Value |
---|---|
Ldap attribure | givenName |
Now enable mapping groups:
User federation -> freeipa.example.org -> Mappers -> Create
Option | Value |
---|---|
Name | groups |
Mapper type | group-ldap-mapper |
LDAP Groups DN | cn=groups,cn=accounts,dc=example,dc=org |
User Groups Retrieve Strategy | GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE |
This completes the federation setup, let's proceed to the client setup.
Create a new client (the application that will receive users from Keycloak). Moving on:
Clients -> Create
Option | Value |
---|---|
Client ID | kubernetes |
Access Type | confidenrial |
Root URL | http://kubernetes.example.org/ |
Valid Redirect URIs | http://kubernetes.example.org/* |
Admin URL | http://kubernetes.example.org/ |
Also create a scope for the groups:
Client Scopes -> Create
Option | Value |
---|---|
Template | No template |
Name | groups |
Full group path | false |
And set up a mapper for them:
Client Scopes -> groups -> Mappers -> Create
Option | Value |
---|---|
Name | groups |
Mapper type | Group membership |
Token claim name | groups |
Now we need to enable the mapping group in our client scope:
Clients -> kubernetes -> Client Scopes -> Default Client Scopes
Select groups in Available Client Scopes , click Add selected
Now we will configure authentication of our application, we pass:
Clients -> kubernetes
Option | Value |
---|---|
Authorization Enabled | ON |
Press save and this completes the client setup, now on the tab
Clients -> kubernetes -> Credentials
You can get Secret which we will use in the future.
Setting up Kubernetes for OIDC authorization is quite trivial and is not something very complicated. All you need is to put the CA certificate of your OIDC server in /etc/kubernetes/pki/oidc-ca.pem
and add the necessary options for kube-apiserver.
To do this, update /etc/kubernetes/manifests/kube-apiserver.yaml
on all your wizards:
... spec: containers: - command: - kube-apiserver ... - --oidc-ca-file=/etc/kubernetes/pki/oidc-ca.pem - --oidc-client-id=kubernetes - --oidc-groups-claim=groups - --oidc-issuer-url=https://keycloak.example.org/auth/realms/kubernetes - --oidc-username-claim=email ...
And also update the kubeadm config in the cluster, so as not to lose these settings when updating:
kubectl edit -n kube-system configmaps kubeadm-config
... data: ClusterConfiguration: | apiServer: extraArgs: oidc-ca-file: /etc/kubernetes/pki/oidc-ca.pem oidc-client-id: kubernetes oidc-groups-claim: groups oidc-issuer-url: https://keycloak.example.org/auth/realms/kubernetes oidc-username-claim: email ...
This completes the Kubernetes setup. You can repeat these actions in all your Kubernetes clusters.
After these actions, you will already have a Kubernetes cluster with configured OIDC authorization. The only time that your users do not yet have a customized client, like their own kubeconfig. To solve this problem, you need to configure the automatic issuance of kubeconfig users after successful authorization.
To do this, you can use special web applications that allow you to authenticate the user and then download the finished kubeconfig. One of the most convenient is Kuberos , it allows you to describe all Kubernetes clusters in one config and easily switch between them.
To configure Kuberos, it suffices to describe the template for kubeconfig and run it with the following parameters:
kuberos https://keycloak.example.org/auth/realms/kubernetes kubernetes /cfg/secret /cfg/template
For more information, see Usage on Github.
It is also possible to use kubelogin if you want to perform authorization directly on the user's computer. In this case, the user will open a browser with an authorization form on localhost.
The resulting kubeconfig can be checked on the jwt.io website. Just copy the value of users[].user.auth-provider.config.id-token
from your kubeconfig to the form on the site and immediately get a decryption.
When configuring RBAC, you can refer to both the user name (the name
field in the jwt-token) and the user group (the groups
field in the jwt-token). Here is an example of setting permissions for the group kubernetes-default-namespace-admins
:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: default-admins namespace: default rules: - apiGroups: - '*' resources: - '*' verbs: - '*' --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kubernetes-default-namespace-admins namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: default-admins subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: kubernetes-default-namespace-admins
More examples for RBAC can be found in the official Kubernetes documentation.
There is a wonderful project keycloak-gatekeeper , which allows you to protect any application, allowing the user to authenticate with the OIDC server. I will show how you can configure it using the Kubernetes Dashboard as an example:
apiVersion: extensions/v1beta1 kind: Deployment metadata: labels: ksonnet.io/component: proxy name: kubernetes-dashboard-proxy spec: replicas: 1 template: metadata: labels: app: kubernetes-dashboard-proxy spec: containers: - args: - --listen=0.0.0.0:80 - --discovery-url=https://keycloak.example.org/auth/realms/kubernetes - --client-id=kubernetes - --client-secret=<your-client-secret-here> - --redirection-url=https://kubernetes-dashboard.example.org - --enable-refresh-tokens=true - --encryption-key=ooTh6Chei1eefooyovai5ohwienuquoh - --upstream-url=https://kubernetes-dashboard.kube-system.svc.cluster.local - --resources=uri=/* image: keycloak/keycloak-gatekeeper name: kubernetes-dashboard-proxy ports: - containerPort: 80 livenessProbe: httpGet: path: /oauth/health port: 80 initialDelaySeconds: 3 timeoutSeconds: 2 readinessProbe: httpGet: path: /oauth/health port: 80 initialDelaySeconds: 3 timeoutSeconds: 2 --- apiVersion: v1 kind: Service metadata: labels: ksonnet.io/component: proxy name: kubernetes-dashboard-proxy spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: kubernetes-dashboard-proxy type: ClusterIP
Source: https://habr.com/ru/post/441112/