Yes, this is possible. One way to do this is by configuring the Undertow server to only accept TLS connections with a registered client certificate.
The following jboss-cli CLI configuration script shows how you can restrict access to /auth/admin via custom port 8444 to clients
### Undertow TLS Configuration
echo Configuring TLS and Client-Certificate authentication
# Add a dedicated port for accessing the admin endpoints
/socket-binding-group=standard-sockets/socket-binding=https-admin/:add(port=${jboss.https-admin.port:8444})
batch
set keycloakKeystore=keystores/keycloak-keystore.p12
set keycloakAdminTruststore=keystores/admin-truststore.p12
# Add the keystores, key manager, trust manager and ssl context configuration in the elytron subsystem
# keycloak-keystore.pkcs12 (Server TLS Cert, JGroups cert)
/subsystem=elytron/key-store=kcKeyStore:add( \
path=$keycloakKeystore, \
relative-to=jboss.server.config.dir, \
type=PKCS12, \
credential-reference={clear-text=kcKeyStore_password}, \
required=false \
)
# keycloak-admin-truststore (Allowed Client certificates)
/subsystem=elytron/key-store=kcAdminTrustStore:add( \
path=$keycloakAdminTruststore, \
relative-to=jboss.server.config.dir, \
type=PKCS12, \
credential-reference={clear-text=kcAdminTrustStore_password}, \
required=false \
)
/subsystem=elytron/key-manager=kcKeyManager:add(key-store=kcKeyStore,credential-reference={clear-text=kcKeyStore_password})
/subsystem=elytron/trust-manager=kcAdminTrustManager:add(key-store=kcAdminTrustStore)
set httpsCipherSuites="TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
/subsystem=elytron/server-ssl-context=kcSSLContext:add( \
key-manager=kcKeyManager, \
cipher-suite-filter=$httpsCipherSuites, \
protocols=["TLSv1.2", "TLSv1.3"] \
)
# Adjust existing https Listener
/subsystem=undertow/server=default-server/https-listener=https:undefine-attribute(name=security-realm)
/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=ssl-context,value=kcSSLContext)
/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=proxy-address-forwarding, value="${env.PROXY_ADDRESS_FORWARDING:TRUE}")
# Note that "need-client-auth=true" is important here, since it forces client-certificate authentication!
# With "need-client-auth=true" enabled, only clients with a client-certificate contained in the kcAdminTrustManager are allowed to access the admin-console.
/subsystem=elytron/server-ssl-context=kcAdminSSLContext:add( \
key-manager=kcKeyManager, \
trust-manager=kcAdminTrustManager, \
cipher-suite-filter=$httpsCipherSuites, \
protocols=["TLSv1.2", "TLSv1.3"], \
need-client-auth=true \
)
# Register new https-admin Listener
/subsystem=undertow/server=default-server/https-listener=https-admin:add( \
socket-binding=https-admin, \
proxy-address-forwarding="${env.PROXY_ADDRESS_FORWARDING:true}", \
enable-http2=false, \
ssl-context=kcAdminSSLContext \
)
# Custom undertow expression-filter to restrict access to the admin-console.
# We allow access to the admin-console in the following ways:
# 1) via port 8444 with known client-certificate
# 2) via port 8443 from localhost (e.g. via local-port forwarding in kubernetes)
# see
http://undertow.io/undertow-docs/undertow-docs-2.0.0/index.html#predicates-attributes-and-handlers/subsystem=undertow/configuration=filter/expression-filter=portAccess:add( \
expression="path-prefix('/auth/admin') and (not (equals(%{LOCAL_PORT}, 8444) or (equals(%{LOCAL_PORT}, 8443) and equals(%{REMOTE_IP}, '127.0.0.1')))) -> response-code(403)" \
)
# Enable undertow expression-filter
/subsystem=undertow/server=default-server/host=default-host/filter-ref=portAccess:add()
# Disable HTTP listener
# echo Disable HTTP listener
# /subsystem=undertow/server=default-server/http-listener=default:remove()
run-batch