p2-inc / keycloak-events

Useful Keycloak event listener implementations and utilities.
https://phasetwo.io
Other
168 stars 35 forks source link

Working with bitnami's keycloak helm chart #19

Closed ddurham2 closed 1 year ago

ddurham2 commented 1 year ago

Hello, I've got a working deployment of keycloak using bitnami's helm chart into a k8s cluster.

I would like to enhance things with keycloak-events (e.g. sending an email when a user registers). My plan is to define a webhook/http-endpoint that sends an http request to a custom service that performs the necessary action. Your keycloak-events extension seems like the perfect thing.

However, I'm having some trouble figuring out how I'm going to alter the deployment programatically.

From the docs, it looks like I need to copy the necessary (4?) jar files to the providers/ directory before starting keycloak.

So I ask the question: how to do this?

  1. I could create a custom container image with these files included, and tell the helm chart to use that image instead of the default one
  2. I could alter the helm chart to mount those extra jars from a supplied volume as the container starts up.

These are probably both doable. But how do I obtain the jar files?

I'm not very familiar with maven. I saw the other Issue that points me to the maven repo. Is there a straight-forward/recommended way to obtain these jar files programatically? I just need them brought down locally somehow. Can maven do that, itself? Any tips?


Following this, I'll need to configure some webhooks as the keycloak starts up. I read in your docs that I can do this either by manually inserting into the realm_attributes table (not a big fan of that). Or I can use the "Realm Update" method (but that link is broken in the docs). Or I can use the API that your extension provides at /auth/realms/<realm>/attributes. I fired up your docker image, but hitting that url in the browser for the master realm gave a "Page not found" error. Is that expected? Are there specific REST operations I must use? Is that documented somewhere?

Thanks in advance for the help!

xgp commented 1 year ago

Hi @ddurham2 thanks for the question. There isn't good documentation on packaging this all up yourself, as our assumption is that you'll use our docker images. Sorry about that.

Regarding packaging, both options are fine. I'm not familiar with the Bitnami Keycloak image, and it looks like from a quick review of their docs that they're assuming option 2, so I'd go with that.

You can get the jar file from the maven repo, but it's not as easy programmatically. What we do is to create a maven pom with the jars we need, have that build a bundle (using the maven ear plugin), and then copy those jars to the image or mount them. Here is an example that fetches all of our extensions: https://github.com/p2-inc/phasetwo-containers/blob/main/libs/pom.xml

Regarding the realm attributes / webhooks question, they are different things that are configured differently. Take a look at my comment here and see if that helps https://github.com/p2-inc/keycloak-events/issues/17#issuecomment-1541996689

Also, if you are getting a 404 on the API endpoint, check to see if you have KC_HTTP_RELATIVE_PATH=/auth set in your env vars. Keycloak now allows this to be empty, which would make the endpoint /realms/<realm>/attributes if it's not set.

ddurham2 commented 1 year ago

You can get the jar file from the maven repo, but it's not as easy programmatically. What we do is to create a maven pom with the jars we need, have that build a bundle (using the maven ear plugin), and then copy those jars to the image or mount them. Here is an example that fetches all of our extensions: https://github.com/p2-inc/phasetwo-containers/blob/main/libs/pom.xml

Regarding obtaining the jar files, perhaps the easiest way is to pull down your docker image and copy them out of there. /opt/keycloak/providers/*phasetwo*.jar, I believe, and put them into the corresponding location in the production container. Or is there more to it than that?

ddurham2 commented 1 year ago

Also, if you are getting a 404 on the API endpoint, check to see if you have KC_HTTP_RELATIVE_PATH=/auth set in your env vars. Keycloak now allows this to be empty, which would make the endpoint /realms/<realm>/attributes if it's not set.

Ah, okay. I was just following what was on the README.md and was using the container locally,

So, I added -e KC_HTTP_RELATIVE_PATH=/auth and instead of 404, now I get "An internal server error has occurred". I enabled debug logging (-e KC_LOG_LEVEL=debug) and it's saying:

2023-05-19 02:04:03,475 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (executor-thread-5) new JtaTransactionWrapper 2023-05-19 02:04:03,475 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (executor-thread-5) was existing? false 2023-05-19 02:04:03,476 DEBUG [io.phasetwo.keycloak.resources.BaseRealmResourceProvider] (executor-thread-5) request method GET 2023-05-19 02:04:03,478 DEBUG [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-5) Error response 401: javax.ws.rs.NotAuthorizedException: HTTP 401 Unauthorized at io.phasetwo.keycloak.resources.AbstractAdminResource.authenticateRealmAdminRequest(AbstractAdminResource.java:80) at io.phasetwo.keycloak.resources.AbstractAdminResource.setupAuth(AbstractAdminResource.java:65) at io.phasetwo.keycloak.resources.AbstractAdminResource.setup(AbstractAdminResource.java:45) at io.phasetwo.keycloak.resources.RealmAttributesResourceProvider.getRealmResource(RealmAttributesResourceProvider.java:14) at io.phasetwo.keycloak.resources.BaseRealmResourceProvider.getResource(BaseRealmResourceProvider.java:30) at org.keycloak.services.resources.RealmsResource.resolveRealmExtension(RealmsResource.java:265) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)

But I'm logged in with admin and can see and creates realms. Any ideas?

xgp commented 1 year ago

Regarding obtaining the jar files, perhaps the easiest way is to pull down your docker image and copy them out of there. /opt/keycloak/providers/phasetwo.jar

You'll need all the jars in there, not just phasetwo as we rely on other dependencies

xgp commented 1 year ago

To help debug the error, I need

  1. the version of keycloak you're using
  2. the versions of the jars
  3. the full request you are trying to make (path, headers, etc)
ddurham2 commented 1 year ago

I'm simply running the official docker image...

docker run --rm -ti -p 8080:8080 -e KC_HTTP_RELATIVE_PATH=/auth -e KC_LOG_LEVEL=debug -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=password quay.io/phasetwo/phasetwo-keycloak:21.1.1.1682702027 start-dev

Then I use chrome to log into http://localhost:8080/auth/admin/master/console/ with admin/password Then I use the browser to go to http://localhost:8080/auth/realms/master/attributes and get the "An internal error has occurred" message.

Is that expected to work? I'm guessing I'm missing something.

xgp commented 1 year ago

http://localhost:8080/auth/realms/master/attributes is an API endpoint. It's documented here: https://phasetwo.io/api/category/i/attributes

ddurham2 commented 1 year ago

Hi, I'm making progress here, but am running into an issue. I realize this is a bit of a frankenstein, but I'd appreciate if you can offer any guidance...

I've got a Dockerfile that copies all the provider jars from your keycloak docker image (quay.io/phasetwo/phasetwo-keycloak:21.1.1.1684876139) into bitnami's (docker.io/bitnami/keycloak:21.1.1-debian-11-r8) and then I deploy that to my cluster.

When it runs, I can successfully program the webhooks using the REST api and I can successfully list them back. So that's working. I've yet to receive a webhook from it yet, but I noticed another problem before diving into that problem.

Before introducing the new provider jars, I could successfully use the "Test connection" button within keycloak to send a test email. However, after introducing the new provider jars, I get this following error when sending a test email (and I'm also including all the keycloak logs since startup):

Appending additional Java properties to JAVA_OPTS: -Djgroups.dns.query=keycloak-headless.auth.svc.cluster.local
Updating the configuration and installing your custom providers, if any. Please wait.
2023-05-27 02:52:19,140 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: freemarker-plus-mustache (io.phasetwo.keycloak.themes.theme.FreeMarkerAndMustacheEmailTemplateProviderFactory) is implementing the internal SPI emailTemplate. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: metrics (org.jboss.aerogear.keycloak.metrics.MetricsEndpointFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: users (io.phasetwo.service.resource.UserResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: emails (io.phasetwo.keycloak.themes.resource.EmailsResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: attributes (io.phasetwo.keycloak.resources.RealmAttributesResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: webhooks (io.phasetwo.keycloak.resources.WebhooksResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: portal (io.phasetwo.portal.PortalResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: orgs (io.phasetwo.service.resource.OrganizationResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: magic-link (io.phasetwo.keycloak.magic.resources.MagicLinkResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: events (io.phasetwo.keycloak.resources.EventsResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: assets (io.phasetwo.keycloak.themes.resource.AssetsResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,149 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: teams (io.phasetwo.service.resource.TeamResourceProviderFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2023-05-27 02:52:19,219 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: oidc-organization-role-mapper (io.phasetwo.service.protocol.oidc.mappers.OrganizationRoleMapper) is implementing the internal SPI protocol-mapper. This SPI is internal and may change without notice
2023-05-27 02:52:19,219 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: oidc-organization-attribute-mapper (io.phasetwo.service.protocol.oidc.mappers.OrganizationAttributeMapper) is implementing the internal SPI protocol-mapper. This SPI is internal and may change without notice
2023-05-27 02:52:19,226 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: organization-entity-provider (io.phasetwo.service.model.jpa.entity.OrganizationEntityProviderFactory) is implementing the internal SPI jpa-entity-provider. This SPI is internal and may change without notice
2023-05-27 02:52:19,226 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-entity-webhook (io.phasetwo.keycloak.model.jpa.entity.WebhookEntityProviderFactory) is implementing the internal SPI jpa-entity-provider. This SPI is internal and may change without notice
2023-05-27 02:52:19,232 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-theme-provider-attribute (io.phasetwo.keycloak.themes.theme.AttributeThemeProviderFactory) is implementing the internal SPI theme. This SPI is internal and may change without notice
2023-05-27 02:52:19,295 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-auth-org-note (io.phasetwo.service.auth.OrgNoteAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-05-27 02:52:19,295 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-auth-home-idp-discovery (io.phasetwo.service.auth.idp.HomeIdpDiscoveryAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-05-27 02:52:19,296 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-auth-idp-selector (io.phasetwo.service.auth.idp.IdpSelectorAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-05-27 02:52:19,296 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-auth-org-add-user (io.phasetwo.service.auth.OrgAddUserAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-05-27 02:52:19,296 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-magic-form (io.phasetwo.keycloak.magic.auth.MagicLinkAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-05-27 02:52:19,296 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-email-otp (io.phasetwo.keycloak.magic.auth.EmailOtpAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-05-27 02:52:19,296 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-portal-link (io.phasetwo.service.auth.PortalLinkAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-05-27 02:52:19,296 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-auth-debugger (io.phasetwo.service.auth.DebugAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-05-27 02:52:19,296 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-auth-username-auth-note (io.phasetwo.service.auth.UsernameNoteAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-05-27 02:52:19,296 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: invitation-authenticator (io.phasetwo.service.auth.invitation.InvitationAuthenticatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
2023-05-27 02:52:19,414 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: invitation-required-action (io.phasetwo.service.auth.invitation.InvitationRequiredActionFactory) is implementing the internal SPI required-action. This SPI is internal and may change without notice
2023-05-27 02:52:19,525 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: org-portal-link (io.phasetwo.service.auth.action.PortalLinkActionTokenHandlerFactory) is implementing the internal SPI actionTokenHandler. This SPI is internal and may change without notice
2023-05-27 02:52:19,526 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-magic-link (io.phasetwo.keycloak.magic.auth.token.MagicLinkActionTokenHandlerFactory) is implementing the internal SPI actionTokenHandler. This SPI is internal and may change without notice
2023-05-27 02:52:19,639 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: metrics-listener (org.jboss.aerogear.keycloak.metrics.MetricsEventListenerFactory) is implementing the internal SPI eventsListener. This SPI is internal and may change without notice
2023-05-27 02:52:19,639 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-event-http (io.phasetwo.keycloak.events.HttpSenderEventListenerProviderFactory) is implementing the internal SPI eventsListener. This SPI is internal and may change without notice
2023-05-27 02:52:19,639 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-event-webhook (io.phasetwo.keycloak.events.WebhookSenderEventListenerProviderFactory) is implementing the internal SPI eventsListener. This SPI is internal and may change without notice
2023-05-27 02:52:19,639 WARN  [org.keycloak.services] (build-25) KC-SERVICES0047: ext-event-script (io.phasetwo.keycloak.events.ScriptEventListenerProviderFactory) is implementing the internal SPI eventsListener. This SPI is internal and may change without notice
2023-05-27 02:52:25,959 INFO  [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 8482ms
2023-05-27 02:52:27,565 INFO  [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: Base URL: <unset>, Hostname: <request>, Strict HTTPS: false, Path: <request>, Strict BackChannel: false, Admin URL: <unset>, Admin: <request>, Port: -1, Proxied: true
2023-05-27 02:52:28,926 WARN  [io.quarkus.agroal.runtime.DataSources] (main) Datasource <default> enables XA but transaction recovery is not enabled. Please enable transaction recovery by setting quarkus.transaction-manager.enable-recovery=true, otherwise data may be lost if the application is terminated abruptly
2023-05-27 02:52:29,870 INFO  [org.infinispan.SERVER] (keycloak-cache-init) ISPN005054: Native IOUring transport not available, using NIO instead: io.netty.incubator.channel.uring.IOUring
2023-05-27 02:52:30,022 WARN  [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
2023-05-27 02:52:30,058 WARN  [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
2023-05-27 02:52:30,107 INFO  [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller 'org.infinispan.jboss.marshalling.core.JBossUserMarshaller'
2023-05-27 02:52:30,320 WARN  [io.quarkus.vertx.http.runtime.VertxHttpRecorder] (main) The X-Forwarded-* and Forwarded headers will be considered when determining the proxy address. This configuration can cause a security issue as clients can forge requests and send a forwarded header that is not overwritten by the proxy. Please consider use one of these headers just to forward the proxy address in requests.
2023-05-27 02:52:31,003 INFO  [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000078: Starting JGroups channel `ISPN`
2023-05-27 02:52:31,010 INFO  [org.jgroups.JChannel] (keycloak-cache-init) local_addr: 4d46cbdf-6209-400b-8019-3f262c8479a7, name: keycloak-0-17189
2023-05-27 02:52:31,040 INFO  [org.jgroups.protocols.FD_SOCK2] (keycloak-cache-init) server listening on *.57800
2023-05-27 02:52:33,058 INFO  [org.jgroups.protocols.pbcast.GMS] (keycloak-cache-init) keycloak-0-17189: no members discovered after 2002 ms: creating cluster as coordinator
2023-05-27 02:52:33,070 INFO  [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000094: Received new cluster view for channel ISPN: [keycloak-0-17189|0] (1) [keycloak-0-17189]
2023-05-27 02:52:33,077 INFO  [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000079: Channel `ISPN` local address is `keycloak-0-17189`, physical addresses are `[10.244.1.26:7800]`
2023-05-27 02:52:33,759 INFO  [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: keycloak-0-17189, Site name: null
2023-05-27 02:52:33,762 INFO  [org.keycloak.broker.provider.AbstractIdentityProviderMapper] (main) Registering class org.keycloak.broker.provider.mappersync.ConfigSyncEventListener
2023-05-27 02:52:35,588 INFO  [io.quarkus] (main) Keycloak 21.1.1 on JVM (powered by Quarkus 2.13.7.Final) started in 9.493s. Listening on: http://0.0.0.0:8080
2023-05-27 02:52:35,589 INFO  [io.quarkus] (main) Profile dev activated. 
2023-05-27 02:52:35,589 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, logging-gelf, micrometer, narayana-jta, reactive-routes, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-health, vertx]
2023-05-27 02:52:35,613 ERROR [org.keycloak.services] (main) KC-SERVICES0010: Failed to add user 'keycloak' to realm 'master': user with username exists
2023-05-27 02:52:35,614 WARN  [org.keycloak.quarkus.runtime.KeycloakMain] (main) Running the server in development mode. DO NOT use this configuration in production.

2023-05-27 03:01:25,482 INFO  [io.phasetwo.keycloak.themes.theme.AttributeThemeProvider] (executor-thread-4) Creating AttributeTheme for master
java.lang.NullPointerException: Cannot invoke "org.keycloak.email.EmailTemplateProvider.sendSmtpTestEmail(java.util.Map, org.keycloak.models.UserModel)" because the return value of "org.keycloak.models.KeycloakSession.getProvider(java.lang.Class)" is null
    at org.keycloak.services.resources.admin.RealmAdminResource.testSMTPConnection(RealmAdminResource.java:938)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
    at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
    at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
    at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
    at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192)
    at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:152)
    at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:183)
    at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141)
    at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
    at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
    at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
    at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
    at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
    at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:82)
    at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:42)
    at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
    at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)
    at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:84)
    at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:71)
    at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
    at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:430)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:408)
    at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
    at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)
    at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$0(QuarkusRequestFilter.java:82)
    at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
    at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
    at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
    at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:833)
2023-05-27 03:01:33,291 ERROR [org.keycloak.services.resources.admin.RealmAdminResource] (executor-thread-3) Failed to send email 
 null

This seems to indicate that email sending would be broken in general just because of the new jar files? Any ideas? Thanks

xgp commented 1 year ago

A requirement when building Keycloak images with --spi-* flags is that the flags must be used in both the build and start commands. So when you are building your image, use the flags:

   --spi-email-template-provider=freemarker-plus-mustache --spi-email-template-freemarker-plus-mustache-enabled=true --spi-theme-cache-themes=false
ddurham2 commented 1 year ago

Hey, thanks for that. Adding those args worked. It seems odd since I didn't build keycloak myself, I'm only adding a few files to the existing Docker image provided by Bitnami. But I suppose your extensions were built with SPI? Is that going to cause issues down the line?

After fixing this, I successfully added the ext-event-webhook extension in the event configuration and events are now flowing to my user-event-processor service. Success!

But, while I see (among others) type=access.REGISTER and type=access.DELETE_ACCOUNT (when a user delete his own account), I don't see any event if the admin deletes a user's account. I see a distinction between user and admin events in the UI when using keycloak's own event capture feature, but are admin events something I should expect the ext-event-webhook listener to capture? I'm still asking for '*' events in the webhook definition.

If webhook doesn't capture them, is ext-event-http or ext-event-script able to capture them?

Thanks again

xgp commented 1 year ago

It's somewhat a quirk of Keycloak that if there are some provider implementations present, if you don't specify the spi flags, there are problems. Those flags pertain to the use of the keycloak-themes extension. If you don't intend to use that, remove that provider jar, and you won't have to set the flags.

The webhook listener should capture admin events. I'd suggest adding some debugging to the provider to see why it's missing.