Securing your site via OIDC, powered by Kong and KeyCloak
Tags: oidc, kong, keycloak, kubernetes
Published: 2022-01-19 06:30:33

_Quick sharing on how you can further secure your api or endpoints with OIDC, and powered by Kong and Keycloak. The examples shared are all open-source solutions._

## Introduction
As we start shipping services out to the open world, one of the primary considerations is how we can prevent any malicious attacks, since now we are in the wild west.Thankfully, We have the opportunity to **tinker and experiment with open-source solutions** due our work nature at that time. In this post, i would like to share how we incorporate **Kong Ingress Controller, KeyCloak and Kubernetes** to have an initial OIDC flow to front our external services.

## System Context

Before we dive deeper, let's take a closer look on how OIDC will verify the authenticity of a user before allowing the request to be fulfilled.

### OIDC (OpenID Connect) Overview

_Extracted from : https://github.com/nokia/kong-oidc_

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h86wh5w7ukelooeq9mjg.png)

## Preparation

Before we begin, we need to have the following :

- Kong - An API Gateway (community edition is open source and free)
- Kong OIDC Plugin - Open-sources OIDC plugin for Kong, maintained by the [community](https://github.com/revomatico)
- Kong JWT KeyCloak Plugin - Plugin for Kong so as to allow JWT token to be issued and validated by Keycloak. Maintained by the [community](https://github.com/BGaunitz/kong-plugin-jwt-keycloak)
- Keycloak - A OpenID Connect Provider (Open Source)
- Kubernetes - Open-source container orchestration system where we will deploy Kong and KeyCloak

### Baking the OIDC Plugin with Kong Base Image

**Important Note** : This is a community maintained OIDC Plugin. If required, please consider checking out the official OIDC Plugin that is only available with [Kong Enterprise](https://docs.konghq.com/hub/kong-inc/openid-connect/)

As we are using the open-source plugin by [Revomatico](https://github.com/revomatico/kong-oidc), we need to bake the plugin with the base kong image.

Sample Dockerfile

```
FROM kong/kong:2.7.0

ENV OIDC_PLUGIN_VERSION=1.2.3-2
ENV JWT_PLUGIN_VERSION=1.1.0-1
ENV GIT_VERSION=2.24.4-r0
ENV UNZIP_VERSION=6.0-r7
ENV LUAROCKS_VERSION=2.4.4-r1


USER root
RUN apk update && apk add git=${GIT_VERSION} unzip=${UNZIP_VERSION} luarocks=${LUAROCKS_VERSION}
RUN luarocks install kong-oidc

RUN git clone --branch v1.2.3-2 https://github.com/revomatico/kong-oidc.git
WORKDIR /kong-oidc
RUN luarocks make

RUN luarocks pack kong-oidc ${OIDC_PLUGIN_VERSION} \
     && luarocks install kong-oidc-${OIDC_PLUGIN_VERSION}.all.rock

WORKDIR /
RUN git clone --branch 20200505-access-token-processing https://github.com/BGaunitz/kong-plugin-jwt-keycloak.git
WORKDIR /kong-plugin-jwt-keycloak
RUN luarocks make

RUN luarocks pack kong-plugin-jwt-keycloak ${JWT_PLUGIN_VERSION} \
     && luarocks install kong-plugin-jwt-keycloak-${JWT_PLUGIN_VERSION}.all.rock

USER kong
```

Build and push the image to a registry

```
# Build the container with any new changes
docker build -t <reponame>/kong-oidc:<tag> -f Dockerfile . 

# Run the container in detached mode
docker run -d --name kong-oidc <reponame>/kong-oidc:<tag>       

# Pushing the container image to a registry
docker push <reponame>/kong-oidc:<tag>   
```

### Understand the Kong Cluster Plugin Configurations

Kong Ingress Controller allow us to configure Kong specific features using several Custom Resource Definitions(CRDs)

These are the following CRDs that we need to take note of

1. **odic** - This plugin is used to communicate with the Keycloak Identity provider and is required if you'd like to enable (recommended) SSO for your ingress.

2. **request-transformer** - To strip off unnecessary headers upon authentication with the identity platform

3. **cors** - Allow Cross Site origin at global level

### Deploying into Kubernetes

Examples manifest can be found on [here](https://github.com/robincher/kong-oidc-keycloak-boilerplate/tree/master/kubernetes)


1. 
#### Deploy the previously baked Kong image (with OIDC plugin). 

```
kubectl apply -f kong-deployment.yaml
```

2. 
#### Deploy KeyCloak

```
kubectl apply -f keycloak-deployment.yaml
```

3.
#### KeyCloak Configurations

- Create a new Realm in KeyCloak

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2nfge78i60lhosn780d0.png)

- Create a new Kong Client in the realm , eg kong-oidc

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/28lfwv7yz6adqoprgugs.png)

- Client Configurations

Go to **Clients**, and then click on **Settings**.

Make the following updates

Access Type: **Confidential**
Valid Redirect URIs: *
Web Origin: localhost (Allowed CORS origin)
 
- Copied the Client ID, and then go to **Credentials** to get the **Secret** value.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0d9cggsqnabak60c50n.png)

- Retrieve OpenID Endpoint Configuration

Go to **Realm Setting**, and select **General**. Click on **OpenID Endpoint Configuration**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/09ujgj518gqwxh33g765.png) 

- Override the values of the OIDC Kong Plugins

```
apiVersion: configuration.konghq.com/v1
kind: KongClusterPlugin
metadata:
  name: oidc
  annotations:
    kubernetes.io/ingress.class: "kong"
  labels:
    global: "false"
disabled: false # optionally disable the plugin in Kong
plugin: oidc
config: # configuration for the plugin
  client_id: kong-oidc # Realm
  client_secret: xxxxxxxx  # Client Secret Copied
  realm: kong
  discovery: https://localhost/.well-known/openid-configuration # OpenID Endpoint Configuration Copied
  scope: openid
  redirect_after_logout_uri : https://localhost/auth/realms/kong/protocol/openid-connect/logout?redirect_uri=https://localhost
```

4.
#### Deploy the required Cluster Plugins as mentioned above

```
kubectl apply -f kong-crds.yaml
```

5
#### Testing your site with OIDC

We can now test a sample ingress that is intercepted by Kong Ingress Controller. All you have to do is indicating the plugins annotations on the ingress

```
# sample-oidc.yaml
....
....
----
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echoserver-oidc
  namespace: default
  annotations:
    konghq.com/plugins: request-transformer,oidc #indicate here
spec:
  ingressClassName: kong
  rules:
    - host: echo-oidc.localhost.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service: 
                name: echoserver
                port: 
                  number: 80
```

You should be prompted to sign in when attempting to access the site, and have successfully implement a minimal OIDC solution using open-source technology !

### Learnings

- We choose Kong because of its flexibility (we only scratch its surface on what it capable of as a full-fledge API Gateway) and being lightweight, which allow us to make changes quickly. Additionally, it is cloud-native which ease the effort of deployment. 

- KeyCloak is the de-facto IAM solution we have in our lab, and integrating it is straight forward enough. We don't really have to re-engineer much in the near future when we onboard more type of user pools (Social Logins, Azure Active Directory etc..)

- If possible, start something small to see if it work as intended, especially when there are many inter-connected dots. It is always good to retain some technical acumen internally to allow better decision making when engaging with our software partners. 

## Credits

This work is not possible without the contribution from my following team mates:

[Wee Liang - DevOps Engineer @ Thales Airlab](https://www.linkedin.com/in/angweeliang)
[Arun - DevOps & Integration @ Thales Airlab](https://www.linkedin.com/in/arunsudhakar)
[Kelvin - Software Engineer @ Thales Airlab](https://www.linkedin.com/in/kelvin-neo)

## References
- [Revomatico OIDC Plugin](https://github.com/revomatico/kong-oidc)
- [Sample Repo with Examples](https://github.com/robincher/kong-oidc-keycloak-boilerplate)
- [KeyCloak](https://www.keycloak.org/)
- [Kong API Gateway](https://konghq.com/kong/)