diff --git a/.env b/.env index 4aa43c3ed..0839976e7 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ # Used in docker-compose # shellcheck disable=SC2034 -KEYCLOAK_VERSION=21.0.1 +KEYCLOAK_VERSION=21.1.1 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e2eabd9ba..b3e0706d9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -30,7 +30,7 @@ jobs: - KEYCLOAK_VERSION: 18.0.2 - KEYCLOAK_VERSION: 19.0.3 - KEYCLOAK_VERSION: 20.0.5 - - KEYCLOAK_VERSION: 21.0.1 + - KEYCLOAK_VERSION: 21.1.1 steps: - uses: actions/checkout@v3 with: @@ -62,14 +62,14 @@ jobs: run: echo "::set-output name=VERSION::$(tail -n1 .env | cut -d= -f2)" - name: Login to Docker Hub - uses: docker/login-action@v2.1.0 + uses: docker/login-action@v2.2.0 if: startsWith(github.event.ref, 'refs/tags/v') with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Login to Quay.io - uses: docker/login-action@v2.1.0 + uses: docker/login-action@v2.2.0 if: startsWith(github.event.ref, 'refs/tags/v') with: registry: quay.io @@ -81,7 +81,7 @@ jobs: - name: Set up Docker Build Metadata id: docker_meta - uses: crazy-max/ghaction-docker-meta@v4.3.0 + uses: crazy-max/ghaction-docker-meta@v4.6.0 with: images: adorsys/keycloak-config-cli,quay.io/adorsys/keycloak-config-cli flavor: | @@ -102,7 +102,7 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Build and push - uses: docker/build-push-action@v4.0.0 + uses: docker/build-push-action@v4.1.1 with: build-args: |- KEYCLOAK_VERSION=${{ matrix.env.KEYCLOAK_VERSION }} @@ -161,7 +161,7 @@ jobs: fail-fast: false matrix: env: - - KEYCLOAK_VERSION: 21.0.1 + - KEYCLOAK_VERSION: 21.1.1 steps: - uses: actions/checkout@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index ef5befff9..5d97a2370 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - copy the JSON array of the old `userProfile` property to the new `userProfile.attributes` property - create a new JSON array for the `userProfile.groups` property (containing the attribute groups definitions) - in the end, the `userProfile` property should match the content of the "JSON editor" tab in the "Realm settings > User profile" page from the Keycloak admin console +- Add support for managing client-policies ## [5.6.1] - 2023-03-05 diff --git a/Dockerfile b/Dockerfile index d23b757cc..b8491f608 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ FROM ${BUILDER_IMAGE} AS BUILDER WORKDIR /app/ -ARG KEYCLOAK_VERSION=21.0.1 +ARG KEYCLOAK_VERSION=21.1.1 ARG MAVEN_CLI_OPTS="-ntp -B" COPY .mvn .mvn diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 1c5a7bb4e..3c2e6c4ed 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -55,6 +55,7 @@ | Remove clientScopeMappings | 2.5.0 | Remove existing clientScopeMappings while creating or updating realms | | Synchronize user federation | 3.5.0 | Synchronize the user federation defined on the realm configuration | | Synchronize user profile | 5.4.0 | Synchronize the user profile configuration defined on the realm configuration | +| Synchronize client-policies | 5.6.0 | Synchronize the client-policies (clientProfiles and clientPolicies) while updating realms | # Specificities diff --git a/pom.xml b/pom.xml index 988efe2a4..7a2a55e08 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.9 + 2.7.12 @@ -59,7 +59,7 @@ UTF-8 UTF-8 - 21.0.1 + 21.1.1 3.2.0 10.0 @@ -68,28 +68,29 @@ 1.10.0 2.4.4 4.9.10 - 2.13.4 - 0.8.9 - 2.0.0 + 2.13.5 + 0.8.10 + 2.0.1 1.1.2 2.1.1 2.0.0 - 7.3 + 7.4 3.0.0-M5 - 3.0.0 + 3.0.1 1.5.3 - 2.0.0 + 2.0.1 3.0.0-M5 5.15.0 - 3.20.0 + 3.21.0 6.55.0 0.15 5.0.4.Final - 4.7.3.3 + 4.7.3.5 4.7.3 - 1.17.6 - 6.0.8 + 1.18.3 + 6.0.9 2.27.2 + 3.24.2 keycloak-config-cli adorsys @@ -176,6 +177,7 @@ org.springframework.security spring-security-crypto + 5.8.3 @@ -189,6 +191,12 @@ spring-boot-loader + + org.yaml + snakeyaml + 2.0 + + org.keycloak keycloak-admin-client @@ -230,11 +238,6 @@ jackson-databind - - org.yaml - snakeyaml - - net.logstash.logback @@ -287,6 +290,13 @@ test + + org.assertj + assertj-core + ${assertj.version} + test + + org.mock-server mockserver-spring-test-listener diff --git a/src/main/java/de/adorsys/keycloak/config/repository/ClientPoliciesRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/ClientPoliciesRepository.java new file mode 100644 index 000000000..157e7e607 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/repository/ClientPoliciesRepository.java @@ -0,0 +1,112 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.repository; + +import de.adorsys.keycloak.config.model.RealmImport; +import org.keycloak.admin.client.resource.ClientPoliciesPoliciesResource; +import org.keycloak.admin.client.resource.ClientPoliciesProfilesResource; +import org.keycloak.representations.idm.ClientPoliciesRepresentation; +import org.keycloak.representations.idm.ClientProfilesRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ClientPoliciesRepository { + + private static final Logger logger = LoggerFactory.getLogger(AuthenticationFlowRepository.class); + + private final RealmRepository realmRepository; + + @Autowired + public ClientPoliciesRepository(RealmRepository realmRepository) { + this.realmRepository = realmRepository; + } + + private ClientPoliciesPoliciesResource getPoliciesResource(String realmName) { + return this.realmRepository.getResource(realmName).clientPoliciesPoliciesResource(); + } + + private ClientPoliciesProfilesResource getProfilesResource(String realmName) { + return this.realmRepository.getResource(realmName).clientPoliciesProfilesResource(); + } + + public void updateClientPoliciesPolicies(RealmImport realmImport, ClientPoliciesRepresentation newClientPolicies) { + + ClientPoliciesPoliciesResource policiesResource = getPoliciesResource(realmImport.getRealm()); + + ClientPoliciesRepresentation existingClientPolicies; + try { + existingClientPolicies = policiesResource.getPolicies(); + } catch (Exception ex) { + existingClientPolicies = null; + } + + if (existingClientPolicies == null && newClientPolicies == null) { + logger.trace("No client-policy policies configured, skipping update."); + return; + } + + if (existingClientPolicies != null && existingClientPolicies.equals(newClientPolicies)) { + logger.trace("Current client-policy policies match existing policies, skipping update."); + return; + } + + if (newClientPolicies == null) { + logger.trace("New client-policy policies resets existing policies."); + newClientPolicies = new ClientPoliciesRepresentation(); + } + + policiesResource.updatePolicies(newClientPolicies); + } + + public void updateClientPoliciesProfiles(RealmImport realmImport, ClientProfilesRepresentation newClientProfiles) { + + ClientPoliciesProfilesResource profilesResource = getProfilesResource(realmImport.getRealm()); + + // Note that we deliberately ignore global profiles, to avoid inconsistencies. + ClientProfilesRepresentation existingClientProfiles; + try { + existingClientProfiles = profilesResource.getProfiles(false); + } catch (Exception ex) { + existingClientProfiles = null; + } + + if (existingClientProfiles == null && newClientProfiles == null) { + logger.trace("No client-policy profiles configured, skipping update."); + return; + } + + if (existingClientProfiles != null && existingClientProfiles.equals(newClientProfiles)) { + logger.trace("Current client-policy profiles match existing profiles, skipping update."); + return; + } + + if (newClientProfiles == null) { + logger.trace("New client-policy profiles resets existing profiles."); + newClientProfiles = new ClientProfilesRepresentation(); + } + + profilesResource.updateProfiles(newClientProfiles); + } + +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/ClientPoliciesImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ClientPoliciesImportService.java new file mode 100644 index 000000000..f660d86ff --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/ClientPoliciesImportService.java @@ -0,0 +1,55 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service; + +import de.adorsys.keycloak.config.model.RealmImport; +import de.adorsys.keycloak.config.repository.ClientPoliciesRepository; +import org.keycloak.representations.idm.ClientPoliciesRepresentation; +import org.keycloak.representations.idm.ClientProfilesRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ClientPoliciesImportService { + + private static final Logger logger = LoggerFactory.getLogger(ClientPoliciesImportService.class); + + private final ClientPoliciesRepository clientPoliciesRepository; + + @Autowired + public ClientPoliciesImportService(ClientPoliciesRepository clientPoliciesRepository) { + this.clientPoliciesRepository = clientPoliciesRepository; + } + + public void doImport(RealmImport realmImport) { + + // client-profile profiles must be imported before client-profile policies + ClientProfilesRepresentation parsedClientProfiles = realmImport.getParsedClientProfiles(); + clientPoliciesRepository.updateClientPoliciesProfiles(realmImport, parsedClientProfiles); + logger.trace("Updated client-policy profiles."); + + ClientPoliciesRepresentation parsedClientPolicies = realmImport.getParsedClientPolicies(); + clientPoliciesRepository.updateClientPoliciesPolicies(realmImport, parsedClientPolicies); + logger.trace("Updated client-policy policies."); + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java b/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java index ebb0543d2..63c928d45 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java @@ -56,6 +56,8 @@ public class RealmImportService { "requiredActions", "defaultDefaultClientScopes", "defaultOptionalClientScopes", + "clientProfiles", + "clientPolicies", }; private static final Logger logger = LoggerFactory.getLogger(RealmImportService.class); @@ -64,6 +66,9 @@ public class RealmImportService { private final UserImportService userImportService; private final UserProfileImportService userProfileImportService; + + private final ClientPoliciesImportService clientPoliciesImportService; + private final RoleImportService roleImportService; private final ClientImportService clientImportService; private final ClientScopeImportService clientScopeImportService; @@ -90,6 +95,7 @@ public RealmImportService( RealmRepository realmRepository, UserImportService userImportService, UserProfileImportService userProfileImportService, + ClientPoliciesImportService clientPoliciesImportService, RoleImportService roleImportService, ClientImportService clientImportService, GroupImportService groupImportService, @@ -110,6 +116,7 @@ public RealmImportService( this.realmRepository = realmRepository; this.userImportService = userImportService; this.userProfileImportService = userProfileImportService; + this.clientPoliciesImportService = clientPoliciesImportService; this.roleImportService = roleImportService; this.clientImportService = clientImportService; this.groupImportService = groupImportService; @@ -194,6 +201,7 @@ private void configureRealm(RealmImport realmImport, RealmRepresentation existin defaultGroupsImportService.doImport(realmImport); componentImportService.doImport(realmImport); userProfileImportService.doImport(realmImport); + clientPoliciesImportService.doImport(realmImport); userImportService.doImport(realmImport); requiredActionsImportService.doImport(realmImport); authenticationFlowsImportService.doImport(realmImport); diff --git a/src/main/java/de/adorsys/keycloak/config/util/resteasy/CookieClientFilter.java b/src/main/java/de/adorsys/keycloak/config/util/resteasy/CookieClientFilter.java index 4608b6aef..d8a3109ad 100644 --- a/src/main/java/de/adorsys/keycloak/config/util/resteasy/CookieClientFilter.java +++ b/src/main/java/de/adorsys/keycloak/config/util/resteasy/CookieClientFilter.java @@ -34,16 +34,17 @@ // Currently, this filter does not valide cookie or is able to remove cookies. // A cookie managed is required to handle sticky sessions at cookie base public class CookieClientFilter implements ClientRequestFilter, ClientResponseFilter { - private final Map cookies = new HashMap<>(); + private final ThreadLocal> cookies = ThreadLocal.withInitial(HashMap::new); @Override public void filter(ClientRequestContext clientRequestContext) { - clientRequestContext.getHeaders().put("Cookie", new ArrayList<>(cookies.values())); + clientRequestContext.getHeaders().put("Cookie", new ArrayList<>(cookies.get().values())); } @Override public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) { - responseContext.getCookies().forEach((name, cookie) -> cookies.put(name, String.format("%s=%s", + cookies.remove(); + responseContext.getCookies().forEach((name, cookie) -> cookies.get().put(name, String.format("%s=%s", cookie.toCookie().getName(), cookie.toCookie().getValue() ))); diff --git a/src/test/java/de/adorsys/keycloak/config/AbstractImportIT.java b/src/test/java/de/adorsys/keycloak/config/AbstractImportIT.java index dcb92327d..a7040d4da 100644 --- a/src/test/java/de/adorsys/keycloak/config/AbstractImportIT.java +++ b/src/test/java/de/adorsys/keycloak/config/AbstractImportIT.java @@ -74,7 +74,7 @@ abstract public class AbstractImportIT extends AbstractImportTest { KEYCLOAK_CONTAINER.setCommand("start-dev"); command.add("start-dev"); command.add("--features"); - command.add("admin-fine-grained-authz,declarative-user-profile"); + command.add("admin-fine-grained-authz,declarative-user-profile,client-policies,client-secret-rotation"); } if (System.getProperties().getOrDefault("skipContainerStart", "false").equals("false")) { diff --git a/src/test/java/de/adorsys/keycloak/config/service/ImportClientPoliciesIT.java b/src/test/java/de/adorsys/keycloak/config/service/ImportClientPoliciesIT.java new file mode 100644 index 000000000..3bc3156ee --- /dev/null +++ b/src/test/java/de/adorsys/keycloak/config/service/ImportClientPoliciesIT.java @@ -0,0 +1,108 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ +package de.adorsys.keycloak.config.service; + +import de.adorsys.keycloak.config.AbstractImportIT; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.keycloak.representations.idm.ClientPolicyRepresentation; +import org.keycloak.representations.idm.ClientProfileRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ImportClientPoliciesIT extends AbstractImportIT { + + private static final String REALM_NAME = "realmWithClientPolicies"; + + ImportClientPoliciesIT() { + this.resourcePath = "import-files/client-policies"; + } + + @Test + @Order(1) + void shouldCreateRealm() throws IOException { + doImport("00_create_realm_with_no_client_policies.json"); + + assertRealm(); + } + + @Test + @Order(2) + void shouldCreateRealmWithClientPolicies() throws IOException { + doImport("01_create_realm_with_client_policies.json"); + + var realm = assertRealm(); + + var parsedClientProfiles = realm.getParsedClientProfiles(); + assertThat(parsedClientProfiles.getProfiles()).hasSize(1); + assertThat(parsedClientProfiles.getProfiles()).first().extracting(ClientProfileRepresentation::getName).isEqualTo("acme-client-profile"); + + var parsedClientPolicies = realm.getParsedClientPolicies(); + assertThat(parsedClientPolicies.getPolicies()).hasSize(1); + assertThat(parsedClientPolicies.getPolicies()).first().extracting(ClientPolicyRepresentation::getName).isEqualTo("acme-client-policy"); + } + + @Test + @Order(3) + void shouldCreateRealmWithClientPoliciesWithOnlyOneProfile() throws IOException { + doImport("02_create_realm_with_client_policies_only_1_profile.json"); + + var realm = assertRealm(); + + var parsedClientProfiles = realm.getParsedClientProfiles(); + assertThat(parsedClientProfiles.getProfiles()).hasSize(1); + assertThat(parsedClientProfiles.getProfiles()).first().extracting(ClientProfileRepresentation::getName).isEqualTo("acme-client-profile"); + } + + @Test + @Order(4) + void shouldCreateRealmWithClientPoliciesWithOnlyTwoProfiles() throws IOException { + doImport("03_create_realm_with_client_policies_only_2_profiles.json"); + + var realm = assertRealm(); + + var parsedClientProfiles = realm.getParsedClientProfiles(); + assertThat(parsedClientProfiles.getProfiles()).hasSize(2); + assertThat(parsedClientProfiles.getProfiles()).first().extracting(ClientProfileRepresentation::getName).isEqualTo("acme-client-profile-1"); + assertThat(parsedClientProfiles.getProfiles()).element(1).extracting(ClientProfileRepresentation::getName).isEqualTo("acme-client-profile-2"); + } + + @Test + @Order(5) + void shouldCreateRealmWithClientPoliciesWithOnlyOnePolicy() throws IOException { + doImport("04_create_realm_with_client_policies_only_1_policies.json"); + + var realm = assertRealm(); + + var parsedClientPolicies = realm.getParsedClientPolicies(); + assertThat(parsedClientPolicies.getPolicies()).hasSize(1); + assertThat(parsedClientPolicies.getPolicies()).hasSize(1); + assertThat(parsedClientPolicies.getPolicies()).first().extracting(ClientPolicyRepresentation::getName).isEqualTo("acme-client-policy"); + } + + private RealmRepresentation assertRealm() { + var realm = keycloakProvider.getInstance().realm(REALM_NAME).toRepresentation(); + assertThat(realm.getRealm()).isEqualTo(REALM_NAME); + return realm; + } +} diff --git a/src/test/resources/import-files/client-policies/00_create_realm_with_no_client_policies.json b/src/test/resources/import-files/client-policies/00_create_realm_with_no_client_policies.json new file mode 100644 index 000000000..de0b91f27 --- /dev/null +++ b/src/test/resources/import-files/client-policies/00_create_realm_with_no_client_policies.json @@ -0,0 +1,4 @@ +{ + "enabled": true, + "realm": "realmWithClientPolicies" +} diff --git a/src/test/resources/import-files/client-policies/01_create_realm_with_client_policies.json b/src/test/resources/import-files/client-policies/01_create_realm_with_client_policies.json new file mode 100644 index 000000000..86b7d1064 --- /dev/null +++ b/src/test/resources/import-files/client-policies/01_create_realm_with_client_policies.json @@ -0,0 +1,45 @@ +{ + "enabled": true, + "realm": "realmWithClientPolicies", + "clientProfiles": { + "profiles": [ + { + "name": "acme-client-profile", + "description": "", + "executors": [ + { + "executor": "secret-rotation", + "configuration": { + "expiration-period": "2505600", + "rotated-expiration-period": "172800", + "remaining-rotation-period": "864000" + } + } + ] + } + ] + }, + "clientPolicies": { + "policies": [ + { + "name": "acme-client-policy", + "description": "", + "enabled": true, + "conditions": [ + { + "condition": "client-access-type", + "configuration": { + "is-negative-logic": false, + "type": [ + "confidential" + ] + } + } + ], + "profiles": [ + "acme-client-profile" + ] + } + ] + } +} diff --git a/src/test/resources/import-files/client-policies/02_create_realm_with_client_policies_only_1_profile.json b/src/test/resources/import-files/client-policies/02_create_realm_with_client_policies_only_1_profile.json new file mode 100644 index 000000000..aee90af01 --- /dev/null +++ b/src/test/resources/import-files/client-policies/02_create_realm_with_client_policies_only_1_profile.json @@ -0,0 +1,22 @@ +{ + "enabled": true, + "realm": "realmWithClientPolicies", + "clientProfiles": { + "profiles": [ + { + "name": "acme-client-profile", + "description": "", + "executors": [ + { + "executor": "secret-rotation", + "configuration": { + "expiration-period": "2505600", + "rotated-expiration-period": "172800", + "remaining-rotation-period": "864000" + } + } + ] + } + ] + } +} diff --git a/src/test/resources/import-files/client-policies/03_create_realm_with_client_policies_only_2_profiles.json b/src/test/resources/import-files/client-policies/03_create_realm_with_client_policies_only_2_profiles.json new file mode 100644 index 000000000..4a2f9c1ec --- /dev/null +++ b/src/test/resources/import-files/client-policies/03_create_realm_with_client_policies_only_2_profiles.json @@ -0,0 +1,36 @@ +{ + "enabled": true, + "realm": "realmWithClientPolicies", + "clientProfiles": { + "profiles": [ + { + "name": "acme-client-profile-1", + "description": "", + "executors": [ + { + "executor": "secret-rotation", + "configuration": { + "expiration-period": "2505600", + "rotated-expiration-period": "172800", + "remaining-rotation-period": "864000" + } + } + ] + }, + { + "name": "acme-client-profile-2", + "description": "", + "executors": [ + { + "executor": "secret-rotation", + "configuration": { + "expiration-period": "2505600", + "rotated-expiration-period": "172800", + "remaining-rotation-period": "864000" + } + } + ] + } + ] + } +} diff --git a/src/test/resources/import-files/client-policies/04_create_realm_with_client_policies_only_1_policies.json b/src/test/resources/import-files/client-policies/04_create_realm_with_client_policies_only_1_policies.json new file mode 100644 index 000000000..da93b88d0 --- /dev/null +++ b/src/test/resources/import-files/client-policies/04_create_realm_with_client_policies_only_1_policies.json @@ -0,0 +1,25 @@ +{ + "enabled": true, + "realm": "realmWithClientPolicies", + "clientPolicies": { + "policies": [ + { + "name": "acme-client-policy", + "description": "", + "enabled": true, + "conditions": [ + { + "condition": "client-access-type", + "configuration": { + "is-negative-logic": false, + "type": [ + "confidential" + ] + } + } + ], + "profiles": [] + } + ] + } +} diff --git a/src/test/resources/import-files/exported-realm/21.0.1/master-realm.json b/src/test/resources/import-files/exported-realm/21.1.1/master-realm.json similarity index 99% rename from src/test/resources/import-files/exported-realm/21.0.1/master-realm.json rename to src/test/resources/import-files/exported-realm/21.1.1/master-realm.json index 2f14acb62..e8f162020 100644 --- a/src/test/resources/import-files/exported-realm/21.0.1/master-realm.json +++ b/src/test/resources/import-files/exported-realm/21.1.1/master-realm.json @@ -1777,7 +1777,7 @@ "cibaInterval" : "5", "realmReusableOtpCode" : "false" }, - "keycloakVersion" : "21.0.1", + "keycloakVersion" : "21.1.1", "userManagedAccessAllowed" : false, "clientProfiles" : { "profiles" : [ ] @@ -1785,4 +1785,4 @@ "clientPolicies" : { "policies" : [ ] } -} \ No newline at end of file +}