【问题标题】:Keycloak.json configuration file importKeycloak.json 配置文件导入
【发布时间】:2019-02-15 06:14:41
【问题描述】:

我已经使用 keycloak 配置了我的 goclient。我正在从我的 Go 客户端中存在的 keycloak.json 文件中读取 keycloak 服务器详细信息。
我的整个设置都在 Kubernetes 集群中。每次新的 keycloak 服务器出现时,我应该如何将 keycloak.json 文件传递​​给 Go 客户端,以便它可以从 json 文件中读取详细信息?
有没有一种方法可以让我获得包含所有客户端配置详细信息的 keycloak.json 文件,而无需登录 keycloak 并下载它?

  "realm": "SolutionAdmin",
  "auth-server-url": "localhost:8081/auth",
  "ssl-required": "none",
  "resource": "admin",
  "credentials": {
    "secret": "6ee0f523-c392-4406-bb14-ba315125c6ea"
  },
  "confidential-port": 0
}

【问题讨论】:

  • 希望每次都更改客户端配置?你是说keycloak url吗?
  • 我的 Go 客户端从 keycloak.json 文件中获取 Keycloak 信息。所以每次我的解决方案都会生成一个新的 keycloak 服务器。所以如果有办法我可以将此 keycloak.json 文件提供给我的 Go 客户端动态
  • 你可以保持你的域名相同,并使用该名称而不是 ip 访问它
  • 假设即使我保持域名相同,我仍然需要获取客户端密码。在我当前的场景中,Keycloak 将有不同的负载均衡器 IP。

标签: go kubernetes keycloak


【解决方案1】:

如果您想拥有一个预配置的嵌入式 keycloak 服务器,您需要扩展 KeycloakApplication 并将其配置为代替基类触发。在这个例子中,KeycloakProperties 只是我们在application.properties 中使用的所有 keycloak 属性的表示。但你可以得到它的要点。公平的警告:我没有写这个,但我正在弄清楚一个同事是如何为另一个项目做的。

public class EmbeddedKeycloakApplication extends KeycloakApplication {

  public final KeycloakProperties keycloakProperties;

  public EmbeddedKeycloakApplication() {

    super();

    keycloakProperties = SpringContextAdapter.getBean(KeycloakProperties.class);
    System.getProperties().putAll(keycloakProperties.getRealmProperties());

    createMasterRealmAdminUser();

    createRealm();
  }

  private void createMasterRealmAdminUser() {

    log.debug("Creating administrative user.");

    String username = keycloakProperties.getServer(KeycloakProperties.ADMIN_USER_USERNAME);
    String password = keycloakProperties.getServer(KeycloakProperties.ADMIN_USER_PASSWORD);
    String email = keycloakProperties.getServer(KeycloakProperties.ADMIN_USER_EMAIL);

    KeycloakSession session = getSessionFactory().create();
    ApplianceBootstrap applianceBootstrap = new ApplianceBootstrap(session);

    try {
      session.getTransactionManager().begin();

      if (!applianceBootstrap.isNoMasterUser()) {
        log.debug("Administrative user already exists. No work to do.");
        return;
      }

      applianceBootstrap.createMasterRealmUser(username, password);
      RealmModel adminRealm = session.realms().getRealm(Config.getAdminRealm());
      UserModel adminUser = session.users().getUserByUsername(username, adminRealm);
      adminUser.setEmail(email);
      adminUser.setEmailVerified(true);
      session.getTransactionManager().commit();
      log.info("Created administrative user {}", username);
    } catch (Exception ex) {
      log.error("Couldn't create keycloak master admin user: {}", ex.getMessage());
      session.getTransactionManager().rollback();
    }

    session.close();
  }

  private void createRealm() {

    String realmImportFilename = keycloakProperties.getRealmImportFile();
    KeycloakSession session = getSessionFactory().create();
    String realmId = keycloakProperties.getRealm(KeycloakProperties.REALM_ID);

    try {
      session.getTransactionManager().begin();

      RealmManager manager = new RealmManager(session);

      if (manager.getRealm(realmId) != null) {
        log.debug("{} realm already exists. No work to do.", realmId);
        return;
      }

      Resource realmImportFile = new ClassPathResource(realmImportFilename);

      RealmRepresentation rep =
          JsonSerialization.readValue(
              realmImportFile.getInputStream(), RealmRepresentation.class, true);
      manager.importRealm(rep);
      log.info("Imported Realm json file {}", realmImportFilename);
      session.getTransactionManager().commit();
    } catch (Exception e) {
      log.error("Failed to import Realm json file {}: {}", realmImportFilename, e.getMessage(), e);
      session.getTransactionManager().rollback();
    }

    session.close();
  }

}
 
@Configuration
public class EmbeddedKeycloakConfig {

  @Bean
  ServletRegistrationBean<HttpServlet30Dispatcher> keycloakJaxRsApplication(
      KeycloakProperties keycloakProperties, DataSource dataSource) throws NamingException {

    mockJndiEnvironment(dataSource);

    var contextPath = keycloakProperties.getServer(KeycloakProperties.SERVER_CONTEXT_PATH);

    ServletRegistrationBean<HttpServlet30Dispatcher> servlet =
        new ServletRegistrationBean<>(new HttpServlet30Dispatcher());
    servlet.addInitParameter(
        "javax.ws.rs.Application", EmbeddedKeycloakApplication.class.getName());
    servlet.addInitParameter(
        ResteasyContextParameters.RESTEASY_SERVLET_MAPPING_PREFIX, contextPath);
    servlet.addInitParameter(ResteasyContextParameters.RESTEASY_USE_CONTAINER_FORM_PARAMS, "true");
    servlet.addInitParameter(ResteasyContextParameters.RESTEASY_DISABLE_HTML_SANITIZER, "true");
    servlet.addUrlMappings(contextPath + "/*");
    servlet.setLoadOnStartup(1);
    servlet.setAsyncSupported(true);

    return servlet;
  }

  @Bean
  FilterRegistrationBean<EmbeddedKeycloakRequestFilter> keycloakSessionManagement(
      KeycloakProperties keycloakProperties) {

    FilterRegistrationBean<EmbeddedKeycloakRequestFilter> filter = new FilterRegistrationBean<>();
    filter.setName("Keycloak Session Management");
    filter.setFilter(new EmbeddedKeycloakRequestFilter());
    filter.addUrlPatterns(
        keycloakProperties.getServer(KeycloakProperties.SERVER_CONTEXT_PATH) + "/*");

    return filter;
  }

  private void mockJndiEnvironment(DataSource dataSource) throws NamingException {
    NamingManager.setInitialContextFactoryBuilder(
        env ->
            environment ->
                new InitialContext() {

                  @Override
                  public Object lookup(Name name) {
                    return lookup(name.toString());
                  }

                  @Override
                  public Object lookup(String name) {

                    if ("spring/datasource".equals(name)) {
                      return dataSource;
                    }

                    return null;
                  }

                  @Override
                  public NameParser getNameParser(String name) {
                    return CompositeName::new;
                  }

                  @Override
                  public void close() {
                    // NOOP
                  }
                });
  }
}

【讨论】:

    猜你喜欢
    • 2019-11-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 2015-09-16
    • 2016-05-14
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多