Skip to content

Commit

Permalink
IT-515: Upgrade For newer version of keycloak (Quarkus based)
Browse files Browse the repository at this point in the history
  • Loading branch information
eugeniosant committed Jan 23, 2024
1 parent 3eff344 commit 917f834
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 130 deletions.
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
<properties>
<github.organization>entando-k8s</github.organization>
<sonar.projectKey>${github.organization}_${project.artifactId}</sonar.projectKey>
<entando-k8s-operator-common.version>7.3.0</entando-k8s-operator-common.version>
<sonar.scanner.force-deprecated-java-version>true</sonar.scanner.force-deprecated-java-version>
<entando-k8s-operator-common.version>7.3.0-IT-515-PR-157</entando-k8s-operator-common.version>
<skipLicenseDownload>true</skipLicenseDownload>
<preDeploymentTestGroups>in-process</preDeploymentTestGroups>
<postDeploymentTestGroups>smoke</postDeploymentTestGroups>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved.
* Copyright 2024-Present Entando Inc. (http://www.entando.com) All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
Expand All @@ -13,7 +13,6 @@
* details.
*
*/

package org.entando.kubernetes.controller.keycloakserver;

import static java.util.Optional.ofNullable;
Expand All @@ -31,32 +30,14 @@

public class EntandoKeycloakHelper {

private EntandoKeycloakHelper() {

}
private EntandoKeycloakHelper() {}

public static StandardKeycloakImage determineStandardImage(EntandoKeycloakServer entandoKeycloakServer) {
StandardKeycloakImage standardKeycloakImage;
if (EntandoOperatorSpiConfig.getComplianceMode() == EntandoOperatorComplianceMode.REDHAT) {
standardKeycloakImage = StandardKeycloakImage.REDHAT_SSO;
} else {
standardKeycloakImage = entandoKeycloakServer.getSpec().getStandardImage().orElse(StandardKeycloakImage.KEYCLOAK);
}
return standardKeycloakImage;

return StandardKeycloakImage.KEYCLOAK;
}

public static DbmsVendor determineDbmsVendor(EntandoKeycloakServer entandoKeycloakServer) {
DbmsVendor dbmsVendor;
if (EntandoOperatorSpiConfig.getComplianceMode() == EntandoOperatorComplianceMode.REDHAT) {
dbmsVendor = entandoKeycloakServer.getSpec().getDbms().orElse(DbmsVendor.POSTGRESQL);
} else {
dbmsVendor = entandoKeycloakServer.getSpec().getDbms().orElse(DbmsVendor.EMBEDDED);
}
if (dbmsVendor == DbmsVendor.NONE) {
dbmsVendor = DbmsVendor.EMBEDDED;
}
return dbmsVendor;
return entandoKeycloakServer.getSpec().getDbms().orElse(DbmsVendor.NONE);
}

public static String deriveFrontEndUrl(ProvidedCapability providedCapability) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import javax.inject.Inject;
import org.entando.kubernetes.controller.spi.capability.CapabilityProvider;
import org.entando.kubernetes.controller.spi.capability.CapabilityProvisioningResult;
import org.entando.kubernetes.controller.spi.client.ExecutionResult;
import org.entando.kubernetes.controller.spi.client.KubernetesClientForControllers;
import org.entando.kubernetes.controller.spi.command.DeploymentProcessor;
import org.entando.kubernetes.controller.spi.common.EntandoControllerException;
Expand Down Expand Up @@ -132,10 +131,6 @@ public void run() {
keycloakServer = k8sClient.updateStatus(keycloakServer, result.getStatus()
.withOriginatingCustomResource(providedCapability));
if (!result.getStatus().hasFailed()) {
if (EntandoKeycloakHelper.provisioningStrategyOf(keycloakServer)
!= CapabilityProvisioningStrategy.USE_EXTERNAL) {
ensureHttpAccess(result);
}
final ServerStatus mainServerStatus = providedCapability.getStatus().getServerStatus(NameUtils.MAIN_QUALIFIER)
.orElseThrow(IllegalStateException::new);
ensureKeycloakRealm(new ProvidedSsoCapability(k8sClient.loadCapabilityProvisioningResult(mainServerStatus)));
Expand Down Expand Up @@ -299,22 +294,7 @@ private Secret resolveCaSecret() {
return EntandoOperatorSpiConfig.getCertificateAuthoritySecretName()
.map(n -> (Secret) k8sClient.loadStandardResource(SECRET_KIND, k8sClient.getNamespace(), n)).orElse(null);
}

private void ensureHttpAccess(KeycloakDeploymentResult serviceDeploymentResult) throws TimeoutException {
//Give the operator access over http for cluster.local calls
final ExecutionResult result = k8sClient.executeOnPod(serviceDeploymentResult.getPod(), "server-container", 30,
"cd \"${KEYCLOAK_HOME}/bin\"",
"./kcadm.sh config credentials --server http://localhost:8080/auth --realm master "
+ "--user \"${KEYCLOAK_USER:-${SSO_ADMIN_USERNAME}}\" "
+ "--password \"${KEYCLOAK_PASSWORD:-${SSO_ADMIN_PASSWORD}}\"",
"./kcadm.sh update realms/master -s sslRequired=NONE"
);
if (result.hasFailed()) {
throw new EntandoControllerException("Could not disable Keycloak HTTPS requirement:" + String
.join("\n", result.getOutputLines()));
}
}


private DatabaseConnectionInfo provideDatabaseIfRequired() throws TimeoutException {
// Create database for Keycloak
final DbmsVendor dbmsVendor = EntandoKeycloakHelper.determineDbmsVendor(keycloakServer);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved.
* Copyright 2024-Present Entando Inc. (http://www.entando.com) All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
Expand All @@ -13,18 +13,14 @@
* details.
*
*/

package org.entando.kubernetes.controller.keycloakserver;

import static java.lang.String.format;

import io.fabric8.kubernetes.api.model.EnvVar;
import io.fabric8.kubernetes.api.model.Secret;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -38,7 +34,6 @@
import org.entando.kubernetes.controller.spi.container.DockerImageInfo;
import org.entando.kubernetes.controller.spi.container.IngressingContainer;
import org.entando.kubernetes.controller.spi.container.ParameterizableContainer;
import org.entando.kubernetes.controller.spi.container.PersistentVolumeAwareContainer;
import org.entando.kubernetes.controller.spi.container.SecretToMount;
import org.entando.kubernetes.controller.spi.result.DatabaseConnectionInfo;
import org.entando.kubernetes.controller.support.client.SecretClient;
Expand All @@ -50,18 +45,17 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class KeycloakDeployableContainer implements IngressingContainer, DbAwareContainer, PersistentVolumeAwareContainer,
ParameterizableContainer, ConfigurableResourceContainer {
public class KeycloakDeployableContainer implements IngressingContainer,
DbAwareContainer, ParameterizableContainer, ConfigurableResourceContainer {

private static final String COMMUNITY_KEYCLOAK_IMAGE_NAME = "entando/entando-keycloak";
public static final String REDHAT_SSO_IMAGE_NAME = "entando/entando-redhat-sso";

private static final Logger LOG = LoggerFactory.getLogger(KeycloakDeployableContainer.class);
private final EntandoKeycloakServer keycloakServer;
private final DatabaseConnectionInfo databaseServiceResult;
private final Secret caCertSecret;
private final List<DatabaseSchemaConnectionInfo> databaseSchemaConnectionInfos;
private static final String DB_SCHEMA_ENV_NAME = "DB_SCHEMA";
private static final String DB_SCHEMA_ENV_NAME = "KC_DB_SCHEMA";

public KeycloakDeployableContainer(EntandoKeycloakServer keycloakServer, DatabaseConnectionInfo databaseServiceResult,
Secret caCertSecret, SecretClient secretClient) {
Expand All @@ -78,11 +72,6 @@ public static String secretName(EntandoKeycloakServer keycloakServer) {
return keycloakServer.getSpec().getAdminSecretName().orElse(NameUtils.standardAdminSecretName(keycloakServer));
}

@Override
public Optional<String> getStorageClass() {
return this.keycloakServer.getSpec().getStorageClass().or(PersistentVolumeAwareContainer.super::getStorageClass);
}

@Override
public Optional<Integer> getMaximumStartupTimeSeconds() {
return Optional.of(180);
Expand All @@ -95,11 +84,7 @@ public DockerImageInfo getDockerImageInfo() {
}

private String determineStandardImageName() {
if (determineStandardKeycloakImage() == StandardKeycloakImage.REDHAT_SSO) {
return REDHAT_SSO_IMAGE_NAME;
} else {
return COMMUNITY_KEYCLOAK_IMAGE_NAME;
}
return COMMUNITY_KEYCLOAK_IMAGE_NAME;
}

@Override
Expand All @@ -114,10 +99,6 @@ protected String caCertsFolder(Secret s) {
return TrustStoreHelper.CERT_SECRET_MOUNT_ROOT + File.separator + s.getMetadata().getName();
}

private StandardKeycloakImage determineStandardKeycloakImage() {
return EntandoKeycloakHelper.determineStandardImage(keycloakServer);
}

@Override
public int getMemoryLimitMebibytes() {
return 1200;
Expand All @@ -138,20 +119,19 @@ public int getPrimaryPort() {
return 8080;
}

@Override
public List<String> getArgs() {
return List.of("start");
}

@Override
public List<EnvVar> getEnvironmentVariables() {
List<EnvVar> vars = new ArrayList<>();
if (determineStandardKeycloakImage() == StandardKeycloakImage.REDHAT_SSO) {
vars.add(
new EnvVar("SSO_ADMIN_USERNAME", null, SecretUtils.secretKeyRef(secretName(keycloakServer), SecretUtils.USERNAME_KEY)));
vars.add(new EnvVar("SSO_ADMIN_PASSWORD", null,
SecretUtils.secretKeyRef(secretName(keycloakServer), SecretUtils.PASSSWORD_KEY)));
} else {
vars.add(new EnvVar("KEYCLOAK_USER", null, SecretUtils.secretKeyRef(secretName(keycloakServer), SecretUtils.USERNAME_KEY)));
vars.add(
new EnvVar("KEYCLOAK_PASSWORD", null, SecretUtils.secretKeyRef(secretName(keycloakServer), SecretUtils.PASSSWORD_KEY)));
}
vars.add(new EnvVar("PROXY_ADDRESS_FORWARDING", "true", null));
vars.add(new EnvVar("KEYCLOAK_ADMIN", null, SecretUtils.secretKeyRef(secretName(keycloakServer), SecretUtils.USERNAME_KEY)));
vars.add(new EnvVar("KEYCLOAK_ADMIN_PASSWORD", null, SecretUtils.secretKeyRef(secretName(keycloakServer), SecretUtils.PASSSWORD_KEY)));
vars.add(new EnvVar("KC_PROXY", "edge", null));
vars.add(new EnvVar("KC_HTTP_RELATIVE_PATH", "/auth", null));
vars.add(new EnvVar("KC_HOSTNAME_STRICT", "false", null));
Optional.ofNullable(caCertSecret).ifPresent(s -> vars.add(getX509CaBundleVariable(s)));
return vars;
}
Expand All @@ -161,56 +141,28 @@ public List<EnvVar> getDatabaseConnectionVariables() {
List<EnvVar> vars = new ArrayList<>();
if (EntandoKeycloakHelper.provisioningStrategyOf(keycloakServer) == CapabilityProvisioningStrategy.DEPLOY_DIRECTLY) {
DbmsVendor dbmsVendor = EntandoKeycloakHelper.determineDbmsVendor(keycloakServer);
if (dbmsVendor == DbmsVendor.EMBEDDED) {
vars.add(new EnvVar("DB_VENDOR", "h2", null));
} else {
if (dbmsVendor != DbmsVendor.EMBEDDED) {
DatabaseSchemaConnectionInfo databaseSchemaConnectionInfo = databaseSchemaConnectionInfos.get(0);
if (determineStandardKeycloakImage() == StandardKeycloakImage.REDHAT_SSO) {
String driverName = databaseSchemaConnectionInfo.getDatabaseServiceResult().getVendor().getName();
vars.add(new EnvVar(format("DB_%s_SERVICE_HOST", driverName.toUpperCase(Locale.ROOT)),
databaseSchemaConnectionInfo.getDatabaseServiceResult().getInternalServiceHostname(), null));
vars.add(new EnvVar(format("DB_%s_SERVICE_PORT", driverName.toUpperCase(Locale.ROOT)),
databaseSchemaConnectionInfo.getDatabaseServiceResult().getPort(), null));
vars.add(new EnvVar("DB_SERVICE_PREFIX_MAPPING", format("db-%s=DB", driverName), null));
vars.add(new EnvVar("DB_USERNAME", null, databaseSchemaConnectionInfo.getUsernameRef()));
} else {
vars.add(new EnvVar("DB_ADDR", databaseSchemaConnectionInfo.getDatabaseServiceResult().getInternalServiceHostname(),
null));
vars.add(new EnvVar("DB_PORT", databaseSchemaConnectionInfo.getDatabaseServiceResult().getPort(), null));
vars.add(new EnvVar("DB_USER", null, databaseSchemaConnectionInfo.getUsernameRef()));
}

vars.add(
new EnvVar("DB_VENDOR", determineKeycloaksNonStandardDbVendorName(databaseSchemaConnectionInfo),
null));

if (dbmsVendor == DbmsVendor.MYSQL) {
vars.add(new EnvVar("DB_DATABASE", null, databaseSchemaConnectionInfo.getUsernameRef()));
} else {
vars.add(new EnvVar("DB_DATABASE", databaseSchemaConnectionInfo.getDatabaseNameToUse(), null));
}

vars.add(new EnvVar("KC_DB", this.determineKeycloaksNonStandardDbVendorName(databaseSchemaConnectionInfo), null));
vars.add(new EnvVar("KC_DB_USERNAME", null, databaseSchemaConnectionInfo.getUsernameRef()));
vars.add(new EnvVar("KC_DB_PASSWORD", null, databaseSchemaConnectionInfo.getPasswordRef()));
if (dbmsVendor == DbmsVendor.POSTGRESQL) {
setSchemaForPostgresql(vars, databaseSchemaConnectionInfo);
this.setSchemaForPostgresql(vars, databaseSchemaConnectionInfo);
}

vars.add(new EnvVar("DB_PASSWORD", null, databaseSchemaConnectionInfo.getPasswordRef()));
vars.add(new EnvVar("JDBC_PARAMS",
vars.add(new EnvVar("KC_DB_URL", databaseSchemaConnectionInfo.getJdbcUrl(), null));
vars.add(new EnvVar("KC_DB_URL_PROPERTIES",
databaseServiceResult.getJdbcParameters().entrySet().stream()
.map(entry -> entry.getKey() + "=" + entry.getValue())
.collect(
Collectors.joining("&")), null));

}
}
return vars;
}

private void setSchemaForPostgresql(List<EnvVar> vars,
DatabaseSchemaConnectionInfo databaseSchemaConnectionInfo) {

private void setSchemaForPostgresql(List<EnvVar> vars, DatabaseSchemaConnectionInfo databaseSchemaConnectionInfo) {
boolean isEnvVarDbSchemaPresent = keycloakServer.getSpec().getEnvironmentVariables().stream()
.anyMatch(e -> StringUtils.equals(DB_SCHEMA_ENV_NAME, e.getName()));

if (isEnvVarDbSchemaPresent) {
LOG.debug("For db vendor:'{}' env var '{}' is not blank use it as schema do nothing",
DbmsVendor.POSTGRESQL,
Expand All @@ -221,16 +173,14 @@ private void setSchemaForPostgresql(List<EnvVar> vars,
DB_SCHEMA_ENV_NAME);
vars.add(new EnvVar(DB_SCHEMA_ENV_NAME, null, databaseSchemaConnectionInfo.getUsernameRef()));
}

}

@Override
public List<DatabaseSchemaConnectionInfo> getSchemaConnectionInfo() {
return this.databaseSchemaConnectionInfos;
}

public EnvVar getX509CaBundleVariable(Secret caCertSecret) {

String certFiles = caCertSecret.getData().keySet().stream()
.map(fileName -> caCertsFolder(caCertSecret) + File.separator + fileName)
.collect(Collectors.joining(" "));
Expand Down Expand Up @@ -259,15 +209,6 @@ public Optional<String> getHealthCheckPath() {
return Optional.of(getWebContextPath());
}

@Override
public String getVolumeMountPath() {
if (determineStandardKeycloakImage() == StandardKeycloakImage.REDHAT_SSO) {
return "/opt/eap/standalone/data";
} else {
return "/opt/jboss/keycloak/standalone/data";
}
}

@Override
public Optional<EntandoResourceRequirements> getResourceRequirementsOverride() {
return keycloakServer.getSpec().getResourceRequirements();
Expand All @@ -277,4 +218,5 @@ public Optional<EntandoResourceRequirements> getResourceRequirementsOverride() {
public List<EnvVar> getEnvironmentVariableOverrides() {
return keycloakServer.getSpec().getEnvironmentVariables();
}

}

0 comments on commit 917f834

Please sign in to comment.