Merge pull request #3791 from mposolda/master
KEYCLOAK-4282 Import authorization after users are imported
This commit is contained in:
commit
b24d2e064a
9 changed files with 57 additions and 52 deletions
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in a new issue