Merge pull request #3791 from mposolda/master

KEYCLOAK-4282 Import authorization after users are imported
This commit is contained in:
Marek Posolda 2017-01-25 12:21:21 +01:00 committed by GitHub
commit b24d2e064a
9 changed files with 57 additions and 52 deletions

View file

@ -1,31 +0,0 @@
/*
* 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.models.utils;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
/**
* Helper interface used just because RealmManager is in keycloak-services and not accessible for ImportUtils
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface RealmImporter {
RealmModel importRealm(RealmRepresentation rep);
}

View file

@ -129,7 +129,7 @@ public class RepresentationToModel {
return policy; return policy;
} }
public static void importRealm(KeycloakSession session, RealmRepresentation rep, RealmModel newRealm) { public static void importRealm(KeycloakSession session, RealmRepresentation rep, RealmModel newRealm, boolean skipUserDependent) {
convertDeprecatedSocialProviders(rep); convertDeprecatedSocialProviders(rep);
convertDeprecatedApplications(session, rep); convertDeprecatedApplications(session, rep);
@ -279,13 +279,6 @@ public class RepresentationToModel {
} }
} }
if (rep.getClients() != null) {
rep.getClients().forEach(clientRepresentation -> {
ClientModel client = newRealm.getClientByClientId(clientRepresentation.getClientId());
importAuthorizationSettings(clientRepresentation, client, session);
});
}
if (rep.getSmtpServer() != null) { if (rep.getSmtpServer() != null) {
newRealm.setSmtpConfig(new HashMap(rep.getSmtpServer())); newRealm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
} }
@ -331,6 +324,10 @@ public class RepresentationToModel {
} }
} }
if (!skipUserDependent) {
importRealmAuthorizationSettings(rep, newRealm, session);
}
if(rep.isInternationalizationEnabled() != null){ if(rep.isInternationalizationEnabled() != null){
newRealm.setInternationalizationEnabled(rep.isInternationalizationEnabled()); newRealm.setInternationalizationEnabled(rep.isInternationalizationEnabled());
} }
@ -1813,6 +1810,15 @@ public class RepresentationToModel {
} }
} }
public static void importRealmAuthorizationSettings(RealmRepresentation rep, RealmModel newRealm, KeycloakSession session) {
if (rep.getClients() != null) {
rep.getClients().forEach(clientRepresentation -> {
ClientModel client = newRealm.getClientByClientId(clientRepresentation.getClientId());
importAuthorizationSettings(clientRepresentation, client, session);
});
}
}
public static void importAuthorizationSettings(ClientRepresentation clientRepresentation, ClientModel client, KeycloakSession session) { public static void importAuthorizationSettings(ClientRepresentation clientRepresentation, ClientModel client, KeycloakSession session) {
if (Boolean.TRUE.equals(clientRepresentation.getAuthorizationServicesEnabled())) { if (Boolean.TRUE.equals(clientRepresentation.getAuthorizationServicesEnabled())) {
AuthorizationProviderFactory authorizationFactory = (AuthorizationProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(AuthorizationProvider.class); AuthorizationProviderFactory authorizationFactory = (AuthorizationProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(AuthorizationProvider.class);

View file

@ -25,7 +25,9 @@ import org.keycloak.exportimport.util.ExportImportSessionTask;
import org.keycloak.exportimport.util.ImportUtils; import org.keycloak.exportimport.util.ImportUtils;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
@ -136,7 +138,7 @@ public class DirImportProvider implements ImportProvider {
@Override @Override
public void runExportImportTask(KeycloakSession session) throws IOException { public void runExportImportTask(KeycloakSession session) throws IOException {
boolean imported = ImportUtils.importRealm(session, realmRep, strategy); boolean imported = ImportUtils.importRealm(session, realmRep, strategy, true);
realmImported.set(imported); realmImported.set(imported);
} }
@ -165,6 +167,17 @@ public class DirImportProvider implements ImportProvider {
}); });
} }
} }
// Import authorization last, as authzPolicies can require users already in DB
KeycloakModelUtils.runJobInTransaction(factory, new ExportImportSessionTask() {
@Override
public void runExportImportTask(KeycloakSession session) throws IOException {
RealmModel realm = session.realms().getRealmByName(realmName);
RepresentationToModel.importRealmAuthorizationSettings(realmRep, realm, session);
}
});
} }
@Override @Override

View file

@ -34,6 +34,9 @@ public class SingleFileImportProviderFactory implements ImportProviderFactory {
@Override @Override
public ImportProvider create(KeycloakSession session) { public ImportProvider create(KeycloakSession session) {
String fileName = ExportImportConfig.getFile(); String fileName = ExportImportConfig.getFile();
if (fileName == null) {
throw new IllegalArgumentException("Property " + ExportImportConfig.FILE + " needs to be provided!");
}
return new SingleFileImportProvider(new File(fileName)); return new SingleFileImportProvider(new File(fileName));
} }

View file

@ -28,7 +28,6 @@ import org.keycloak.exportimport.Strategy;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmProvider; import org.keycloak.models.RealmProvider;
import org.keycloak.models.utils.RealmImporter;
import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
@ -55,7 +54,7 @@ public class ImportUtils {
// Import admin realm first // Import admin realm first
for (RealmRepresentation realm : realms) { for (RealmRepresentation realm : realms) {
if (Config.getAdminRealm().equals(realm.getRealm())) { if (Config.getAdminRealm().equals(realm.getRealm())) {
if (importRealm(session, realm, strategy)) { if (importRealm(session, realm, strategy, false)) {
masterImported = true; masterImported = true;
} }
} }
@ -63,7 +62,7 @@ public class ImportUtils {
for (RealmRepresentation realm : realms) { for (RealmRepresentation realm : realms) {
if (!Config.getAdminRealm().equals(realm.getRealm())) { if (!Config.getAdminRealm().equals(realm.getRealm())) {
importRealm(session, realm, strategy); importRealm(session, realm, strategy, false);
} }
} }
@ -84,9 +83,10 @@ public class ImportUtils {
* @param session * @param session
* @param rep * @param rep
* @param strategy specifies whether to overwrite or ignore existing realm or user entries * @param strategy specifies whether to overwrite or ignore existing realm or user entries
* @param skipUserDependent If true, then import of any models, which needs users already imported in DB, will be skipped. For example authorization
* @return newly imported realm (or existing realm if ignoreExisting is true and realm of this name already exists) * @return newly imported realm (or existing realm if ignoreExisting is true and realm of this name already exists)
*/ */
public static boolean importRealm(KeycloakSession session, RealmRepresentation rep, Strategy strategy) { public static boolean importRealm(KeycloakSession session, RealmRepresentation rep, Strategy strategy, boolean skipUserDependent) {
String realmName = rep.getRealm(); String realmName = rep.getRealm();
RealmProvider model = session.realms(); RealmProvider model = session.realms();
RealmModel realm = model.getRealmByName(realmName); RealmModel realm = model.getRealmByName(realmName);
@ -110,7 +110,7 @@ public class ImportUtils {
RealmManager realmManager = new RealmManager(session); RealmManager realmManager = new RealmManager(session);
realmManager.setContextPath(session.getContext().getContextPath()); realmManager.setContextPath(session.getContext().getContextPath());
realmManager.importRealm(rep); realmManager.importRealm(rep, skipUserDependent);
if (System.getProperty(ExportImportConfig.ACTION) != null) { if (System.getProperty(ExportImportConfig.ACTION) != null) {
logger.infof("Realm '%s' imported", realmName); logger.infof("Realm '%s' imported", realmName);

View file

@ -24,8 +24,6 @@ import org.keycloak.models.KeycloakContext;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.models.utils.RealmImporter;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication; import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.util.LocaleHelper; import org.keycloak.services.util.LocaleHelper;

View file

@ -37,7 +37,6 @@ import org.keycloak.models.session.UserSessionPersisterProvider;
import org.keycloak.models.utils.DefaultAuthenticationFlows; import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.models.utils.DefaultRequiredActions; import org.keycloak.models.utils.DefaultRequiredActions;
import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.RealmImporter;
import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.protocol.ProtocolMapperUtils; import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocol;
@ -61,7 +60,7 @@ import java.util.List;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class RealmManager implements RealmImporter { public class RealmManager {
protected KeycloakSession session; protected KeycloakSession session;
protected RealmProvider model; protected RealmProvider model;
@ -420,8 +419,15 @@ public class RealmManager implements RealmImporter {
} }
} }
@Override
public RealmModel importRealm(RealmRepresentation rep) { public RealmModel importRealm(RealmRepresentation rep) {
return importRealm(rep, false);
}
/**
* if "skipUserDependent" is true, then import of any models, which needs users already imported in DB, will be skipped. For example authorization
*/
public RealmModel importRealm(RealmRepresentation rep, boolean skipUserDependent) {
String id = rep.getId(); String id = rep.getId();
if (id == null) { if (id == null) {
id = KeycloakModelUtils.generateId(); id = KeycloakModelUtils.generateId();
@ -463,7 +469,7 @@ public class RealmManager implements RealmImporter {
if (!hasRealmRole(rep, Constants.OFFLINE_ACCESS_ROLE)) setupOfflineTokens(realm); if (!hasRealmRole(rep, Constants.OFFLINE_ACCESS_ROLE)) setupOfflineTokens(realm);
RepresentationToModel.importRealm(session, rep, realm); RepresentationToModel.importRealm(session, rep, realm, skipUserDependent);
setupAdminConsoleLocaleMapper(realm); setupAdminConsoleLocaleMapper(realm);

View file

@ -627,11 +627,12 @@ public class ExportImportUtil {
assertPredicate(scopes, scopePredicates); assertPredicate(scopes, scopePredicates);
List<PolicyRepresentation> policies = authzResource.policies().policies(); List<PolicyRepresentation> policies = authzResource.policies().policies();
Assert.assertEquals(10, policies.size()); Assert.assertEquals(11, policies.size());
List<Predicate<PolicyRepresentation>> policyPredicates = new ArrayList<>(); List<Predicate<PolicyRepresentation>> policyPredicates = new ArrayList<>();
policyPredicates.add(policyRepresentation -> "Any Admin Policy".equals(policyRepresentation.getName())); policyPredicates.add(policyRepresentation -> "Any Admin Policy".equals(policyRepresentation.getName()));
policyPredicates.add(policyRepresentation -> "Any User Policy".equals(policyRepresentation.getName())); policyPredicates.add(policyRepresentation -> "Any User Policy".equals(policyRepresentation.getName()));
policyPredicates.add(policyRepresentation -> "Only Premium User Policy".equals(policyRepresentation.getName())); policyPredicates.add(policyRepresentation -> "Only Premium User Policy".equals(policyRepresentation.getName()));
policyPredicates.add(policyRepresentation -> "wburke policy".equals(policyRepresentation.getName()));
policyPredicates.add(policyRepresentation -> "All Users Policy".equals(policyRepresentation.getName())); policyPredicates.add(policyRepresentation -> "All Users Policy".equals(policyRepresentation.getName()));
policyPredicates.add(policyRepresentation -> "Premium Resource Permission".equals(policyRepresentation.getName())); policyPredicates.add(policyRepresentation -> "Premium Resource Permission".equals(policyRepresentation.getName()));
policyPredicates.add(policyRepresentation -> "Administrative Resource Permission".equals(policyRepresentation.getName())); policyPredicates.add(policyRepresentation -> "Administrative Resource Permission".equals(policyRepresentation.getName()));

View file

@ -291,6 +291,15 @@
"roles": "[{\"id\":\"customer-user-premium\"}]" "roles": "[{\"id\":\"customer-user-premium\"}]"
} }
}, },
{
"name": "wburke policy",
"description": "Defines that only wburke can do something",
"type": "user",
"logic": "POSITIVE",
"config": {
"users" : "[\"wburke\"]"
}
},
{ {
"name": "All Users Policy", "name": "All Users Policy",
"description": "Defines that all users can do something", "description": "Defines that all users can do something",