<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stelios Mantzouranis</title>
    <description>The latest articles on DEV Community by Stelios Mantzouranis (@stelios_mantzouranis).</description>
    <link>https://dev.to/stelios_mantzouranis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3179185%2F36e6b5a0-4ba5-4852-827e-4cfc17ce3233.png</url>
      <title>DEV Community: Stelios Mantzouranis</title>
      <link>https://dev.to/stelios_mantzouranis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stelios_mantzouranis"/>
    <language>en</language>
    <item>
      <title>Kubernetes cluster Tenancy and OIDC Login made easy with Capsule, Keycloak and Kubelogin</title>
      <dc:creator>Stelios Mantzouranis</dc:creator>
      <pubDate>Thu, 05 Jun 2025 08:34:27 +0000</pubDate>
      <link>https://dev.to/agileactors/kubernetes-cluster-tenancy-and-oidc-login-made-easy-with-capsule-keycloak-and-kubelogin-376p</link>
      <guid>https://dev.to/agileactors/kubernetes-cluster-tenancy-and-oidc-login-made-easy-with-capsule-keycloak-and-kubelogin-376p</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As organizations pursue greater scalability and operational efficiency, microservices have become a preferred architectural approach. This shift often leads to development teams being organized around individual microservices, with each team owning and maintaining its specific service. These microservices are typically deployed within a shared Kubernetes cluster. &lt;/p&gt;

&lt;p&gt;However, this setup can introduce logistical challenges for cluster administrators. Team members often have varying levels of familiarity with Kubernetes concepts, and developer experience can differ significantly across teams. As a result, there is a growing need to isolate each team within its own partition of the cluster while still providing them with &lt;strong&gt;API&lt;/strong&gt; access (for &lt;strong&gt;kubectl **or **k9s&lt;/strong&gt;) to manage their workloads independently. &lt;/p&gt;

&lt;p&gt;In this article, you’ll learn how to partition a Kubernetes cluster into separate tenants and provide tenant administrators and users with &lt;strong&gt;API&lt;/strong&gt;&lt;br&gt;
access to their specific environments. This will be achieved using Capsule for multi-tenancy, Keycloak for user management, and &lt;strong&gt;kubelogin&lt;/strong&gt; for dynamic context creation. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up a development environment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before setting up the development environment, ensure that &lt;strong&gt;kubectl&lt;/strong&gt; and &lt;strong&gt;helm&lt;/strong&gt; are installed on your local machine. &lt;/p&gt;

&lt;p&gt;To test our solution, we’ll need a local development environment that simulates a Kubernetes cluster. There are several options available, but one of the most popular and user-friendly tools is &lt;strong&gt;Minikube&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;You can follow this guide to install Minikube: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://minikube.sigs.k8s.io/docs/start/?arch=%2Fwindows%2Fx86-64%2Fstable%2F.exe+download" rel="noopener noreferrer"&gt;Mac/Windows/Linux: Minikube official installation guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Optional&lt;/strong&gt;: It is recommended to use &lt;strong&gt;k9s&lt;/strong&gt; to easily view, edit and delete our cluster resources without typing &lt;strong&gt;kubectl&lt;/strong&gt; commands. You will find installation instructions &lt;a href="https://k9scli.io/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installing Dependencies to our Minikube cluster&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Installing Keycloak&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can now start by deploying Keycloak, which will serve as our identity provider for managing users and authentication. &lt;/p&gt;

&lt;p&gt;We’ll use Bitnami’s &lt;strong&gt;Helm&lt;/strong&gt; chart for Keycloak, which makes the installation and configuration process straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create ns keycloak
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install keycloak bitnami/keycloak -n keycloak --set auth.adminUser=admin --set auth.adminPassword=admin123 --set postgresql.enabled=true --set postgresql.auth.postgresPassword=admin123 --set postgresql.auth.username=keycloak --set postgresql.auth.password=keycloak123 --set postgresql.auth.database=keycloak
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a while to verify installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods -n keycloak 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Installing Capsule&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://projectcapsule.dev/" rel="noopener noreferrer"&gt;Capsule&lt;/a&gt; is a Kubernetes multi-tenancy operator that helps isolate workloads between teams while sharing the same cluster. In this step, we’ll install Capsule and configure it to recognize three specific user groups the default one &lt;strong&gt;capsule.clastix.io&lt;/strong&gt;, &lt;strong&gt;group-a&lt;/strong&gt; and &lt;strong&gt;group-b&lt;/strong&gt;.    &lt;/p&gt;

&lt;p&gt;Save the following as &lt;strong&gt;capsule-values.yaml&lt;/strong&gt; &lt;br&gt;
This file contains the full configuration for Capsule. It defines security contexts, CRD behaviour, user group access, and more.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global:
  jobs:
    kubectl:
       ttlSecondsAfterFinished: 60
manager:
  options:
    forceTenantPrefix: true
    capsuleUserGroups: ["capsule.clastix.io", "group-a", "group-b"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Capsule with configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add projectcapsule https://projectcapsule.github.io/charts 
helm repo update   
kubectl create ns capsule-system 
helm install capsule projectcapsule/capsule -n capsule-system --version 0.7.4 -f capsule-values.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a while to verify installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods -n capsule-system 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the Capsule manager pod running in the capsule-system namespace. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Install kubelogin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To create the kubectl contexts dynamically when authenticating via OIDC we will need to install kubelogin, which works as an add-on of our kubectl tool. The installation instructions can be found &lt;a href="https://github.com/int128/kubelogin" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up OIDC configuration with Minikube + Keycloak + Kube OIDC Login&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install Ingress Controller in Minikube&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to provide an HTTPS secure &lt;strong&gt;OIDC_ISSUER_URL&lt;/strong&gt; to our Minikube cluster API Server, we will need first to configure our minikube installation with an ingress controller enabled.&lt;/p&gt;

&lt;p&gt;While the minikube cluster is up and running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube addons enable ingress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a while an ingress controller will be installed in our minikube cluster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Install mkcert and create a local certificate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/FiloSottile/mkcert" rel="noopener noreferrer"&gt;Mkcert&lt;/a&gt; is a zero-config tool that will allow us to create a local certificate.&lt;/p&gt;

&lt;p&gt;After installing we will use it in order to create a certificate for keycloak.local.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkcert -cert-file tls.crt -key-file tls.key keycloak.local 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Reconfigure Keycloak to include Ingress configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With the certificate "at hand" we will update our keycloak installation to include ingress configuration.&lt;/p&gt;

&lt;p&gt;But first let us create a tls secret for the certificate&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create secret tls keycloak-tls --cert=tls.crt --key=tls.key --namespace=keycloak 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And afterwards update the existing keycloak configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm upgrade keycloak bitnami/keycloak -n keycloak --set auth.adminUser=admin --set auth.adminPassword=admin123 --set postgresql.enabled=true --set postgresql.auth.postgresPassword=admin123 --set postgresql.auth.username=keycloak --set postgresql.auth.password=keycloak123 --set postgresql.auth.database=keycloak --set ingress.enabled=true --set ingress.ingressClassName=nginx --set ingress.tls=true --set ingress.extraTls[0].hosts[0]=keycloak.local --set ingress.extraTls[0].secretName=keycloak-tls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our Keycloak server is exposed but our browser needs to somehow recognise the minikube ip as keycloak.local. That is achieved by editing the &lt;strong&gt;C:\Windows\System32\drivers\etc\hosts&lt;/strong&gt; file and adding a line in the following format "Minikube IP keycloak.local". You can get the &lt;strong&gt;minikube&lt;/strong&gt; ip by using the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube ip 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a brief moment you should be able to see keycloak login page in your browser at &lt;a href="https://keycloak.local" rel="noopener noreferrer"&gt;https://keycloak.local&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Create our test realm and user&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since we can view our keycloak installation front-end, we will use it to create our first test user. (Remember that username is admin and password is admin123) But first we will need to create a test realm, in order to do that we will navigate as following &lt;strong&gt;Manage realms&lt;/strong&gt;&amp;gt;&lt;strong&gt;Create Realm&lt;/strong&gt;. Then fill out the form:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14k0pa84ui841ut5qxg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14k0pa84ui841ut5qxg3.png" alt="Screenshot of keycloak realm creation" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Afterwards we wil navigate to &lt;strong&gt;Users&lt;/strong&gt;&amp;gt;&lt;strong&gt;Add User&lt;/strong&gt; and submit the creation form as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljcrx8kp8ngong4j3pst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljcrx8kp8ngong4j3pst.png" alt="Screenshot of keycloak user creation" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok so having done that we need to configure a password for our user, by nagivating to &lt;strong&gt;Users&lt;/strong&gt;&amp;gt;&lt;strong&gt;Our user&lt;/strong&gt;&amp;gt;&lt;strong&gt;Credentials&lt;/strong&gt;&amp;gt;&lt;strong&gt;Set Password&lt;/strong&gt; where we will add our password as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12fwzr6an0n0qmva2c31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12fwzr6an0n0qmva2c31.png" alt="Screenshot of password creation in keycloak" width="710" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important Notice&lt;/strong&gt;: Keycloak is a very active project and these instructions may be outdated at time of reading.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Create a Kubernetes client&lt;/strong&gt;&lt;br&gt;
In Keycloak, a client represents an application or service that wants to authenticate users or access protected resources.&lt;br&gt;
Clients can be web applications, mobile apps, APIs, or any system that needs to integrate with Keycloak for authentication and authorization. Each client is configured with specific settings like redirect URIs, authentication flows, and access permissions that define how it can interact with Keycloak's identity and access management features.&lt;br&gt;
So we will create a client name Kubernetes. By clicking on &lt;strong&gt;Clients&lt;/strong&gt;&amp;gt;&lt;strong&gt;Create Client&lt;/strong&gt; we will create the client as follows page per page.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fighf348iarxhedr6i01i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fighf348iarxhedr6i01i.png" alt=" " width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdh3rj8bkxkyu6vq1no5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdh3rj8bkxkyu6vq1no5h.png" alt=" " width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk4nh8gdbwb6nt9ttx7o1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk4nh8gdbwb6nt9ttx7o1.png" alt=" " width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Create a Kubernetes client dedicated mapper&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Keycloak mapper dedicated to one client is a configuration that defines how user data (like roles, attributes, or groups) is included in tokens only for a specific client. It customizes the token content that the client receives, without affecting others.&lt;br&gt;
First of all we need to navigate to &lt;strong&gt;Clients&lt;/strong&gt;&amp;gt;&lt;strong&gt;kubernetes&lt;/strong&gt;&amp;gt;&lt;strong&gt;Client scopes&lt;/strong&gt;&amp;gt;&lt;strong&gt;kubernetes-dedicated&lt;/strong&gt;&amp;gt;&lt;strong&gt;Configure a new mapper&lt;/strong&gt;. There will select &lt;strong&gt;group membership&lt;/strong&gt; and fill it out as follows:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2uznv07utvx2vikw5oj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2uznv07utvx2vikw5oj.png" alt="Screenshot of keycloak app" width="800" height="495"&gt;&lt;/a&gt;&lt;br&gt;
Afterwards we will repeat the process and select &lt;strong&gt;audience&lt;/strong&gt; and fill it out as follows:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frgtxa2brng6nvbmlwv0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frgtxa2brng6nvbmlwv0r.png" alt="screenshot of keycloak app" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Test our user and client setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to execute this step we will need first to export some variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export KEYCLOAK=keycloak.local
export REALM=demo
export OIDC_ISSUER=${KEYCLOAK}/realms/${REALM}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then execute the command below. Keep in mind that you can find your &lt;strong&gt;CLIENT_SECRET&lt;/strong&gt; by navigating to &lt;strong&gt;Clients&lt;/strong&gt; &amp;gt; &lt;strong&gt;Kubernetes&lt;/strong&gt; &amp;gt; &lt;strong&gt;Credentials&lt;/strong&gt; and copy it to your clipboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -k -s https://${OIDC_ISSUER}/protocol/openid-connect/token \
     -d grant_type=password \
     -d response_type=id_token \
     -d scope=openid \
     -d client_id=kubernetes \
     -d client_secret=${OIDC_CLIENT_SECRET} \
     -d username=test \
     -d password=test | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expected result is like the one below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"access_token":"**token gibberish**","not-before-policy":0,"session_state":"e9cfe1a8-5d84-41db-a2ef-0cac8aa7787d","scope":"openid email audience groups profile"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: It is critical that you see groups and audience in the request's response. We will leverage this info later for Capsule integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Configure Minikube API Server to use our Keycloak server as its OIDC Issuer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To authenticate our users based on Keycloak's response we will need to make our Kube API server to trust Keycloak.&lt;/p&gt;

&lt;p&gt;First things first we will need to create a custom directory in our &lt;strong&gt;minikube&lt;/strong&gt; node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube ssh -- sudo mkdir -p /var/lib/minikube/certs/custom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that we will need to copy the tls.crt file ,that we used as a certificate, to our &lt;strong&gt;minikube&lt;/strong&gt; node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube cp /path/to/tls.crt /var/lib/minikube/certs/custom/tls.crt 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally we will restart our &lt;strong&gt;minikube&lt;/strong&gt; cluster with our new configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube start --extra-config=apiserver.oidc-issuer-url=https://keycloak.local/realms/demo --extra-config=apiserver.oidc-username-claim=preferred_username --extra-config=apiserver.oidc-ca-file=/var/lib/minikube/certs/custom/tls.crt --extra-config=apiserver.oidc-groups-claim=groups --extra-config=apiserver.oidc-username-prefix=- --extra-config=apiserver.oidc-client-id=kubernetes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more details on the matter of minikube oidc connect you can find information &lt;a href="https://minikube.sigs.k8s.io/docs/tutorials/openid_connect_auth/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Connect to the cluster via kube oidc login&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now it is time to validate if we can login via kube oidc-login to our cluster via Keycloak.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl oidc-login setup --oidc-issuer-url=https://keycloak.local/realms/demo --oidc-client-id=kubernetes --oidc-client-secret=$OIDC_CLIENT_SECRET --certificate-authority=./tls.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you were prompted to visit localhost:8000 and authenticated with username test and password test. Then congrats you have succesfully connected your kubectl to the minikube cluster via Keycloak. That is great, but we are not done yet. Now it is time to setup the tenancy-side of things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuring Cluster Tenancy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Back when we configured Capsule we specified 3 different &lt;strong&gt;capsuleUserGroups&lt;/strong&gt; in our YAML configuration (&lt;strong&gt;capsule-values.yaml&lt;/strong&gt;).&lt;br&gt;
These 3 groups are the key to partioning the cluster. So we will leverage them in order to complete our endeavour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create Keycloak User Groups&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These 3 groups should not only be part of Capsule but also of Keycloak, therefore we will navigate to &lt;strong&gt;Groups&lt;/strong&gt;&amp;gt;&lt;strong&gt;Create Group&lt;/strong&gt;. We will create a group called &lt;strong&gt;capsule.clastix.io&lt;/strong&gt;. After creating the group we will click &lt;strong&gt;capsule.clastix.io&lt;/strong&gt; and create two &lt;strong&gt;child&lt;/strong&gt; groups one called &lt;strong&gt;group-a&lt;/strong&gt; and called &lt;strong&gt;group-b&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Create Capsule Tenants&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A tenant is &lt;strong&gt;Capsule&lt;/strong&gt;'s way of partitioning the cluster and designating partition (tenant) admins. More information about the kubernetes resource can be found &lt;a href="https://projectcapsule.dev/docs/tenants/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. We will create two tenants one called &lt;strong&gt;group-a&lt;/strong&gt; and one called &lt;strong&gt;group-b&lt;/strong&gt;. Copy the code blocks below into a yaml file and then use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f /path/to/file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
apiVersion: capsule.clastix.io/v1beta2
kind: Tenant
metadata:
  name: group-a
spec:
  owners:
  - name: group-a
    kind: Group
---
apiVersion: capsule.clastix.io/v1beta2
kind: Tenant
metadata:
  name: group-b
spec:
  owners:
  - name: group-b
    kind: Group
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Create our tenant admins&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our test user has proven invaluable so far, but we will need to create two more users in our keycloak demo realm. You can follow the exact same process for our new users with the only addition being that you can make them join groups on the user creation form. Choose the group that corresponds to their name accordingly. The article will be referencing the two new users from now on as &lt;strong&gt;group-a-admin&lt;/strong&gt; and &lt;strong&gt;group-b-admin&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Login as group-a admin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to login as group-a tenant admin initiate the OIDC Login process with the same command as before from your terminal. In the login page use the &lt;strong&gt;group-a&lt;/strong&gt; credentials to login. You will be prompted to run the following command by kubelogin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl config set-credentials oidc \
  --exec-api-version=client.authentication.k8s.io/v1 \
  --exec-interactive-mode=Never \
  --exec-command=kubectl \
  --exec-arg=oidc-login \
  --exec-arg=get-token \
  --exec-arg="--oidc-issuer-url=https://keycloak.local/realms/demo" \
  --exec-arg="--oidc-client-id=kubernetes" \
  --exec-arg="--oidc-client-secret=mVBu9OyoBX6YPmuD0TgwZtNRHKjNAoc9" \
  --exec-arg="--certificate-authority=./tls.crt"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will setup user credentials for our oidc user which we can use to login as anybody that we have the credentials for. But before testing it we need to configure our kubectl context. Here is the kubectl command to configure it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl config set-context oidc@minikube --cluster='minikube'  --namespace='default' --user='oidc'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the login by first changing your kubectl context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl config use-context oidc@minikube 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create ns test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the result was the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error from server (Forbidden): admission webhook "namespaces.projectcapsule.dev" denied the request: The namespace doesn't match the tenant prefix, expected group-a-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then congrats you have managed to configure Tenancy in the cluster. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experimenting with our solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First of all, let us start by creating a group-a tenant namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create ns group-a-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let us give a go to creating an nginx deployment in our new group-a namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create deployment test-deployment --image=nginx -n group-a-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome now let us see if another tenant can interact with our nginx deployment in the group-a tenant. Use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl oidc-login clean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To remove your token and session from kubectl. And go to &lt;strong&gt;Sessions&lt;/strong&gt; in Keycloak in order to remove the existing group-a session.&lt;br&gt;
Now execute the following command which will prompt you to re-login.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods -A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Login as the group-b tenant admin and try the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl delete deployment test-deployment -n group-a-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error from server (Forbidden): deployments.apps "test-deployment" is forbidden: User "group-b" cannot delete resource "deployments" in API group "apps" in the namespace "group-a-test"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tenancy has been successfully set up. Now the possibilities are endless you can create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many tenants and many admins.&lt;/li&gt;
&lt;li&gt;Make users part of many groups.&lt;/li&gt;
&lt;li&gt;Create tenant admins that are service accounts for automation pipelines.&lt;/li&gt;
&lt;li&gt;Create cluster wide admins groups.&lt;/li&gt;
&lt;li&gt;Create different roles that tenant owners will adopt to restrict permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This solution maybe be a little bit configuration-heavy but once setup it is as pliable as play-doh. So have fun experimenting!&lt;/p&gt;

&lt;p&gt;In case you are looking for an environment where learning and experimenting with new solutions is key, we invite you to explore our &lt;a href="https://apply.workable.com/agileactors/" rel="noopener noreferrer"&gt;current job opportunities&lt;/a&gt; and be part of Agile Actors.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>development</category>
      <category>kubernetes</category>
    </item>
  </channel>
</rss>
