diff --git a/CHANGELOG.md b/CHANGELOG.md index c5ba93ec8..d2d67a089 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Updating `protocolMappers` on `clients` + ### Removed - `import.file` parameter diff --git a/contrib/example-config/moped.json b/contrib/example-config/moped.json index e12b589be..aaa3f7c73 100644 --- a/contrib/example-config/moped.json +++ b/contrib/example-config/moped.json @@ -186,6 +186,24 @@ ], "webOrigins": [ "*" + ], + "protocolMappers": [ + { + "name": "BranchCodeMapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "false", + "userinfo.token.claim": "true", + "multivalued": "false", + "user.attribute": "branch", + "id.token.claim": "false", + "access.token.claim": "true", + "claim.name": "branch", + "jsonType.label": "String" + } + } ] } ], diff --git a/contrib/native/test-with-import-files.sh b/contrib/native/test-with-import-files.sh index 7bcdb0ddf..9cfdd5395 100755 --- a/contrib/native/test-with-import-files.sh +++ b/contrib/native/test-with-import-files.sh @@ -13,6 +13,7 @@ while read -r file; do done < <( find src/test/resources/import-files \ -type f \ + -name '*.json' \ ! -path '*cli*' \ -and ! -path '*exported-realm*' \ -and ! -name '*invalid*' \ diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 78b09015c..562747a41 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -2,8 +2,8 @@ | Feature | Since | Description | | ------------------------------------------ | ----- | -------------------------------------------------------------------------------------------------------- | -| Create clients | 1.0.0 | Create client configuration while creating or updating realms | -| Update clients | 1.0.0 | Update client configuration while updating realms | +| Create clients | 1.0.0 | Create client configuration (inclusive protocolMappers) while creating or updating realms | +| Update clients | 1.0.0 | Update client configuration (inclusive protocolMappers) while updating realms | | Add roles | 1.0.0 | Add roles while creating or updating realms | | Update roles | 1.0.0 | Update role properties while updating realms | | Add composites to roles | 1.3.0 | Add role with realm-level and client-level composite roles while creating or updating realms | diff --git a/src/main/java/de/adorsys/keycloak/config/repository/ClientRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/ClientRepository.java index edb6b0f45..4a0cc5821 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/ClientRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/ClientRepository.java @@ -22,13 +22,16 @@ import de.adorsys.keycloak.config.util.ResponseUtil; import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ClientsResource; +import org.keycloak.admin.client.resource.ProtocolMappersResource; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.ws.rs.core.Response; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -60,8 +63,12 @@ public Optional tryToFindClient(String realm, String clien return maybeClient; } - public ClientRepresentation getClient(String realm, String clientId) { - return loadClient(realm, clientId); + public ClientRepresentation getClientByClientId(String realm, String clientId) { + return loadClientByClientId(realm, clientId); + } + + public ClientRepresentation getClientById(String realm, String id) { + return loadClientById(realm, id).toRepresentation(); } public String getClientSecret(String realm, String clientId) { @@ -85,8 +92,7 @@ public void update(String realm, ClientRepresentation clientToUpdate) { clientResource.update(clientToUpdate); } - - private ClientRepresentation loadClient(String realm, String clientId) { + private ClientRepresentation loadClientByClientId(String realm, String clientId) { List foundClients = realmRepository.loadRealm(realm) .clients() .findByClientId(clientId); @@ -98,8 +104,20 @@ private ClientRepresentation loadClient(String realm, String clientId) { return foundClients.get(0); } + private ClientResource loadClientById(String realm, String id) { + ClientResource client = realmRepository.loadRealm(realm) + .clients() + .get(id); + + if (client == null) { + throw new KeycloakRepositoryException("Cannot find client by id '" + id + "'"); + } + + return client; + } + final ClientResource getClientResource(String realm, String clientId) { - ClientRepresentation client = loadClient(realm, clientId); + ClientRepresentation client = loadClientByClientId(realm, clientId); return realmRepository.loadRealm(realm) .clients() .get(client.getId()); @@ -119,4 +137,35 @@ public final List getClients(String realm) { .clients() .findAll(); } + + public void addProtocolMappers(String realm, String clientId, List protocolMappers) { + ClientResource clientScopeResource = loadClientById(realm, clientId); + ProtocolMappersResource protocolMappersResource = clientScopeResource.getProtocolMappers(); + + for (ProtocolMapperRepresentation protocolMapper : protocolMappers) { + Response response = protocolMappersResource.createMapper(protocolMapper); + ResponseUtil.throwOnError(response); + } + } + + public void removeProtocolMappers(String realm, String clientId, List protocolMappers) { + ClientResource clientScopeResource = loadClientById(realm, clientId); + ProtocolMappersResource protocolMappersResource = clientScopeResource.getProtocolMappers(); + + List existingProtocolMappers = clientScopeResource.getProtocolMappers().getMappers(); + List protocolMapperToRemove = existingProtocolMappers.stream().filter(em -> protocolMappers.stream().anyMatch(m -> Objects.equals(m.getName(), em.getName()))).collect(Collectors.toList()); + + for (ProtocolMapperRepresentation protocolMapper : protocolMapperToRemove) { + protocolMappersResource.delete(protocolMapper.getId()); + } + } + + public void updateProtocolMappers(String realm, String clientId, List protocolMappers) { + ClientResource clientScopeResource = loadClientById(realm, clientId); + ProtocolMappersResource protocolMappersResource = clientScopeResource.getProtocolMappers(); + + for (ProtocolMapperRepresentation protocolMapper : protocolMappers) { + protocolMappersResource.update(protocolMapper.getId(), protocolMapper); + } + } } diff --git a/src/main/java/de/adorsys/keycloak/config/repository/GroupRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/GroupRepository.java index 93fe67dba..15777675a 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/GroupRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/GroupRepository.java @@ -128,7 +128,7 @@ public void addClientRoles(String realm, String groupId, String clientId, List clientRoles = roleRepository.searchClientRoles(realm, clientId, roleNames); @@ -139,7 +139,7 @@ public void removeClientRoles(String realm, String groupId, String clientId, Lis GroupResource groupResource = loadGroupById(realm, groupId); RoleMappingResource rolesResource = groupResource.roles(); - ClientRepresentation client = clientRepository.getClient(realm, clientId); + ClientRepresentation client = clientRepository.getClientByClientId(realm, clientId); RoleScopeResource groupClientRolesResource = rolesResource.clientLevel(client.getId()); List clientRoles = roleRepository.searchClientRoles(realm, clientId, roleNames); diff --git a/src/main/java/de/adorsys/keycloak/config/repository/RoleCompositeRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/RoleCompositeRepository.java index 6d8deb97b..c5fd1823a 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/RoleCompositeRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/RoleCompositeRepository.java @@ -261,7 +261,7 @@ private MultivaluedHashMap findClientComposites(Stri private Set findClientComposites(String realm, String clientId, Supplier roleSupplier) { RoleResource roleResource = roleSupplier.get(); - ClientRepresentation client = clientRepository.getClient(realm, clientId); + ClientRepresentation client = clientRepository.getClientByClientId(realm, clientId); return roleResource.getClientRoleComposites(client.getId()); } diff --git a/src/main/java/de/adorsys/keycloak/config/repository/RoleRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/RoleRepository.java index 2fa781a92..b7b480d17 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/RoleRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/RoleRepository.java @@ -94,7 +94,7 @@ public List findRealmRoles(String realm, Collection } public final Optional tryToFindClientRole(String realm, String clientId, String roleName) { - ClientRepresentation client = clientRepository.getClient(realm, clientId); + ClientRepresentation client = clientRepository.getClientByClientId(realm, clientId); RealmResource realmResource = realmRepository.loadRealm(realm); List clientRoles = realmResource.clients() @@ -113,7 +113,7 @@ public RoleRepresentation findClientRole(String realm, String clientId, String r } public List searchClientRoles(String realm, String clientId, List roles) { - ClientRepresentation foundClient = clientRepository.getClient(realm, clientId); + ClientRepresentation foundClient = clientRepository.getClientByClientId(realm, clientId); ClientResource clientResource = realmRepository.loadRealm(realm) .clients() @@ -127,7 +127,7 @@ public List searchClientRoles(String realm, String clientId, } public void createClientRole(String realm, String clientId, RoleRepresentation role) { - ClientRepresentation client = clientRepository.getClient(realm, clientId); + ClientRepresentation client = clientRepository.getClientByClientId(realm, clientId); RolesResource rolesResource = realmRepository.loadRealm(realm) .clients() .get(client.getId()) @@ -177,7 +177,7 @@ public void removeRealmRolesForUser(String realm, String username, List clientRoles) { - ClientRepresentation client = clientRepository.getClient(realm, clientId); + ClientRepresentation client = clientRepository.getClientByClientId(realm, clientId); UserResource userResource = userRepository.getUserResource(realm, username); RoleScopeResource userClientRoles = userResource.roles() @@ -187,7 +187,7 @@ public void addClientRolesToUser(String realm, String username, String clientId, } public void removeClientRolesForUser(String realm, String username, String clientId, List clientRoles) { - ClientRepresentation client = clientRepository.getClient(realm, clientId); + ClientRepresentation client = clientRepository.getClientByClientId(realm, clientId); UserResource userResource = userRepository.getUserResource(realm, username); RoleScopeResource userClientRoles = userResource.roles() @@ -197,7 +197,7 @@ public void removeClientRolesForUser(String realm, String username, String clien } public List getUserClientLevelRoles(String realm, String username, String clientId) { - ClientRepresentation client = clientRepository.getClient(realm, clientId); + ClientRepresentation client = clientRepository.getClientByClientId(realm, clientId); UserResource userResource = userRepository.getUserResource(realm, username); List roles = userResource.roles() @@ -215,7 +215,7 @@ final RoleResource loadRealmRole(String realm, String roleName) { } final RoleResource loadClientRole(String realm, String roleClientId, String roleName) { - ClientRepresentation client = clientRepository.getClient(realm, roleClientId); + ClientRepresentation client = clientRepository.getClientByClientId(realm, roleClientId); return realmRepository.loadRealm(realm) .clients() diff --git a/src/main/java/de/adorsys/keycloak/config/service/ClientImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ClientImportService.java index 9aea4a228..911a5779e 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ClientImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ClientImportService.java @@ -21,7 +21,9 @@ import de.adorsys.keycloak.config.model.RealmImport; import de.adorsys.keycloak.config.repository.ClientRepository; import de.adorsys.keycloak.config.util.CloneUtil; +import de.adorsys.keycloak.config.util.ProtocolMapperUtil; import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -82,7 +84,8 @@ private void updateClientIfNeeded(String realm, ClientRepresentation clientToUpd } private boolean areClientsEqual(String realm, ClientRepresentation clientToUpdate, ClientRepresentation existingClient) { - if (CloneUtil.deepEquals(clientToUpdate, existingClient, "id", "secret")) { + // Clients are never equal except every properties if defined in import realm + if (CloneUtil.deepEquals(clientToUpdate, existingClient, "id", "secret", "access")) { String clientSecret = clientRepository.getClientSecret(realm, clientToUpdate.getClientId()); return clientSecret.equals(clientToUpdate.getSecret()); } @@ -93,5 +96,25 @@ private boolean areClientsEqual(String realm, ClientRepresentation clientToUpdat private void updateClient(String realm, ClientRepresentation existingClient, ClientRepresentation clientToImport) { ClientRepresentation patchedClient = CloneUtil.patch(existingClient, clientToImport, "id"); clientRepository.update(realm, patchedClient); + + List protocolMappers = patchedClient.getProtocolMappers(); + if (protocolMappers != null) { + String clientId = patchedClient.getId(); + updateProtocolMappers(realm, clientId, protocolMappers); + } + } + + private void updateProtocolMappers(String realm, String clientId, List protocolMappers) { + ClientRepresentation existingClient = clientRepository.getClientById(realm, clientId); + + List existingProtocolMappers = existingClient.getProtocolMappers(); + + List protocolMappersToAdd = ProtocolMapperUtil.estimateProtocolMappersToAdd(protocolMappers, existingProtocolMappers); + List protocolMappersToRemove = ProtocolMapperUtil.estimateProtocolMappersToRemove(protocolMappers, existingProtocolMappers); + List protocolMappersToUpdate = ProtocolMapperUtil.estimateProtocolMappersToUpdate(protocolMappers, existingProtocolMappers); + + clientRepository.addProtocolMappers(realm, clientId, protocolMappersToAdd); + clientRepository.removeProtocolMappers(realm, clientId, protocolMappersToRemove); + clientRepository.updateProtocolMappers(realm, clientId, protocolMappersToUpdate); } } diff --git a/src/main/java/de/adorsys/keycloak/config/service/ClientScopeImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ClientScopeImportService.java index 57dda191d..c1a4ec3a8 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ClientScopeImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ClientScopeImportService.java @@ -23,13 +23,13 @@ import de.adorsys.keycloak.config.properties.ImportConfigProperties.ImportManagedProperties.ImportManagedPropertiesValues; import de.adorsys.keycloak.config.repository.ClientScopeRepository; import de.adorsys.keycloak.config.util.CloneUtil; +import de.adorsys.keycloak.config.util.ProtocolMapperUtil; import org.keycloak.representations.idm.ClientScopeRepresentation; import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -160,63 +160,12 @@ private void updateProtocolMappers(String realm, String clientScopeId, List existingProtocolMappers = existingClientScope.getProtocolMappers(); - List protocolMappersToAdd = estimateProtocolMappersToAdd(protocolMappers, existingProtocolMappers); - List protocolMappersToRemove = estimateProtocolMappersToRemove(protocolMappers, existingProtocolMappers); - List protocolMappersToUpdate = estimateProtocolMappersToUpdate(protocolMappers, existingProtocolMappers); + List protocolMappersToAdd = ProtocolMapperUtil.estimateProtocolMappersToAdd(protocolMappers, existingProtocolMappers); + List protocolMappersToRemove = ProtocolMapperUtil.estimateProtocolMappersToRemove(protocolMappers, existingProtocolMappers); + List protocolMappersToUpdate = ProtocolMapperUtil.estimateProtocolMappersToUpdate(protocolMappers, existingProtocolMappers); clientScopeRepository.addProtocolMappers(realm, clientScopeId, protocolMappersToAdd); clientScopeRepository.removeProtocolMappers(realm, clientScopeId, protocolMappersToRemove); clientScopeRepository.updateProtocolMappers(realm, clientScopeId, protocolMappersToUpdate); } - - private List estimateProtocolMappersToRemove(List protocolMappers, List existingProtocolMappers) { - List protocolMappersToRemove = new ArrayList<>(); - - if (existingProtocolMappers == null) { - return protocolMappersToRemove; - } - - for (ProtocolMapperRepresentation existingProtocolMapper : existingProtocolMappers) { - if (protocolMappers.stream().noneMatch(m -> Objects.equals(m.getName(), existingProtocolMapper.getName()))) { - protocolMappersToRemove.add(existingProtocolMapper); - } - } - - return protocolMappersToRemove; - } - - private List estimateProtocolMappersToAdd(List protocolMappers, List existingProtocolMappers) { - List protocolMappersToAdd = new ArrayList<>(); - - if (existingProtocolMappers == null) { - return protocolMappers; - } - - for (ProtocolMapperRepresentation protocolMapper : protocolMappers) { - if (existingProtocolMappers.stream().noneMatch(em -> Objects.equals(em.getName(), protocolMapper.getName()))) { - protocolMappersToAdd.add(protocolMapper); - } - } - - return protocolMappersToAdd; - } - - private List estimateProtocolMappersToUpdate(List protocolMappers, List existingProtocolMappers) { - List protocolMappersToUpdate = new ArrayList<>(); - - if (existingProtocolMappers == null) { - return protocolMappersToUpdate; - } - - for (ProtocolMapperRepresentation protocolMapper : protocolMappers) { - Optional existingProtocolMapper = existingProtocolMappers.stream().filter(em -> Objects.equals(em.getName(), protocolMapper.getName())).findFirst(); - if (existingProtocolMapper.isPresent()) { - ProtocolMapperRepresentation patchedProtocolMapper = CloneUtil.patch(existingProtocolMapper.get(), protocolMapper); - protocolMappersToUpdate.add(patchedProtocolMapper); - } - } - - return protocolMappersToUpdate; - } - } diff --git a/src/main/java/de/adorsys/keycloak/config/service/CustomImportService.java b/src/main/java/de/adorsys/keycloak/config/service/CustomImportService.java index 04526eed7..0b73e75c7 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/CustomImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/CustomImportService.java @@ -75,7 +75,7 @@ private void removeImpersonation(RealmImport realmImport) { } private void removeImpersonationRoleFromClient(RealmResource master, String clientId) { - ClientRepresentation client = clientRepository.getClient("master", clientId); + ClientRepresentation client = clientRepository.getClientByClientId("master", clientId); ClientResource clientResource = master.clients() .get(client.getId()); diff --git a/src/main/java/de/adorsys/keycloak/config/util/ProtocolMapperUtil.java b/src/main/java/de/adorsys/keycloak/config/util/ProtocolMapperUtil.java new file mode 100644 index 000000000..147e49bba --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/util/ProtocolMapperUtil.java @@ -0,0 +1,78 @@ +/* + * Copyright 2019-2020 adorsys GmbH & Co. KG @ https://adorsys.de + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package de.adorsys.keycloak.config.util; + +import org.keycloak.representations.idm.ProtocolMapperRepresentation; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +public class ProtocolMapperUtil { + public static List estimateProtocolMappersToRemove(List protocolMappers, List existingProtocolMappers) { + List protocolMappersToRemove = new ArrayList<>(); + + if (existingProtocolMappers == null) { + return protocolMappersToRemove; + } + + for (ProtocolMapperRepresentation existingProtocolMapper : existingProtocolMappers) { + if (protocolMappers.stream().noneMatch(m -> Objects.equals(m.getName(), existingProtocolMapper.getName()))) { + protocolMappersToRemove.add(existingProtocolMapper); + } + } + + return protocolMappersToRemove; + } + + public static List estimateProtocolMappersToAdd(List protocolMappers, List existingProtocolMappers) { + List protocolMappersToAdd = new ArrayList<>(); + + if (existingProtocolMappers == null) { + return protocolMappers; + } + + for (ProtocolMapperRepresentation protocolMapper : protocolMappers) { + if (existingProtocolMappers.stream().noneMatch(em -> Objects.equals(em.getName(), protocolMapper.getName()))) { + protocolMappersToAdd.add(protocolMapper); + } + } + + return protocolMappersToAdd; + } + + public static List estimateProtocolMappersToUpdate(List protocolMappers, List existingProtocolMappers) { + List protocolMappersToUpdate = new ArrayList<>(); + + if (existingProtocolMappers == null) { + return protocolMappersToUpdate; + } + + for (ProtocolMapperRepresentation protocolMapper : protocolMappers) { + Optional existingProtocolMapper = existingProtocolMappers.stream().filter(em -> Objects.equals(em.getName(), protocolMapper.getName())).findFirst(); + if (existingProtocolMapper.isPresent()) { + ProtocolMapperRepresentation patchedProtocolMapper = CloneUtil.patch(existingProtocolMapper.get(), protocolMapper, "id"); + protocolMappersToUpdate.add(patchedProtocolMapper); + } + } + + return protocolMappersToUpdate; + } +} diff --git a/src/main/resources/META-INF/native-image/10.0.2/proxy-config.json b/src/main/resources/META-INF/native-image/10.0.2/proxy-config.json index 3a2011da4..d6e375ed5 100644 --- a/src/main/resources/META-INF/native-image/10.0.2/proxy-config.json +++ b/src/main/resources/META-INF/native-image/10.0.2/proxy-config.json @@ -43,6 +43,10 @@ "org.keycloak.admin.client.resource.IdentityProvidersResource", "org.jboss.resteasy.client.jaxrs.internal.proxy.ResteasyClientProxy" ], + [ + "org.keycloak.admin.client.resource.ProtocolMappersResource", + "org.jboss.resteasy.client.jaxrs.internal.proxy.ResteasyClientProxy" + ], [ "org.keycloak.admin.client.resource.RealmResource", "org.jboss.resteasy.client.jaxrs.internal.proxy.ResteasyClientProxy" diff --git a/src/main/resources/META-INF/native-image/10.0.2/reflect-config.json b/src/main/resources/META-INF/native-image/10.0.2/reflect-config.json index 29bca140e..145a14876 100644 --- a/src/main/resources/META-INF/native-image/10.0.2/reflect-config.json +++ b/src/main/resources/META-INF/native-image/10.0.2/reflect-config.json @@ -95,6 +95,14 @@ "name": "org.keycloak.admin.client.resource.IdentityProvidersResource", "allPublicMethods": true }, + { + "name": "org.keycloak.admin.client.resource.ProtocolMapperResource", + "allPublicMethods": true + }, + { + "name": "org.keycloak.admin.client.resource.ProtocolMappersResource", + "allPublicMethods": true + }, { "name": "org.keycloak.admin.client.resource.RealmResource", "allPublicMethods": true diff --git a/src/test/java/de/adorsys/keycloak/config/ImportClientsIT.java b/src/test/java/de/adorsys/keycloak/config/ImportClientsIT.java index 36c8ae436..255e3ff01 100644 --- a/src/test/java/de/adorsys/keycloak/config/ImportClientsIT.java +++ b/src/test/java/de/adorsys/keycloak/config/ImportClientsIT.java @@ -22,10 +22,14 @@ import org.junit.jupiter.api.Test; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.representations.idm.RealmRepresentation; +import java.util.Objects; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.not; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.nullValue; @@ -46,10 +50,7 @@ public void shouldCreateRealmWithClient() { assertThat(createdRealm.getRealm(), is(REALM_NAME)); assertThat(createdRealm.isEnabled(), is(true)); - ClientRepresentation createdClient = keycloakRepository.getClient( - REALM_NAME, - "moped-client" - ); + ClientRepresentation createdClient = getClient("moped-client"); assertThat(createdClient.getName(), is("moped-client")); assertThat(createdClient.getClientId(), is("moped-client")); @@ -58,9 +59,7 @@ public void shouldCreateRealmWithClient() { assertThat(createdClient.getClientAuthenticatorType(), is("client-secret")); assertThat(createdClient.getRedirectUris(), is(containsInAnyOrder("*"))); assertThat(createdClient.getWebOrigins(), is(containsInAnyOrder("*"))); - - // client secret on this place is always null... - assertThat(createdClient.getSecret(), is(nullValue())); + assertThat(createdClient.getProtocolMappers(), is(nullValue())); // ... and has to be retrieved separately String clientSecret = getClientSecret(createdClient.getId()); @@ -72,29 +71,24 @@ public void shouldCreateRealmWithClient() { public void shouldUpdateRealmByAddingClient() { doImport("1_update_realm__add_client.json"); - RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); + RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); - assertThat(createdRealm.getRealm(), is(REALM_NAME)); - assertThat(createdRealm.isEnabled(), is(true)); - - ClientRepresentation createdClient = keycloakRepository.getClient( - REALM_NAME, - "another-client" - ); + assertThat(realm.getRealm(), is(REALM_NAME)); + assertThat(realm.isEnabled(), is(true)); - assertThat(createdClient.getName(), is("another-client")); - assertThat(createdClient.getClientId(), is("another-client")); - assertThat(createdClient.getDescription(), is("Another-Client")); - assertThat(createdClient.isEnabled(), is(true)); - assertThat(createdClient.getClientAuthenticatorType(), is("client-secret")); - assertThat(createdClient.getRedirectUris(), is(containsInAnyOrder("*"))); - assertThat(createdClient.getWebOrigins(), is(containsInAnyOrder("*"))); + ClientRepresentation client = getClient("another-client"); - // client secret on this place is always null... - assertThat(createdClient.getSecret(), is(nullValue())); + assertThat(client.getName(), is("another-client")); + assertThat(client.getClientId(), is("another-client")); + assertThat(client.getDescription(), is("Another-Client")); + assertThat(client.isEnabled(), is(true)); + assertThat(client.getClientAuthenticatorType(), is("client-secret")); + assertThat(client.getRedirectUris(), is(containsInAnyOrder("*"))); + assertThat(client.getWebOrigins(), is(containsInAnyOrder("*"))); + assertThat(client.getProtocolMappers(), is(nullValue())); // ... and has to be retrieved separately - String clientSecret = getClientSecret(createdClient.getId()); + String clientSecret = getClientSecret(client.getId()); assertThat(clientSecret, is("my-other-client-secret")); } @@ -108,13 +102,68 @@ void shouldUpdateRealmWithChangedClientProperties() { assertThat(createdRealm.getRealm(), is(REALM_NAME)); assertThat(createdRealm.isEnabled(), is(true)); + ClientRepresentation createdClient = getClient("moped-client"); + + assertThat(createdClient.getName(), is("moped-client")); + assertThat(createdClient.getClientId(), is("moped-client")); + assertThat(createdClient.getDescription(), is("Moped-Client")); + assertThat(createdClient.isEnabled(), is(true)); + assertThat(createdClient.getClientAuthenticatorType(), is("client-secret")); + assertThat(createdClient.getRedirectUris(), is(containsInAnyOrder("https://moped-client.org/redirect"))); + assertThat(createdClient.getWebOrigins(), is(containsInAnyOrder("https://moped-client.org/webOrigin"))); + assertThat(createdClient.getProtocolMappers(), is(nullValue())); + + // ... and has to be retrieved separately + String clientSecret = getClientSecret(createdClient.getId()); + assertThat(clientSecret, is("changed-special-client-secret")); + } + + @Test + @Order(3) + void shouldUpdateRealmAddProtocolMapper() { + doImport("3_update_realm__add_protocol-mapper.json"); + + RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); + + assertThat(realm.getRealm(), is(REALM_NAME)); + assertThat(realm.isEnabled(), is(true)); + + ClientRepresentation updatedClient = getClient("moped-client"); + + assertThat(updatedClient.getName(), is("moped-client")); + assertThat(updatedClient.getClientId(), is("moped-client")); + assertThat(updatedClient.getDescription(), is("Moped-Client")); + assertThat(updatedClient.isEnabled(), is(true)); + assertThat(updatedClient.getClientAuthenticatorType(), is("client-secret")); + assertThat(updatedClient.getRedirectUris(), is(containsInAnyOrder("https://moped-client.org/redirect"))); + assertThat(updatedClient.getWebOrigins(), is(containsInAnyOrder("https://moped-client.org/webOrigin"))); + assertThat(updatedClient.getProtocolMappers(), not(nullValue())); + + // ... and has to be retrieved separately + String clientSecret = getClientSecret(updatedClient.getId()); + assertThat(clientSecret, is("changed-special-client-secret")); + + ProtocolMapperRepresentation updatedClientProtocolMappers = updatedClient.getProtocolMappers().stream().filter(m -> Objects.equals(m.getName(), "BranchCodeMapper")).findFirst().orElse(null); + + assertThat(updatedClientProtocolMappers, not(nullValue())); + assertThat(updatedClientProtocolMappers.getProtocol(), is("openid-connect")); + assertThat(updatedClientProtocolMappers.getProtocolMapper(), is("oidc-usermodel-attribute-mapper")); + assertThat(updatedClientProtocolMappers.getConfig().get("aggregate.attrs"), is("false")); + assertThat(updatedClientProtocolMappers.getConfig().get("userinfo.token.claim"), is("true")); + assertThat(updatedClientProtocolMappers.getConfig().get("user.attribute"), is("branch")); + assertThat(updatedClientProtocolMappers.getConfig().get("multivalued"), is("false")); + assertThat(updatedClientProtocolMappers.getConfig().get("id.token.claim"), is("false")); + assertThat(updatedClientProtocolMappers.getConfig().get("access.token.claim"), is("true")); + assertThat(updatedClientProtocolMappers.getConfig().get("claim.name"), is("branch")); + assertThat(updatedClientProtocolMappers.getConfig().get("jsonType.label"), is("String")); + ClientRepresentation createdClient = keycloakRepository.getClient( REALM_NAME, - "moped-client" + "moped-mapper-client" ); - assertThat(createdClient.getName(), is("moped-client")); - assertThat(createdClient.getClientId(), is("moped-client")); + assertThat(createdClient.getName(), is("moped-mapper-client")); + assertThat(createdClient.getClientId(), is("moped-mapper-client")); assertThat(createdClient.getDescription(), is("Moped-Client")); assertThat(createdClient.isEnabled(), is(true)); assertThat(createdClient.getClientAuthenticatorType(), is("client-secret")); @@ -125,8 +174,239 @@ void shouldUpdateRealmWithChangedClientProperties() { assertThat(createdClient.getSecret(), is(nullValue())); // ... and has to be retrieved separately - String clientSecret = getClientSecret(createdClient.getId()); + String clientSecret2 = getClientSecret(createdClient.getId()); + assertThat(clientSecret2, is("changed-special-client-secret")); + + ProtocolMapperRepresentation createdClientProtocolMappers = createdClient.getProtocolMappers().stream().filter(m -> Objects.equals(m.getName(), "BranchCodeMapper")).findFirst().orElse(null); + + assertThat(createdClientProtocolMappers, not(nullValue())); + assertThat(createdClientProtocolMappers.getProtocol(), is("openid-connect")); + assertThat(createdClientProtocolMappers.getProtocolMapper(), is("oidc-usermodel-attribute-mapper")); + assertThat(createdClientProtocolMappers.getConfig().get("aggregate.attrs"), is("false")); + assertThat(createdClientProtocolMappers.getConfig().get("userinfo.token.claim"), is("true")); + assertThat(createdClientProtocolMappers.getConfig().get("user.attribute"), is("branch")); + assertThat(createdClientProtocolMappers.getConfig().get("multivalued"), is("false")); + assertThat(createdClientProtocolMappers.getConfig().get("id.token.claim"), is("false")); + assertThat(createdClientProtocolMappers.getConfig().get("access.token.claim"), is("true")); + assertThat(createdClientProtocolMappers.getConfig().get("claim.name"), is("branch")); + assertThat(createdClientProtocolMappers.getConfig().get("jsonType.label"), is("String")); + } + + @Test + @Order(4) + void shouldUpdateRealmAddMoreProtocolMapper() { + doImport("4_update_realm__add_more_protocol-mapper.json"); + + RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); + + assertThat(realm.getRealm(), is(REALM_NAME)); + assertThat(realm.isEnabled(), is(true)); + + ClientRepresentation client = keycloakRepository.getClient( + REALM_NAME, + "moped-client" + ); + + assertThat(client.getName(), is("moped-client")); + assertThat(client.getClientId(), is("moped-client")); + assertThat(client.getDescription(), is("Moped-Client")); + assertThat(client.isEnabled(), is(true)); + assertThat(client.getClientAuthenticatorType(), is("client-secret")); + assertThat(client.getRedirectUris(), is(containsInAnyOrder("https://moped-client.org/redirect"))); + assertThat(client.getWebOrigins(), is(containsInAnyOrder("https://moped-client.org/webOrigin"))); + + // ... and has to be retrieved separately + String clientSecret = getClientSecret(client.getId()); + assertThat(clientSecret, is("changed-special-client-secret")); + + ProtocolMapperRepresentation protocolMapper = client.getProtocolMappers().stream().filter(m -> Objects.equals(m.getName(), "BranchCodeMapper")).findFirst().orElse(null); + + assertThat(protocolMapper, not(nullValue())); + assertThat(protocolMapper.getProtocol(), is("openid-connect")); + assertThat(protocolMapper.getProtocolMapper(), is("oidc-usermodel-attribute-mapper")); + assertThat(protocolMapper.getConfig().get("aggregate.attrs"), is("false")); + assertThat(protocolMapper.getConfig().get("userinfo.token.claim"), is("true")); + assertThat(protocolMapper.getConfig().get("user.attribute"), is("branch")); + assertThat(protocolMapper.getConfig().get("multivalued"), is("false")); + assertThat(protocolMapper.getConfig().get("id.token.claim"), is("false")); + assertThat(protocolMapper.getConfig().get("access.token.claim"), is("true")); + assertThat(protocolMapper.getConfig().get("claim.name"), is("branch")); + assertThat(protocolMapper.getConfig().get("jsonType.label"), is("String")); + + ProtocolMapperRepresentation protocolMapper2 = client.getProtocolMappers().stream().filter(m -> Objects.equals(m.getName(), "full name")).findFirst().orElse(null); + + assertThat(protocolMapper2, not(nullValue())); + assertThat(protocolMapper2.getProtocol(), is("openid-connect")); + assertThat(protocolMapper2.getProtocolMapper(), is("oidc-full-name-mapper")); + assertThat(protocolMapper2.getConfig().get("id.token.claim"), is("true")); + assertThat(protocolMapper2.getConfig().get("access.token.claim"), is("true")); + } + + @Test + @Order(5) + void shouldUpdateRealmChangeProtocolMapper() { + doImport("5_update_realm__change_protocol-mapper.json"); + + RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); + + assertThat(realm.getRealm(), is(REALM_NAME)); + assertThat(realm.isEnabled(), is(true)); + + ClientRepresentation clien = keycloakRepository.getClient( + REALM_NAME, + "moped-client" + ); + + assertThat(clien.getName(), is("moped-client")); + assertThat(clien.getClientId(), is("moped-client")); + assertThat(clien.getDescription(), is("Moped-Client")); + assertThat(clien.isEnabled(), is(true)); + assertThat(clien.getClientAuthenticatorType(), is("client-secret")); + assertThat(clien.getRedirectUris(), is(containsInAnyOrder("https://moped-client.org/redirect"))); + assertThat(clien.getWebOrigins(), is(containsInAnyOrder("https://moped-client.org/webOrigin"))); + + // ... and has to be retrieved separately + String clientSecret = getClientSecret(clien.getId()); assertThat(clientSecret, is("changed-special-client-secret")); + + ProtocolMapperRepresentation protocolMapper = clien.getProtocolMappers().stream().filter(m -> Objects.equals(m.getName(), "BranchCodeMapper")).findFirst().orElse(null); + + assertThat(protocolMapper, not(nullValue())); + assertThat(protocolMapper.getProtocol(), is("openid-connect")); + assertThat(protocolMapper.getProtocolMapper(), is("oidc-usermodel-attribute-mapper")); + assertThat(protocolMapper.getConfig().get("aggregate.attrs"), is("false")); + assertThat(protocolMapper.getConfig().get("userinfo.token.claim"), is("true")); + assertThat(protocolMapper.getConfig().get("user.attribute"), is("branch")); + assertThat(protocolMapper.getConfig().get("multivalued"), is("true")); + assertThat(protocolMapper.getConfig().get("id.token.claim"), is("false")); + assertThat(protocolMapper.getConfig().get("access.token.claim"), is("true")); + assertThat(protocolMapper.getConfig().get("claim.name"), is("branch")); + assertThat(protocolMapper.getConfig().get("jsonType.label"), is("String")); + + ProtocolMapperRepresentation protocolMapper2 = clien.getProtocolMappers().stream().filter(m -> Objects.equals(m.getName(), "full name")).findFirst().orElse(null); + + assertThat(protocolMapper2, not(nullValue())); + assertThat(protocolMapper2.getProtocol(), is("openid-connect")); + assertThat(protocolMapper2.getProtocolMapper(), is("oidc-full-name-mapper")); + assertThat(protocolMapper2.getConfig().get("id.token.claim"), is("true")); + assertThat(protocolMapper2.getConfig().get("access.token.claim"), is("false")); + } + + @Test + @Order(6) + void shouldUpdateRealmIgnoreProtocolMapper() { + doImport("6_update_realm__ignore_protocol-mapper.json"); + + RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); + + assertThat(realm.getRealm(), is(REALM_NAME)); + assertThat(realm.isEnabled(), is(true)); + + ClientRepresentation client = keycloakRepository.getClient( + REALM_NAME, + "moped-client" + ); + + assertThat(client.getName(), is("moped-client")); + assertThat(client.getClientId(), is("moped-client")); + assertThat(client.getDescription(), is("Moped-Client")); + assertThat(client.isEnabled(), is(true)); + assertThat(client.getClientAuthenticatorType(), is("client-secret")); + assertThat(client.getRedirectUris(), is(containsInAnyOrder("https://moped-client.org/redirect"))); + assertThat(client.getWebOrigins(), is(containsInAnyOrder("https://moped-client.org/webOrigin"))); + + String clientSecret = getClientSecret(client.getId()); + assertThat(clientSecret, is("changed-special-client-secret")); + + ProtocolMapperRepresentation protocolMapper = client.getProtocolMappers().stream().filter(m -> Objects.equals(m.getName(), "BranchCodeMapper")).findFirst().orElse(null); + + assertThat(protocolMapper, not(nullValue())); + assertThat(protocolMapper.getProtocol(), is("openid-connect")); + assertThat(protocolMapper.getProtocolMapper(), is("oidc-usermodel-attribute-mapper")); + assertThat(protocolMapper.getConfig().get("aggregate.attrs"), is("false")); + assertThat(protocolMapper.getConfig().get("userinfo.token.claim"), is("true")); + assertThat(protocolMapper.getConfig().get("user.attribute"), is("branch")); + assertThat(protocolMapper.getConfig().get("multivalued"), is("true")); + assertThat(protocolMapper.getConfig().get("id.token.claim"), is("false")); + assertThat(protocolMapper.getConfig().get("access.token.claim"), is("true")); + assertThat(protocolMapper.getConfig().get("claim.name"), is("branch")); + assertThat(protocolMapper.getConfig().get("jsonType.label"), is("String")); + + ProtocolMapperRepresentation protocolMapper2 = client.getProtocolMappers().stream().filter(m -> Objects.equals(m.getName(), "full name")).findFirst().orElse(null); + + assertThat(protocolMapper2, not(nullValue())); + assertThat(protocolMapper2.getProtocol(), is("openid-connect")); + assertThat(protocolMapper2.getProtocolMapper(), is("oidc-full-name-mapper")); + assertThat(protocolMapper2.getConfig().get("id.token.claim"), is("true")); + assertThat(protocolMapper2.getConfig().get("access.token.claim"), is("false")); + } + + @Test + @Order(98) + void shouldUpdateRealmDeleteProtocolMapper() { + doImport("98_update_realm__delete_protocol-mapper.json"); + + RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); + + assertThat(realm.getRealm(), is(REALM_NAME)); + assertThat(realm.isEnabled(), is(true)); + + ClientRepresentation client = keycloakRepository.getClient( + REALM_NAME, + "moped-client" + ); + + assertThat(client.getName(), is("moped-client")); + assertThat(client.getClientId(), is("moped-client")); + assertThat(client.getDescription(), is("Moped-Client")); + assertThat(client.isEnabled(), is(true)); + assertThat(client.getClientAuthenticatorType(), is("client-secret")); + assertThat(client.getRedirectUris(), is(containsInAnyOrder("https://moped-client.org/redirect"))); + assertThat(client.getWebOrigins(), is(containsInAnyOrder("https://moped-client.org/webOrigin"))); + + String clientSecret = getClientSecret(client.getId()); + assertThat(clientSecret, is("changed-special-client-secret")); + + ProtocolMapperRepresentation protocolMapper = client.getProtocolMappers().stream().filter(m -> Objects.equals(m.getName(), "BranchCodeMapper")).findFirst().orElse(null); + + assertThat(protocolMapper, is(nullValue())); + + ProtocolMapperRepresentation protocolMapper2 = client.getProtocolMappers().stream().filter(m -> Objects.equals(m.getName(), "full name")).findFirst().orElse(null); + + assertThat(protocolMapper2, not(nullValue())); + assertThat(protocolMapper2.getProtocol(), is("openid-connect")); + assertThat(protocolMapper2.getProtocolMapper(), is("oidc-full-name-mapper")); + assertThat(protocolMapper2.getConfig().get("id.token.claim"), is("true")); + assertThat(protocolMapper2.getConfig().get("access.token.claim"), is("false")); + } + + @Test + @Order(99) + void shouldUpdateRealmDeleteAllProtocolMapper() { + doImport("99_update_realm__delete_all_protocol-mapper.json"); + + RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); + + assertThat(realm.getRealm(), is(REALM_NAME)); + assertThat(realm.isEnabled(), is(true)); + + ClientRepresentation client = keycloakRepository.getClient( + REALM_NAME, + "moped-client" + ); + + assertThat(client.getName(), is("moped-client")); + assertThat(client.getClientId(), is("moped-client")); + assertThat(client.getDescription(), is("Moped-Client")); + assertThat(client.isEnabled(), is(true)); + assertThat(client.getClientAuthenticatorType(), is("client-secret")); + assertThat(client.getRedirectUris(), is(containsInAnyOrder("https://moped-client.org/redirect"))); + assertThat(client.getWebOrigins(), is(containsInAnyOrder("https://moped-client.org/webOrigin"))); + + String clientSecret = getClientSecret(client.getId()); + assertThat(clientSecret, is("changed-special-client-secret")); + + assertThat(client.getProtocolMappers(), is(nullValue())); } /** @@ -139,4 +419,15 @@ private String getClientSecret(String id) { return secret.getValue(); } + + private ClientRepresentation getClient(String clientName) { + return keycloakProvider.get() + .realm(REALM_NAME) + .partialExport(true, true) + .getClients() + .stream() + .filter(s -> Objects.equals(s.getName(), clientName)) + .findFirst() + .orElse(null); + } } diff --git a/src/test/java/de/adorsys/keycloak/config/ImportExportedRealmIT.java b/src/test/java/de/adorsys/keycloak/config/ImportExportedRealmIT.java index e7c6f657c..4617bef1c 100644 --- a/src/test/java/de/adorsys/keycloak/config/ImportExportedRealmIT.java +++ b/src/test/java/de/adorsys/keycloak/config/ImportExportedRealmIT.java @@ -39,10 +39,9 @@ public class ImportExportedRealmIT extends AbstractImportTest { EXPECTED_CHECKSUMS.put("10.0.2", "634b84b3ee12efdbb6000aa80ce0092cee1e76d02d41d3ac4df6b6af770dbcc2"); } - private final String keycloakVersion; + private final String keycloakVersion = System.getProperty("keycloak.version"); ImportExportedRealmIT() { - keycloakVersion = System.getProperty("keycloak.version"); this.resourcePath = "import-files/exported-realm/" + keycloakVersion; } diff --git a/src/test/resources/import-files/clients/3_update_realm__add_protocol-mapper.json b/src/test/resources/import-files/clients/3_update_realm__add_protocol-mapper.json new file mode 100644 index 000000000..d83850d38 --- /dev/null +++ b/src/test/resources/import-files/clients/3_update_realm__add_protocol-mapper.json @@ -0,0 +1,84 @@ +{ + "enabled": true, + "realm": "realmWithClients", + "clients": [ + { + "clientId": "moped-client", + "name": "moped-client", + "description": "Moped-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "changed-special-client-secret", + "redirectUris": [ + "https://moped-client.org/redirect" + ], + "webOrigins": [ + "https://moped-client.org/webOrigin" + ], + "protocolMappers": [ + { + "name": "BranchCodeMapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "false", + "userinfo.token.claim": "true", + "multivalued": "false", + "user.attribute": "branch", + "id.token.claim": "false", + "access.token.claim": "true", + "claim.name": "branch", + "jsonType.label": "String" + } + } + ] + }, + { + "clientId": "moped-mapper-client", + "name": "moped-mapper-client", + "description": "Moped-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "changed-special-client-secret", + "redirectUris": [ + "https://moped-client.org/redirect" + ], + "webOrigins": [ + "https://moped-client.org/webOrigin" + ], + "protocolMappers": [ + { + "name": "BranchCodeMapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "false", + "userinfo.token.claim": "true", + "multivalued": "false", + "user.attribute": "branch", + "id.token.claim": "false", + "access.token.claim": "true", + "claim.name": "branch", + "jsonType.label": "String" + } + } + ] + }, + { + "clientId": "another-client", + "name": "another-client", + "description": "Another-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "my-other-client-secret", + "redirectUris": [ + "*" + ], + "webOrigins": [ + "*" + ] + } + ] +} diff --git a/src/test/resources/import-files/clients/4_update_realm__add_more_protocol-mapper.json b/src/test/resources/import-files/clients/4_update_realm__add_more_protocol-mapper.json new file mode 100644 index 000000000..bedaf9dba --- /dev/null +++ b/src/test/resources/import-files/clients/4_update_realm__add_more_protocol-mapper.json @@ -0,0 +1,61 @@ +{ + "enabled": true, + "realm": "realmWithClients", + "clients": [ + { + "clientId": "moped-client", + "name": "moped-client", + "description": "Moped-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "changed-special-client-secret", + "redirectUris": [ + "https://moped-client.org/redirect" + ], + "webOrigins": [ + "https://moped-client.org/webOrigin" + ], + "protocolMappers": [ + { + "name": "BranchCodeMapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "false", + "userinfo.token.claim": "true", + "multivalued": "false", + "user.attribute": "branch", + "id.token.claim": "false", + "access.token.claim": "true", + "claim.name": "branch", + "jsonType.label": "String" + } + }, + { + "protocolMapper": "oidc-full-name-mapper", + "protocol": "openid-connect", + "name": "full name", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "clientId": "another-client", + "name": "another-client", + "description": "Another-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "my-other-client-secret", + "redirectUris": [ + "*" + ], + "webOrigins": [ + "*" + ] + } + ] +} diff --git a/src/test/resources/import-files/clients/5_update_realm__change_protocol-mapper.json b/src/test/resources/import-files/clients/5_update_realm__change_protocol-mapper.json new file mode 100644 index 000000000..e056ec367 --- /dev/null +++ b/src/test/resources/import-files/clients/5_update_realm__change_protocol-mapper.json @@ -0,0 +1,61 @@ +{ + "enabled": true, + "realm": "realmWithClients", + "clients": [ + { + "clientId": "moped-client", + "name": "moped-client", + "description": "Moped-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "changed-special-client-secret", + "redirectUris": [ + "https://moped-client.org/redirect" + ], + "webOrigins": [ + "https://moped-client.org/webOrigin" + ], + "protocolMappers": [ + { + "name": "BranchCodeMapper", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "aggregate.attrs": "false", + "userinfo.token.claim": "true", + "multivalued": "true", + "user.attribute": "branch", + "id.token.claim": "false", + "access.token.claim": "true", + "claim.name": "branch", + "jsonType.label": "String" + } + }, + { + "protocolMapper": "oidc-full-name-mapper", + "protocol": "openid-connect", + "name": "full name", + "config": { + "id.token.claim": "true", + "access.token.claim": "false" + } + } + ] + }, + { + "clientId": "another-client", + "name": "another-client", + "description": "Another-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "my-other-client-secret", + "redirectUris": [ + "*" + ], + "webOrigins": [ + "*" + ] + } + ] +} diff --git a/src/test/resources/import-files/clients/6_update_realm__ignore_protocol-mapper.json b/src/test/resources/import-files/clients/6_update_realm__ignore_protocol-mapper.json new file mode 100644 index 000000000..b2554f6df --- /dev/null +++ b/src/test/resources/import-files/clients/6_update_realm__ignore_protocol-mapper.json @@ -0,0 +1,34 @@ +{ + "enabled": true, + "realm": "realmWithClients", + "clients": [ + { + "clientId": "moped-client", + "name": "moped-client", + "description": "Moped-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "changed-special-client-secret", + "redirectUris": [ + "https://moped-client.org/redirect" + ], + "webOrigins": [ + "https://moped-client.org/webOrigin" + ] + }, + { + "clientId": "another-client", + "name": "another-client", + "description": "Another-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "my-other-client-secret", + "redirectUris": [ + "*" + ], + "webOrigins": [ + "*" + ] + } + ] +} diff --git a/src/test/resources/import-files/clients/98_update_realm__delete_protocol-mapper.json b/src/test/resources/import-files/clients/98_update_realm__delete_protocol-mapper.json new file mode 100644 index 000000000..de22c84ba --- /dev/null +++ b/src/test/resources/import-files/clients/98_update_realm__delete_protocol-mapper.json @@ -0,0 +1,45 @@ +{ + "enabled": true, + "realm": "realmWithClients", + "clients": [ + { + "clientId": "moped-client", + "name": "moped-client", + "description": "Moped-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "changed-special-client-secret", + "redirectUris": [ + "https://moped-client.org/redirect" + ], + "webOrigins": [ + "https://moped-client.org/webOrigin" + ], + "protocolMappers": [ + { + "protocolMapper": "oidc-full-name-mapper", + "protocol": "openid-connect", + "name": "full name", + "config": { + "id.token.claim": "true", + "access.token.claim": "false" + } + } + ] + }, + { + "clientId": "another-client", + "name": "another-client", + "description": "Another-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "my-other-client-secret", + "redirectUris": [ + "*" + ], + "webOrigins": [ + "*" + ] + } + ] +} diff --git a/src/test/resources/import-files/clients/99_update_realm__delete_all_protocol-mapper.json b/src/test/resources/import-files/clients/99_update_realm__delete_all_protocol-mapper.json new file mode 100644 index 000000000..5bd2c0ce0 --- /dev/null +++ b/src/test/resources/import-files/clients/99_update_realm__delete_all_protocol-mapper.json @@ -0,0 +1,35 @@ +{ + "enabled": true, + "realm": "realmWithClients", + "clients": [ + { + "clientId": "moped-client", + "name": "moped-client", + "description": "Moped-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "changed-special-client-secret", + "redirectUris": [ + "https://moped-client.org/redirect" + ], + "webOrigins": [ + "https://moped-client.org/webOrigin" + ], + "protocolMappers": [] + }, + { + "clientId": "another-client", + "name": "another-client", + "description": "Another-Client", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "my-other-client-secret", + "redirectUris": [ + "*" + ], + "webOrigins": [ + "*" + ] + } + ] +}