keycloak-aplcache
Changes
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractJsonFileImportMigrationTest.java 65(+65 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java 422(+422 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/JsonFileImport198MigrationTest.java 74(+74 -0)
Details
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
index c70f755..6f23dc5 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
@@ -26,6 +26,7 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.RoleContainerModel;
@@ -183,11 +184,14 @@ public class JpaRealmProvider implements RealmProvider {
@Override
public RoleModel addRealmRole(RealmModel realm, String name) {
- return addRealmRole(realm, KeycloakModelUtils.generateId(), name);
+ return addRealmRole(realm, KeycloakModelUtils.generateId(), name);
}
@Override
public RoleModel addRealmRole(RealmModel realm, String id, String name) {
+ if (getRealmRole(realm, name) != null) {
+ throw new ModelDuplicateException();
+ }
RoleEntity entity = new RoleEntity();
entity.setId(id);
entity.setName(name);
@@ -217,6 +221,9 @@ public class JpaRealmProvider implements RealmProvider {
}
@Override
public RoleModel addClientRole(RealmModel realm, ClientModel client, String id, String name) {
+ if (getClientRole(realm, client, name) != null) {
+ throw new ModelDuplicateException();
+ }
ClientEntity clientEntity = em.getReference(ClientEntity.class, client.getId());
RoleEntity roleEntity = new RoleEntity();
roleEntity.setId(id);
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java b/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java
index c286aa0..db980c4 100755
--- a/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java
@@ -39,6 +39,8 @@ import org.keycloak.migration.migrators.MigrateTo3_4_0;
import org.keycloak.migration.migrators.MigrateTo3_4_1;
import org.keycloak.migration.migrators.Migration;
import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.RealmRepresentation;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -91,4 +93,48 @@ public class MigrationModelManager {
model.setStoredVersion(latest.toString());
}
+
+ public static final ModelVersion RHSSO_VERSION_7_0_KEYCLOAK_VERSION = new ModelVersion("1.9.8");
+ public static final ModelVersion RHSSO_VERSION_7_1_KEYCLOAK_VERSION = new ModelVersion("2.5.0");
+ public static final ModelVersion RHSSO_VERSION_7_2_KEYCLOAK_VERSION = new ModelVersion("3.4.2");
+
+
+ public static void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ ModelVersion latest = migrations[migrations.length-1].getVersion();
+ ModelVersion stored = migrations[0].getVersion();
+ if (rep.getKeycloakVersion() != null) {
+ stored = new ModelVersion(rep.getKeycloakVersion());
+ // hack for importing RH-SSO json export
+ // NOTE!!!!! We need to do something once we reach community version 7. If community version is 7 or higher, look for the GA qualifier to identify it as RH SSO
+ if (latest.getMajor() < 7 || (stored.getMajor() == 7 && stored.getQualifier().equals("GA"))) {
+ if (stored.getMajor() == 7) {
+ if (stored.getMinor() == 0) {
+ stored = RHSSO_VERSION_7_0_KEYCLOAK_VERSION;
+ } else if (stored.getMinor() == 1) {
+ stored = RHSSO_VERSION_7_1_KEYCLOAK_VERSION;
+ } else if (stored.getMinor() == 2) {
+ stored = RHSSO_VERSION_7_2_KEYCLOAK_VERSION;
+ }
+ }
+ }
+ // strip out qualifier
+ stored = new ModelVersion(stored.major, stored.minor, stored.micro);
+ if (latest.equals(stored) || latest.lessThan(stored)) {
+ return;
+ }
+ }
+
+ for (Migration m : migrations) {
+ if (stored == null || stored.lessThan(m.getVersion())) {
+ if (stored != null) {
+ logger.debugf("Migrating older json representation to %s", m.getVersion());
+ }
+ try {
+ m.migrateImport(session, realm, rep, skipUserDependent);
+ } catch (Exception e) {
+ logger.error("Failed to migrate json representation for version: " + m.getVersion(), e);
+ }
+ }
+ }
+ }
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_2_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_2_0.java
index 5cd0037..1dffc27 100755
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_2_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_2_0.java
@@ -24,6 +24,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
@@ -48,7 +49,9 @@ public class MigrateTo1_2_0 implements Migration {
client.setFullScopeAllowed(false);
for (String role : Constants.BROKER_SERVICE_ROLES) {
- RoleModel roleModel = client.addRole(role);
+ RoleModel roleModel = client.getRole(role);
+ if (roleModel != null) continue;
+ roleModel = client.addRole(role);
roleModel.setDescription("${role_" + role.toLowerCase().replaceAll("_", "-") + "}");
roleModel.setScopeParamRequired(false);
}
@@ -73,4 +76,10 @@ public class MigrateTo1_2_0 implements Migration {
}
}
+
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ setupBrokerService(realm);
+ setupClientNames(realm);
+ }
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java
index cda91a4..ea98f58 100755
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java
@@ -25,6 +25,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderFactory;
+import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
@@ -52,6 +53,11 @@ public class MigrateTo1_3_0 implements Migration {
}
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateLDAPProviders(session, realm);
+ }
+
private void migrateLDAPProviders(KeycloakSession session, RealmModel realm) {
List<UserStorageProviderModel> federationProviders = realm.getUserStorageProviders();
for (UserStorageProviderModel fedProvider : federationProviders) {
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
index 160906c..792a151 100755
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
@@ -28,6 +28,7 @@ import org.keycloak.models.cache.UserCache;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.models.utils.DefaultRequiredActions;
import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.storage.UserStorageProviderModel;
import java.util.Arrays;
@@ -46,15 +47,25 @@ public class MigrateTo1_4_0 implements Migration {
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
- if (realm.getAuthenticationFlows().size() == 0) {
- DefaultAuthenticationFlows.migrateFlows(realm);
- DefaultRequiredActions.addActions(realm);
- }
- ImpersonationConstants.setupImpersonationService(session, realm);
+ migrateRealm(session, realm);
+ }
+
+ }
- migrateLDAPMappers(session, realm);
- migrateUsers(session, realm);
+ protected void migrateRealm(KeycloakSession session, RealmModel realm) {
+ if (realm.getAuthenticationFlows().size() == 0) {
+ DefaultAuthenticationFlows.migrateFlows(realm);
+ DefaultRequiredActions.addActions(realm);
}
+ ImpersonationConstants.setupImpersonationService(session, realm);
+
+ migrateLDAPMappers(session, realm);
+ migrateUsers(session, realm);
+ }
+
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(session, realm);
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java
index 6969d5c..ec019f2 100755
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java
@@ -25,6 +25,7 @@ import org.keycloak.models.OTPPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
@@ -42,30 +43,39 @@ public class MigrateTo1_5_0 implements Migration {
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
- DefaultAuthenticationFlows.migrateFlows(realm); // add reset credentials flo
- realm.setOTPPolicy(OTPPolicy.DEFAULT_POLICY);
- realm.setBrowserFlow(realm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW));
- realm.setRegistrationFlow(realm.getFlowByAlias(DefaultAuthenticationFlows.REGISTRATION_FLOW));
- realm.setDirectGrantFlow(realm.getFlowByAlias(DefaultAuthenticationFlows.DIRECT_GRANT_FLOW));
+ migrateRealm(realm);
+ }
+
+ }
- AuthenticationFlowModel resetFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.RESET_CREDENTIALS_FLOW);
- if (resetFlow == null) {
- DefaultAuthenticationFlows.resetCredentialsFlow(realm);
- } else {
- realm.setResetCredentialsFlow(resetFlow);
- }
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(realm);
+ }
- AuthenticationFlowModel clientAuthFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.CLIENT_AUTHENTICATION_FLOW);
- if (clientAuthFlow == null) {
- DefaultAuthenticationFlows.clientAuthFlow(realm);
- } else {
- realm.setClientAuthenticationFlow(clientAuthFlow);
- }
+ protected void migrateRealm(RealmModel realm) {
+ DefaultAuthenticationFlows.migrateFlows(realm); // add reset credentials flo
+ realm.setOTPPolicy(OTPPolicy.DEFAULT_POLICY);
+ realm.setBrowserFlow(realm.getFlowByAlias(DefaultAuthenticationFlows.BROWSER_FLOW));
+ realm.setRegistrationFlow(realm.getFlowByAlias(DefaultAuthenticationFlows.REGISTRATION_FLOW));
+ realm.setDirectGrantFlow(realm.getFlowByAlias(DefaultAuthenticationFlows.DIRECT_GRANT_FLOW));
- for (ClientModel client : realm.getClients()) {
- client.setClientAuthenticatorType(KeycloakModelUtils.getDefaultClientAuthenticatorType());
- }
+ AuthenticationFlowModel resetFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.RESET_CREDENTIALS_FLOW);
+ if (resetFlow == null) {
+ DefaultAuthenticationFlows.resetCredentialsFlow(realm);
+ } else {
+ realm.setResetCredentialsFlow(resetFlow);
}
+ AuthenticationFlowModel clientAuthFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.CLIENT_AUTHENTICATION_FLOW);
+ if (clientAuthFlow == null) {
+ DefaultAuthenticationFlows.clientAuthFlow(realm);
+ } else {
+ realm.setClientAuthenticationFlow(clientAuthFlow);
+ }
+
+ for (ClientModel client : realm.getClients()) {
+ client.setClientAuthenticatorType(KeycloakModelUtils.getDefaultClientAuthenticatorType());
+ }
}
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
index aab2d52..d044d92 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
@@ -27,6 +27,7 @@ import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
@@ -58,48 +59,70 @@ public class MigrateTo1_6_0 implements Migration {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
- realm.setOfflineSessionIdleTimeout(Constants.DEFAULT_OFFLINE_SESSION_IDLE_TIMEOUT);
+ migrateRealm(session, localeMapper, realm);
+ }
+ }
- if (realm.getRole(Constants.OFFLINE_ACCESS_ROLE) == null) {
- for (RoleModel realmRole : realm.getRoles()) {
- realmRole.setScopeParamRequired(false);
- }
- for (ClientModel client : realm.getClients()) {
- for (RoleModel clientRole : client.getRoles()) {
- clientRole.setScopeParamRequired(false);
- }
- }
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ MigrationProvider provider = session.getProvider(MigrationProvider.class);
+ List<ProtocolMapperModel> builtinMappers = provider.getBuiltinMappers("openid-connect");
+ ProtocolMapperModel localeMapper = null;
+ for (ProtocolMapperModel m : builtinMappers) {
+ if (m.getName().equals("locale")) {
+ localeMapper = m;
+ }
+ }
+ if (localeMapper == null) {
+ throw new RuntimeException("Can't find default locale mapper");
+ }
+ migrateRealm(session, localeMapper, realm);
- KeycloakModelUtils.setupOfflineTokens(realm);
- RoleModel role = realm.getRole(Constants.OFFLINE_ACCESS_ROLE);
- // Bulk grant of offline_access role to all users
- session.users().grantToAllUsers(realm, role);
- }
+ }
+
+ protected void migrateRealm(KeycloakSession session, ProtocolMapperModel localeMapper, RealmModel realm) {
+ realm.setOfflineSessionIdleTimeout(Constants.DEFAULT_OFFLINE_SESSION_IDLE_TIMEOUT);
- ClientModel adminConsoleClient = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
- if ((adminConsoleClient != null) && !localeMapperAdded(adminConsoleClient)) {
- adminConsoleClient.addProtocolMapper(localeMapper);
+ if (realm.getRole(Constants.OFFLINE_ACCESS_ROLE) == null) {
+ for (RoleModel realmRole : realm.getRoles()) {
+ realmRole.setScopeParamRequired(false);
+ }
+ for (ClientModel client : realm.getClients()) {
+ for (RoleModel clientRole : client.getRoles()) {
+ clientRole.setScopeParamRequired(false);
+ }
}
- ClientModel client = realm.getMasterAdminClient();
+ KeycloakModelUtils.setupOfflineTokens(realm);
+ RoleModel role = realm.getRole(Constants.OFFLINE_ACCESS_ROLE);
+
+ // Bulk grant of offline_access role to all users
+ session.users().grantToAllUsers(realm, role);
+ }
+
+ ClientModel adminConsoleClient = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
+ if ((adminConsoleClient != null) && !localeMapperAdded(adminConsoleClient)) {
+ adminConsoleClient.addProtocolMapper(localeMapper);
+ }
+
+ ClientModel client = realm.getMasterAdminClient();
+ if (client.getRole(AdminRoles.CREATE_CLIENT) == null) {
+ RoleModel role = client.addRole(AdminRoles.CREATE_CLIENT);
+ role.setDescription("${role_" + AdminRoles.CREATE_CLIENT + "}");
+ role.setScopeParamRequired(false);
+
+ client.getRealm().getRole(AdminRoles.ADMIN).addCompositeRole(role);
+ }
+
+ if (!realm.getName().equals(Config.getAdminRealm())) {
+ client = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
if (client.getRole(AdminRoles.CREATE_CLIENT) == null) {
RoleModel role = client.addRole(AdminRoles.CREATE_CLIENT);
role.setDescription("${role_" + AdminRoles.CREATE_CLIENT + "}");
role.setScopeParamRequired(false);
- client.getRealm().getRole(AdminRoles.ADMIN).addCompositeRole(role);
- }
-
- if (!realm.getName().equals(Config.getAdminRealm())) {
- client = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
- if (client.getRole(AdminRoles.CREATE_CLIENT) == null) {
- RoleModel role = client.addRole(AdminRoles.CREATE_CLIENT);
- role.setDescription("${role_" + AdminRoles.CREATE_CLIENT + "}");
- role.setScopeParamRequired(false);
-
- client.getRole(AdminRoles.REALM_ADMIN).addCompositeRole(role);
- }
+ client.getRole(AdminRoles.REALM_ADMIN).addCompositeRole(role);
}
}
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java
index 55e0958..adb6801 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java
@@ -25,6 +25,7 @@ import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
+import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
@@ -42,23 +43,33 @@ public class MigrateTo1_7_0 implements Migration {
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
- // Set default accessToken timeout for implicit flow
- realm.setAccessTokenLifespanForImplicitFlow(Constants.DEFAULT_ACCESS_TOKEN_LIFESPAN_FOR_IMPLICIT_FLOW_TIMEOUT);
+ migrateRealm(session, realm);
- // Add 'admin-cli' builtin client
- MigrationProvider migrationProvider = session.getProvider(MigrationProvider.class);
- migrationProvider.setupAdminCli(realm);
+ }
+ }
+
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(session, realm);
+ }
+
+ protected void migrateRealm(KeycloakSession session, RealmModel realm) {
+ // Set default accessToken timeout for implicit flow
+ realm.setAccessTokenLifespanForImplicitFlow(Constants.DEFAULT_ACCESS_TOKEN_LIFESPAN_FOR_IMPLICIT_FLOW_TIMEOUT);
+
+ // Add 'admin-cli' builtin client
+ MigrationProvider migrationProvider = session.getProvider(MigrationProvider.class);
+ migrationProvider.setupAdminCli(realm);
- // add firstBrokerLogin flow and set it to all identityProviders
- DefaultAuthenticationFlows.migrateFlows(realm);
- AuthenticationFlowModel firstBrokerLoginFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.FIRST_BROKER_LOGIN_FLOW);
+ // add firstBrokerLogin flow and set it to all identityProviders
+ DefaultAuthenticationFlows.migrateFlows(realm);
+ AuthenticationFlowModel firstBrokerLoginFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.FIRST_BROKER_LOGIN_FLOW);
- List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
- for (IdentityProviderModel identityProvider : identityProviders) {
- if (identityProvider.getFirstBrokerLoginFlowId() == null) {
- identityProvider.setFirstBrokerLoginFlowId(firstBrokerLoginFlow.getId());
- realm.updateIdentityProvider(identityProvider);
- }
+ List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
+ for (IdentityProviderModel identityProvider : identityProviders) {
+ if (identityProvider.getFirstBrokerLoginFlowId() == null) {
+ identityProvider.setFirstBrokerLoginFlowId(firstBrokerLoginFlow.getId());
+ realm.updateIdentityProvider(identityProvider);
}
}
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java
index 3c5d4d9..d291e16 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java
@@ -24,6 +24,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.storage.UserStorageProviderModel;
import java.util.List;
@@ -45,21 +46,30 @@ public class MigrateTo1_8_0 implements Migration {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
- List<UserStorageProviderModel> federationProviders = realm.getUserStorageProviders();
- for (UserStorageProviderModel fedProvider : federationProviders) {
+ migrateRealm(realm);
- if (fedProvider.getProviderId().equals(LDAPConstants.LDAP_PROVIDER)) {
+ }
+ }
+
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(realm);
+ }
- if (isActiveDirectory(fedProvider)) {
- // Create mapper for MSAD account controls
- if (getMapperByName(realm, fedProvider, "MSAD account controls") == null) {
- ComponentModel mapperModel = KeycloakModelUtils.createComponentModel("MSAD account controls", fedProvider.getId(), LDAPConstants.MSAD_USER_ACCOUNT_CONTROL_MAPPER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
- realm.addComponentModel(mapperModel);
- }
+ protected void migrateRealm(RealmModel realm) {
+ List<UserStorageProviderModel> federationProviders = realm.getUserStorageProviders();
+ for (UserStorageProviderModel fedProvider : federationProviders) {
+
+ if (fedProvider.getProviderId().equals(LDAPConstants.LDAP_PROVIDER)) {
+
+ if (isActiveDirectory(fedProvider)) {
+ // Create mapper for MSAD account controls
+ if (getMapperByName(realm, fedProvider, "MSAD account controls") == null) {
+ ComponentModel mapperModel = KeycloakModelUtils.createComponentModel("MSAD account controls", fedProvider.getId(), LDAPConstants.MSAD_USER_ACCOUNT_CONTROL_MAPPER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
+ realm.addComponentModel(mapperModel);
}
}
}
-
}
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
index 3a41058..171d9ef 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
@@ -20,6 +20,7 @@ package org.keycloak.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.RealmRepresentation;
import java.util.Collections;
import java.util.HashMap;
@@ -35,13 +36,22 @@ public class MigrateTo1_9_2 implements Migration {
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
- if (realm.getBrowserSecurityHeaders() != null) {
+ migrateRealm(realm);
+ }
+ }
+
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(realm);
+ }
+
+ protected void migrateRealm(RealmModel realm) {
+ if (realm.getBrowserSecurityHeaders() != null) {
- Map<String, String> browserSecurityHeaders = new HashMap<>(realm.getBrowserSecurityHeaders());
- browserSecurityHeaders.put("xContentTypeOptions", "nosniff");
+ Map<String, String> browserSecurityHeaders = new HashMap<>(realm.getBrowserSecurityHeaders());
+ browserSecurityHeaders.put("xContentTypeOptions", "nosniff");
- realm.setBrowserSecurityHeaders(Collections.unmodifiableMap(browserSecurityHeaders));
- }
+ realm.setBrowserSecurityHeaders(Collections.unmodifiableMap(browserSecurityHeaders));
}
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java
index d36a858..788e373 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java
@@ -22,6 +22,7 @@ import org.keycloak.models.AdminRoles;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.idm.RealmRepresentation;
public class MigrateTo2_0_0 implements Migration {
@@ -37,6 +38,12 @@ public class MigrateTo2_0_0 implements Migration {
}
}
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateAuthorizationServices(realm);
+
+ }
+
private void migrateAuthorizationServices(RealmModel realm) {
KeycloakModelUtils.setupAuthorizationServices(realm);
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
index 9ff2a52..2bb7f88 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
@@ -26,6 +26,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.util.JsonSerialization;
import java.util.HashMap;
@@ -51,7 +52,14 @@ public class MigrateTo2_1_0 implements Migration {
migrateRolePolicies(realm, session);
}
}
-
+
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateDefaultRequiredAction(realm);
+ migrateRolePolicies(realm, session);
+
+ }
+
// KEYCLOAK-3244: Required Action "Configure Totp" should be "Configure OTP"
private void migrateDefaultRequiredAction(RealmModel realm) {
RequiredActionProviderModel otpAction = realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.CONFIGURE_TOTP.name());
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java
index 411bf24..19ab4c4 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java
@@ -23,6 +23,7 @@ import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
+import org.keycloak.representations.idm.RealmRepresentation;
public class MigrateTo2_2_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("2.2.0");
@@ -39,6 +40,12 @@ public class MigrateTo2_2_0 implements Migration {
}
}
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ addIdentityProviderAuthenticator(realm);
+
+ }
+
private void addIdentityProviderAuthenticator(RealmModel realm) {
String defaultProvider = null;
for (IdentityProviderModel provider : realm.getIdentityProviders()) {
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java
index 56aee36..8568776 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java
@@ -23,6 +23,7 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.RealmRepresentation;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -34,17 +35,26 @@ public class MigrateTo2_3_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
- for (ClientModel client : realm.getClients()) {
- MigrationUtils.updateProtocolMappers(client);
- }
+ migrateRealm(realm);
+ }
+ }
+
+ protected void migrateRealm(RealmModel realm) {
+ for (ClientModel client : realm.getClients()) {
+ MigrationUtils.updateProtocolMappers(client);
+ }
- for (ClientTemplateModel clientTemplate : realm.getClientTemplates()) {
- MigrationUtils.updateProtocolMappers(clientTemplate);
- }
+ for (ClientTemplateModel clientTemplate : realm.getClientTemplates()) {
+ MigrationUtils.updateProtocolMappers(clientTemplate);
}
}
@Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(realm);
+ }
+
+ @Override
public ModelVersion getVersion() {
return VERSION;
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_5_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_5_0.java
index ee9a041..95623c0 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_5_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_5_0.java
@@ -24,6 +24,7 @@ import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.DefaultKeyProviders;
+import org.keycloak.representations.idm.RealmRepresentation;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -40,6 +41,11 @@ public class MigrateTo2_5_0 implements Migration {
}
@Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ DefaultKeyProviders.createSecretProvider(realm);
+ }
+
+ @Override
public ModelVersion getVersion() {
return VERSION;
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_0_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_0_0.java
index 4daf755..1999dd4 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_0_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_0_0.java
@@ -24,6 +24,7 @@ import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
+import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;
import java.util.Objects;
@@ -44,27 +45,36 @@ public class MigrateTo3_0_0 implements Migration {
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
- realm.getClients().stream()
- .filter(clientModel -> defaultClients.contains(clientModel.getId()))
- .filter(clientModel -> Objects.isNull(clientModel.getProtocol()))
- .forEach(clientModel -> clientModel.setProtocol("openid-connect"));
-
- ClientModel client = realm.getClientByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID);
- if (client == null) continue;
- RoleModel linkRole = client.getRole(MANAGE_ACCOUNT_LINKS);
- if (linkRole == null) {
- client.addRole(MANAGE_ACCOUNT_LINKS);
- }
- RoleModel manageAccount = client.getRole(MANAGE_ACCOUNT);
- if (manageAccount == null) continue;
- RoleModel manageAccountLinks = client.getRole(MANAGE_ACCOUNT_LINKS);
- manageAccount.addCompositeRole(manageAccountLinks);
+ migrateRealm(realm);
}
}
@Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(realm);
+ }
+
+ protected void migrateRealm(RealmModel realm) {
+ realm.getClients().stream()
+ .filter(clientModel -> defaultClients.contains(clientModel.getId()))
+ .filter(clientModel -> Objects.isNull(clientModel.getProtocol()))
+ .forEach(clientModel -> clientModel.setProtocol("openid-connect"));
+
+ ClientModel client = realm.getClientByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID);
+ if (client == null) return;
+ RoleModel linkRole = client.getRole(MANAGE_ACCOUNT_LINKS);
+ if (linkRole == null) {
+ client.addRole(MANAGE_ACCOUNT_LINKS);
+ }
+ RoleModel manageAccount = client.getRole(MANAGE_ACCOUNT);
+ if (manageAccount == null) return;
+ RoleModel manageAccountLinks = client.getRole(MANAGE_ACCOUNT_LINKS);
+ manageAccount.addCompositeRole(manageAccountLinks);
+ }
+
+ @Override
public ModelVersion getVersion() {
return VERSION;
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_1_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_1_0.java
index b405d42..4f66fc0 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_1_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_1_0.java
@@ -21,6 +21,7 @@ package org.keycloak.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.RealmRepresentation;
import java.util.Collections;
import java.util.HashMap;
@@ -36,18 +37,28 @@ public class MigrateTo3_1_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
- if (realm.getBrowserSecurityHeaders() != null) {
+ migrateRealm(realm);
+ }
+ }
- Map<String, String> browserSecurityHeaders = new HashMap<>(realm.getBrowserSecurityHeaders());
- browserSecurityHeaders.put("xRobotsTag", "none");
- browserSecurityHeaders.put("xXSSProtection", "1; mode=block");
+ protected void migrateRealm(RealmModel realm) {
+ if (realm.getBrowserSecurityHeaders() != null) {
- realm.setBrowserSecurityHeaders(Collections.unmodifiableMap(browserSecurityHeaders));
- }
+ Map<String, String> browserSecurityHeaders = new HashMap<>(realm.getBrowserSecurityHeaders());
+ browserSecurityHeaders.put("xRobotsTag", "none");
+ browserSecurityHeaders.put("xXSSProtection", "1; mode=block");
+
+ realm.setBrowserSecurityHeaders(Collections.unmodifiableMap(browserSecurityHeaders));
}
}
@Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(realm);
+
+ }
+
+ @Override
public ModelVersion getVersion() {
return VERSION;
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java
index 98686af..b2935a1 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_2_0.java
@@ -28,6 +28,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
+import org.keycloak.representations.idm.RealmRepresentation;
public class MigrateTo3_2_0 implements Migration {
@@ -36,41 +37,55 @@ public class MigrateTo3_2_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
- PasswordPolicy.Builder builder = realm.getPasswordPolicy().toBuilder();
- if (!builder.contains(PasswordPolicy.HASH_ALGORITHM_ID) && "20000".equals(builder.get(PasswordPolicy.HASH_ITERATIONS_ID))) {
- realm.setPasswordPolicy(builder.remove(PasswordPolicy.HASH_ITERATIONS_ID).build(session));
- }
+ migrateRealm(session, realm);
- if (realm.getDockerAuthenticationFlow() == null) {
- DefaultAuthenticationFlows.dockerAuthenticationFlow(realm);
- }
+ }
+ }
- ClientModel realmAccess = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
- if (realmAccess != null) {
- addRoles(realmAccess);
- }
- ClientModel masterAdminClient = realm.getMasterAdminClient();
- if (masterAdminClient != null) {
- addRoles(masterAdminClient);
+ @Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(session, realm);
+ }
- }
+ protected void migrateRealm(KeycloakSession session, RealmModel realm) {
+ PasswordPolicy.Builder builder = realm.getPasswordPolicy().toBuilder();
+ if (!builder.contains(PasswordPolicy.HASH_ALGORITHM_ID) && "20000".equals(builder.get(PasswordPolicy.HASH_ITERATIONS_ID))) {
+ realm.setPasswordPolicy(builder.remove(PasswordPolicy.HASH_ITERATIONS_ID).build(session));
+ }
+
+ if (realm.getDockerAuthenticationFlow() == null) {
+ DefaultAuthenticationFlows.dockerAuthenticationFlow(realm);
+ }
+
+ ClientModel realmAccess = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
+ if (realmAccess != null) {
+ addRoles(realmAccess);
+ }
+ ClientModel masterAdminClient = realm.getMasterAdminClient();
+ if (masterAdminClient != null) {
+ addRoles(masterAdminClient);
}
}
public void addRoles(ClientModel realmAccess) {
- RoleModel queryClients = realmAccess.addRole(AdminRoles.QUERY_CLIENTS);
- RoleModel queryUsers = realmAccess.addRole(AdminRoles.QUERY_USERS);
- RoleModel queryGroups = realmAccess.addRole(AdminRoles.QUERY_GROUPS);
-
- RoleModel viewClients = realmAccess.getRole(AdminRoles.VIEW_CLIENTS);
- if (viewClients != null) {
- viewClients.addCompositeRole(queryClients);
+ RoleModel queryClients = realmAccess.getRole(AdminRoles.QUERY_CLIENTS);
+ if (queryClients == null) {
+ queryClients = realmAccess.addRole(AdminRoles.QUERY_CLIENTS);
+ RoleModel viewClients = realmAccess.getRole(AdminRoles.VIEW_CLIENTS);
+ if (viewClients != null) {
+ viewClients.addCompositeRole(queryClients);
+ }
}
+ RoleModel queryUsers = realmAccess.getRole(AdminRoles.QUERY_USERS);
+ if (queryUsers == null) queryUsers = realmAccess.addRole(AdminRoles.QUERY_USERS);
+ RoleModel queryGroups = realmAccess.getRole(AdminRoles.QUERY_GROUPS);
+ if (queryGroups == null) queryGroups = realmAccess.addRole(AdminRoles.QUERY_GROUPS);
+
RoleModel viewUsers = realmAccess.getRole(AdminRoles.VIEW_USERS);
if (viewUsers != null) {
- viewUsers.addCompositeRole(queryUsers);
- viewUsers.addCompositeRole(queryGroups);
+ if (!viewUsers.hasRole(queryUsers)) viewUsers.addCompositeRole(queryUsers);
+ if (!viewUsers.hasRole(queryGroups)) viewUsers.addCompositeRole(queryGroups);
}
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java
index 53e152f..8e6c133 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java
@@ -17,9 +17,12 @@
package org.keycloak.migration.migrators;
+import org.keycloak.keys.KeyProvider;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.DefaultKeyProviders;
+import org.keycloak.representations.idm.RealmRepresentation;
import java.util.Collections;
import java.util.HashMap;
@@ -36,20 +39,30 @@ public class MigrateTo3_4_0 implements Migration {
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(
r -> {
- DefaultKeyProviders.createAesProvider(r);
- Map<String, String> securityHeaders = r.getBrowserSecurityHeaders();
- if (securityHeaders != null) {
-
- Map<String, String> browserSecurityHeaders = new HashMap<>(securityHeaders);
- browserSecurityHeaders.put("strictTransportSecurity", "max-age=31536000; includeSubDomains");
-
- r.setBrowserSecurityHeaders(Collections.unmodifiableMap(browserSecurityHeaders));
- }
+ migrateRealm(r);
}
);
}
@Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(realm);
+
+ }
+
+ protected void migrateRealm(RealmModel r) {
+ DefaultKeyProviders.createAesProvider(r);
+ Map<String, String> securityHeaders = r.getBrowserSecurityHeaders();
+ if (securityHeaders != null) {
+
+ Map<String, String> browserSecurityHeaders = new HashMap<>(securityHeaders);
+ browserSecurityHeaders.put("strictTransportSecurity", "max-age=31536000; includeSubDomains");
+
+ r.setBrowserSecurityHeaders(Collections.unmodifiableMap(browserSecurityHeaders));
+ }
+ }
+
+ @Override
public ModelVersion getVersion() {
return VERSION;
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_1.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_1.java
index 5df34f6..c855643 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_1.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_1.java
@@ -21,6 +21,7 @@ package org.keycloak.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.RealmRepresentation;
import java.util.Collections;
import java.util.HashMap;
@@ -38,17 +39,26 @@ public class MigrateTo3_4_1 implements Migration {
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(
r -> {
- Map<String, String> securityHeaders = new HashMap<>(r.getBrowserSecurityHeaders());
- securityHeaders.entrySet().stream()
- .filter(Objects::nonNull)
- .filter(entry -> entry.getValue().equals("frame-src 'self'"))
- .forEach(entry -> entry.setValue("frame-src 'self'; frame-ancestors 'self'; object-src 'none';"));
- r.setBrowserSecurityHeaders(Collections.unmodifiableMap(securityHeaders));
+ migrateRealm(r);
}
);
}
@Override
+ public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+ migrateRealm(realm);
+ }
+
+ protected void migrateRealm(RealmModel r) {
+ Map<String, String> securityHeaders = new HashMap<>(r.getBrowserSecurityHeaders());
+ securityHeaders.entrySet().stream()
+ .filter(Objects::nonNull)
+ .filter(entry -> entry.getValue().equals("frame-src 'self'"))
+ .forEach(entry -> entry.setValue("frame-src 'self'; frame-ancestors 'self'; object-src 'none';"));
+ r.setBrowserSecurityHeaders(Collections.unmodifiableMap(securityHeaders));
+ }
+
+ @Override
public ModelVersion getVersion() {
return VERSION;
}
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/Migration.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/Migration.java
index e37dad2..c92dbbc 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/Migration.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/Migration.java
@@ -19,6 +19,8 @@ package org.keycloak.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.RealmRepresentation;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -27,6 +29,22 @@ public interface Migration {
void migrate(KeycloakSession session);
+ /**
+ * Called after full import of representation.
+ *
+ * Implementations of this method should try not make assumptions about what was imported from the representations.
+ * We have no idea what the user will do to an exported json file.
+ *
+ * @param session
+ * @param realm
+ * @param rep
+ * @param skipUserDependent
+ */
+ default
+ void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
+
+ }
+
ModelVersion getVersion();
}
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultKeyProviders.java b/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultKeyProviders.java
index fbc01ed..288f9e1 100644
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultKeyProviders.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultKeyProviders.java
@@ -22,29 +22,34 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.keys.KeyProvider;
import org.keycloak.models.RealmModel;
+import java.util.List;
+
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultKeyProviders {
public static void createProviders(RealmModel realm) {
- ComponentModel generated = new ComponentModel();
- generated.setName("rsa-generated");
- generated.setParentId(realm.getId());
- generated.setProviderId("rsa-generated");
- generated.setProviderType(KeyProvider.class.getName());
-
- MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
- config.putSingle("priority", "100");
- generated.setConfig(config);
-
- realm.addComponentModel(generated);
+ if (!hasProvider(realm, "rsa-generated")) {
+ ComponentModel generated = new ComponentModel();
+ generated.setName("rsa-generated");
+ generated.setParentId(realm.getId());
+ generated.setProviderId("rsa-generated");
+ generated.setProviderType(KeyProvider.class.getName());
+
+ MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
+ config.putSingle("priority", "100");
+ generated.setConfig(config);
+
+ realm.addComponentModel(generated);
+ }
createSecretProvider(realm);
createAesProvider(realm);
}
public static void createSecretProvider(RealmModel realm) {
+ if (hasProvider(realm, "hmac-generated")) return;
ComponentModel generated = new ComponentModel();
generated.setName("hmac-generated");
generated.setParentId(realm.getId());
@@ -59,6 +64,7 @@ public class DefaultKeyProviders {
}
public static void createAesProvider(RealmModel realm) {
+ if (hasProvider(realm, "aes-generated")) return;
ComponentModel generated = new ComponentModel();
generated.setName("aes-generated");
generated.setParentId(realm.getId());
@@ -72,22 +78,34 @@ public class DefaultKeyProviders {
realm.addComponentModel(generated);
}
- public static void createProviders(RealmModel realm, String privateKeyPem, String certificatePem) {
- ComponentModel rsa = new ComponentModel();
- rsa.setName("rsa");
- rsa.setParentId(realm.getId());
- rsa.setProviderId("rsa");
- rsa.setProviderType(KeyProvider.class.getName());
-
- MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
- config.putSingle("priority", "100");
- config.putSingle("privateKey", privateKeyPem);
- if (certificatePem != null) {
- config.putSingle("certificate", certificatePem);
+ protected static boolean hasProvider(RealmModel realm, String providerId) {
+ List<ComponentModel> currentComponents = realm.getComponents(realm.getId(), KeyProvider.class.getName());
+ for (ComponentModel current : currentComponents) {
+ if (current.getProviderId().equals(providerId)) {
+ return true;
+ }
}
- rsa.setConfig(config);
+ return false;
+ }
- realm.addComponentModel(rsa);
+ public static void createProviders(RealmModel realm, String privateKeyPem, String certificatePem) {
+ if (!hasProvider(realm, "rsa")) {
+ ComponentModel rsa = new ComponentModel();
+ rsa.setName("rsa");
+ rsa.setParentId(realm.getId());
+ rsa.setProviderId("rsa");
+ rsa.setProviderType(KeyProvider.class.getName());
+
+ MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
+ config.putSingle("priority", "100");
+ config.putSingle("privateKey", privateKeyPem);
+ if (certificatePem != null) {
+ config.putSingle("certificate", certificatePem);
+ }
+ rsa.setConfig(config);
+
+ realm.addComponentModel(rsa);
+ }
createSecretProvider(realm);
createAesProvider(realm);
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index bab0440..e3643bb 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -18,6 +18,7 @@ package org.keycloak.services.managers;
import org.keycloak.Config;
import org.keycloak.common.enums.SslRequired;
+import org.keycloak.migration.MigrationModelManager;
import org.keycloak.models.AccountRoles;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.BrowserSecurityHeaders;
@@ -534,6 +535,10 @@ public class RealmManager {
setupAuthorizationServices(realm);
setupClientRegistrations(realm);
+ if (rep.getKeycloakVersion() != null) {
+ MigrationModelManager.migrateImport(session, realm, rep, skipUserDependent);
+ }
+
fireRealmPostCreate(realm);
return realm;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractJsonFileImportMigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractJsonFileImportMigrationTest.java
new file mode 100644
index 0000000..1376a47
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractJsonFileImportMigrationTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * 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.
+ */
+package org.keycloak.testsuite.migration;
+
+import org.junit.Before;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.GroupRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+
+import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractJsonFileImportMigrationTest extends AbstractMigrationTest {
+ protected RealmRepresentation masterRep;
+
+ @Before
+ public void beforeMigrationTest() {
+ migrationRealm = adminClient.realms().realm(MIGRATION);
+ migrationRealm2 = adminClient.realms().realm(MIGRATION2);
+ migrationRealm3 = adminClient.realms().realm("authorization");
+ masterRealm = adminClient.realms().realm(MASTER);
+
+
+
+ // hack to reuse AbstractMigrationTest
+ RoleRepresentation newRole = new RoleRepresentation();
+ newRole.setName("master-test-realm-role");
+
+ masterRealm.roles().create(newRole);
+ ClientRepresentation newClient = new ClientRepresentation();
+ newClient.setClientId("master-test-client");
+ masterRealm.clients().create(newClient);
+ newClient = masterRealm.clients().findByClientId("master-test-client").get(0);
+ newRole.setName("master-test-client-role");
+ masterRealm.clients().get(newClient.getId()).roles().create(newRole);
+
+ for (GroupRepresentation group : masterRep.getGroups()) {
+ group.setId(null);
+ masterRealm.groups().add(group);
+ }
+ for (UserRepresentation user : masterRep.getUsers()) {
+ user.setId(null);
+ if (!user.getUsername().equals("admin")) masterRealm.users().create(user);
+ }
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java
new file mode 100644
index 0000000..47de484
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java
@@ -0,0 +1,422 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * 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.
+ */
+package org.keycloak.testsuite.migration;
+
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.admin.client.resource.RoleResource;
+import org.keycloak.common.constants.KerberosConstants;
+import org.keycloak.component.PrioritizedComponentModel;
+import org.keycloak.keys.KeyProvider;
+import org.keycloak.models.AdminRoles;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.DefaultAuthenticationFlows;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation;
+import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.ClientTemplateRepresentation;
+import org.keycloak.representations.idm.ComponentRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.storage.UserStorageProvider;
+import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.Assert;
+import org.keycloak.testsuite.runonserver.RunHelpers;
+import org.keycloak.testsuite.util.OAuthClient;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT;
+import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT_LINKS;
+import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
+import static org.keycloak.testsuite.Assert.assertNames;
+import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractMigrationTest extends AbstractKeycloakTest {
+ public static final String MIGRATION = "Migration";
+ public static final String MIGRATION2 = "Migration2";
+ protected RealmResource migrationRealm;
+ protected RealmResource migrationRealm2;
+ protected RealmResource migrationRealm3;
+ protected RealmResource masterRealm;
+
+ protected void testMigratedData() {
+ log.info("testing migrated data");
+ //master realm
+ assertNames(masterRealm.roles().list(), "offline_access", "uma_authorization", "create-realm", "master-test-realm-role", "admin");
+ assertNames(masterRealm.clients().findAll(), "admin-cli", "security-admin-console", "broker", "account",
+ "master-realm", "master-test-client", "Migration-realm", "Migration2-realm");
+ String id = masterRealm.clients().findByClientId("master-test-client").get(0).getId();
+ assertNames(masterRealm.clients().get(id).roles().list(), "master-test-client-role");
+ assertNames(masterRealm.users().search("", 0, 5), "admin", "master-test-user");
+ assertNames(masterRealm.groups().groups(), "master-test-group");
+ //migrationRealm
+ assertNames(migrationRealm.roles().list(), "offline_access", "uma_authorization", "migration-test-realm-role");
+ assertNames(migrationRealm.clients().findAll(), "account", "admin-cli", "broker", "migration-test-client", "realm-management", "security-admin-console");
+ String id2 = migrationRealm.clients().findByClientId("migration-test-client").get(0).getId();
+ assertNames(migrationRealm.clients().get(id2).roles().list(), "migration-test-client-role");
+ assertNames(migrationRealm.users().search("", 0, 5), "migration-test-user");
+ assertNames(migrationRealm.groups().groups(), "migration-test-group");
+ }
+
+ /**
+ * @see org.keycloak.migration.migrators.MigrateTo2_0_0
+ */
+ protected void testMigrationTo2_0_0() {
+ testAuthorizationServices(masterRealm, migrationRealm);
+ }
+
+ /**
+ * @see org.keycloak.migration.migrators.MigrateTo2_1_0
+ */
+ protected void testMigrationTo2_1_0() {
+ testNameOfOTPRequiredAction(masterRealm, migrationRealm);
+ }
+
+ /**
+ * @see org.keycloak.migration.migrators.MigrateTo2_2_0
+ */
+ protected void testMigrationTo2_2_0() {
+ testIdentityProviderAuthenticator(masterRealm, migrationRealm);
+ //MigrateTo2_2_0#migrateRolePolicies is not relevant any more
+ }
+
+ /**
+ * @see org.keycloak.migration.migrators.MigrateTo2_3_0
+ */
+ protected void testMigrationTo2_3_0() {
+ testUpdateProtocolMappers(masterRealm, migrationRealm);
+ testExtractRealmKeysMasterRealm(masterRealm);
+ testExtractRealmKeysMigrationRealm(migrationRealm);
+ }
+
+ /**
+ * @see org.keycloak.migration.migrators.MigrateTo2_5_0
+ */
+ protected void testMigrationTo2_5_0() {
+ testLdapKerberosMigration_2_5_0();
+ //https://github.com/keycloak/keycloak/pull/3630
+ testDuplicateEmailSupport(masterRealm, migrationRealm);
+ }
+
+ protected void testMigrationTo2_5_1() throws Exception {
+ testOfflineTokenLogin();
+ }
+
+ /**
+ * @see org.keycloak.migration.migrators.MigrateTo3_0_0
+ */
+ protected void testMigrationTo3_0_0() {
+ testRoleManageAccountLinks(masterRealm, migrationRealm);
+ }
+
+ protected void testMigrationTo3_2_0() {
+ assertNull(masterRealm.toRepresentation().getPasswordPolicy());
+ assertNull(migrationRealm.toRepresentation().getPasswordPolicy());
+
+ testDockerAuthenticationFlow(masterRealm, migrationRealm);
+ }
+
+ protected void testMigrationTo3_4_0() {
+ Map<String, String> securityHeaders = masterRealm.toRepresentation().getBrowserSecurityHeaders();
+ if (securityHeaders != null) {
+ assertEquals("max-age=31536000; includeSubDomains",
+ securityHeaders.get("strictTransportSecurity"));
+ } else {
+ fail("Browser security headers not found");
+ }
+ }
+
+ protected void testMigrationTo3_4_1() {
+ Map<String, String> securityHeaders = masterRealm.toRepresentation().getBrowserSecurityHeaders();
+ if (securityHeaders != null) {
+ assertEquals("frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
+ securityHeaders.get("contentSecurityPolicy"));
+ } else {
+ fail("Browser security headers not found");
+ }
+ }
+
+ protected void testDockerAuthenticationFlow(RealmResource... realms) {
+ for (RealmResource realm : realms) {
+ AuthenticationFlowRepresentation flow = null;
+ for (AuthenticationFlowRepresentation f : realm.flows().getFlows()) {
+ if (DefaultAuthenticationFlows.DOCKER_AUTH.equals(f.getAlias())) {
+ flow = f;
+ }
+ }
+ assertNotNull(flow);
+ }
+ }
+
+ protected void testRoleManageAccountLinks(RealmResource... realms) {
+ log.info("testing role manage account links");
+ for (RealmResource realm : realms) {
+ List<ClientRepresentation> clients = realm.clients().findByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID);
+ if (!clients.isEmpty()) {
+ String accountClientId = clients.get(0).getId();
+ ClientResource accountClient = realm.clients().get(accountClientId);
+ accountClient.roles().get(MANAGE_ACCOUNT_LINKS).toRepresentation(); //the role should be presented, it'll throw javax.ws.rs.NotFoundException in case the role is not found
+
+ Set<RoleRepresentation> roleComposites = accountClient.roles().get(MANAGE_ACCOUNT).getRoleComposites();
+ boolean success = false;
+ for (RoleRepresentation roleComposite : roleComposites) {
+ if (roleComposite.getName().equals(MANAGE_ACCOUNT_LINKS)) {
+ success = true;
+ }
+ }
+ if (!success) {
+ fail("'manage-account' role of client 'account' should have composite role 'manage-account-links'.");
+ }
+ }
+ }
+ }
+
+ protected void testExtractRealmKeysMasterRealm(RealmResource masterRealm) {
+ log.info("testing extract realm keys");
+ String expectedMasterRealmKey = "MIIEowIBAAKCAQEAiU54OXoCbHy0L0gHn1yasctcnKHRU1pHFIJnWvaI7rClJydet9dDJaiYXOxMKseiBm3eYznfN3cPyU8udYmRnMuKjiocZ77LT2IEttAjXb6Ggazx7loriFHRy0IOJeX4KxXhAPWmxqa3mkFNfLBEvFqVaBgUDHQ60cmnPvNSHYudBTW9K80s8nvmP2pso7HTwWJ1+Xatj1Ey/gTmB3CXlyqBegGWC9TeuErEYpYhdh+11TVWasgMBZyUCtL3NRPaBuhaPg1LpW8lWGk05nS+YM6dvTk3Mppv+z2RygEpxyO09oT3b4G+Zfwit1STqn0AvDTGzINdoKcNtFScV0j8TwIDAQABAoIBAHcbPKsPLZ8SJfOF1iblW8OzFulAbaaSf2pJHIMJrQrw7LKkMkPjVXoLX+/rgr7xYZmWIP2OLBWfEHCeYTzQUyHiZpSf7vgHx7Fa45/5uVQOe/ttHIiYa37bCtP4vvEdJkOpvP7qGPvljwsebqsk9Ns28LfVez66bHOjK5Mt2yOIulbTeEs7ch//h39YwKJv96vc+CHbV2O6qoOxZessO6y+287cOBvbFXmS2GaGle5Nx/EwncBNS4b7czoetmm70+9ht3yX+kxaP311YUT31KQjuaJt275kOiKsrXr27PvgO++bsIyGuSzqyS7G7fmxF2zUyphEqEpalyDGMKMnrAECgYEA1fCgFox03rPDjm0MhW/ThoS2Ld27sbWQ6reS+PBMdUTJZVZIU1D2//h6VXDnlddhk6avKjA4smdy1aDKzmjz3pt9AKn+kgkXqtTC2fD3wp+fC9hND0z+rQPGe/Gk7ZUnTdsqnfyowxr+woIgzdnRukOUrG+xQiP3RUUT7tt6NQECgYEApEz2xvgqMm+9/f/YxjLdsFUfLqc4WlafB863stYEVqlCYy5ujyo0VQ0ahKSKJkLDnf52+aMUqPOpwaGePpu3O6VkvpcKfPY2MUlZW7/6Sa9et9hxNkdTS7Gui2d1ELpaCBe1Bc62sk8EA01iHXE1PpvyUqDWrhNh+NrDICA9oU8CgYBgGDYACtTP11TmW2r9YK5VRLUDww30k4ZlN1GnyV++aMhBYVEZQ0u+y+A/EnijIFwu0vbo70H4OGknNZMCxbeMbLDoJHM5KyZbUDe5ZvgSjloFGwH59m6KTiDQOUkIgi9mVCQ/VGaFRFHcElEjxUvj60kTbxPijn8ZuR5r8l9hAQKBgQCQ9jL5pHWeoIayN20smi6M6N2lTPbkhe60dcgQatHTIG2pkosLl8IqlHAkPgSB84AiwyR351JQKwRJCm7TcJI/dxMnMZ6YWKfB3qSP1hdfsfJRJQ/mQxIUBAYrizF3e+P5peka4aLCOgMhYsJBlePThMZN7wja99EGPwXQL4IQ8wKBgB8Nis1lQK6Z30GCp9u4dYleGfEP71Lwqvk/eJb89/uz0fjF9CTpJMULFc+nA5u4yHP3LFnRg3zCU6aEwfwUyk4GH9lWGV/qIAisQtgrCEraVe4qxz0DVE59C7qjO26IhU2U66TEzPAqvQ3zqey+woDn/cz/JMWK1vpcSk+TKn3K";
+ List<ComponentRepresentation> components = masterRealm.components().query(MASTER, KeyProvider.class.getName());
+ assertEquals(3, components.size());
+
+ components = masterRealm.components().query(MASTER, KeyProvider.class.getName(), "rsa");
+ assertEquals(1, components.size());
+
+ ComponentRepresentation component = testingClient.server(MASTER).fetch(RunHelpers.internalComponent(components.get(0).getId()));
+ assertEquals(expectedMasterRealmKey, component.getConfig().getFirst("privateKey"));
+
+ components = masterRealm.components().query(MASTER, KeyProvider.class.getName(), "hmac-generated");
+ assertEquals(1, components.size());
+
+ }
+
+ protected void testExtractRealmKeysMigrationRealm(RealmResource migrationRealm) {
+ log.info("testing extract realm keys");
+ String expectedMigrationRealmKey = "MIIEpAIBAAKCAQEApt6gCllWkVTZ7fy/oRIx6Bxjt9x3eKKyKGFXvN4iaafrNqpYU9lcqPngWJ9DyXGqUf8RpjPaQWiLWLxjw3xGBqLk2E1/Frb9e/dy8rj//fHGq6bujN1iguzyFwxPGT5Asd7jflRI3qU04M8JE52PArqPhGL2Fn+FiSK5SWRIGm+hVL7Ck/E/tVxM25sFG1/UTQqvrROm4q76TmP8FsyZaTLVf7cCwW2QPIX0N5HTVb3QbBb5KIsk4kKmk/g7uUxS9r42tu533LISzRr5CTyWZAL2XFRuF2RrKdE8gwqkEubw6sDmB2mE0EoPdY1DUhBQgVP/5rwJrCtTsUBR2xdEYQIDAQABAoIBAFbbsNBSOlZBpYJUOmcb8nBQPrOYhXN8tGGCccn0klMOvcdhmcJjdPDbyCQ5Gm7DxJUTwNsTSHsdcNMKlJ9Pk5+msJnKlOl87KrXXbTsCQvlCrWUmb0nCzz9GvJWTOHl3oT3cND0DE4gDksqWR4luCgCdevCGzgQvrBoK6wBD+r578uEW3iw10hnJ0+wnGiw8IvPzE1a9xbY4HD8/QrYdaLxuLb/aC1PDuzrz0cOjnvPkrws5JrbUSnbFygJiOv1z4l2Q00uGIxlHtXdwQBnTZZjVi4vOec2BYSHffgwDYEZIglw1mnrV7y0N1nnPbtJK/cegIkXoBQHXm8Q99TrWMUCgYEA9au86qcwrXZZg5H4BpR5cpy0MSkcKDbA1aRL1cAyTCqJxsczlAtLhFADF+NhnlXj4y7gwDEYWrz064nF73I+ZGicvCiyOy+tCTugTyTGS+XR948ElDMS6PCUUXsotS3dKa0b3c9wd2mxeddTjq/ArfgEVZJ6fE1KtjLt9dtfA+8CgYEAreK3JsvjR5b/Xct28TghYUU7Qnasombb/shqqy8FOMjYUr5OUm/OjNIgoCqhOlE8oQDJ4dOZofNSa7tL+oM8Gmbal+E3fRzxnx/9/EC4QV6sVaPLTIyk7EPfKTcZuzH7+BNZtAziTxJw9d6YJQRbkpg92EZIEoR8iDj2Xs5xrK8CgYEAwMVWwwYX8zT3vn7ukTM2LRH7bsvkVUXJgJqgCwT6Mrv6SmkK9vL5+cPS+Y6pjdW1sRGauBSOGL1Grf/4ug/6F03jFt4UJM8fRyxreU7Q7sNSQ6AMpsGA6BnHODycz7ZCYa59PErG5FyiL4of/cm5Nolz1TXQOPNpWZiTEqVlZC8CgYA4YPbjVF4nuxSnU64H/hwMjsbtAM9uhI016cN0J3W4+J3zDhMU9X1x+Tts0wWdg/N1fGz4lIQOl3cUyRCUc/KL2OdtMS+tmDHbVyMho9ZaE5kq10W2Vy+uDz+O/HeSU12QDK4cC8Vgv+jyPy7zaZtLR6NduUPrBRvfiyCOkr8WrwKBgQCY0h4RCdNFhr0KKLLmJipAtV8wBCGcg1jY1KoWKQswbcykfBKwHbF6EooVqkRW0ITjWB7ZZCf8TnSUxe0NXCUAkVBrhzS4DScgtoSZYOOUaSHgOxpfwgnQ3oYotKi98Yg3IsaLs1j4RuPG5Sp1z6o+ELP1uvr8azyn9YlLa+523Q==";
+
+ List<ComponentRepresentation> components = migrationRealm.components().query(MIGRATION, KeyProvider.class.getName());
+ assertEquals(3, components.size());
+
+ components = migrationRealm.components().query(MIGRATION, KeyProvider.class.getName(), "rsa");
+ assertEquals(1, components.size());
+
+ ComponentRepresentation component = testingClient.server(MIGRATION).fetch(RunHelpers.internalComponent(components.get(0).getId()));
+ assertEquals(expectedMigrationRealmKey, component.getConfig().getFirst("privateKey"));
+
+ components = migrationRealm.components().query(MIGRATION, KeyProvider.class.getName(), "hmac-generated");
+ assertEquals(1, components.size());
+ }
+
+ protected void testLdapKerberosMigration_2_5_0() {
+ log.info("testing ldap kerberos migration");
+ RealmRepresentation realmRep = migrationRealm2.toRepresentation();
+ List<ComponentRepresentation> components = migrationRealm2.components().query(realmRep.getId(), UserStorageProvider.class.getName());
+ assertEquals(2, components.size());
+ boolean testedLdap = false;
+ boolean testedKerberos = false;
+
+ for (ComponentRepresentation component : components) {
+ if (component.getName().equals("ldap-provider")) {
+ assertEquals("2", component.getConfig().getFirst(PrioritizedComponentModel.PRIORITY));
+ assertEquals("READ_ONLY", component.getConfig().getFirst(LDAPConstants.EDIT_MODE));
+ assertEquals("true", component.getConfig().getFirst(LDAPConstants.SYNC_REGISTRATIONS));
+ assertEquals(LDAPConstants.VENDOR_RHDS, component.getConfig().getFirst(LDAPConstants.VENDOR));
+ assertEquals("uid", component.getConfig().getFirst(LDAPConstants.USERNAME_LDAP_ATTRIBUTE));
+ assertEquals("uid", component.getConfig().getFirst(LDAPConstants.RDN_LDAP_ATTRIBUTE));
+ assertEquals("nsuniqueid", component.getConfig().getFirst(LDAPConstants.UUID_LDAP_ATTRIBUTE));
+ assertEquals("inetOrgPerson, organizationalPerson", component.getConfig().getFirst(LDAPConstants.USER_OBJECT_CLASSES));
+ assertEquals("http://localhost", component.getConfig().getFirst(LDAPConstants.CONNECTION_URL));
+ assertEquals("dn", component.getConfig().getFirst(LDAPConstants.USERS_DN));
+ assertEquals(LDAPConstants.AUTH_TYPE_NONE, component.getConfig().getFirst(LDAPConstants.AUTH_TYPE));
+ assertEquals("true", component.getConfig().getFirst(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION));
+ assertEquals("realm", component.getConfig().getFirst(KerberosConstants.KERBEROS_REALM));
+ assertEquals("principal", component.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL));
+ assertEquals("keytab", component.getConfig().getFirst(KerberosConstants.KEYTAB));
+ testedLdap = true;
+ } else if (component.getName().equals("kerberos-provider")) {
+ assertEquals("3", component.getConfig().getFirst(PrioritizedComponentModel.PRIORITY));
+ assertEquals("realm", component.getConfig().getFirst(KerberosConstants.KERBEROS_REALM));
+ assertEquals("principal", component.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL));
+ assertEquals("keytab", component.getConfig().getFirst(KerberosConstants.KEYTAB));
+ }
+ }
+ }
+
+ protected void testDroolsToRulesPolicyTypeMigration() {
+ log.info("testing drools to rules in authorization services");
+ List<ClientRepresentation> client = migrationRealm3.clients().findByClientId("photoz-restful-api");
+
+ assertEquals(1, client.size());
+
+ ClientRepresentation representation = client.get(0);
+
+ List<PolicyRepresentation> policies = migrationRealm3.clients().get(representation.getId()).authorization().policies().policies();
+
+ List<PolicyRepresentation> migratedRulesPolicies = policies.stream().filter(policyRepresentation -> "rules".equals(policyRepresentation.getType())).collect(Collectors.toList());
+
+ assertEquals(1, migratedRulesPolicies.size());
+ }
+
+ protected void testAuthorizationServices(RealmResource... realms) {
+ log.info("testing authorization services");
+ for (RealmResource realm : realms) {
+ //test setup of authorization services
+ for (String roleName : Constants.AUTHZ_DEFAULT_AUTHORIZATION_ROLES) {
+ RoleResource role = realm.roles().get(roleName); //throws javax.ws.rs.NotFoundException if not found
+
+ assertFalse("Role's scopeParamRequired should be false.", role.toRepresentation().isScopeParamRequired());
+ assertFalse("Role shouldn't be composite should be false.", role.toRepresentation().isComposite());
+
+ assertTrue("role should be added to default roles for new users", realm.toRepresentation().getDefaultRoles().contains(roleName));
+ }
+ //test admin roles - master admin client
+ List<ClientRepresentation> clients = realm.clients().findByClientId(realm.toRepresentation().getRealm() + "-realm");
+ if (!clients.isEmpty()) {
+ ClientResource masterAdminClient = realm.clients().get(clients.get(0).getId());
+ masterAdminClient.roles().get(AdminRoles.VIEW_AUTHORIZATION).toRepresentation();
+ masterAdminClient.roles().get(AdminRoles.MANAGE_AUTHORIZATION).toRepresentation();
+ //test admin roles - admin role composite
+ Set<String> roleNames = new HashSet<>();
+ for (RoleRepresentation role : realm.roles().get(AdminRoles.ADMIN).getRoleComposites()) {
+ roleNames.add(role.getName());
+ }
+ assertTrue(AdminRoles.VIEW_AUTHORIZATION + " should be composite role of " + AdminRoles.ADMIN, roleNames.contains(AdminRoles.VIEW_AUTHORIZATION));
+ assertTrue(AdminRoles.MANAGE_AUTHORIZATION + " should be composite role of " + AdminRoles.ADMIN, roleNames.contains(AdminRoles.MANAGE_AUTHORIZATION));
+ }
+ }
+ }
+
+ protected void testNameOfOTPRequiredAction(RealmResource... realms) {
+ log.info("testing OTP Required Action");
+ for (RealmResource realm : realms) {
+ RequiredActionProviderRepresentation otpAction = realm.flows().getRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP.name());
+
+ assertEquals("The name of CONFIGURE_TOTP required action should be 'Configure OTP'.", "Configure OTP", otpAction.getName());
+ }
+ }
+
+ protected void testIdentityProviderAuthenticator(RealmResource... realms) {
+ log.info("testing identity provider authenticator");
+ for (RealmResource realm : realms) {
+ boolean success = false;
+ for (AuthenticationFlowRepresentation flow : realm.flows().getFlows()) {
+ if (flow.getAlias().equals(DefaultAuthenticationFlows.BROWSER_FLOW)) {
+ for (AuthenticationExecutionExportRepresentation execution : flow.getAuthenticationExecutions()) {
+ if ("identity-provider-redirector".equals(execution.getAuthenticator())) {
+ assertEquals("Requirement should be ALTERNATIVE.", AuthenticationExecutionModel.Requirement.ALTERNATIVE.name(), execution.getRequirement());
+ assertTrue("Priority should be 25.", execution.getPriority() == 25);
+ success = true;
+ }
+ }
+ }
+ }
+ if (!success) {
+ fail("BROWSER_FLOW should contain execution: 'identity-provider-redirector' authenticator.");
+ }
+ }
+ }
+
+ protected void testUpdateProtocolMappers(RealmResource... realms) {
+ log.info("testing updated protocol mappers");
+ for (RealmResource realm : realms) {
+ for (ClientRepresentation client : realm.clients().findAll()) {
+ for (ProtocolMapperRepresentation protocolMapper : client.getProtocolMappers()) {
+ testUpdateProtocolMapper(protocolMapper);
+ }
+ }
+ for (ClientTemplateRepresentation clientTemlate : realm.clientTemplates().findAll()) {
+ for (ProtocolMapperRepresentation protocolMapper : clientTemlate.getProtocolMappers()) {
+ testUpdateProtocolMapper(protocolMapper);
+ }
+ }
+ }
+ }
+
+ protected void testUpdateProtocolMapper(ProtocolMapperRepresentation protocolMapper) {
+ if (protocolMapper.getConfig().get("id.token.claim") != null) {
+ assertEquals("ProtocolMapper's config should contain key 'userinfo.token.claim'.",
+ protocolMapper.getConfig().get("id.token.claim"), protocolMapper.getConfig().get("userinfo.token.claim"));
+ }
+ }
+
+ protected void testDuplicateEmailSupport(RealmResource... realms) {
+ log.info("testing duplicate email");
+ for (RealmResource realm : realms) {
+ RealmRepresentation rep = realm.toRepresentation();
+ assertTrue("LoginWithEmailAllowed should be enabled.", rep.isLoginWithEmailAllowed());
+ assertFalse("DuplicateEmailsAllowed should be disabled.", rep.isDuplicateEmailsAllowed());
+ }
+ }
+
+ protected void testOfflineTokenLogin() throws Exception {
+ if (isImportMigrationMode()) {
+ log.info("Skip offline token login test in the 'import' migrationMode");
+ } else {
+ log.info("test login with old offline token");
+ String oldOfflineToken = suiteContext.getMigrationContext().loadOfflineToken();
+ Assert.assertNotNull(oldOfflineToken);
+
+ oauth.realm(MIGRATION);
+ oauth.clientId("migration-test-client");
+ OAuthClient.AccessTokenResponse response = oauth.doRefreshTokenRequest(oldOfflineToken, "b2c07929-69e3-44c6-8d7f-76939000b3e4");
+ AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
+ assertEquals("migration-test-user", accessToken.getPreferredUsername());
+ }
+ }
+
+ protected String getMigrationMode() {
+ return System.getProperty("migration.mode");
+ }
+
+ protected boolean isImportMigrationMode() {
+ String mode = getMigrationMode();
+ return "import".equals(mode);
+ }
+ protected void testMigrationTo3_x() {
+ // NOTE:
+ testMigrationTo3_0_0();
+ testMigrationTo3_2_0();
+ testMigrationTo3_4_0();
+ testMigrationTo3_4_1();
+ }
+
+
+ protected void testMigrationTo3_x_and_higher() {
+ // NOTE: add future methods
+ testMigrationTo3_x();
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/JsonFileImport198MigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/JsonFileImport198MigrationTest.java
new file mode 100644
index 0000000..3d721bd
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/JsonFileImport198MigrationTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * 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.
+ */
+package org.keycloak.testsuite.migration;
+
+import org.junit.Test;
+import org.keycloak.exportimport.util.ImportUtils;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.testsuite.util.IOUtil;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Tests that we can import json file from previous version. MigrationTest only tests DB.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JsonFileImport198MigrationTest extends AbstractJsonFileImportMigrationTest {
+
+ @Override
+ public void addTestRealms(List<RealmRepresentation> testRealms) {
+ Map<String, RealmRepresentation> reps = null;
+ try {
+ reps = ImportUtils.getRealmsFromStream(JsonSerialization.mapper, IOUtil.class.getResourceAsStream("/migration-test/migration-realm-1.9.8.Final.json"));
+ masterRep = reps.remove("master");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ for (RealmRepresentation rep : reps.values()) {
+ testRealms.add(rep);
+ }
+
+
+ }
+
+ @Test
+ public void migration1_9_8Test() throws Exception {
+ testMigratedData();
+ testMigrationTo2_0_0();
+ testMigrationTo2_1_0();
+ testMigrationTo2_2_0();
+ testMigrationTo2_3_0();
+ testMigrationTo2_5_0();
+ //testMigrationTo2_5_1(); // todo do not know how to fix
+ testMigrationTo3_x_and_higher();
+ }
+
+ protected void testMigrationTo2_3_0() {
+ testUpdateProtocolMappers(migrationRealm);
+ testExtractRealmKeysMigrationRealm(migrationRealm);
+ }
+
+
+
+
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/JsonFileImport255MigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/JsonFileImport255MigrationTest.java
new file mode 100644
index 0000000..c246874
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/JsonFileImport255MigrationTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * 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.
+ */
+package org.keycloak.testsuite.migration;
+
+import org.junit.Test;
+import org.keycloak.exportimport.util.ImportUtils;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.testsuite.util.IOUtil;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Tests that we can import json file from previous version. MigrationTest only tests DB.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class JsonFileImport255MigrationTest extends AbstractJsonFileImportMigrationTest {
+
+ @Override
+ public void addTestRealms(List<RealmRepresentation> testRealms) {
+ Map<String, RealmRepresentation> reps = null;
+ try {
+ reps = ImportUtils.getRealmsFromStream(JsonSerialization.mapper, IOUtil.class.getResourceAsStream("/migration-test/migration-realm-2.5.5.Final.json"));
+ masterRep = reps.remove("master");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ for (RealmRepresentation rep : reps.values()) {
+ testRealms.add(rep);
+ }
+
+
+ }
+
+ @Test
+ public void migration2_5_5Test() throws Exception {
+ testMigrationTo3_x_and_higher();
+ }
+
+ }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
index 74fce03..8395403 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
@@ -21,49 +21,17 @@ import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Before;
import org.junit.Test;
-import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.RealmResource;
-import org.keycloak.admin.client.resource.RoleResource;
-import org.keycloak.common.constants.KerberosConstants;
-import org.keycloak.component.PrioritizedComponentModel;
-import org.keycloak.keys.KeyProvider;
-import org.keycloak.models.AdminRoles;
-import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.Constants;
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.DefaultAuthenticationFlows;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation;
-import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
-import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.ClientTemplateRepresentation;
-import org.keycloak.representations.idm.ComponentRepresentation;
-import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.representations.idm.authorization.PolicyRepresentation;
-import org.keycloak.storage.UserStorageProvider;
-import org.keycloak.testsuite.AbstractKeycloakTest;
-import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.arquillian.DeploymentTargetModifier;
import org.keycloak.testsuite.arquillian.migration.Migration;
-import org.keycloak.testsuite.runonserver.RunHelpers;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
-import org.keycloak.testsuite.util.OAuthClient;
import javax.ws.rs.NotFoundException;
-import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
+
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT;
-import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT_LINKS;
-import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
import static org.keycloak.testsuite.Assert.assertEquals;
import static org.keycloak.testsuite.Assert.assertFalse;
import static org.keycloak.testsuite.Assert.assertNames;
@@ -74,15 +42,7 @@ import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
/**
* @author <a href="mailto:vramik@redhat.com">Vlastislav Ramik</a>
*/
-public class MigrationTest extends AbstractKeycloakTest {
-
- public static final String MIGRATION = "Migration";
- public static final String MIGRATION2 = "Migration2";
-
- private RealmResource migrationRealm;
- private RealmResource migrationRealm2;
- private RealmResource migrationRealm3;
- private RealmResource masterRealm;
+public class MigrationTest extends AbstractMigrationTest {
@Deployment
@TargetsContainer(DeploymentTargetModifier.AUTH_SERVER_CURRENT)
@@ -115,8 +75,7 @@ public class MigrationTest extends AbstractKeycloakTest {
@Migration(versionFrom = "2.5.5.Final")
public void migration2_5_5Test() {
testMigratedData();
- testMigrationTo3_0_0();
- testMigrationTo3_4_1();
+ testMigrationTo3_x_and_higher();
}
@Test
@Migration(versionFrom = "1.9.8.Final")
@@ -128,328 +87,13 @@ public class MigrationTest extends AbstractKeycloakTest {
testMigrationTo2_3_0();
testMigrationTo2_5_0();
testMigrationTo2_5_1();
- testMigrationTo3_0_0();
- testMigrationTo3_2_0();
- testMigrationTo3_4_0();
- testMigrationTo3_4_1();
+ testMigrationTo3_x_and_higher();
}
+
@Test
@Migration(versionFrom = "2.2.1.Final")
public void migrationInAuthorizationServicesTest() {
testDroolsToRulesPolicyTypeMigration();
}
- private void testMigratedData() {
- log.info("testing migrated data");
- //master realm
- assertNames(masterRealm.roles().list(), "offline_access", "uma_authorization", "create-realm", "master-test-realm-role", "admin");
- assertNames(masterRealm.clients().findAll(), "admin-cli", "security-admin-console", "broker", "account",
- "master-realm", "master-test-client", "Migration-realm", "Migration2-realm");
- String id = masterRealm.clients().findByClientId("master-test-client").get(0).getId();
- assertNames(masterRealm.clients().get(id).roles().list(), "master-test-client-role");
- assertNames(masterRealm.users().search("", 0, 5), "admin", "master-test-user");
- assertNames(masterRealm.groups().groups(), "master-test-group");
- //migrationRealm
- assertNames(migrationRealm.roles().list(), "offline_access", "uma_authorization", "migration-test-realm-role");
- assertNames(migrationRealm.clients().findAll(), "account", "admin-cli", "broker", "migration-test-client", "realm-management", "security-admin-console");
- String id2 = migrationRealm.clients().findByClientId("migration-test-client").get(0).getId();
- assertNames(migrationRealm.clients().get(id2).roles().list(), "migration-test-client-role");
- assertNames(migrationRealm.users().search("", 0, 5), "migration-test-user");
- assertNames(migrationRealm.groups().groups(), "migration-test-group");
- }
- /**
- * @see org.keycloak.migration.migrators.MigrateTo2_0_0
- */
- private void testMigrationTo2_0_0() {
- testAuthorizationServices(masterRealm, migrationRealm);
- }
- /**
- * @see org.keycloak.migration.migrators.MigrateTo2_1_0
- */
- private void testMigrationTo2_1_0() {
- testNameOfOTPRequiredAction(masterRealm, migrationRealm);
- }
- /**
- * @see org.keycloak.migration.migrators.MigrateTo2_2_0
- */
- private void testMigrationTo2_2_0() {
- testIdentityProviderAuthenticator(masterRealm, migrationRealm);
- //MigrateTo2_2_0#migrateRolePolicies is not relevant any more
- }
- /**
- * @see org.keycloak.migration.migrators.MigrateTo2_3_0
- */
- private void testMigrationTo2_3_0() {
- testUpdateProtocolMappers(masterRealm, migrationRealm);
- testExtractRealmKeys(masterRealm, migrationRealm);
- }
- /**
- * @see org.keycloak.migration.migrators.MigrateTo2_5_0
- */
- private void testMigrationTo2_5_0() {
- testLdapKerberosMigration_2_5_0();
- //https://github.com/keycloak/keycloak/pull/3630
- testDuplicateEmailSupport(masterRealm, migrationRealm);
- }
-
- private void testMigrationTo2_5_1() throws Exception {
- testOfflineTokenLogin();
- }
- /**
- * @see org.keycloak.migration.migrators.MigrateTo3_0_0
- */
- private void testMigrationTo3_0_0() {
- testRoleManageAccountLinks(masterRealm, migrationRealm);
- }
-
- private void testMigrationTo3_2_0() {
- assertNull(masterRealm.toRepresentation().getPasswordPolicy());
- assertNull(migrationRealm.toRepresentation().getPasswordPolicy());
-
- testDockerAuthenticationFlow(masterRealm, migrationRealm);
- }
-
- private void testMigrationTo3_4_0() {
- Map<String, String> securityHeaders = masterRealm.toRepresentation().getBrowserSecurityHeaders();
- if (securityHeaders != null) {
- assertEquals("max-age=31536000; includeSubDomains",
- securityHeaders.get("strictTransportSecurity"));
- } else {
- fail("Browser security headers not found");
- }
- }
-
- private void testMigrationTo3_4_1() {
- Map<String, String> securityHeaders = masterRealm.toRepresentation().getBrowserSecurityHeaders();
- if (securityHeaders != null) {
- assertEquals("frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
- securityHeaders.get("contentSecurityPolicy"));
- } else {
- fail("Browser security headers not found");
- }
- }
-
- private void testDockerAuthenticationFlow(RealmResource... realms) {
- for (RealmResource realm : realms) {
- AuthenticationFlowRepresentation flow = null;
- for (AuthenticationFlowRepresentation f : realm.flows().getFlows()) {
- if (DefaultAuthenticationFlows.DOCKER_AUTH.equals(f.getAlias())) {
- flow = f;
- }
- }
- assertNotNull(flow);
- }
- }
-
- private void testRoleManageAccountLinks(RealmResource... realms) {
- log.info("testing role manage account links");
- for (RealmResource realm : realms) {
- List<ClientRepresentation> clients = realm.clients().findByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID);
- if (!clients.isEmpty()) {
- String accountClientId = clients.get(0).getId();
- ClientResource accountClient = realm.clients().get(accountClientId);
- accountClient.roles().get(MANAGE_ACCOUNT_LINKS).toRepresentation(); //the role should be presented, it'll throw javax.ws.rs.NotFoundException in case the role is not found
-
- Set<RoleRepresentation> roleComposites = accountClient.roles().get(MANAGE_ACCOUNT).getRoleComposites();
- boolean success = false;
- for (RoleRepresentation roleComposite : roleComposites) {
- if (roleComposite.getName().equals(MANAGE_ACCOUNT_LINKS)) {
- success = true;
- }
- }
- if (!success) {
- fail("'manage-account' role of client 'account' should have composite role 'manage-account-links'.");
- }
- }
- }
- }
- private void testExtractRealmKeys(RealmResource masterRealm, RealmResource migrationRealm) {
- log.info("testing extract realm keys");
- String expectedMasterRealmKey = "MIIEowIBAAKCAQEAiU54OXoCbHy0L0gHn1yasctcnKHRU1pHFIJnWvaI7rClJydet9dDJaiYXOxMKseiBm3eYznfN3cPyU8udYmRnMuKjiocZ77LT2IEttAjXb6Ggazx7loriFHRy0IOJeX4KxXhAPWmxqa3mkFNfLBEvFqVaBgUDHQ60cmnPvNSHYudBTW9K80s8nvmP2pso7HTwWJ1+Xatj1Ey/gTmB3CXlyqBegGWC9TeuErEYpYhdh+11TVWasgMBZyUCtL3NRPaBuhaPg1LpW8lWGk05nS+YM6dvTk3Mppv+z2RygEpxyO09oT3b4G+Zfwit1STqn0AvDTGzINdoKcNtFScV0j8TwIDAQABAoIBAHcbPKsPLZ8SJfOF1iblW8OzFulAbaaSf2pJHIMJrQrw7LKkMkPjVXoLX+/rgr7xYZmWIP2OLBWfEHCeYTzQUyHiZpSf7vgHx7Fa45/5uVQOe/ttHIiYa37bCtP4vvEdJkOpvP7qGPvljwsebqsk9Ns28LfVez66bHOjK5Mt2yOIulbTeEs7ch//h39YwKJv96vc+CHbV2O6qoOxZessO6y+287cOBvbFXmS2GaGle5Nx/EwncBNS4b7czoetmm70+9ht3yX+kxaP311YUT31KQjuaJt275kOiKsrXr27PvgO++bsIyGuSzqyS7G7fmxF2zUyphEqEpalyDGMKMnrAECgYEA1fCgFox03rPDjm0MhW/ThoS2Ld27sbWQ6reS+PBMdUTJZVZIU1D2//h6VXDnlddhk6avKjA4smdy1aDKzmjz3pt9AKn+kgkXqtTC2fD3wp+fC9hND0z+rQPGe/Gk7ZUnTdsqnfyowxr+woIgzdnRukOUrG+xQiP3RUUT7tt6NQECgYEApEz2xvgqMm+9/f/YxjLdsFUfLqc4WlafB863stYEVqlCYy5ujyo0VQ0ahKSKJkLDnf52+aMUqPOpwaGePpu3O6VkvpcKfPY2MUlZW7/6Sa9et9hxNkdTS7Gui2d1ELpaCBe1Bc62sk8EA01iHXE1PpvyUqDWrhNh+NrDICA9oU8CgYBgGDYACtTP11TmW2r9YK5VRLUDww30k4ZlN1GnyV++aMhBYVEZQ0u+y+A/EnijIFwu0vbo70H4OGknNZMCxbeMbLDoJHM5KyZbUDe5ZvgSjloFGwH59m6KTiDQOUkIgi9mVCQ/VGaFRFHcElEjxUvj60kTbxPijn8ZuR5r8l9hAQKBgQCQ9jL5pHWeoIayN20smi6M6N2lTPbkhe60dcgQatHTIG2pkosLl8IqlHAkPgSB84AiwyR351JQKwRJCm7TcJI/dxMnMZ6YWKfB3qSP1hdfsfJRJQ/mQxIUBAYrizF3e+P5peka4aLCOgMhYsJBlePThMZN7wja99EGPwXQL4IQ8wKBgB8Nis1lQK6Z30GCp9u4dYleGfEP71Lwqvk/eJb89/uz0fjF9CTpJMULFc+nA5u4yHP3LFnRg3zCU6aEwfwUyk4GH9lWGV/qIAisQtgrCEraVe4qxz0DVE59C7qjO26IhU2U66TEzPAqvQ3zqey+woDn/cz/JMWK1vpcSk+TKn3K";
- String expectedMigrationRealmKey = "MIIEpAIBAAKCAQEApt6gCllWkVTZ7fy/oRIx6Bxjt9x3eKKyKGFXvN4iaafrNqpYU9lcqPngWJ9DyXGqUf8RpjPaQWiLWLxjw3xGBqLk2E1/Frb9e/dy8rj//fHGq6bujN1iguzyFwxPGT5Asd7jflRI3qU04M8JE52PArqPhGL2Fn+FiSK5SWRIGm+hVL7Ck/E/tVxM25sFG1/UTQqvrROm4q76TmP8FsyZaTLVf7cCwW2QPIX0N5HTVb3QbBb5KIsk4kKmk/g7uUxS9r42tu533LISzRr5CTyWZAL2XFRuF2RrKdE8gwqkEubw6sDmB2mE0EoPdY1DUhBQgVP/5rwJrCtTsUBR2xdEYQIDAQABAoIBAFbbsNBSOlZBpYJUOmcb8nBQPrOYhXN8tGGCccn0klMOvcdhmcJjdPDbyCQ5Gm7DxJUTwNsTSHsdcNMKlJ9Pk5+msJnKlOl87KrXXbTsCQvlCrWUmb0nCzz9GvJWTOHl3oT3cND0DE4gDksqWR4luCgCdevCGzgQvrBoK6wBD+r578uEW3iw10hnJ0+wnGiw8IvPzE1a9xbY4HD8/QrYdaLxuLb/aC1PDuzrz0cOjnvPkrws5JrbUSnbFygJiOv1z4l2Q00uGIxlHtXdwQBnTZZjVi4vOec2BYSHffgwDYEZIglw1mnrV7y0N1nnPbtJK/cegIkXoBQHXm8Q99TrWMUCgYEA9au86qcwrXZZg5H4BpR5cpy0MSkcKDbA1aRL1cAyTCqJxsczlAtLhFADF+NhnlXj4y7gwDEYWrz064nF73I+ZGicvCiyOy+tCTugTyTGS+XR948ElDMS6PCUUXsotS3dKa0b3c9wd2mxeddTjq/ArfgEVZJ6fE1KtjLt9dtfA+8CgYEAreK3JsvjR5b/Xct28TghYUU7Qnasombb/shqqy8FOMjYUr5OUm/OjNIgoCqhOlE8oQDJ4dOZofNSa7tL+oM8Gmbal+E3fRzxnx/9/EC4QV6sVaPLTIyk7EPfKTcZuzH7+BNZtAziTxJw9d6YJQRbkpg92EZIEoR8iDj2Xs5xrK8CgYEAwMVWwwYX8zT3vn7ukTM2LRH7bsvkVUXJgJqgCwT6Mrv6SmkK9vL5+cPS+Y6pjdW1sRGauBSOGL1Grf/4ug/6F03jFt4UJM8fRyxreU7Q7sNSQ6AMpsGA6BnHODycz7ZCYa59PErG5FyiL4of/cm5Nolz1TXQOPNpWZiTEqVlZC8CgYA4YPbjVF4nuxSnU64H/hwMjsbtAM9uhI016cN0J3W4+J3zDhMU9X1x+Tts0wWdg/N1fGz4lIQOl3cUyRCUc/KL2OdtMS+tmDHbVyMho9ZaE5kq10W2Vy+uDz+O/HeSU12QDK4cC8Vgv+jyPy7zaZtLR6NduUPrBRvfiyCOkr8WrwKBgQCY0h4RCdNFhr0KKLLmJipAtV8wBCGcg1jY1KoWKQswbcykfBKwHbF6EooVqkRW0ITjWB7ZZCf8TnSUxe0NXCUAkVBrhzS4DScgtoSZYOOUaSHgOxpfwgnQ3oYotKi98Yg3IsaLs1j4RuPG5Sp1z6o+ELP1uvr8azyn9YlLa+523Q==";
-
- List<ComponentRepresentation> components = masterRealm.components().query(MASTER, KeyProvider.class.getName());
- assertEquals(3, components.size());
-
- components = masterRealm.components().query(MASTER, KeyProvider.class.getName(), "rsa");
- assertEquals(1, components.size());
-
- ComponentRepresentation component = testingClient.server(MASTER).fetch(RunHelpers.internalComponent(components.get(0).getId()));
- assertEquals(expectedMasterRealmKey, component.getConfig().getFirst("privateKey"));
-
- components = masterRealm.components().query(MASTER, KeyProvider.class.getName(), "hmac-generated");
- assertEquals(1, components.size());
-
- components = migrationRealm.components().query(MIGRATION, KeyProvider.class.getName());
- assertEquals(3, components.size());
-
- components = migrationRealm.components().query(MIGRATION, KeyProvider.class.getName(), "rsa");
- assertEquals(1, components.size());
-
- component = testingClient.server(MIGRATION).fetch(RunHelpers.internalComponent(components.get(0).getId()));
- assertEquals(expectedMigrationRealmKey, component.getConfig().getFirst("privateKey"));
-
- components = migrationRealm.components().query(MIGRATION, KeyProvider.class.getName(), "hmac-generated");
- assertEquals(1, components.size());
- }
-
- private void testLdapKerberosMigration_2_5_0() {
- log.info("testing ldap kerberos migration");
- RealmRepresentation realmRep = migrationRealm2.toRepresentation();
- List<ComponentRepresentation> components = migrationRealm2.components().query(realmRep.getId(), UserStorageProvider.class.getName());
- assertEquals(2, components.size());
- boolean testedLdap = false;
- boolean testedKerberos = false;
-
- for (ComponentRepresentation component : components) {
- if (component.getName().equals("ldap-provider")) {
- assertEquals("2", component.getConfig().getFirst(PrioritizedComponentModel.PRIORITY));
- assertEquals("READ_ONLY", component.getConfig().getFirst(LDAPConstants.EDIT_MODE));
- assertEquals("true", component.getConfig().getFirst(LDAPConstants.SYNC_REGISTRATIONS));
- assertEquals(LDAPConstants.VENDOR_RHDS, component.getConfig().getFirst(LDAPConstants.VENDOR));
- assertEquals("uid", component.getConfig().getFirst(LDAPConstants.USERNAME_LDAP_ATTRIBUTE));
- assertEquals("uid", component.getConfig().getFirst(LDAPConstants.RDN_LDAP_ATTRIBUTE));
- assertEquals("nsuniqueid", component.getConfig().getFirst(LDAPConstants.UUID_LDAP_ATTRIBUTE));
- assertEquals("inetOrgPerson, organizationalPerson", component.getConfig().getFirst(LDAPConstants.USER_OBJECT_CLASSES));
- assertEquals("http://localhost", component.getConfig().getFirst(LDAPConstants.CONNECTION_URL));
- assertEquals("dn", component.getConfig().getFirst(LDAPConstants.USERS_DN));
- assertEquals(LDAPConstants.AUTH_TYPE_NONE, component.getConfig().getFirst(LDAPConstants.AUTH_TYPE));
- assertEquals("true", component.getConfig().getFirst(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION));
- assertEquals("realm", component.getConfig().getFirst(KerberosConstants.KERBEROS_REALM));
- assertEquals("principal", component.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL));
- assertEquals("keytab", component.getConfig().getFirst(KerberosConstants.KEYTAB));
- testedLdap = true;
- } else if (component.getName().equals("kerberos-provider")) {
- assertEquals("3", component.getConfig().getFirst(PrioritizedComponentModel.PRIORITY));
- assertEquals("realm", component.getConfig().getFirst(KerberosConstants.KERBEROS_REALM));
- assertEquals("principal", component.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL));
- assertEquals("keytab", component.getConfig().getFirst(KerberosConstants.KEYTAB));
- }
- }
- }
-
- private void testDroolsToRulesPolicyTypeMigration() {
- log.info("testing drools to rules in authorization services");
- List<ClientRepresentation> client = migrationRealm3.clients().findByClientId("photoz-restful-api");
-
- assertEquals(1, client.size());
-
- ClientRepresentation representation = client.get(0);
-
- List<PolicyRepresentation> policies = migrationRealm3.clients().get(representation.getId()).authorization().policies().policies();
-
- List<PolicyRepresentation> migratedRulesPolicies = policies.stream().filter(policyRepresentation -> "rules".equals(policyRepresentation.getType())).collect(Collectors.toList());
-
- assertEquals(1, migratedRulesPolicies.size());
- }
- private void testAuthorizationServices(RealmResource... realms) {
- log.info("testing authorization services");
- for (RealmResource realm : realms) {
- //test setup of authorization services
- for (String roleName : Constants.AUTHZ_DEFAULT_AUTHORIZATION_ROLES) {
- RoleResource role = realm.roles().get(roleName); //throws javax.ws.rs.NotFoundException if not found
-
- assertFalse("Role's scopeParamRequired should be false.", role.toRepresentation().isScopeParamRequired());
- assertFalse("Role shouldn't be composite should be false.", role.toRepresentation().isComposite());
-
- assertTrue("role should be added to default roles for new users", realm.toRepresentation().getDefaultRoles().contains(roleName));
- }
- //test admin roles - master admin client
- List<ClientRepresentation> clients = realm.clients().findByClientId(realm.toRepresentation().getRealm() + "-realm");
- if (!clients.isEmpty()) {
- ClientResource masterAdminClient = realm.clients().get(clients.get(0).getId());
- masterAdminClient.roles().get(AdminRoles.VIEW_AUTHORIZATION).toRepresentation();
- masterAdminClient.roles().get(AdminRoles.MANAGE_AUTHORIZATION).toRepresentation();
- //test admin roles - admin role composite
- Set<String> roleNames = new HashSet<>();
- for (RoleRepresentation role : realm.roles().get(AdminRoles.ADMIN).getRoleComposites()) {
- roleNames.add(role.getName());
- }
- assertTrue(AdminRoles.VIEW_AUTHORIZATION + " should be composite role of " + AdminRoles.ADMIN, roleNames.contains(AdminRoles.VIEW_AUTHORIZATION));
- assertTrue(AdminRoles.MANAGE_AUTHORIZATION + " should be composite role of " + AdminRoles.ADMIN, roleNames.contains(AdminRoles.MANAGE_AUTHORIZATION));
- }
- }
- }
- private void testNameOfOTPRequiredAction(RealmResource... realms) {
- log.info("testing OTP Required Action");
- for (RealmResource realm : realms) {
- RequiredActionProviderRepresentation otpAction = realm.flows().getRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP.name());
-
- assertEquals("The name of CONFIGURE_TOTP required action should be 'Configure OTP'.", "Configure OTP", otpAction.getName());
- }
- }
- private void testIdentityProviderAuthenticator(RealmResource... realms) {
- log.info("testing identity provider authenticator");
- for (RealmResource realm : realms) {
- boolean success = false;
- for (AuthenticationFlowRepresentation flow : realm.flows().getFlows()) {
- if (flow.getAlias().equals(DefaultAuthenticationFlows.BROWSER_FLOW)) {
- for (AuthenticationExecutionExportRepresentation execution : flow.getAuthenticationExecutions()) {
- if ("identity-provider-redirector".equals(execution.getAuthenticator())) {
- assertEquals("Requirement should be ALTERNATIVE.", AuthenticationExecutionModel.Requirement.ALTERNATIVE.name(), execution.getRequirement());
- assertTrue("Priority should be 25.", execution.getPriority() == 25);
- success = true;
- }
- }
- }
- }
- if (!success) {
- fail("BROWSER_FLOW should contain execution: 'identity-provider-redirector' authenticator.");
- }
- }
- }
- private void testUpdateProtocolMappers(RealmResource... realms) {
- log.info("testing updated protocol mappers");
- for (RealmResource realm : realms) {
- for (ClientRepresentation client : realm.clients().findAll()) {
- for (ProtocolMapperRepresentation protocolMapper : client.getProtocolMappers()) {
- testUpdateProtocolMapper(protocolMapper);
- }
- }
- for (ClientTemplateRepresentation clientTemlate : realm.clientTemplates().findAll()) {
- for (ProtocolMapperRepresentation protocolMapper : clientTemlate.getProtocolMappers()) {
- testUpdateProtocolMapper(protocolMapper);
- }
- }
- }
- }
- private void testUpdateProtocolMapper(ProtocolMapperRepresentation protocolMapper) {
- if (protocolMapper.getConfig().get("id.token.claim") != null) {
- assertEquals("ProtocolMapper's config should contain key 'userinfo.token.claim'.",
- protocolMapper.getConfig().get("id.token.claim"), protocolMapper.getConfig().get("userinfo.token.claim"));
- }
- }
- private void testDuplicateEmailSupport(RealmResource... realms) {
- log.info("testing duplicate email");
- for (RealmResource realm : realms) {
- RealmRepresentation rep = realm.toRepresentation();
- assertTrue("LoginWithEmailAllowed should be enabled.", rep.isLoginWithEmailAllowed());
- assertFalse("DuplicateEmailsAllowed should be disabled.", rep.isDuplicateEmailsAllowed());
- }
- }
-
- private void testOfflineTokenLogin() throws Exception {
- if (isImportMigrationMode()) {
- log.info("Skip offline token login test in the 'import' migrationMode");
- } else {
- log.info("test login with old offline token");
- String oldOfflineToken = suiteContext.getMigrationContext().loadOfflineToken();
- Assert.assertNotNull(oldOfflineToken);
-
- oauth.realm(MIGRATION);
- oauth.clientId("migration-test-client");
- OAuthClient.AccessTokenResponse response = oauth.doRefreshTokenRequest(oldOfflineToken, "b2c07929-69e3-44c6-8d7f-76939000b3e4");
- AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
- assertEquals("migration-test-user", accessToken.getPreferredUsername());
- }
- }
-
- private String getMigrationMode() {
- return System.getProperty("migration.mode");
- }
-
- private boolean isImportMigrationMode() {
- String mode = getMigrationMode();
- return "import".equals(mode);
- }
}