Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keycloak 23 #957

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Used in docker-compose
# shellcheck disable=SC2034
KEYCLOAK_VERSION=22.0.4
KEYCLOAK_VERSION=23.0.1
16 changes: 16 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ jobs:
- KEYCLOAK_VERSION: 20.0.5
- KEYCLOAK_VERSION: 21.1.1
- KEYCLOAK_VERSION: 22.0.4
- KEYCLOAK_VERSION: 23.0.1
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -50,6 +51,11 @@ jobs:
key: ${{ runner.os }}-maven-${{ matrix.env.KEYCLOAK_VERSION }}-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-maven-${{ matrix.env.KEYCLOAK_VERSION }}

- name: Adapt sources for Keycloak versions < 23.0.0 (UPConfig -> String)
if: ${{ matrix.env.KEYCLOAK_VERSION < '23.0.0' }}
run: |
echo "JAVAX_PROFILE=-Ppre-keycloak23" >> $GITHUB_ENV

- name: Adapt sources for Keycloak versions < 22.0.0 (jakarta -> javax)
if: ${{ matrix.env.KEYCLOAK_VERSION < '22.0.0' }}
run: |
Expand Down Expand Up @@ -159,6 +165,11 @@ jobs:
key: ${{ runner.os }}-${{ matrix.java }}-maven-build-pom-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-${{ matrix.java }}-maven-build-pom

- name: Adapt sources for Keycloak versions < 23.0.0 (UPConfig -> String)
if: ${{ matrix.env.KEYCLOAK_VERSION < '23.0.0' }}
run: |
echo "JAVAX_PROFILE=-Ppre-keycloak23" >> $GITHUB_ENV

- name: Adapt sources for Keycloak versions < 22.0.0 (jakarta -> javax)
if: ${{ matrix.env.KEYCLOAK_VERSION < '22.0.0' }}
run: |
Expand Down Expand Up @@ -192,6 +203,11 @@ jobs:
restore-keys: |
${{ runner.os }}-maven-keycloak-legacy

- name: Adapt sources for Keycloak versions < 23.0.0 (UPConfig -> String)
if: ${{ matrix.env.KEYCLOAK_VERSION < '23.0.0' }}
run: |
echo "JAVAX_PROFILE=-Ppre-keycloak23" >> $GITHUB_ENV

- name: Adapt sources for Keycloak versions < 22.0.0 (jakarta -> javax)
if: ${{ matrix.env.KEYCLOAK_VERSION < '22.0.0' }}
run: |
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ FROM ${BUILDER_IMAGE} AS BUILDER

WORKDIR /app/

ARG KEYCLOAK_VERSION=22.0.4
ARG KEYCLOAK_VERSION=23.0.1
ARG MAVEN_CLI_OPTS="-ntp -B"

COPY .mvn .mvn
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ Additionally, the tag `maven` contains the source code and compile keycloak-conf
Keycloak versions, that not official supported., e.g.:

```bash
docker run --rm -ti -v $PWD:/config/ -eKEYCLOAK_VERSION=22.0.4 -eMAVEN_CLI_OPTS="-B -ntp -q" adorsys/keycloak-config-cli:edge-build
docker run --rm -ti -v $PWD:/config/ -eKEYCLOAK_VERSION=23.0.1 -eMAVEN_CLI_OPTS="-B -ntp -q" adorsys/keycloak-config-cli:edge-build
```

### Docker run
Expand Down
57 changes: 56 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<keycloak.version>22.0.4</keycloak.version>
<keycloak.version>23.0.1</keycloak.version>

<checkstyle-plugin.version>3.2.0</checkstyle-plugin.version>
<checkstyle.version>10.0</checkstyle.version>
Expand Down Expand Up @@ -727,6 +727,61 @@
<token>import jakarta</token>
<value>import javax</value>
</replacement>
<replacement>
<token>import org.keycloak.representations.userprofile.config.UPConfig;</token>
<value>;</value>
</replacement>
<replacement>
<token>return JsonUtil.toJson\(userProfileResource.getConfiguration\(\)\);</token>
<value>return userProfileResource.getConfiguration();</value>
</replacement>
<replacement>
<token>userProfileResource.update\(JsonUtil.readValue\(newUserProfileConfiguration, UPConfig.class\)\);</token>
<value>userProfileResource.update(newUserProfileConfiguration);</value>
</replacement>
</replacements>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>pre-keycloak23</id>
<build>
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>${maven-replacer.version}</version>
<executions>
<execution>
<id>replace-upconfig-with-string</id>
<phase>generate-sources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<basedir>
${project.basedir}/src
</basedir>
<includes>
<include>main/java/de/adorsys/keycloak/config/repository/UserProfileRepository.java</include>
</includes>
<replacements>
<replacement>
<token>import org.keycloak.representations.userprofile.config.UPConfig;</token>
<value>;</value>
</replacement>
<replacement>
<token>return JsonUtil.toJson\(userProfileResource.getConfiguration\(\)\);</token>
<value>return userProfileResource.getConfiguration();</value>
</replacement>
<replacement>
<token>userProfileResource.update\(JsonUtil.readValue\(newUserProfileConfiguration, UPConfig.class\)\);</token>
<value>userProfileResource.update(newUserProfileConfiguration);</value>
</replacement>
</replacements>
</configuration>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,12 @@ public void addSubGroup(String realmName, String parentGroupId, GroupRepresentat
}

public GroupRepresentation getSubGroupByName(String realmName, String parentGroupId, String name) {
GroupRepresentation existingGroup = getResourceById(realmName, parentGroupId).toRepresentation();

return existingGroup.getSubGroups()
GroupRepresentation subGroup = getSubGroups(realmName, parentGroupId)
.stream()
.filter(subgroup -> Objects.equals(subgroup.getName(), name))
.findFirst()
.orElse(null);
return subGroup;
}

public void addRealmRoles(String realmName, String groupId, List<String> roleNames) {
Expand Down Expand Up @@ -239,4 +238,12 @@ private GroupResource getResourceById(String realmName, String groupId) {
.groups()
.group(groupId);
}

public List<GroupRepresentation> getSubGroups(String realmName, String parentGroupId) {
// TODO make max size configurable
// note this is currently the only way to populate the subgroup information
// The meaning of the briefRepresentation was apprently inverted by mistake in Keycloak 23.0.0
// see: https://github.com/keycloak/keycloak/issues/25096
return getResourceById(realmName, parentGroupId).getSubGroups(0, 100, true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,13 @@
import de.adorsys.keycloak.config.exception.KeycloakRepositoryException;
import de.adorsys.keycloak.config.util.JsonUtil;
import org.keycloak.admin.client.resource.UserProfileResource;
import org.keycloak.representations.userprofile.config.UPConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Optional;

import jakarta.ws.rs.core.Response;

@Component
public class UserProfileRepository {

Expand All @@ -57,35 +54,36 @@ public void updateUserProfile(String realm, boolean newUserProfileEnabled, Strin

if (!newUserProfileEnabled) {
logger.trace("UserProfile is explicitly disabled, removing configuration.");
try (var response = userProfileResource.update(null)) {
logger.trace("UserProfile configuration removed.");
}
return;
userProfileResource.update(null);
logger.trace("UserProfile configuration removed.");
}

var realmAttributes = realmRepository.get(realm).getAttributesOrEmpty();
var currentUserProfileConfiguration = Optional.ofNullable(userProfileResource.getConfiguration()).orElse("");
var currentUserProfileConfiguration = getUserProfileConfiguration(userProfileResource);
if (!StringUtils.hasText(currentUserProfileConfiguration)) {
logger.warn("UserProfile is enabled, but no configuration string provided.");
return;
}

var currentUserProfileEnabled = Boolean.parseBoolean(realmAttributes.getOrDefault(REALM_ATTRIBUTES_USER_PROFILE_ENABLED_STRING, "false"));
var currentUserProfileEnabled =
Boolean.parseBoolean(realmAttributes.getOrDefault(REALM_ATTRIBUTES_USER_PROFILE_ENABLED_STRING, "false"));

if (!currentUserProfileEnabled) {
logger.warn("UserProfile enabled attribute in realm differs from configuration. "
+ "This is strange, because the attribute import should have done that already.");
}

var userProfileConfigChanged = hasUserProfileConfigurationChanged(newUserProfileConfiguration, currentUserProfileConfiguration);

if (!userProfileConfigChanged) {
logger.trace("UserProfile did not change, skipping update.");
return;
}

try (var updateUserProfileResponse = userProfileResource.update(newUserProfileConfiguration)) {
if (!updateUserProfileResponse.getStatusInfo().equals(Response.Status.OK)) {
throw new KeycloakRepositoryException("Could not update UserProfile Definition");
}
try {
resolveUserProfileUpdate(userProfileResource, newUserProfileConfiguration);
} catch (Exception ex) {
throw new KeycloakRepositoryException("Could not update UserProfile Definition", ex);
}

logger.trace("UserProfile updated.");
Expand All @@ -97,6 +95,14 @@ private boolean hasUserProfileConfigurationChanged(String newUserProfileConfigur
return !currentValue.equals(newValue);
}

private String getUserProfileConfiguration(UserProfileResource userProfileResource) {
return JsonUtil.toJson(userProfileResource.getConfiguration());
}

private void resolveUserProfileUpdate(UserProfileResource userProfileResource, String newUserProfileConfiguration) {
userProfileResource.update(JsonUtil.readValue(newUserProfileConfiguration, UPConfig.class));
}

private UserProfileResource getResource(String realmName) {
return this.realmRepository.getResource(realmName).users().userProfile();
}
Expand Down
Loading
Loading