Мультитенантный Quarkus с KeyCloak?

Я пишу набор услуг, используя структуру Quarkus. Сервисы предназначены для работы с несколькими арендаторами и должны быть защищены с помощью KeyCloak. У каждого арендатора будет отдельная область безопасности KeyCloak со своим собственным набором пользователей, групп, ролей и т. Д.

Я нашел руководство Quarkus по защите KeyCloak, в котором объясняется, как настроить JAX-RS для авторизации. с помощью KeyCloak. Однако в этом руководстве предполагается только 1 область KeyCloak. Я также нашел этот пример, показывающий, как развернуть файл WAR. в Wildfly, который загружает один из нескольких файлов конфигурации области KeyCloak в зависимости от указанной области.

Однако неясно, можно ли преобразовать этот код в Quarkus.
Можно ли таким образом динамически загружать конфигурацию KeyCloak в Quarkus? Есть ли лучший способ реализовать мультитенантную безопасность для этих сервисов Quarkus?

ОБНОВЛЕНИЕ. Основываясь на предложениях Педро и Шадова, приведенных ниже, я добавил действительно простую KeycloakConfigResolver реализацию и пометил ее как @ApplicationScoped. Однако, когда я попытался запустить Quarkus, я получил следующее исключение и никогда не видел, как вызывается мой пользовательский KeycloakConfigResolver:

17:53:55,340 INFO  [io.qua.dep.QuarkusAugmentor] Beginning quarkus augmentation
17:53:55,758 INFO  [org.jbo.threads] JBoss Threads version 3.0.0.Beta4
17:53:56,888 INFO  [org.hib.Version] HHH000412: Hibernate Core {5.4.3.Final}
17:53:57,812 INFO  [io.qua.dep.QuarkusAugmentor] Quarkus augmentation completed in 2472ms
17:53:57,967 ERROR [io.qua.dev.DevModeMain] Failed to start quarkus: java.lang.ExceptionInInitializerError
    at java.base/java.lang.J9VMInternals.ensureError(J9VMInternals.java:193)
    at java.base/java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:182)
    at java.base/java.lang.J9VMInternals.newInstanceImpl(Native Method)
    at java.base/java.lang.Class.newInstance(Class.java:2082)
    at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:117)
    at io.quarkus.dev.DevModeMain.doStart(DevModeMain.java:166)
    at io.quarkus.dev.DevModeMain.main(DevModeMain.java:88)
Caused by: java.lang.RuntimeException: Failed to start quarkus
    at io.quarkus.runner.ApplicationImpl1.<clinit>(ApplicationImpl1.zig:333)
    ... 5 more
Caused by: java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
 at [Source: UNKNOWN; line: 1, column: 0]
    at org.keycloak.adapters.KeycloakDeploymentBuilder.loadAdapterConfig(KeycloakDeploymentBuilder.java:198)
    at org.keycloak.adapters.KeycloakDeploymentBuilder.build(KeycloakDeploymentBuilder.java:187)
    at io.quarkus.keycloak.KeycloakTemplate.createKeycloakDeploymentContext(KeycloakTemplate.java:36)
    at io.quarkus.deployment.steps.KeycloakAdapterProcessor$configureAdapter5.deploy_0(KeycloakAdapterProcessor$configureAdapter5.zig:47)
    at io.quarkus.deployment.steps.KeycloakAdapterProcessor$configureAdapter5.deploy(KeycloakAdapterProcessor$configureAdapter5.zig:106)
    at io.quarkus.runner.ApplicationImpl1.<clinit>(ApplicationImpl1.zig:207)
    ... 5 more
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
 at [Source: UNKNOWN; line: 1, column: 0]
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
    at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4145)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4000)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3070)
    at org.keycloak.adapters.KeycloakDeploymentBuilder.loadAdapterConfig(KeycloakDeploymentBuilder.java:196)
    ... 10 more

17:53:57,968 ERROR [io.qua.dev.DevModeMain] Failed to start Quarkus, attempting to start hot replacement endpoint to recover
17:53:58,003 INFO  [org.xnio] XNIO version 3.7.2.Final
17:53:58,017 INFO  [org.xni.nio] XNIO NIO Implementation Version 3.7.2.Final

Мой пользовательский KeycloakConfigResolver пуст, за исключением некоторых операторов регистрации. Я никогда не видел, чтобы был вызван мой resolve метод или какие-либо операторы регистрации. Вот как выглядит реализация:

@ApplicationScoped
public class MultiTenantKeycloakConfigResolver implements KeycloakConfigResolver {

    /**
     * Logger for this class
     */
    private static final Logger logger = LoggerFactory.getLogger(MultiTenantKeycloakConfigResolver.class);

    /*
     * (non-Javadoc)
     *
     * @see
     * org.keycloak.adapters.KeycloakConfigResolver#resolve(org.keycloak.adapters.
     * spi.HttpFacade.Request)
     */
    @Override
    public KeycloakDeployment resolve(Request facade) {
        if (logger.isDebugEnabled()) {
            logger.debug("resolve(Request) - start"); //$NON-NLS-1$
        }

        if (logger.isInfoEnabled()) {
            logger.info("resolve(Request) - HERE!!!"); //$NON-NLS-1$
        }

        // TODO Implement method

        if (logger.isDebugEnabled()) {
            logger.debug("resolve(Request) - end"); //$NON-NLS-1$
        }
        return null;
    }

}

person Shadowman    schedule 26.06.2019    source источник


Ответы (2)


@ Шадов, верно. Вам нужен KeycloakConfigResolver.

В Quarkus вам просто нужно создать класс, реализующий KeycloakConfigResolver. Подобно это.

Я обновлю руководство с некоторыми ссылками на это.

person Pedro Igor    schedule 27.06.2019
comment
Спасибо, Педро! Я попробую сегодня позже. - person Shadowman; 27.06.2019
comment
Только что обновил результаты моего теста и трассировку стека, которую я вижу. Короче говоря, это не сработало. - person Shadowman; 28.06.2019
comment
Просто провел еще немного тестов. Похоже, что мой пользовательский KeycloakConfigResolver не находится в io.quarkus.keycloak.QuarkusKeycloakConfigResolver по какой-либо причине. Если я создаю файл keycloak.json и помещаю его в src / main / resources, проект строится без проблем, но мой KeycloakConfigResolver все еще не найден и не вызван. - person Shadowman; 28.06.2019
comment
Пару чистых / пересборок позже, и все заработало. Не знаю, почему так долго собирали сдачу. Спасибо за вашу помощь! - person Shadowman; 01.07.2019
comment
Ссылка не работает: '( - person Dorian Maliszewski; 04.02.2020

Это возможно в Spring-Boot, почти так же, как в опубликованном вами примере. Только начиная с версии 4.6.0-Final они добавили класс KeycloakSpringBootConfigResolverWrapper, который фактически проверяет, есть ли уже KeycloakConfigResolver. В предыдущей версии он просто ставил собственный преобразователь. Теперь все, что вам нужно сделать, это зарегистрировать собственный KeycloakConfigResolver bean, и он заработает.

Я вижу, что в Quarkus есть очень похожий класс, как в keycloak-spring-boot-adapters - https://github.com/quarkusio/quarkus/blob/master/extensions/keycloak/runtime/src/main/java/io/quarkus/keycloak/QuarkusKeycloakConfigResolver.java. Код довольно очевиден, объяснять его не нужно.

Поскольку я не знаком с Quarkus, я не могу быть на 100% уверен, что он сработает, но поле помечено Inject, поэтому это предполагает, что вы можете просто предоставить свой собственный преобразователь, так же, как это возможно в Spring-Boot и в опубликованном вами примере.

person Shadov    schedule 27.06.2019
comment
Только что обновил результаты моего теста и трассировку стека, которую я вижу. Короче говоря, это не сработало. - person Shadowman; 28.06.2019