In production, Keycloak always uses HTTPS. This guide explains how to configure the Keycloak MCP Server to connect to HTTPS-enabled Keycloak instances.
If your Keycloak uses a certificate from a trusted CA (We will Encrypt, DigiCert, etc.), no additional configuration is needed.
# configmap.yaml
data:
keycloak-url: "https://keycloak.example.com"
The Java runtime will trust these certificates by default.
When Keycloak uses self-signed certificates (common in development/test), you need to configure trust.
If Keycloak was deployed using the Keycloak Operator (as shown in your tutorial):
# Get the TLS secret name from Keycloak CR
KEYCLOAK_NAMESPACE=rhbk # Your Keycloak namespace
KEYCLOAK_TLS_SECRET=example-tls-secret # From Keycloak CR spec.http.tlsSecret
# Extract CA certificate
oc get secret ${KEYCLOAK_TLS_SECRET} -n ${KEYCLOAK_NAMESPACE} \
-o jsonpath='{.data.tls\.crt}' | base64 -d > keycloak-ca.crt
# Create ConfigMap in your namespace
oc create configmap keycloak-ca-bundle \
--from-file=ca.crt=keycloak-ca.crt \
-n keycloak-mcp
Edit deploy/openshift/deployment.yaml:
spec:
template:
spec:
containers:
- name: keycloak-mcp-server
volumeMounts:
- name: keycloak-ca-cert
mountPath: /certs
readOnly: true
env:
# Add JVM trust store configuration
- name: JAVA_OPTS
value: "-Djavax.net.ssl.trustStore=/certs/cacerts -Djavax.net.ssl.trustStorePassword=changeit"
volumes:
- name: keycloak-ca-cert
configMap:
name: keycloak-ca-bundle
For more control, create a custom Java truststore:
# Import CA certificate into truststore
keytool -import -trustcacerts \
-alias keycloak-ca \
-file keycloak-ca.crt \
-keystore truststore.jks \
-storepass changeit \
-noprompt
# Create secret with truststore
oc create secret generic keycloak-truststore \
--from-file=truststore.jks=truststore.jks
Update deployment:
spec:
template:
spec:
containers:
- name: keycloak-mcp-server
volumeMounts:
- name: truststore
mountPath: /certs
readOnly: true
env:
- name: JAVAX_NET_SSL_TRUSTSTORE
value: /certs/truststore.jks
- name: JAVAX_NET_SSL_TRUSTSTOREPASSWORD
value: changeit
volumes:
- name: truststore
secret:
secretName: keycloak-truststore
When Keycloak is deployed on OpenShift and uses the platform’s service CA:
apiVersion: v1
kind: ConfigMap
metadata:
name: keycloak-ca-bundle
annotations:
service.beta.openshift.io/inject-cabundle: "true"
data: {}
OpenShift automatically injects the service CA certificate.
spec:
template:
spec:
containers:
- name: keycloak-mcp-server
volumeMounts:
- name: keycloak-ca-cert
mountPath: /etc/ssl/certs/openshift-ca.crt
subPath: service-ca.crt
readOnly: true
env:
- name: JAVA_OPTS
value: "-Djavax.net.ssl.trustStore=/etc/ssl/certs/openshift-ca.crt"
volumes:
- name: keycloak-ca-cert
configMap:
name: keycloak-ca-bundle
When using the Keycloak Operator (recommended approach from your tutorial):
apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
name: example-kc
namespace: rhbk
spec:
instances: 1
db:
vendor: postgres
host: postgres-db
usernameSecret:
name: keycloak-db-secret
key: username
passwordSecret:
name: keycloak-db-secret
key: password
http:
tlsSecret: example-tls-secret # TLS certificate
hostname:
hostname: keycloak.rhbk.apps.example.com
# configmap.yaml
data:
# Use the hostname from Keycloak CR with HTTPS
keycloak-url: "https://keycloak.rhbk.apps.example.com"
# Extract CA from Keycloak's TLS secret
oc get secret example-tls-secret -n rhbk \
-o jsonpath='{.data.tls\.crt}' | base64 -d > keycloak-ca.crt
# Create ConfigMap in MCP namespace
oc create configmap keycloak-ca-bundle \
--from-file=ca.crt=keycloak-ca.crt \
-n keycloak-mcp
# 1. Create namespace
oc new-project keycloak-mcp
# 2. Extract Keycloak CA certificate
oc get secret example-tls-secret -n rhbk \
-o jsonpath='{.data.tls\.crt}' | base64 -d > keycloak-ca.crt
# 3. Create CA ConfigMap
oc create configmap keycloak-ca-bundle \
--from-file=ca.crt=keycloak-ca.crt
# 4. Create secrets
oc create secret generic keycloak-mcp-secret \
--from-literal=username=admin \
--from-literal=password='YourPassword'
# 5. Create ConfigMap with HTTPS URL
cat <<EOF | oc apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: keycloak-mcp-config
data:
keycloak-url: "https://keycloak.rhbk.apps.example.com"
EOF
# 6. Deploy with CA certificate mounting
# (Use updated deployment.yaml with uncommented volumes)
oc apply -f deploy/openshift/deployment.yaml
oc apply -f deploy/openshift/service.yaml
oc apply -f deploy/openshift/route.yaml
# Execute into the pod
oc exec -it deployment/keycloak-mcp-server -- /bin/sh
# Test HTTPS connection
curl -v https://keycloak.rhbk.apps.example.com/realms/master
# If using custom CA, test with certificate
curl --cacert /certs/ca.crt https://keycloak.rhbk.apps.example.com/realms/master
# View logs for connection errors
oc logs -f deployment/keycloak-mcp-server
# Look for SSL/TLS errors like:
# - "PKIX path building failed"
# - "unable to find valid certification path"
# - "SSLHandshakeException"
Cause: Java doesn’t trust the Keycloak certificate.
Solution:
oc exec deployment/keycloak-mcp-server -- ls -la /certsCause: Certificate chain is incomplete or CA certificate is missing.
Solution:
openssl s_client -connect keycloak.example.com:443 -showcertsCause: TLS version mismatch or cipher suite incompatibility.
Solution:
env:
- name: JAVA_OPTS
value: "-Dhttps.protocols=TLSv1.2,TLSv1.3"
Cause: Keycloak not listening on HTTPS or firewall blocking.
Solution:
oc get route -n rhbkcurl -v https://keycloak.example.comoc get pods -n rhbkDon’t do this:
env:
- name: JAVA_OPTS
value: "-Djavax.net.ssl.trustAll=true" # INSECURE!
Do this: Always configure proper certificate trust.
# Update CA certificate
oc create configmap keycloak-ca-bundle \
--from-file=ca.crt=new-keycloak-ca.crt \
--dry-run=client -o yaml | oc replace -f -
# Restart pods to pick up new certificate
oc rollout restart deployment/keycloak-mcp-server
env:
- name: JAVAX_NET_SSL_TRUSTSTOREPASSWORD
valueFrom:
secretKeyRef:
name: keycloak-mcp-secret
key: truststore-password
# Check certificate expiration
openssl s_client -connect keycloak.example.com:443 2>/dev/null | \
openssl x509 -noout -dates
Based on your tutorial, here is the complete Keycloak setup:
# Via OpenShift Console or CLI
oc create -f https://operatorhub.io/install/keycloak-operator.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgresql-db
namespace: rhbk
spec:
serviceName: postgresql-db-service
selector:
matchLabels:
app: postgresql-db
replicas: 1
template:
metadata:
labels:
app: postgresql-db
spec:
containers:
- name: postgresql-db
image: postgres:latest
env:
- name: POSTGRES_PASSWORD
value: testpassword
- name: POSTGRES_DB
value: keycloak
# Create self-signed certificate
openssl req -subj '/CN=keycloak.rhbk.apps.example.com/O=Example Org/C=US' \
-newkey rsa:2048 -nodes -keyout key.pem \
-x509 -days 365 -out certificate.pem
# Create secret
oc create secret tls example-tls-secret \
--cert certificate.pem \
--key key.pem \
-n rhbk
apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
name: example-kc
namespace: rhbk
spec:
instances: 1
db:
vendor: postgres
host: postgres-db
usernameSecret:
name: keycloak-db-secret
key: username
passwordSecret:
name: keycloak-db-secret
key: password
http:
tlsSecret: example-tls-secret
hostname:
hostname: keycloak.rhbk.apps.example.com
# Extract Keycloak CA
oc get secret example-tls-secret -n rhbk \
-o jsonpath='{.data.tls\.crt}' | base64 -d > keycloak-ca.crt
# Deploy MCP Server with CA trust
oc create configmap keycloak-ca-bundle \
--from-file=ca.crt=keycloak-ca.crt \
-n keycloak-mcp
# Update configmap with HTTPS URL
oc patch configmap keycloak-mcp-config \
-p '{"data":{"keycloak-url":"https://keycloak.rhbk.apps.example.com"}}'
Production Keycloak always uses HTTPS Configure certificate trust based on CA type Use Keycloak Operator for managed deployments Never disable certificate verification Test connections before deploying Monitor certificate expiration
For more details on Keycloak Operator deployment, see: Keycloak Operator for Kubernetes - a Basic Tutorial