How to Configure Apicurio Authentication
This guide shows you how to stand Keycloak up on a MySQL datastore, switch Apicurio Registry over to authenticating against it, and confirm the registry accepts a token from that realm.
Type |
How-to guide |
Goal |
Move an Apicurio Registry installation from its default access model onto authenticated, role-based access. |
Audience |
Platform Operator who can edit the Axual Streaming values and apply them. |
When to use |
Use this guide before an installation carries production data, since the default allows anonymous reads. |
The chart runs Apicurio Registry without authentication by default, so any caller that reaches the registry views, registers and deletes artifacts. Apicurio Registry accepts one authentication method at a time, so to accept OAuth and Basic Auth together, see How to Enable the Apicurio Auth Proxy. For the settings the Axual chart does not wrap, see the Apicurio documentation.
Prerequisites
Confirm the following before you begin.
Access and permissions required
You need the following access and permissions:
-
Permission to edit the Axual Streaming values and apply them.
-
Administrator access to the Apicurio Keycloak realm, to check its realm-level roles.
Tools and versions required
You need the following tools:
-
helm>= 3.12, or access to the pipeline that applies the values. -
curlandjq, for the verification step.
Resources that must exist before starting
The following must already exist:
-
A running Apicurio Registry v3, from How to Enable Apicurio Registry.
-
A DNS name and a TLS certificate for the Keycloak ingress host, because Apicurio Registry reaches Keycloak over HTTPS at that name.
-
A MySQL database for Keycloak, either the one the Apicurio chart bundles or an external instance.
-
The
sr-readonlyrealm-level role in the Apicurio Keycloak realm, when the installation moves to authenticated read access. A realm imported before2026.1does not carry it.
Choose a read access model
Decide whether reads stay anonymous or require credentials before you apply any values, because apicurio.auth.anonymous-read-access.enabled sits in the same security block as the rest of the authentication settings. Apicurio Registry Read Access Models compares the two models, states what each exposes, and describes the order in which an existing installation switches over.
Enable the MySQL datastore for Keycloak
Keycloak stores its realm, clients and users in a database, so configure that database first. The Apicurio chart bundles MySQL for this purpose.
Replace every <VALUE> placeholder below with your own value before applying the values or running a command.
|
apicurio-registry-v3:
apicurioKeycloakMysql:
enabled: true
fullnameOverride: "apicurio-kc-mysql"
auth:
rootPassword: "<MYSQL_ROOT_PASSWORD>"
database: "<KEYCLOAK_DB_NAME>"
username: "<KEYCLOAK_DB_USERNAME>"
password: "<KEYCLOAK_DB_PASSWORD>"
The bundled chart is the Bitnami MySQL chart, so its MySQL public documentation lists every value it accepts.
Enable Keycloak
Point Keycloak at the database from the previous section and import the Apicurio realm the Streaming charts ship.
The className: "nginx" value in the example below refers to the community ingress-nginx controller, which was deprecated in March 2026. Axual has migrated to a supported ingress controller. Update this value to match the ingress class configured in your cluster.
|
apicurio-registry-v3:
apicurioKeycloak:
# -- Required when running Apicurio Keycloak on the same k8s cluster as Governance Keycloak
nameOverride: "apicurio-keycloak"
enabled: true
# -- By default, we are importing the Apicurio realm used to Authenticate Admin access
args: [ 'start', '--import-realm' ]
realm: "apicurio"
# -- Required since Keycloak 25.0.1 when running behind an ingress
proxy:
mode: xforwarded
http:
enabled: true
autoscaling:
enabled: false
database:
vendor: "mysql"
hostname: "apicurio-kc-mysql"
database: "<KEYCLOAK_DB_NAME>"
port: "3306"
username: "<KEYCLOAK_DB_USERNAME>"
password: "<KEYCLOAK_DB_PASSWORD>"
extraVolumes: |
- name: keycloak-init-realm
configMap:
name: "<APICURIO_FULLNAME>-keycloak-realm"
extraVolumeMounts: |
- name: keycloak-init-realm
mountPath: "/opt/keycloak/data/import"
readOnly: true
extraEnv: |
- name: KEYCLOAK_ADMIN
value: "admin"
- name: KEYCLOAK_ADMIN_PASSWORD
value: "<KEYCLOAK_ADMIN_PASSWORD>"
- name: JAVA_OPTS_APPEND
value: -Djgroups.dns.query={{ template "keycloak.serviceDnsName" . }}
- name: KC_HTTP_ENABLED
value: "true"
- name: KC_HOSTNAME_STRICT
value: "false"
ingress:
enabled: true
className: "nginx"
rules:
- # -- The fully qualified domain name of a network host.
host: "<APICURIO_KEYCLOAK_HOST>"
paths:
- # -- Matched against the path of an incoming request.
path: "/auth"
# -- Determines the interpretation of the Path matching.
# Can be one of the following values: `Exact`, `Prefix`, `ImplementationSpecific`.
pathType: "ImplementationSpecific"
tls: [ ]
The bundled chart is the Codecentric KeycloakX chart, so its KeycloakX public documentation lists every value it accepts.
Enable Apicurio authentication
Point Apicurio Registry at the Keycloak realm and turn HTTP Basic authentication on. Every other authentication feature depends on security.authentication.enabled, so it stays true for all of them.
apicurio-registry-v3:
# The configuration related to authentication and authorization of users to the registry
# Note: In order for any other authentication feature to work,
# security.authentication.enabled needs to be enabled
security:
authentication:
enabled: true
basicAuthEnabled: true
# Attributes that are required for Apicurio to access the Keycloak instance
# in case the security.authentication.enabled is enabled and
# security.authentication.basicAuthEnabled is enabled
keycloak:
authUrl: "https://<APICURIO_KEYCLOAK_HOST>/auth"
realm: "apicurio"
webClientId: "apicurio-web"
webRedirectUrl: "https://<APICURIO_HOST>"
Role-based authorisation and the anonymous read property live in the same security block. Every key the block accepts is listed in Apicurio Chart Values Reference.
Confirm authentication is enforced
Apply the values, then check that the registry accepts a token from the Apicurio Keycloak realm. Request a token with the client credentials grant and call the registry’s search endpoint with it.
TOKEN=$(curl -sk -X POST \
"https://<APICURIO_KEYCLOAK_HOST>/auth/realms/apicurio/protocol/openid-connect/token" \
-d "grant_type=client_credentials&client_id=<CLIENT_ID>&client_secret=<CLIENT_SECRET>" \
| jq -r '.access_token')
curl -sk -o /dev/null -w '%{http_code}\n' \
-H "Authorization: Bearer $TOKEN" \
"https://<APICURIO_HOST>/apis/registry/v3/search/artifacts"
The authenticated call returns 200. An empty TOKEN means Keycloak rejected the client credentials, so check the realm import before looking at the registry.
Then open the registry web UI at the webRedirectUrl host. With authentication enabled the UI sends you to the Apicurio Keycloak realm to log in before it loads the artifact list.