External OpenID Connect Authentication

Overview

This article will describe how to use Keycloak for OIDC authentication in Kubernetes cluster (kubectl & Kubernetes Dashboard)

Prerequisites

  1. Kubernetes cluster is up and running
  2. Keycloak server is up and running

Configuring Keycloak

[OPTIONAL] Add realm called “iam” (or use existing realm instead)

[OPTIONAL] Add groups “kubernetes-admin” and “kubernetes-viewer”

[OPTIONAL] Add users “admin-user” assigned to group “kubernetes-admin” and “read-only-user” assigned to group “kubernetes-viewer”

Add client called “kubernetes”

For “kubernetes” client create protocol mapper called “user groups”

If everything done correctly - now you should be able to authenticate in keycloak and see user groups in JWT token Use following snippet to authenticate in Keycloak:

curl \
    -d "grant_type=password" \
    -d "client_id=kubernetes" \
    -d "client_secret=<CLIENT_SECRET>" \
    -d "username=<USER_NAME>" \
    -d "password=<USER_PASSWORD>" \
    https://<KEYCLOAK_URL>/auth/realms/<REALM>/protocol/openid-connect/token

The result will include ACCESS_TOKEN and REFRESH_TOKEN:

{  
   "access_token":"ACCESS_TOKEN",
   "refresh_token":"REFRESH_TOKEN",
   "token_type":"bearer",
   ...
}

To introspect you JWT token run following snippet:

curl \
    --user "kubernetes:<CLIENT_SECRET>" \
    -d "token=<ACCESS_TOKEN>" \
    https://<KEYCLOAK_URL>/auth/realms/<REALM>/protocol/openid-connect/token/introspect

The result will be like following:

{
   "iss":"https://auth.dev.alpha.kublr.com/auth/realms/iam",
   "preferred_username":"admin",
   "user_groups":[
      "kubernetes-admin"
   ],
   "client_id":"kubernetes",
   ...
}

Configuring Kubernetes cluster

API Server configuration

Configuring Kubernetes for OIDC requires adding several parameters to the API Server. The below table details the parameters:

Parameter Description Required Example
–oidc-issuer-url The base URL for the issuer Y https://mycluster-endpoint.example.com/auth/realms/iam
–oidc-client-id The name of your client as identified by your IdP Y kubernetes
–oidc-username-claim The name of the claim in the JWT that stores the user’s ID Y preferred_username
–oidc-groups-claim The name of the claim in the JWT that stores the user’s group memberships Y user_groups
–oidc-ca-file The path to the certificate for the CA that signed your IdP’s web certificate N /etc/kubernetes/ssl/kc-ca.pem

Example of cluster spec:

kind: Cluster
spec:
  master:
    kublrAgentConfig:
      kublr:
        kube_api_server_flag:
          oidc_issuer_url: '--oidc-issuer-url=https://<KEYCLOAK_URL>/auth/realms/<REALM>'
          oidc_client_id: '--oidc-client-id=kubernetes'
          oidc_username_claim: '--oidc-username-claim=preferred_username'
          oidc-groups-claim: '--oidc-groups-claim=user_groups'

Configuring RBAC

Use following snippet to create basic RBAC roles

cat <<EOF | kubectl apply -f -
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: oidc-kubernetes-admin
subjects:
- kind: Group
  name: kubernetes-admin
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: admin
  apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: oidc-kubernetes-view
subjects:
- kind: Group
  name: kubernetes-viewer
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io  
EOF

Kubectl

There are two options to use kubectl with OIDC.

For more details and examples - refer to kubernetes documentation

OIDC Authenticator

NB: kubectl does not refresh access_token/refresh_token. So when they will expire - you will get an error, and will need to refresh them manually.

To configure kubectl OIDC Authenticator:

Add “admin-oidc” user entry to kubeconfig

kubectl config set-credentials admin-oidc \
    --auth-provider=oidc \
    --auth-provider-arg=idp-issuer-url=https://<KEYCLOAK_URL>/auth/realms/<REALM> \
    --auth-provider-arg=client-id=kubernetes \
    --auth-provider-arg=client-secret=<CLIENT_SECRET> \
    --auth-provider-arg=refresh-token=<REFRESH_TOKEN> \
    --auth-provider-arg=id-token=<ACCESS_TOKEN> \
    --auth-provider-arg=extra-scopes=groups

Now you should be able to use kubectl with OIDC:

kubectl --user=admin-oidc version

–token option

You can embed you ACCESS_TOKEN directly to kubectl command using --token option:

kubectl --token=<ACCESS_TOKEN> cluster-info
  1. Kubernetes Documentation / Authenticating
  2. Kubernetes Authentication – OpenID Connect
  3. Kubernetes Identity Management

Questions? Suggestions? Need help? Contact us.