Skip to content

Commit

Permalink
Merge pull request #40662 from sberyozkin/keycloak_24.0.4
Browse files Browse the repository at this point in the history
Bump Keycloak version to 24.0.4
  • Loading branch information
sberyozkin authored May 16, 2024
2 parents 8402d10 + 52207f7 commit f7b8d69
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 9 deletions.
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@
<jna.version>5.8.0</jna.version><!-- should satisfy both testcontainers and mongodb -->
<antlr.version>4.13.0</antlr.version><!-- needs to align with same property in build-parent/pom.xml -->
<quarkus-security.version>2.0.3.Final</quarkus-security.version>
<keycloak.version>23.0.7</keycloak.version>
<keycloak.version>24.0.4</keycloak.version>
<logstash-gelf.version>1.15.1</logstash-gelf.version>
<checker-qual.version>3.43.0</checker-qual.version>
<error-prone-annotations.version>2.27.1</error-prone-annotations.version>
Expand Down
2 changes: 1 addition & 1 deletion build-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@

<!-- The image to use for tests that run Keycloak -->
<!-- IMPORTANT: If this is changed you must also update bom/application/pom.xml and KeycloakBuildTimeConfig/DevServicesConfig in quarkus-oidc/deployment to match the version -->
<keycloak.version>23.0.7</keycloak.version>
<keycloak.version>24.0.4</keycloak.version>
<keycloak.wildfly.version>19.0.3</keycloak.wildfly.version>
<keycloak.docker.image>quay.io/keycloak/keycloak:${keycloak.version}</keycloak.docker.image>
<keycloak.docker.legacy.image>quay.io/keycloak/keycloak:${keycloak.wildfly.version}-legacy</keycloak.docker.legacy.image>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ For more information, see xref:security-oidc-bearer-token-authentication.adoc#in
[[keycloak-initialization]]
=== Keycloak initialization

The `quay.io/keycloak/keycloak:23.0.7` image which contains a Keycloak distribution powered by Quarkus is used to start a container by default.
The `quay.io/keycloak/keycloak:24.0.4` image which contains a Keycloak distribution powered by Quarkus is used to start a container by default.
`quarkus.keycloak.devservices.image-name` can be used to change the Keycloak image name.
For example, set it to `quay.io/keycloak/keycloak:19.0.3-legacy` to use a Keycloak distribution powered by WildFly.
Be aware that a Quarkus-based Keycloak distribution is only available starting from Keycloak `20.0.0`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class DevServicesConfig {
* ends with `-legacy`.
* Override with `quarkus.keycloak.devservices.keycloak-x-image`.
*/
@ConfigItem(defaultValue = "quay.io/keycloak/keycloak:23.0.7")
@ConfigItem(defaultValue = "quay.io/keycloak/keycloak:24.0.4")
public String imageName;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ public class KeycloakDevServicesProcessor {
private static final String KEYCLOAK_QUARKUS_HOSTNAME = "KC_HOSTNAME";
private static final String KEYCLOAK_QUARKUS_ADMIN_PROP = "KEYCLOAK_ADMIN";
private static final String KEYCLOAK_QUARKUS_ADMIN_PASSWORD_PROP = "KEYCLOAK_ADMIN_PASSWORD";
private static final String KEYCLOAK_QUARKUS_START_CMD = "start --http-enabled=true --hostname-strict=false --hostname-strict-https=false";
private static final String KEYCLOAK_QUARKUS_START_CMD = "start --http-enabled=true --hostname-strict=false --hostname-strict-https=false "
+ "--spi-user-profile-declarative-user-profile-config-file=/opt/keycloak/upconfig.json";

private static final String JAVA_OPTS = "JAVA_OPTS";
private static final String OIDC_USERS = "oidc.users";
Expand Down Expand Up @@ -509,6 +510,7 @@ protected void configure() {
addEnv(KEYCLOAK_QUARKUS_ADMIN_PASSWORD_PROP, KEYCLOAK_ADMIN_PASSWORD);
withCommand(startCommand.orElse(KEYCLOAK_QUARKUS_START_CMD)
+ (useSharedNetwork ? " --hostname-port=" + fixedExposedPort.getAsInt() : ""));
addUpConfigResource();
} else {
addEnv(KEYCLOAK_WILDFLY_USER_PROP, KEYCLOAK_ADMIN_USER);
addEnv(KEYCLOAK_WILDFLY_PASSWORD_PROP, KEYCLOAK_ADMIN_PASSWORD);
Expand Down Expand Up @@ -560,6 +562,13 @@ private void mapResource(String resourcePath, String mappedResource) {
}
}

private void addUpConfigResource() {
if (Thread.currentThread().getContextClassLoader().getResource("/dev-service/upconfig.json") != null) {
LOG.debug("Mapping the classpath /dev-service/upconfig.json resource to /opt/keycloak/upconfig.json");
withClasspathResourceMapping("/dev-service/upconfig.json", "/opt/keycloak/upconfig.json", BindMode.READ_ONLY);
}
}

private Integer findRandomPort() {
try (ServerSocket socket = new ServerSocket(0)) {
return socket.getLocalPort();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"attributes": [
{
"name": "username",
"displayName": "${username}",
"permissions": {
"view": ["admin", "user"],
"edit": ["admin", "user"]
},
"validations": {
"length": { "min": 3, "max": 255 },
"username-prohibited-characters": {},
"up-username-not-idn-homograph": {}
}
},
{
"name": "email",
"displayName": "${email}",
"permissions": {
"view": ["admin", "user"],
"edit": ["admin", "user"]
},
"validations": {
"email" : {},
"length": { "max": 255 }
}
},
{
"name": "firstName",
"displayName": "${firstName}",
"permissions": {
"view": ["admin", "user"],
"edit": ["admin", "user"]
},
"validations": {
"length": { "max": 255 },
"person-name-prohibited-characters": {}
}
},
{
"name": "lastName",
"displayName": "${lastName}",
"permissions": {
"view": ["admin", "user"],
"edit": ["admin", "user"]
},
"validations": {
"length": { "max": 255 },
"person-name-prohibited-characters": {}
}
}
],
"groups": [
{
"name": "user-metadata",
"displayHeader": "User metadata",
"displayDescription": "Attributes, which refer to user metadata"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,5 @@ admin-url=${keycloak.url}

# Configure Keycloak Admin Client
quarkus.keycloak.admin-client.server-url=${admin-url}

quarkus.log.category."com.gargoylesoftware.htmlunit".level=ERROR
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
quarkus.keycloak.devservices.create-realm=false
quarkus.keycloak.devservices.show-logs=true
# Default tenant configurationf
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.secret=secret
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ quarkus.http.auth.permission.authenticated.policy=authenticated
smallrye.jwt.sign.key.location=/privateKey.pem
smallrye.jwt.new-token.lifespan=5

quarkus.log.category."com.gargoylesoftware.htmlunit.javascript.host.css.CSSStyleSheet".level=FATAL
quarkus.log.category."com.gargoylesoftware.htmlunit".level=ERROR
quarkus.http.auth.proactive=false

quarkus.native.additional-build-args=-H:IncludeResources=.*\\.pem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@
import java.io.IOException;
import java.net.URI;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import com.gargoylesoftware.htmlunit.CookieManager;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.SilentCssErrorHandler;
import com.gargoylesoftware.htmlunit.WebClient;
Expand Down Expand Up @@ -307,7 +311,9 @@ public void testReAuthenticateWhenSwitchingTenants() throws IOException {
page = loginForm.getInputByName("login").click();
assertEquals("tenant-web-app2:alice", page.getBody().asNormalizedText());
assertNull(getSessionCookie(webClient, "tenant-web-app"));
assertNotNull(getSessionCookie(webClient, "tenant-web-app2"));
List<Cookie> sessionCookieChunks = getSessionCookies(webClient, "tenant-web-app2");
assertNotNull(sessionCookieChunks);
assertEquals(2, sessionCookieChunks.size());
webClient.getCookieManager().clearCookies();
}
}
Expand Down Expand Up @@ -932,4 +938,17 @@ private Cookie getSessionAtCookie(WebClient webClient, String tenantId) {
private Cookie getSessionRtCookie(WebClient webClient, String tenantId) {
return webClient.getCookieManager().getCookie("q_session_rt" + (tenantId == null ? "_Default_test" : "_" + tenantId));
}

private List<Cookie> getSessionCookies(WebClient webClient, String tenantId) {
String sessionCookieNameChunk = "q_session" + (tenantId == null ? "" : "_" + tenantId) + "_chunk_";
CookieManager cookieManager = webClient.getCookieManager();
SortedMap<String, Cookie> sessionCookies = new TreeMap<>();
for (Cookie cookie : cookieManager.getCookies()) {
if (cookie.getName().startsWith(sessionCookieNameChunk)) {
sessionCookies.put(cookie.getName(), cookie);
}
}

return sessionCookies.isEmpty() ? null : new ArrayList<Cookie>(sessionCookies.values());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void testGetUserNameWithAccessTokenPropagation() {
//.statusCode(200)
//.body(equalTo("alice"));
.statusCode(500)
.body(containsString("Feature not enabled"));
.body(containsString("Client not allowed to exchange"));
}

@Test
Expand Down
60 changes: 60 additions & 0 deletions integration-tests/oidc/src/main/resources/upconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"attributes": [
{
"name": "username",
"displayName": "${username}",
"permissions": {
"view": ["admin", "user"],
"edit": ["admin", "user"]
},
"validations": {
"length": { "min": 3, "max": 255 },
"username-prohibited-characters": {},
"up-username-not-idn-homograph": {}
}
},
{
"name": "email",
"displayName": "${email}",
"permissions": {
"view": ["admin", "user"],
"edit": ["admin", "user"]
},
"validations": {
"email" : {},
"length": { "max": 255 }
}
},
{
"name": "firstName",
"displayName": "${firstName}",
"permissions": {
"view": ["admin", "user"],
"edit": ["admin", "user"]
},
"validations": {
"length": { "max": 255 },
"person-name-prohibited-characters": {}
}
},
{
"name": "lastName",
"displayName": "${lastName}",
"permissions": {
"view": ["admin", "user"],
"edit": ["admin", "user"]
},
"validations": {
"length": { "max": 255 },
"person-name-prohibited-characters": {}
}
}
],
"groups": [
{
"name": "user-metadata",
"displayHeader": "User metadata",
"displayDescription": "Attributes, which refer to user metadata"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ public Map<String, String> start() {
keycloak = keycloak
.withClasspathResourceMapping(SERVER_KEYSTORE, SERVER_KEYSTORE_MOUNTED_PATH, BindMode.READ_ONLY)
.withClasspathResourceMapping(SERVER_TRUSTSTORE, SERVER_TRUSTSTORE_MOUNTED_PATH, BindMode.READ_ONLY)
.withClasspathResourceMapping("/upconfig.json", "/opt/keycloak/upconfig.json", BindMode.READ_ONLY)
.withCommand("build --https-client-auth=required")
.withCommand(String.format(
"start --https-client-auth=required --hostname-strict=false --hostname-strict-https=false"
+ " --https-key-store-file=%s --https-trust-store-file=%s --https-trust-store-password=password",
+ " --https-key-store-file=%s --https-trust-store-file=%s --https-trust-store-password=password"
+ " --spi-user-profile-declarative-user-profile-config-file=/opt/keycloak/upconfig.json",
SERVER_KEYSTORE_MOUNTED_PATH, SERVER_TRUSTSTORE_MOUNTED_PATH));
keycloak.start();
LOGGER.info(keycloak.getLogs());
Expand Down

0 comments on commit f7b8d69

Please sign in to comment.