How to setup a Keycloak Gatekeeper to secure the services in your Kubernetes cluster
Tags: kubernetes, devops, docker, tutorial
Published: 2020-01-17 14:48:56

**1. Prerequisite for configuring gatekeeper for a specific application:**
 

- create a client, called **my-app** in Keycloak. In the creation step select access-type: confidential

- once created you will see a credentials tab for the newly created client with the secret. You will need that for the gatekeeper.yaml config file

- create Realm role for that application **my-app-role**

- create a group **my-group** and add the role **my-app-role** in role-mappings of the group

- go to your user and add it to the **my-group**. This user will be authorized to access the secured application, once we configure it

 

**2. Create a gatekeeper configuration file, gatekeeper.yaml, as a secret**
 

```
client-id: my-app

client-secret: my-app-secret-from-credentials

discovery-url: https://my-keycloak-server.com/auth/realms/my-realm

skip-upstream-tls-verify: false

skip-openid-provider-tls-verify: true

encryption-key: random-secret-value-of-16-or-32-characters

listen: 0.0.0.0:3000

secure-cookie: false

enable-logging: true

enable-json-logging: true

enable-default-deny: true

enable-refresh-tokens: true

enable-session-cookies: true

debug: true

ingress.enabled: true

resources:

  - uri: /favicon

  white-listed: true
```
 
Values to be replaced and set in the above config file:

- **client-secret** set from the client credentials tab

- **encryption-key** random hash value 16 or 32 characters

- **discovery-url** keycloak endpoint

 

Some of the important values explained:

- **discovery-url** is keycloak's realm url that the my-app client resides in

- **skip-openid-provider-tls-verify** ignores Keycloak's self-signed certificate warning for gatekeeper client request

- **enable-default-deny** - all resources are by default secured unless explicitly allowed in resources

- **listen** - port where the gatekeeper will start and listen on

- **redirection-url** - where the successful login will be redirected to

- **upstream-url** - where gatekeeper will forward the request after successful authorization

- **resources** configures which resources can be accessed (white-listed) without authentication.

 

The configuration values are needed by the gatekeeper to communicate with Keycloak. So with the **endpoint**, we tell gatekeeper where to find the Keycloak server to talk to, with the **client-id** and **client-secret** gatekeeper can authenticate itself with Keycloak to make requests to it.

 
```
kubectl create secret generic gatekeeper --from-file= ./gatekeeper.yaml -n my-namespace
```
 

Now that you have set up all the necessary configuration, you need to deploy gatekeeper container inside the pod where the application you want to secure is running. SO gatekeeper will be a side-car container to your actual app, acting as a... well, gatekeeper to all incoming requests. 

So to deploy both containers inside one pod, you need to configure it like this:

 
```
apiVersion: apps/v1

kind: Deployment

metadata:

  name: my-app

spec: 

  template:

    ...

    spec:

      containers:

      - image: keycloak/keycloak-gatekeeper:7.0.0

        name: gatekeeper

        ports:

        - containerPort: 3000

        args:

        - --config=/etc/secrets/gatekeeper.yaml

        - --redirection-url=https://my-app-server-url

        - --upstream-url=http://127.0.0.1:8080

        - --resources=uri=/*|roles=my-app-role

        volumeMounts:

        - name: gatekeeper-secrets

          mountPath: /etc/secrets

      - image: my-app-image

        name: my-app

        ports:

        - containerPort: 8080

      volumes:

      - name: gatekeeper-secrets

        secret:

          secretName: gatekeeper
```

 

So with the above configuration, a pod will be created with the application and gatekeeper containers and the gatekeeper.yaml file that we created above will be mounted inside the gatekeeper container. 

 

As you see in the deployment config, gatekeeper container has args configured.

- **redirection-url** is where the successful login will be redirected to. This points to the url of the my-app, which will also land with the gatekeeper

- **upstream-url** - after the redirect-url is called for the authenticated user, gatekeeper will allow access to my-app, by forwarding the request to it on `http://127.0.0.1:8080`.

 

Why `http://127.0.0.1:8080`? because both my-app and gatekeeper run in the same pod, they can communicate via localhost. 

 

So, now we need to configure the service for my-app to forward the incoming requests NOT to **my-app**, but to the gatekeeper container. As you see from above **my-app** and **gatekeeper** are running on different ports (**8080** and **3000**), so we just need to tell the service to forward the request to **gatekeeper's port 3000**.

 

```
apiVersion: v1

kind: Service

metadata:

  name: my-service

spec:

  selector:

    service: my-service

  type: ClusterIP

  ports:

  - port: 32111

    targetPort: 3000
```

-----------------
► Get **30% off** - with this code: UDEMY_NANA_OCT2020: [Udemy course here](https://bit.ly/2IkzZez)
► **Kubernetes 101**: [Compact and easy-to-read ebook bundle 🚀](https://www.techworld-with-nana.com/e-books) 
It's a handy way to quickly look something up or refresh your knowledge at work and use it as your cheatsheet  😎

**Like, share and follow me** 😍 for more content:
- [Private FB group](https://www.facebook.com/groups/techworldwithnana)
- [Twitter](https://twitter.com/Njuchi_)
- [YouTube](https://www.youtube.com/channel/UCdngmbVKX1Tgre699-XLlUA?sub_confirmation=1)
- [Instagram](https://www.instagram.com/techworld_with_nana/)
- [LinkedIn](linkedin.com/in/nana-janashia)