📜 ⬆️ ⬇️

Screw LDAP authentication to Kubernetes


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.


Install keycloak


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 .


Federation setting


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


OptionValue
Namekubernetes
Display nameKubernetes
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:


OptionValue
Console Display Namefreeipa.example.org
VendorRed Hat Directory Server
UUID LDAP attributeipauniqueid
Connection URLldaps://freeipa.example.org
Users DNcn=users,cn=accounts,dc=example,dc=org
Bind DNuid=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


OptionValue
Ldap attriburegivenName

Now enable mapping groups:


User federation -> freeipa.example.org -> Mappers -> Create


OptionValue
Namegroups
Mapper typegroup-ldap-mapper
LDAP Groups DNcn=groups,cn=accounts,dc=example,dc=org
User Groups Retrieve StrategyGET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE

This completes the federation setup, let's proceed to the client setup.


Client setup


Create a new client (the application that will receive users from Keycloak). Moving on:


Clients -> Create


OptionValue
Client IDkubernetes
Access Typeconfidenrial
Root URLhttp://kubernetes.example.org/
Valid Redirect URIshttp://kubernetes.example.org/*
Admin URLhttp://kubernetes.example.org/

Also create a scope for the groups:


Client Scopes -> Create


OptionValue
TemplateNo template
Namegroups
Full group pathfalse

And set up a mapper for them:


Client Scopes -> groups -> Mappers -> Create


OptionValue
Namegroups
Mapper typeGroup membership
Token claim namegroups

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


OptionValue
Authorization EnabledON

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.


Kubernetes Setup


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.


Initial authorization


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.


RBAC setup


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 :


kubernetes-default-namespace-admins.yaml
 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.


Configure auth-proxy


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:


dashboard-proxy.yaml
 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/