diff --git a/CHANGELOG.md b/CHANGELOG.md index 388f18b78..c65103ee8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Added +- Support for managing `Client Authorization Policies` like other resources by configuring `import.managed.client-authorization-policies=`. This prevents deletion of remote managed policies. +- Support for managing `Client Authorization Scopes` like other resources by configuring `import.managed.client-authorization-scopes=`. This prevents deletion of remote managed scopes. + ## [5.8.0] - 2023-07-14 ### Added diff --git a/docs/MANAGED.md b/docs/MANAGED.md index c7aa1eeb2..55b01e3d4 100644 --- a/docs/MANAGED.md +++ b/docs/MANAGED.md @@ -35,6 +35,8 @@ groups will be deleted. If you define `groups` but set an empty array, keycloak | Identity Provider Mappers | - | `identity-provider-mapper` | | Clients | - | `client` | | Clients Authorization Resources | The 'Default Resource' is always included. | `client-authorization-resources` | +| Clients Authorization Policies | - | `client-authorization-policies` | +| Clients Authorization Scopes | - | `client-authorization-scopes` | ## Disable deletion of managed entities diff --git a/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java b/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java index 6370776b8..8db50b1a8 100644 --- a/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java +++ b/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java @@ -150,13 +150,21 @@ public static class ImportManagedProperties { @NotNull private final ImportManagedPropertiesValues clientAuthorizationResources; + @NotNull + private final ImportManagedPropertiesValues clientAuthorizationPolicies; + + @NotNull + private final ImportManagedPropertiesValues clientAuthorizationScopes; + public ImportManagedProperties(ImportManagedPropertiesValues requiredAction, ImportManagedPropertiesValues group, ImportManagedPropertiesValues clientScope, ImportManagedPropertiesValues scopeMapping, ImportManagedPropertiesValues clientScopeMapping, ImportManagedPropertiesValues component, ImportManagedPropertiesValues subComponent, ImportManagedPropertiesValues authenticationFlow, ImportManagedPropertiesValues identityProvider, ImportManagedPropertiesValues identityProviderMapper, ImportManagedPropertiesValues role, ImportManagedPropertiesValues client, - ImportManagedPropertiesValues clientAuthorizationResources) { + ImportManagedPropertiesValues clientAuthorizationResources, + ImportManagedPropertiesValues clientAuthorizationPolicies, + ImportManagedPropertiesValues clientAuthorizationScopes) { this.requiredAction = requiredAction; this.group = group; this.clientScope = clientScope; @@ -170,6 +178,8 @@ public ImportManagedProperties(ImportManagedPropertiesValues requiredAction, Imp this.role = role; this.client = client; this.clientAuthorizationResources = clientAuthorizationResources; + this.clientAuthorizationPolicies = clientAuthorizationPolicies; + this.clientAuthorizationScopes = clientAuthorizationScopes; } public ImportManagedPropertiesValues getRequiredAction() { @@ -224,6 +234,14 @@ public ImportManagedPropertiesValues getClientAuthorizationResources() { return clientAuthorizationResources; } + public ImportManagedPropertiesValues getClientAuthorizationPolicies() { + return clientAuthorizationPolicies; + } + + public ImportManagedPropertiesValues getClientAuthorizationScopes() { + return clientAuthorizationScopes; + } + public enum ImportManagedPropertiesValues { FULL, NO_DELETE } diff --git a/src/main/java/de/adorsys/keycloak/config/service/ClientAuthorizationImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ClientAuthorizationImportService.java index 4d93b127e..d7797039a 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ClientAuthorizationImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ClientAuthorizationImportService.java @@ -153,8 +153,13 @@ private void updateAuthorization( removeAuthorizationResources(realmName, client, existingAuthorization.getResources(), sanitizedAuthorizationResources); } - removeAuthorizationPolicies(realmName, client, existingAuthorization.getPolicies(), sanitizedAuthorizationPolicies); - removeAuthorizationScopes(realmName, client, existingAuthorization.getScopes(), authorizationSettingsToImport.getScopes()); + if (importConfigProperties.getManaged().getClientAuthorizationPolicies() == FULL) { + removeAuthorizationPolicies(realmName, client, existingAuthorization.getPolicies(), sanitizedAuthorizationPolicies); + } + + if (importConfigProperties.getManaged().getClientAuthorizationScopes() == FULL) { + removeAuthorizationScopes(realmName, client, existingAuthorization.getScopes(), authorizationSettingsToImport.getScopes()); + } // refresh existingAuthorization existingAuthorization = clientRepository.getAuthorizationConfigById( diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8378d75aa..c89b6a13c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -47,6 +47,9 @@ import.managed.identity-provider-mapper=full import.managed.role=full import.managed.client=full import.managed.client-authorization-resources=full +import.managed.client-authorization-policies=full +import.managed.client-authorization-scopes=full + logging.group.http=org.apache.http.wire logging.group.realm-config=de.adorsys.keycloak.config.provider.KeycloakImportProvider logging.group.keycloak-config-cli=de.adorsys.keycloak.config.service,de.adorsys.keycloak.config.KeycloakConfigRunner,de.adorsys.keycloak.config.provider.KeycloakProvider diff --git a/src/test/java/de/adorsys/keycloak/config/service/ImportManagedNoDeleteIT.java b/src/test/java/de/adorsys/keycloak/config/service/ImportManagedNoDeleteIT.java index 68c5477db..457b2ffa4 100644 --- a/src/test/java/de/adorsys/keycloak/config/service/ImportManagedNoDeleteIT.java +++ b/src/test/java/de/adorsys/keycloak/config/service/ImportManagedNoDeleteIT.java @@ -33,6 +33,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; @TestPropertySource(properties = { "import.managed.authentication-flow=no-delete", @@ -48,6 +49,8 @@ "import.managed.role=no-delete", "import.managed.client=no-delete", "import.managed.client-authorization-resources=no-delete", + "import.managed.client-authorization-policies=no-delete", + "import.managed.client-authorization-scopes=no-delete", }) @SuppressWarnings({"java:S5961", "java:S5976"}) class ImportManagedNoDeleteIT extends AbstractImportIT { @@ -155,5 +158,23 @@ private void assertRealm() { .stream().filter(resource -> clientResourcesList.contains(resource.getName())) .collect(Collectors.toList()); assertThat(createdClientResourcesList, hasSize(2)); + + int createdScopesCount = createdRealm + .getClients() + .stream().filter(client -> Objects.equals(client.getName(), "moped-client")).findAny() + .orElseThrow(() -> new RuntimeException("Cannot find client 'moped-client'")) + .getAuthorizationSettings().getScopes() + .size(); + assertThat(createdScopesCount, is(4)); + + long createdPoliciesCount = createdRealm + .getClients() + .stream().filter(client -> Objects.equals(client.getName(), "moped-client")).findAny() + .orElseThrow(() -> new RuntimeException("Cannot find client 'moped-client'")) + .getAuthorizationSettings().getPolicies().stream() + .filter(policy -> !policy.getName().equals("Default Policy")) + .filter(policy -> !policy.getName().equals("Default Permission")) + .count(); + assertThat(createdPoliciesCount, is(1L)); } } diff --git a/src/test/resources/import-files/managed-no-delete/0_create_realm.json b/src/test/resources/import-files/managed-no-delete/0_create_realm.json index 3b41bf13b..f8ee1801e 100644 --- a/src/test/resources/import-files/managed-no-delete/0_create_realm.json +++ b/src/test/resources/import-files/managed-no-delete/0_create_realm.json @@ -504,7 +504,18 @@ ] } ], - "policies": [], + "policies": [ + { + "name": "Policy A", + "description": "", + "type": "client", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "clients": "[\"moped-client\"]" + } + } + ], "scopes": [ { "name": "urn:servlet-authz:protected:admin:access"