Import Keystores and Truststores with Keycloak Operator

Hi everyone

I recently started using the Keycloak Operator to deploy Keycloak instances on Kubernetes, where previously I deployed Keycloak using this guide as my starting point. The operator and instances are working perfectly at the moment but i encountered a problem that I don’t seem to be able to find a solution/workaround for.

With my previous setup I used to mount a keystore and a truststore in the container. This, combined with the standalone-ha.xml file with necessary config, did the job I wanted it to. I am now trying to imitate that setup with the Keycloak operator but don’t seem to be able to find a suitable alternative. I tried using the volume mount settings (as documented here) but I must be doing something wrong because no files or configmaps are getting mounted. Below is the configuration I use for a configmap & Keycloak instance (I use Helm for templating).

apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap-{{ .Values.app.name }}
  namespace: {{ .Values.namespace }}
data:
  standalone-ha.xml: |
  ...
---
apiVersion: keycloak.org/v1alpha1
kind: Keycloak
metadata:
  name: {{ .Values.app.name }}
  labels:
    app: sso
spec:
  instances: 1
  extensions:
    - >-
      https://github.com/aerogear/keycloak-metrics-spi/releases/download/1.0.4/keycloak-metrics-spi-1.0.4.jar
  externalAccess:
    enabled: false
  keycloakDeploymentSpec:
    experimental:
      volumes:
        defaultMode: 0777
        items:
          - name: configmap-{{ .Values.app.name }}
            mountPath: /configmap
            configMaps:
              - configmap-{{ .Values.app.name }}

This is the result of a kubectl describe of the Keycloak instance:

    Name:         keycloak
    Namespace:    test-keycloak
    Labels:       app=sso
                  app.kubernetes.io/instance=test-keycloak
    Annotations:  <none>
    API Version:  keycloak.org/v1alpha1
    Kind:         Keycloak
    Metadata:
      Creation Timestamp:  2021-04-23T09:06:56Z
      Generation:          1
      Managed Fields:
        API Version:  keycloak.org/v1alpha1
        Fields Type:  FieldsV1
        Manager:      argocd-application-controller
        Operation:    Update
        Time:         2021-04-23T09:06:56Z
        API Version:  keycloak.org/v1alpha1
        Fields Type:  FieldsV1
        fieldsV1:
        Manager:         keycloak-operator
        Operation:       Update
        Time:            2021-04-23T11:42:05Z
      Resource Version:  29879435
      Self Link:         /apis/keycloak.org/v1alpha1/namespaces/test-keycloak/keycloaks/keycloak
      UID:               dae852c9-f733-40ba-928b-2358b1f5908c
    Spec:
      Extensions:
        https://github.com/aerogear/keycloak-metrics-spi/releases/download/1.0.4/keycloak-metrics-spi-1.0.4.jar
      External Access:
        Enabled:  false
      Instances:  1
      Keycloak Deployment Spec:
        Experimental:
          Volumes:
            Default Mode:  511
            Items:
              Config Maps:
                configmap-keycloak
              Mount Path:  /configmap
              Name:        configmap-keycloak
    Status:
      Credential Secret:  credential-keycloak
      Internal URL:       https://keycloak.test-keycloak.svc:8443
      Message:            
      Phase:              reconciling
      Ready:              true
      Secondary Resources:
        Config Map:
          keycloak-probes
        Deployment:
          keycloak-postgresql
        Persistent Volume Claim:
          keycloak-postgresql-claim
        Prometheus Rule:
          keycloak
        Secret:
          credential-keycloak
          keycloak-db-secret
        Service:
          keycloak-postgresql
          keycloak
          keycloak-discovery
        Service Monitor:
          keycloak-service-monitor
        Stateful Set:
          keycloak
      Version:  12.0.1
    Events:     <none>

Does anyone have similar issues, some tips or possibly a solution for my problem?

Thanks in advance.

Tom

@tbeuck have you found any solution how CA certificates can be added to the trust store when the Keycloak Operator handles the provisioning?

I spent a few hours on this today and it looks like, because of how the operator works, it has closed off any possibility of trusting a CA.

  • You cannot add initContainers that could be used to run some custom code.
  • You cannot use anything except secrets and configMaps as custom volume mounts.
  • The X509_CA_BUNDLE environment variable points at the default Kubernetes service account. While it would be possible to override that to point at a secret mounted as a volume, Keycloak would then lose access to the Kubernetes API server’s CA certificate I’m not sure how bad of a thing that is but I haven’t tried it.

There’s a ticket on the Keycloak Jira about this: [KEYCLOAK-16207] Keycloak Operator needs a mechanism to support LDAPS with non-public certificates - Red Hat Issue Tracker.

I was able to import a custom CA into Keycloak using the following settings:

apiVersion: keycloak.org/v1alpha1
kind: Keycloak
metadata:
  labels:
    app: keycloak
  name: keycloak
spec:
  keycloakDeploymentSpec:
    experimental:
      env:
      - name: X509_CA_BUNDLE
        value: /var/run/secrets/kubernetes.io/serviceaccount/*.crt /etc/x509/ca-bundle/*.crt
      volumes:
        items:
        - mountPath: /etc/x509/ca-bundle
          name: x509-ca-bundle
          secrets:
          - keycloak-cabundle
---
apiVersion: v1
kind: Secret
metadata:
  name: keycloak-cabundle
data:
  ca.crt: MY_CABUNDLE