Export/import refactoring to use same representation as admin endpoints

This commit is contained in:
mposolda 2014-07-08 13:58:20 +02:00
parent c4ff4e030a
commit 24a492ffe0
79 changed files with 3120 additions and 1103 deletions

View file

@ -11,9 +11,16 @@ public class CredentialRepresentation {
public static final String CLIENT_CERT = "cert";
protected String type;
protected String value;
protected String device;
// Plain-text value of credential (used for example during import from manually created JSON file)
protected String value;
// Value stored in DB (used for example during export/import)
protected String hashedSaltedValue;
protected String salt;
protected Integer hashIterations;
public String getType() {
return type;
}
@ -37,4 +44,28 @@ public class CredentialRepresentation {
public void setDevice(String device) {
this.device = device;
}
public String getHashedSaltedValue() {
return hashedSaltedValue;
}
public void setHashedSaltedValue(String hashedSaltedValue) {
this.hashedSaltedValue = hashedSaltedValue;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
public Integer getHashIterations() {
return hashIterations;
}
public void setHashIterations(Integer hashIterations) {
this.hashIterations = hashIterations;
}
}

View file

@ -9,7 +9,6 @@ import java.util.List;
public class OAuthClientRepresentation {
protected String id;
protected String name;
protected String baseUrl;
protected List<String> redirectUris;
protected List<String> webOrigins;
protected Boolean enabled;
@ -44,14 +43,6 @@ public class OAuthClientRepresentation {
this.enabled = enabled;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public List<String> getRedirectUris() {
return redirectUris;
}

View file

@ -423,4 +423,28 @@ public class RealmRepresentation {
public void setFailureFactor(Integer failureFactor) {
this.failureFactor = failureFactor;
}
public boolean isAuditEnabled() {
return auditEnabled;
}
public void setAuditEnabled(boolean auditEnabled) {
this.auditEnabled = auditEnabled;
}
public long getAuditExpiration() {
return auditExpiration;
}
public void setAuditExpiration(long auditExpiration) {
this.auditExpiration = auditExpiration;
}
public List<String> getAuditListeners() {
return auditListeners;
}
public void setAuditListeners(List<String> auditListeners) {
this.auditListeners = auditListeners;
}
}

View file

@ -26,6 +26,32 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-invalidation-cache-model</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.iharder</groupId>
<artifactId>base64</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>

View file

@ -0,0 +1,107 @@
package org.keycloak.exportimport;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ExportImportConfig {
public static final String ACTION = "keycloak.migration.action";
public static final String ACTION_EXPORT = "export";
public static final String ACTION_IMPORT = "import";
public static final String PROVIDER = "keycloak.migration.provider";
public static final String PROVIDER_DEFAULT = "zip";
// Name of the realm to export. If null, then full export will be triggered
public static final String REALM_NAME = "keycloak.migration.realmName";
// used for "dir" provider
public static final String DIR = "keycloak.migration.dir";
// used for "zip" provider
public static final String ZIP_FILE = "keycloak.migration.zipFile";
public static final String ZIP_PASSWORD = "keycloak.migration.zipPassword";
// used for "singleFile" provider
public static final String FILE = "keycloak.migration.file";
// Number of users per file used in "dir" and "zip" providers. -1 means adding users to same file with realm. 0 means adding to separate file with unlimited page number
public static final String USERS_PER_FILE = "keycloak.migration.usersPerFile";
public static final Integer DEFAULT_USERS_PER_FILE = 5000;
// Strategy used during import data
public static final String STRATEGY = "keycloak.migration.strategy";
public static final Strategy DEFAULT_STRATEGY = Strategy.OVERWRITE_EXISTING;
public static String getAction() {
return System.getProperty(ACTION);
}
public static void setAction(String exportImportAction) {
System.setProperty(ACTION, exportImportAction);
}
public static String getProvider() {
return System.getProperty(PROVIDER, PROVIDER_DEFAULT);
}
public static void setProvider(String exportImportProvider) {
System.setProperty(PROVIDER, exportImportProvider);
}
public static String getRealmName() {
return System.getProperty(REALM_NAME);
}
public static void setRealmName(String realmName) {
if (realmName != null) {
System.setProperty(REALM_NAME, realmName);
} else {
System.getProperties().remove(REALM_NAME);
}
}
public static String getDir() {
return System.getProperty(DIR);
}
public static String setDir(String dir) {
return System.setProperty(DIR, dir);
}
public static String getZipFile() {
return System.getProperty(ZIP_FILE);
}
public static void setZipFile(String exportImportZipFile) {
System.setProperty(ZIP_FILE, exportImportZipFile);
}
public static String getZipPassword() {
return System.getProperty(ZIP_PASSWORD);
}
public static void setZipPassword(String exportImportZipPassword) {
System.setProperty(ZIP_PASSWORD, exportImportZipPassword);
}
public static String getFile() {
return System.getProperty(FILE);
}
public static void setFile(String file) {
System.setProperty(FILE, file);
}
public static Integer getUsersPerFile() {
String usersPerFile = System.getProperty(USERS_PER_FILE, String.valueOf(DEFAULT_USERS_PER_FILE));
return Integer.parseInt(usersPerFile.trim());
}
public static void setUsersPerFile(Integer usersPerFile) {
System.setProperty(USERS_PER_FILE, String.valueOf(usersPerFile));
}
public static Strategy getStrategy() {
String strategy = System.getProperty(STRATEGY, DEFAULT_STRATEGY.toString());
return Enum.valueOf(Strategy.class, strategy);
}
}

View file

@ -0,0 +1,63 @@
package org.keycloak.exportimport;
import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ExportImportManager {
private static final Logger logger = Logger.getLogger(ExportImportManager.class);
public void checkExportImport(KeycloakSessionFactory sessionFactory) {
String exportImportAction = ExportImportConfig.getAction();
String realmName = ExportImportConfig.getRealmName();
boolean export = false;
boolean importt = false;
if (ExportImportConfig.ACTION_EXPORT.equals(exportImportAction)) {
export = true;
} else if (ExportImportConfig.ACTION_IMPORT.equals(exportImportAction)) {
importt = true;
}
if (export || importt) {
String exportImportProviderId = ExportImportConfig.getProvider();
logger.debug("Will use provider: " + exportImportProviderId);
KeycloakSession session = sessionFactory.create();
try {
if (export) {
ExportProvider exportProvider = session.getProvider(ExportProvider.class, exportImportProviderId);
if (realmName == null) {
logger.info("Full model export requested");
exportProvider.exportModel(session);
} else {
logger.infof("Export of realm '%s' requested", realmName);
exportProvider.exportRealm(session, realmName);
}
logger.info("Export finished successfully");
} else {
ImportProvider importProvider = session.getProvider(ImportProvider.class, exportImportProviderId);
Strategy strategy = ExportImportConfig.getStrategy();
if (realmName == null) {
logger.infof("Full model import requested. Strategy: %s", strategy.toString());
importProvider.importModel(session, strategy);
} else {
logger.infof("Import of realm '%s' requested. Strategy: %s", realmName, strategy.toString());
importProvider.importRealm(session, realmName, strategy);
}
logger.info("Import finished successfully");
}
} catch (Throwable ioe) {
logger.error("Error during export/import", ioe);
} finally {
session.close();
}
}
}
}

View file

@ -1,12 +0,0 @@
package org.keycloak.exportimport;
import org.keycloak.models.KeycloakSessionFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ExportImportProvider {
void checkExportImport(KeycloakSessionFactory sessionFactory);
}

View file

@ -0,0 +1,18 @@
package org.keycloak.exportimport;
import java.io.IOException;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ExportProvider extends Provider {
void exportModel(KeycloakSession session) throws IOException;
void exportRealm(KeycloakSession session, String realmName) throws IOException;
}

View file

@ -0,0 +1,9 @@
package org.keycloak.exportimport;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ExportProviderFactory extends ProviderFactory<ExportProvider> {
}

View file

@ -0,0 +1,26 @@
package org.keycloak.exportimport;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ExportSpi implements Spi {
@Override
public String getName() {
return "export";
}
@Override
public Class<? extends Provider> getProviderClass() {
return ExportProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return ExportProviderFactory.class;
}
}

View file

@ -0,0 +1,16 @@
package org.keycloak.exportimport;
import java.io.IOException;
import org.keycloak.models.KeycloakSession;
import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ImportProvider extends Provider {
void importModel(KeycloakSession session, Strategy strategy) throws IOException;
void importRealm(KeycloakSession session, String realmName, Strategy strategy) throws IOException;
}

View file

@ -0,0 +1,9 @@
package org.keycloak.exportimport;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ImportProviderFactory extends ProviderFactory<ImportProvider> {
}

View file

@ -0,0 +1,26 @@
package org.keycloak.exportimport;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ImportSpi implements Spi {
@Override
public String getName() {
return "import";
}
@Override
public Class<? extends Provider> getProviderClass() {
return ImportProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return ImportProviderFactory.class;
}
}

View file

@ -0,0 +1,10 @@
package org.keycloak.exportimport;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public enum Strategy {
IGNORE_EXISTING, // Ignore existing user entries
OVERWRITE_EXISTING // Overwrite existing user entries
}

View file

@ -0,0 +1,13 @@
package org.keycloak.exportimport.util;
import java.io.IOException;
/**
* Task to be executed inside transaction
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ExportImportJob {
public void run() throws IOException;
}

View file

@ -0,0 +1,45 @@
package org.keycloak.exportimport.util;
import java.io.IOException;
import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakTransaction;
import org.keycloak.models.RealmModel;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ExportImportUtils {
/**
* Wrap given runnable job into KeycloakTransaction. Assumption is that session already exists and it doesn't need to be closed when finished
*
* @param session
* @param job
*/
public static void runJobInTransaction(KeycloakSession session, ExportImportJob job) throws IOException {
KeycloakTransaction tx = session.getTransaction();
try {
tx.begin();
job.run();
if (tx.isActive()) {
if (tx.getRollbackOnly()) {
tx.rollback();
} else {
tx.commit();
}
}
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
}
public static String getMasterRealmAdminApplicationName(RealmModel realm) {
return realm.getName() + "-realm";
}
}

View file

@ -0,0 +1,365 @@
package org.keycloak.exportimport.util;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.iharder.Base64;
import org.codehaus.jackson.JsonEncoding;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.keycloak.exportimport.Strategy;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.representations.idm.AuthenticationLinkRepresentation;
import org.keycloak.representations.idm.ClaimRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.OAuthClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.RolesRepresentation;
import org.keycloak.representations.idm.ScopeMappingRepresentation;
import org.keycloak.representations.idm.SocialLinkRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ExportUtils {
public static RealmRepresentation exportRealm(RealmModel realm, boolean includeUsers) {
RealmRepresentation rep = ModelToRepresentation.toRepresentation(realm);
// Audit
rep.setAuditEnabled(realm.isAuditEnabled());
if (realm.getAuditExpiration() != 0) {
rep.setAuditExpiration(realm.getAuditExpiration());
}
if (realm.getAuditListeners() != null) {
rep.setAuditListeners(new LinkedList<String>(realm.getAuditListeners()));
}
// Applications
List<ApplicationModel> applications = realm.getApplications();
List<ApplicationRepresentation> appReps = new ArrayList<ApplicationRepresentation>();
for (ApplicationModel app : applications) {
ApplicationRepresentation appRep = exportApplication(app);
appReps.add(appRep);
}
rep.setApplications(appReps);
// OAuth clients
List<OAuthClientModel> oauthClients = realm.getOAuthClients();
List<OAuthClientRepresentation> oauthClientReps = new ArrayList<OAuthClientRepresentation>();
for (OAuthClientModel oauthClient : oauthClients) {
OAuthClientRepresentation clientRep = ModelToRepresentation.toRepresentation(oauthClient);
oauthClientReps.add(clientRep);
}
rep.setOauthClients(oauthClientReps);
// Roles
List<RoleRepresentation> realmRoleReps = null;
Map<String, List<RoleRepresentation>> appRolesReps = new HashMap<String, List<RoleRepresentation>>();
Set<RoleModel> realmRoles = realm.getRoles();
if (realmRoles != null && realmRoles.size() > 0) {
realmRoleReps = exportRoles(realmRoles);
}
for (ApplicationModel app : applications) {
Set<RoleModel> currentAppRoles = app.getRoles();
List<RoleRepresentation> currentAppRoleReps = exportRoles(currentAppRoles);
appRolesReps.put(app.getName(), currentAppRoleReps);
}
RolesRepresentation rolesRep = new RolesRepresentation();
if (realmRoleReps != null) {
rolesRep.setRealm(realmRoleReps);
}
if (appRolesReps.size() > 0) {
rolesRep.setApplication(appRolesReps);
}
rep.setRoles(rolesRep);
// Scopes
List<ClientModel> allClients = new ArrayList<ClientModel>(applications);
allClients.addAll(realm.getOAuthClients());
Map<String, List<ScopeMappingRepresentation>> appScopeReps = new HashMap<String, List<ScopeMappingRepresentation>>();
for (ClientModel client : allClients) {
Set<RoleModel> clientScopes = client.getScopeMappings();
ScopeMappingRepresentation scopeMappingRep = null;
for (RoleModel scope : clientScopes) {
if (scope.getContainer() instanceof RealmModel) {
if (scopeMappingRep == null) {
scopeMappingRep = rep.scopeMapping(client.getClientId());
}
scopeMappingRep.role(scope.getName());
} else {
ApplicationModel app = (ApplicationModel)scope.getContainer();
String appName = app.getName();
List<ScopeMappingRepresentation> currentAppScopes = appScopeReps.get(appName);
if (currentAppScopes == null) {
currentAppScopes = new ArrayList<ScopeMappingRepresentation>();
appScopeReps.put(appName, currentAppScopes);
}
ScopeMappingRepresentation currentClientScope = null;
for (ScopeMappingRepresentation scopeMapping : currentAppScopes) {
if (scopeMapping.getClient().equals(client.getClientId())) {
currentClientScope = scopeMapping;
break;
}
}
if (currentClientScope == null) {
currentClientScope = new ScopeMappingRepresentation();
currentClientScope.setClient(client.getClientId());
currentAppScopes.add(currentClientScope);
}
currentClientScope.role(scope.getName());
}
}
}
if (appScopeReps.size() > 0) {
rep.setApplicationScopeMappings(appScopeReps);
}
// Finally users if needed
if (includeUsers) {
List<UserModel> allUsers = realm.getUsers();
List<UserRepresentation> users = new ArrayList<UserRepresentation>();
for (UserModel user : allUsers) {
UserRepresentation userRep = exportUser(realm, user);
users.add(userRep);
}
if (users.size() > 0) {
rep.setUsers(users);
}
}
return rep;
}
/**
* Full export of application including claims and secret
* @param app
* @return full ApplicationRepresentation
*/
public static ApplicationRepresentation exportApplication(ApplicationModel app) {
ApplicationRepresentation appRep = ModelToRepresentation.toRepresentation(app);
appRep.setSecret(app.getSecret());
ClaimRepresentation claimRep = ModelToRepresentation.toRepresentation((ClientModel)app);
appRep.setClaims(claimRep);
return appRep;
}
public static List<RoleRepresentation> exportRoles(Collection<RoleModel> roles) {
List<RoleRepresentation> roleReps = new ArrayList<RoleRepresentation>();
for (RoleModel role : roles) {
RoleRepresentation roleRep = exportRole(role);
roleReps.add(roleRep);
}
return roleReps;
}
public static List<String> getRoleNames(Collection<RoleModel> roles) {
List<String> roleNames = new ArrayList<String>();
for (RoleModel role : roles) {
roleNames.add(role.getName());
}
return roleNames;
}
/**
* Full export of role including composite roles
* @param role
* @return RoleRepresentation with all stuff filled (including composite roles)
*/
public static RoleRepresentation exportRole(RoleModel role) {
RoleRepresentation roleRep = ModelToRepresentation.toRepresentation(role);
Set<RoleModel> composites = role.getComposites();
if (composites != null && composites.size() > 0) {
Set<String> compositeRealmRoles = null;
Map<String, List<String>> compositeAppRoles = null;
for (RoleModel composite : composites) {
RoleContainerModel crContainer = composite.getContainer();
if (crContainer instanceof RealmModel) {
if (compositeRealmRoles == null) {
compositeRealmRoles = new HashSet<String>();
}
compositeRealmRoles.add(composite.getName());
} else {
if (compositeAppRoles == null) {
compositeAppRoles = new HashMap<String, List<String>>();
}
ApplicationModel app = (ApplicationModel)crContainer;
String appName = app.getName();
List<String> currentAppComposites = compositeAppRoles.get(appName);
if (currentAppComposites == null) {
currentAppComposites = new ArrayList<String>();
compositeAppRoles.put(appName, currentAppComposites);
}
currentAppComposites.add(composite.getName());
}
}
RoleRepresentation.Composites compRep = new RoleRepresentation.Composites();
if (compositeRealmRoles != null) {
compRep.setRealm(compositeRealmRoles);
}
if (compositeAppRoles != null) {
compRep.setApplication(compositeAppRoles);
}
roleRep.setComposites(compRep);
}
return roleRep;
}
/**
* Full export of user (including role mappings and credentials)
*
* @param user
* @return fully exported user representation
*/
public static UserRepresentation exportUser(RealmModel realm, UserModel user) {
UserRepresentation userRep = ModelToRepresentation.toRepresentation(user);
// AuthenticationLink
AuthenticationLinkModel authLink = user.getAuthenticationLink();
if (authLink != null) {
AuthenticationLinkRepresentation authLinkRepresentation = exportAuthLink(authLink);
userRep.setAuthenticationLink(authLinkRepresentation);
}
// Social links
Set<SocialLinkModel> socialLinks = realm.getSocialLinks(user);
List<SocialLinkRepresentation> socialLinkReps = new ArrayList<SocialLinkRepresentation>();
for (SocialLinkModel socialLink : socialLinks) {
SocialLinkRepresentation socialLinkRep = exportSocialLink(socialLink);
socialLinkReps.add(socialLinkRep);
}
if (socialLinkReps.size() > 0) {
userRep.setSocialLinks(socialLinkReps);
}
// Role mappings
Set<RoleModel> roles = user.getRoleMappings();
List<String> realmRoleNames = new ArrayList<String>();
Map<String, List<String>> appRoleNames = new HashMap<String, List<String>>();
for (RoleModel role : roles) {
if (role.getContainer() instanceof RealmModel) {
realmRoleNames.add(role.getName());
} else {
ApplicationModel app = (ApplicationModel)role.getContainer();
String appName = app.getName();
List<String> currentAppRoles = appRoleNames.get(appName);
if (currentAppRoles == null) {
currentAppRoles = new ArrayList<String>();
appRoleNames.put(appName, currentAppRoles);
}
currentAppRoles.add(role.getName());
}
}
if (realmRoleNames.size() > 0) {
userRep.setRealmRoles(realmRoleNames);
}
if (appRoleNames.size() > 0) {
userRep.setApplicationRoles(appRoleNames);
}
// Credentials
List<UserCredentialValueModel> creds = user.getCredentialsDirectly();
List<CredentialRepresentation> credReps = new ArrayList<CredentialRepresentation>();
for (UserCredentialValueModel cred : creds) {
CredentialRepresentation credRep = exportCredential(cred);
credReps.add(credRep);
}
userRep.setCredentials(credReps);
return userRep;
}
public static AuthenticationLinkRepresentation exportAuthLink(AuthenticationLinkModel authLinkModel) {
AuthenticationLinkRepresentation authLinkRep = new AuthenticationLinkRepresentation();
authLinkRep.setAuthProvider(authLinkModel.getAuthProvider());
authLinkRep.setAuthUserId(authLinkModel.getAuthUserId());
return authLinkRep;
}
public static SocialLinkRepresentation exportSocialLink(SocialLinkModel socialLink) {
SocialLinkRepresentation socialLinkRep = new SocialLinkRepresentation();
socialLinkRep.setSocialProvider(socialLink.getSocialProvider());
socialLinkRep.setSocialUserId(socialLink.getSocialUserId());
socialLinkRep.setSocialUsername(socialLink.getSocialUsername());
return socialLinkRep;
}
public static CredentialRepresentation exportCredential(UserCredentialValueModel userCred) {
CredentialRepresentation credRep = new CredentialRepresentation();
credRep.setType(userCred.getType());
credRep.setDevice(userCred.getDevice());
credRep.setHashedSaltedValue(userCred.getValue());
credRep.setSalt(Base64.encodeBytes(userCred.getSalt()));
credRep.setHashIterations(userCred.getHashIterations());
return credRep;
}
// Streaming API
public static void exportUsersToStream(RealmModel realm, List<UserModel> usersToExport, ObjectMapper mapper, OutputStream os) throws IOException {
JsonFactory factory = mapper.getJsonFactory();
JsonGenerator generator = factory.createJsonGenerator(os, JsonEncoding.UTF8);
try {
if (mapper.isEnabled(SerializationConfig.Feature.INDENT_OUTPUT)) {
generator.useDefaultPrettyPrinter();
}
generator.writeStartObject();
generator.writeStringField("realm", realm.getName());
// generator.writeStringField("strategy", strategy.toString());
generator.writeFieldName("users");
generator.writeStartArray();
for (UserModel user : usersToExport) {
UserRepresentation userRep = ExportUtils.exportUser(realm, user);
generator.writeObject(userRep);
}
generator.writeEndArray();
generator.writeEndObject();
} finally {
generator.close();
}
}
}

View file

@ -0,0 +1,170 @@
package org.keycloak.exportimport.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.codehaus.jackson.JsonEncoding;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.io.SerializedString;
import org.codehaus.jackson.map.ObjectMapper;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.exportimport.Strategy;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelProvider;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ImportUtils {
private static final Logger logger = Logger.getLogger(ImportUtils.class);
/**
* Fully import realm from representation, save it to model and return model of newly created realm
*
* @param session
* @param rep
* @param strategy specifies whether to overwrite or ignore existing realm or user entries
* @return newly imported realm (or existing realm if ignoreExisting is true and realm of this name already exists)
*/
public static RealmModel importRealm(KeycloakSession session, RealmRepresentation rep, Strategy strategy) {
String realmName = rep.getRealm();
ModelProvider model = session.getModel();
RealmModel realm = model.getRealmByName(realmName);
if (realm != null) {
if (strategy == Strategy.IGNORE_EXISTING) {
logger.infof("Realm '%s' already exists. Import skipped", realmName);
return realm;
} else {
logger.infof("Realm '%s' already exists. Removing it before import", realmName);
model.removeRealm(realm.getId());
}
}
realm = rep.getId() != null ? model.createRealm(rep.getId(), realmName) : model.createRealm(realmName);
RepresentationToModel.importRealm(rep, realm);
refreshMasterAdminApps(model, realm);
logger.infof("Realm '%s' imported", realmName);
return realm;
}
private static void refreshMasterAdminApps(ModelProvider model, RealmModel realm) {
String adminRealmId = Config.getAdminRealm();
if (adminRealmId.equals(realm.getId())) {
// We just imported master realm. All 'masterAdminApps' need to be refreshed
RealmModel adminRealm = realm;
for (RealmModel currentRealm : model.getRealms()) {
ApplicationModel masterApp = adminRealm.getApplicationByName(ExportImportUtils.getMasterRealmAdminApplicationName(currentRealm));
currentRealm.setMasterAdminApp(masterApp);
}
} else {
// Need to refresh masterApp for current realm
RealmModel adminRealm = model.getRealm(adminRealmId);
ApplicationModel masterApp = adminRealm.getApplicationByName(ExportImportUtils.getMasterRealmAdminApplicationName(realm));
realm.setMasterAdminApp(masterApp);
}
}
/**
* Fully import realm (or more realms from particular stream)
*
* @param session
* @param mapper
* @param is
* @param strategy
* @throws IOException
*/
public static void importFromStream(KeycloakSession session, ObjectMapper mapper, InputStream is, Strategy strategy) throws IOException {
JsonFactory factory = mapper.getJsonFactory();
JsonParser parser = factory.createJsonParser(is);
try {
parser.nextToken();
if (parser.getCurrentToken() == JsonToken.START_ARRAY) {
// Case with more realms in stream
parser.nextToken();
while (parser.getCurrentToken() == JsonToken.START_OBJECT) {
RealmRepresentation realmRep = parser.readValueAs(RealmRepresentation.class);
parser.nextToken();
importRealm(session, realmRep, strategy);
}
} else if (parser.getCurrentToken() == JsonToken.START_OBJECT) {
// Case with single realm in stream
RealmRepresentation realmRep = parser.readValueAs(RealmRepresentation.class);
importRealm(session, realmRep, strategy);
}
} finally {
parser.close();
}
}
// Assuming that it's invoked inside transaction
public static void importUsersFromStream(KeycloakSession session, String realmName, ObjectMapper mapper, InputStream is) throws IOException {
ModelProvider model = session.getModel();
JsonFactory factory = mapper.getJsonFactory();
JsonParser parser = factory.createJsonParser(is);
try {
parser.nextToken();
while (parser.nextToken() == JsonToken.FIELD_NAME) {
if ("realm".equals(parser.getText())) {
parser.nextToken();
String currRealmName = parser.getText();
if (!currRealmName.equals(realmName)) {
throw new IllegalStateException("Trying to import users into invalid realm. Realm name: " + realmName + ", Expected realm name: " + realmName);
}
} else if ("users".equals(parser.getText())) {
parser.nextToken();
if (parser.getCurrentToken() == JsonToken.START_ARRAY) {
parser.nextToken();
}
// TODO: support for more transactions per single users file (if needed)
List<UserRepresentation> userReps = new ArrayList<UserRepresentation>();
while (parser.getCurrentToken() == JsonToken.START_OBJECT) {
UserRepresentation user = parser.readValueAs(UserRepresentation.class);
userReps.add(user);
parser.nextToken();
}
importUsers(model, realmName, userReps);
if (parser.getCurrentToken() == JsonToken.END_ARRAY) {
parser.nextToken();
}
}
}
} finally {
parser.close();
}
}
private static void importUsers(ModelProvider model, String realmName, List<UserRepresentation> userReps) {
RealmModel realm = model.getRealmByName(realmName);
Map<String, ApplicationModel> apps = realm.getApplicationNameMap();
for (UserRepresentation user : userReps) {
RepresentationToModel.createUser(realm, user, apps);
}
}
}

View file

@ -0,0 +1,115 @@
package org.keycloak.exportimport.util;
import java.io.IOException;
import java.util.List;
import org.jboss.logging.Logger;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.ExportProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public abstract class MultipleStepsExportProvider implements ExportProvider {
protected final Logger logger = Logger.getLogger(getClass());
@Override
public void exportModel(final KeycloakSession session) throws IOException {
final RealmsHolder holder = new RealmsHolder();
// Import users into same file with realm
ExportImportUtils.runJobInTransaction(session, new ExportImportJob() {
@Override
public void run() {
List<RealmModel> realms = session.getModel().getRealms();
holder.realms = realms;
}
});
for (RealmModel realm : holder.realms) {
exportRealm(session, realm.getName());
}
}
@Override
public void exportRealm(final KeycloakSession session, final String realmName) throws IOException {
final int usersPerFile = ExportImportConfig.getUsersPerFile();
final UsersHolder usersHolder = new UsersHolder();
final boolean exportUsersIntoSameFile = usersPerFile < 0;
ExportImportUtils.runJobInTransaction(session, new ExportImportJob() {
@Override
public void run() throws IOException {
RealmModel realm = session.getModel().getRealmByName(realmName);
RealmRepresentation rep = ExportUtils.exportRealm(realm, exportUsersIntoSameFile);
writeRealm(realmName + "-realm.json", rep);
logger.info("Realm '" + realmName + "' - data exported");
// Count total number of users
if (!exportUsersIntoSameFile) {
// TODO: getUsersCount method on model
usersHolder.totalCount = realm.getUsers().size();
}
}
});
if (!exportUsersIntoSameFile) {
usersHolder.currentPageStart = 0;
// usersPerFile==0 means exporting all users into single file (but separate to realm)
final int countPerPage = usersPerFile == 0 ? usersHolder.totalCount : usersPerFile;
while (usersHolder.currentPageStart < usersHolder.totalCount) {
if (usersHolder.currentPageStart + countPerPage < usersHolder.totalCount) {
usersHolder.currentPageEnd = usersHolder.currentPageStart + countPerPage;
} else {
usersHolder.currentPageEnd = usersHolder.totalCount;
}
ExportImportUtils.runJobInTransaction(session, new ExportImportJob() {
@Override
public void run() throws IOException {
RealmModel realm = session.getModel().getRealmByName(realmName);
// TODO: pagination
List<UserModel> users = realm.getUsers();
usersHolder.users = users.subList(usersHolder.currentPageStart, usersHolder.currentPageEnd);
writeUsers(realmName + "-users-" + (usersHolder.currentPageStart / countPerPage) + ".json", realm, usersHolder.users);
logger.info("Users " + usersHolder.currentPageStart + "-" + usersHolder.currentPageEnd + " exported");
}
});
usersHolder.currentPageStart = usersHolder.currentPageEnd;
}
}
}
protected abstract void writeRealm(String fileName, RealmRepresentation rep) throws IOException;
protected abstract void writeUsers(String fileName, RealmModel realm, List<UserModel> users) throws IOException;
public static class RealmsHolder {
List<RealmModel> realms;
}
public static class UsersHolder {
List<UserModel> users;
int totalCount;
int currentPageStart;
int currentPageEnd;
}
}

View file

@ -0,0 +1,2 @@
org.keycloak.exportimport.ExportSpi
org.keycloak.exportimport.ImportSpi

View file

@ -0,0 +1,66 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-export-import-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-export-import-dir</artifactId>
<name>Keycloak Export Import To Directory</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-export-import-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,73 @@
package org.keycloak.exportimport.dir;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import org.keycloak.exportimport.util.ExportUtils;
import org.keycloak.exportimport.util.MultipleStepsExportProvider;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.util.JsonSerialization;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class DirExportProvider extends MultipleStepsExportProvider {
private final File rootDirectory;
public DirExportProvider() {
// Determine system tmp directory
String tempDir = System.getProperty("java.io.tmpdir");
this.rootDirectory = new File(tempDir + "/keycloak-export");
this.rootDirectory.mkdirs();
logger.infof("Exporting into directory %s", this.rootDirectory.getAbsolutePath());
}
public DirExportProvider(File rootDirectory) {
this.rootDirectory = rootDirectory;
this.rootDirectory.mkdirs();
logger.infof("Exporting into directory %s", this.rootDirectory.getAbsolutePath());
}
public static boolean recursiveDeleteDir(File dirPath) {
if (dirPath.exists()) {
File[] files = dirPath.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
recursiveDeleteDir(files[i]);
} else {
files[i].delete();
}
}
}
if (dirPath.exists())
return dirPath.delete();
else
return true;
}
@Override
public void writeRealm(String fileName, RealmRepresentation rep) throws IOException {
File file = new File(this.rootDirectory, fileName);
FileOutputStream stream = new FileOutputStream(file);
JsonSerialization.prettyMapper.writeValue(stream, rep);
}
@Override
protected void writeUsers(String fileName, RealmModel realm, List<UserModel> users) throws IOException {
File file = new File(this.rootDirectory, fileName);
FileOutputStream os = new FileOutputStream(file);
ExportUtils.exportUsersToStream(realm, users, JsonSerialization.prettyMapper, os);
}
@Override
public void close() {
}
}

View file

@ -0,0 +1,36 @@
package org.keycloak.exportimport.dir;
import java.io.File;
import org.keycloak.Config;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.ExportProvider;
import org.keycloak.exportimport.ExportProviderFactory;
import org.keycloak.models.KeycloakSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class DirExportProviderFactory implements ExportProviderFactory {
public static final String PROVIDER_ID = "dir";
@Override
public ExportProvider create(KeycloakSession session) {
String dir = ExportImportConfig.getDir();
return dir!=null ? new DirExportProvider(new File(dir)) : new DirExportProvider();
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
}

View file

@ -0,0 +1,109 @@
package org.keycloak.exportimport.dir;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import org.codehaus.jackson.map.ObjectMapper;
import org.jboss.logging.Logger;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.ImportProvider;
import org.keycloak.exportimport.Strategy;
import org.keycloak.exportimport.util.ExportImportJob;
import org.keycloak.exportimport.util.ExportImportUtils;
import org.keycloak.exportimport.util.ImportUtils;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.util.JsonSerialization;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class DirImportProvider implements ImportProvider {
private static final Logger logger = Logger.getLogger(DirImportProvider.class);
private final File rootDirectory;
public DirImportProvider() {
// Determine system tmp directory
String tempDir = System.getProperty("java.io.tmpdir");
// Delete and recreate directory inside tmp
this.rootDirectory = new File(tempDir + "/keycloak-export");
if (!this.rootDirectory .exists()) {
throw new IllegalStateException("Directory " + this.rootDirectory + " doesn't exists");
}
logger.infof("Importing from directory %s", this.rootDirectory.getAbsolutePath());
}
public DirImportProvider(File rootDirectory) {
this.rootDirectory = rootDirectory;
logger.infof("Importing from directory %s", this.rootDirectory.getAbsolutePath());
}
@Override
public void importModel(KeycloakSession session, Strategy strategy) throws IOException {
File[] realmFiles = this.rootDirectory.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return (name.endsWith("-realm.json"));
}
});
for (File file : realmFiles) {
String fileName = file.getName();
// Parse "foo" from "foo-realm.json"
String realmName = fileName.substring(0, fileName.length() - 11);
importRealm(session, realmName, strategy);
}
}
@Override
public void importRealm(final KeycloakSession session, final String realmName, final Strategy strategy) throws IOException {
File realmFile = new File(this.rootDirectory + File.separator + realmName + "-realm.json");
File[] userFiles = this.rootDirectory.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return (name.startsWith(realmName)) && (name.endsWith(".json")) && (name.substring(realmName.length()).contains("-users-") );
}
});
// Import realm first
FileInputStream is = new FileInputStream(realmFile);
final RealmRepresentation realmRep = JsonSerialization.readValue(is, RealmRepresentation.class);
ExportImportUtils.runJobInTransaction(session, new ExportImportJob() {
@Override
public void run() throws IOException {
ImportUtils.importRealm(session, realmRep, strategy);
}
});
// Import users
for (File userFile : userFiles) {
final FileInputStream fis = new FileInputStream(userFile);
ExportImportUtils.runJobInTransaction(session, new ExportImportJob() {
@Override
public void run() throws IOException {
ImportUtils.importUsersFromStream(session, realmName, JsonSerialization.mapper, fis);
}
});
}
}
@Override
public void close() {
}
}

View file

@ -0,0 +1,34 @@
package org.keycloak.exportimport.dir;
import java.io.File;
import org.keycloak.Config;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.ImportProvider;
import org.keycloak.exportimport.ImportProviderFactory;
import org.keycloak.models.KeycloakSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class DirImportProviderFactory implements ImportProviderFactory {
@Override
public ImportProvider create(KeycloakSession session) {
String dir = ExportImportConfig.getDir();
return dir!=null ? new DirImportProvider(new File(dir)) : new DirImportProvider();
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return DirExportProviderFactory.PROVIDER_ID;
}
}

View file

@ -0,0 +1 @@
org.keycloak.exportimport.dir.DirExportProviderFactory

View file

@ -0,0 +1 @@
org.keycloak.exportimport.dir.DirImportProviderFactory

View file

@ -1,58 +0,0 @@
package org.keycloak.exportimport;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ExportImportConfig {
public static final String ACTION = "keycloak.migration.action";
public static final String PROVIDER = "keycloak.migration.provider";
public static final String PROVIDER_DEFAULT = "zip";
// used for "directory" provider
public static final String DIR = "keycloak.migration.dir";
// used for "zip" provider
public static final String FILE = "keycloak.migration.zipFile";
public static final String PASSWORD = "keycloak.migration.zipPassword";
public static String getAction() {
return System.getProperty(ACTION);
}
public static void setAction(String exportImportAction) {
System.setProperty(ACTION, exportImportAction);
}
public static String getProvider() {
return System.getProperty(PROVIDER, PROVIDER_DEFAULT);
}
public static void setProvider(String exportImportProvider) {
System.setProperty(PROVIDER, exportImportProvider);
}
public static String getDir() {
return System.getProperty(DIR);
}
public static String setDir(String dir) {
return System.setProperty(DIR, dir);
}
public static String getZipFile() {
return System.getProperty(FILE);
}
public static void setZipFile(String exportImportZipFile) {
System.setProperty(FILE, exportImportZipFile);
}
public static String getZipPassword() {
return System.getProperty(PASSWORD);
}
public static void setZipPassword(String exportImportZipPassword) {
System.setProperty(PASSWORD, exportImportZipPassword);
}
}

View file

@ -12,14 +12,13 @@ import org.keycloak.util.ProviderLoader;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ExportImportProviderImpl implements ExportImportProvider {
public class ExportImportProviderImpl {
private static final Logger logger = Logger.getLogger(ExportImportProviderImpl.class);
public static final String ACTION_EXPORT = "export";
public static final String ACTION_IMPORT = "import";
@Override
public void checkExportImport(KeycloakSessionFactory sessionFactory) {
String exportImportAction = ExportImportConfig.getAction();

View file

@ -1,20 +0,0 @@
package org.keycloak.exportimport;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ExportImportUtils {
public RealmRepresentation exportRealm(RealmModel realm, boolean includeUsers) {
return null;
}
public RealmRepresentation exportUsers(RealmModel realm, int start, int count) {
return null;
}
}

View file

@ -1,115 +0,0 @@
package org.keycloak.exportimport;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.model.test.AbstractModelTest;
import org.keycloak.model.test.ImportTest;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.util.ProviderLoader;
import java.util.Iterator;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public abstract class ExportImportTestBase {
protected KeycloakSessionFactory factory;
protected KeycloakSession session;
protected RealmManager realmManager;
@After
public void after() {
System.getProperties().remove("keycloak.model.provider");
}
@Test
public void testExportImport() throws Exception {
// Init JPA model
System.setProperty("keycloak.model.provider", getExportModelProvider());
factory = KeycloakApplication.createSessionFactory();
// Bootstrap admin realm
beginTransaction();
new ApplianceBootstrap().bootstrap(session, "/auth");
commitTransaction();
// Classic import of realm to JPA model
beginTransaction();
RealmRepresentation rep = AbstractModelTest.loadJson("testrealm.json");
realmManager = new RealmManager(session);
RealmModel realm = realmManager.createRealm("demo", rep.getRealm());
realmManager.importRealm(rep, realm);
commitTransaction();
// Full export of realm
exportModel(factory);
beginTransaction();
realm = session.model().getRealm("demo");
String wburkeId = realm.getUser("wburke").getId();
String appId = realm.getApplicationByName("Application").getId();
// Commit transaction and close JPA now
commitTransaction();
factory.close();
// Bootstrap mongo session and factory
System.setProperty("keycloak.model.provider", getImportModelProvider());
factory = KeycloakApplication.createSessionFactory();
// Full import of previous export into mongo
importModel(factory);
// Verify it's imported in mongo (reusing ImportTest)
beginTransaction();
RealmModel importedRealm = session.model().getRealm("demo");
System.out.println("Exported realm: " + realm + ", Imported realm: " + importedRealm);
Assert.assertEquals(wburkeId, importedRealm.getUser("wburke").getId());
Assert.assertEquals(appId, importedRealm.getApplicationByName("Application").getId());
ImportTest.assertDataImportedInRealm(importedRealm);
// Commit and close Mongo
commitTransaction();
factory.close();
}
protected abstract String getExportModelProvider();
protected abstract String getImportModelProvider();
protected abstract void exportModel(KeycloakSessionFactory factory);
protected abstract void importModel(KeycloakSessionFactory factory);
protected void beginTransaction() {
session = factory.create();
session.getTransaction().begin();
realmManager = new RealmManager(session);
}
protected void commitTransaction() {
session.getTransaction().commit();
session.close();
}
protected ExportImportProvider getExportImportProvider() {
Iterator<ExportImportProvider> providers = ProviderLoader.load(ExportImportProvider.class).iterator();
if (providers.hasNext()) {
return providers.next();
} else {
throw new IllegalStateException("ExportImportProvider not found");
}
}
}

View file

@ -10,29 +10,5 @@ import org.keycloak.models.KeycloakSessionFactory;
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@Ignore
public class JPAToMongoExportImportTest extends ExportImportTestBase {
@Override
protected String getExportModelProvider() {
return "jpa";
}
@Override
protected String getImportModelProvider() {
return "mongo";
}
@Override
protected void exportModel(KeycloakSessionFactory factory) {
ExportImportConfig.setAction(ExportImportProviderImpl.ACTION_EXPORT);
ExportImportConfig.setProvider(TmpDirExportImportIOProvider.PROVIDER_ID);
getExportImportProvider().checkExportImport(factory);
}
@Override
protected void importModel(KeycloakSessionFactory factory) {
ExportImportConfig.setAction(ExportImportProviderImpl.ACTION_IMPORT);
ExportImportConfig.setProvider(TmpDirExportImportIOProvider.PROVIDER_ID);
getExportImportProvider().checkExportImport(factory);
}
public class JPAToMongoExportImportTest {
}

View file

@ -13,59 +13,5 @@ import java.io.File;
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@Ignore
public class MongoToJPAExportImportTest extends ExportImportTestBase {
private static final String zipFile = "keycloak-export.zip";
@Override
protected String getExportModelProvider() {
return "mongo";
}
@Override
protected String getImportModelProvider() {
return "jpa";
}
@Override
protected void exportModel(KeycloakSessionFactory factory) {
ExportImportConfig.setAction(ExportImportProviderImpl.ACTION_EXPORT);
ExportImportConfig.setProvider(EncryptedZIPIOProvider.PROVIDER_ID);
File zipFile = getZipFile();
ExportImportConfig.setZipFile(zipFile.getAbsolutePath());
ExportImportConfig.setZipPassword("password123");
if (zipFile.exists()) {
zipFile.delete();
}
new ExportImportProviderImpl().checkExportImport(factory);
}
@Override
protected void importModel(KeycloakSessionFactory factory) {
ExportImportConfig.setAction(ExportImportProviderImpl.ACTION_IMPORT);
ExportImportConfig.setProvider(EncryptedZIPIOProvider.PROVIDER_ID);
File zipFile = getZipFile();
ExportImportConfig.setZipFile(zipFile.getAbsolutePath());
ExportImportConfig.setZipPassword("password-invalid");
// Try invalid password
try {
new ExportImportProviderImpl().checkExportImport(factory);
Assert.fail("Not expected to be here. Exception should be thrown");
} catch (Exception e) {};
ExportImportConfig.setZipPassword("password123");
new ExportImportProviderImpl().checkExportImport(factory);
if (zipFile.exists()) {
zipFile.delete();
}
}
private File getZipFile() {
String tempDir = System.getProperty("java.io.tmpdir");
return new File(tempDir + File.separator + "keycloak-export.zip");
}
public class MongoToJPAExportImportTest {
}

View file

@ -0,0 +1,65 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-export-import-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-export-import-single-file</artifactId>
<name>Keycloak Export Import To Single File</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-export-import-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,84 @@
package org.keycloak.exportimport.singlefile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.codehaus.jackson.map.ObjectMapper;
import org.jboss.logging.Logger;
import org.keycloak.exportimport.ExportProvider;
import org.keycloak.exportimport.util.ExportImportJob;
import org.keycloak.exportimport.util.ExportImportUtils;
import org.keycloak.exportimport.util.ExportUtils;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.util.JsonSerialization;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class SingleFileExportProvider implements ExportProvider {
private static final Logger logger = Logger.getLogger(SingleFileExportProvider.class);
private File file;
public SingleFileExportProvider(File file) {
this.file = file;
}
public void setFile(File file) {
this.file = file;
}
@Override
public void exportModel(final KeycloakSession session) throws IOException {
logger.infof("Exporting model into file %s", this.file.getAbsolutePath());
ExportImportUtils.runJobInTransaction(session, new ExportImportJob() {
@Override
public void run() throws IOException {
List<RealmModel> realms = session.getModel().getRealms();
List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
for (RealmModel realm : realms) {
reps.add(ExportUtils.exportRealm(realm, true));
}
writeToFile(reps);
}
});
}
@Override
public void exportRealm(final KeycloakSession session, final String realmName) throws IOException {
logger.infof("Exporting realm '%s' into file %s", realmName, this.file.getAbsolutePath());
ExportImportUtils.runJobInTransaction(session, new ExportImportJob() {
@Override
public void run() throws IOException {
RealmModel realm = session.getModel().getRealmByName(realmName);
RealmRepresentation realmRep = ExportUtils.exportRealm(realm, true);
writeToFile(realmRep);
}
});
}
@Override
public void close() {
}
private ObjectMapper getObjectMapper() {
return JsonSerialization.prettyMapper;
}
private void writeToFile(Object reps) throws IOException {
FileOutputStream stream = new FileOutputStream(this.file);
getObjectMapper().writeValue(stream, reps);
}
}

View file

@ -0,0 +1,36 @@
package org.keycloak.exportimport.singlefile;
import java.io.File;
import org.keycloak.Config;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.ExportProvider;
import org.keycloak.exportimport.ExportProviderFactory;
import org.keycloak.models.KeycloakSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class SingleFileExportProviderFactory implements ExportProviderFactory {
public static final String PROVIDER_ID = "singleFile";
@Override
public ExportProvider create(KeycloakSession session) {
String fileName = ExportImportConfig.getFile();
return new SingleFileExportProvider(new File(fileName));
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
}

View file

@ -0,0 +1,58 @@
package org.keycloak.exportimport.singlefile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jboss.logging.Logger;
import org.keycloak.exportimport.ImportProvider;
import org.keycloak.exportimport.Strategy;
import org.keycloak.exportimport.util.ExportImportJob;
import org.keycloak.exportimport.util.ExportImportUtils;
import org.keycloak.exportimport.util.ExportUtils;
import org.keycloak.exportimport.util.ImportUtils;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.util.JsonSerialization;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class SingleFileImportProvider implements ImportProvider {
private static final Logger logger = Logger.getLogger(SingleFileImportProvider.class);
private File file;
public SingleFileImportProvider(File file) {
this.file = file;
}
@Override
public void importModel(final KeycloakSession session, final Strategy strategy) throws IOException {
logger.infof("Full importing from file %s", this.file.getAbsolutePath());
ExportImportUtils.runJobInTransaction(session, new ExportImportJob() {
@Override
public void run() throws IOException {
FileInputStream is = new FileInputStream(file);
ImportUtils.importFromStream(session, JsonSerialization.mapper, is, strategy);
}
});
}
@Override
public void importRealm(KeycloakSession session, String realmName, Strategy strategy) throws IOException {
// TODO: just that single realm in case that file contains many realms?
importModel(session, strategy);
}
@Override
public void close() {
}
}

View file

@ -0,0 +1,34 @@
package org.keycloak.exportimport.singlefile;
import java.io.File;
import org.keycloak.Config;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.ImportProvider;
import org.keycloak.exportimport.ImportProviderFactory;
import org.keycloak.models.KeycloakSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class SingleFileImportProviderFactory implements ImportProviderFactory {
@Override
public ImportProvider create(KeycloakSession session) {
String fileName = ExportImportConfig.getFile();
return new SingleFileImportProvider(new File(fileName));
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return SingleFileExportProviderFactory.PROVIDER_ID;
}
}

View file

@ -0,0 +1 @@
org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory

View file

@ -0,0 +1 @@
org.keycloak.exportimport.singlefile.SingleFileImportProviderFactory

View file

@ -0,0 +1,70 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-export-import-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-export-import-zip</artifactId>
<name>Keycloak Export Import To Encrypted ZIP</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-export-import-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.idyl</groupId>
<artifactId>winzipaes</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,73 @@
package org.keycloak.exportimport.zip;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.List;
import de.idyl.winzipaes.AesZipFileEncrypter;
import de.idyl.winzipaes.impl.AESEncrypter;
import de.idyl.winzipaes.impl.AESEncrypterBC;
import org.jboss.logging.Logger;
import org.keycloak.exportimport.util.ExportUtils;
import org.keycloak.exportimport.util.MultipleStepsExportProvider;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.util.JsonSerialization;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ZipExportProvider extends MultipleStepsExportProvider {
private static final Logger logger = Logger.getLogger(ZipExportProvider.class);
private final AesZipFileEncrypter encrypter;
private final String password;
public ZipExportProvider(File zipFile, String password) {
if (zipFile.exists()) {
throw new IllegalStateException("File " + zipFile.getAbsolutePath() + " already exists");
}
this.password = password;
try {
AESEncrypter encrypter = new AESEncrypterBC();
this.encrypter = new AesZipFileEncrypter(zipFile, encrypter);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
logger.infof("Exporting into zip file %s", zipFile.getAbsolutePath());
}
@Override
protected void writeRealm(String fileName, RealmRepresentation rep) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonSerialization.mapper.writeValue(stream, rep);
byte[] byteArray = stream.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
this.encrypter.add(fileName, bis, this.password);
}
@Override
protected void writeUsers(String fileName, RealmModel realm, List<UserModel> users) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ExportUtils.exportUsersToStream(realm, users, JsonSerialization.mapper, stream);
byte[] byteArray = stream.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
this.encrypter.add(fileName, bis, this.password);
}
@Override
public void close() {
try {
this.encrypter.close();
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}

View file

@ -0,0 +1,44 @@
package org.keycloak.exportimport.zip;
import java.io.File;
import org.keycloak.Config;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.ExportProvider;
import org.keycloak.exportimport.ExportProviderFactory;
import org.keycloak.models.KeycloakSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ZipExportProviderFactory implements ExportProviderFactory {
public static final String PROVIDER_ID = "zip";
@Override
public ExportProvider create(KeycloakSession session) {
String fileName = ExportImportConfig.getZipFile();
String password = ExportImportConfig.getZipPassword();
if (fileName == null) {
throw new IllegalArgumentException("ZIP file for export not provided");
}
if (password == null) {
throw new IllegalArgumentException("Password for encrypting ZIP not provided");
}
return new ZipExportProvider(new File(fileName), password);
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
}

View file

@ -0,0 +1,109 @@
package org.keycloak.exportimport.zip;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.zip.DataFormatException;
import de.idyl.winzipaes.AesZipFileDecrypter;
import de.idyl.winzipaes.impl.AESDecrypter;
import de.idyl.winzipaes.impl.AESDecrypterBC;
import de.idyl.winzipaes.impl.ExtZipEntry;
import org.jboss.logging.Logger;
import org.keycloak.exportimport.ImportProvider;
import org.keycloak.exportimport.Strategy;
import org.keycloak.exportimport.util.ExportImportJob;
import org.keycloak.exportimport.util.ExportImportUtils;
import org.keycloak.exportimport.util.ImportUtils;
import org.keycloak.models.KeycloakSession;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.util.JsonSerialization;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ZipImportProvider implements ImportProvider {
private static final Logger logger = Logger.getLogger(ZipImportProvider.class);
private final AesZipFileDecrypter decrypter;
private final String password;
public ZipImportProvider(File zipFile, String password) {
try {
if (!zipFile.exists()) {
throw new IllegalStateException("File " + zipFile.getAbsolutePath() + " doesn't exists");
}
AESDecrypter decrypter = new AESDecrypterBC();
this.decrypter = new AesZipFileDecrypter(zipFile, decrypter);
this.password = password;
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
logger.infof("Importing from ZIP file %s", zipFile.getAbsolutePath());
}
@Override
public void importModel(KeycloakSession session, Strategy strategy) throws IOException {
for (ExtZipEntry entry : this.decrypter.getEntryList()) {
String entryName = entry.getName();
if (entryName.endsWith("-realm.json")) {
// Parse "foo" from "foo-realm.json"
String realmName = entryName.substring(0, entryName.length() - 11);
importRealm(session, realmName, strategy);
}
}
}
@Override
public void importRealm(final KeycloakSession session, final String realmName, final Strategy strategy) throws IOException {
try {
// Import realm first
ByteArrayOutputStream bos = new ByteArrayOutputStream();
this.decrypter.extractEntry(this.decrypter.getEntry(realmName + "-realm.json"), bos, this.password);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
final RealmRepresentation realmRep = JsonSerialization.mapper.readValue(bis, RealmRepresentation.class);
ExportImportUtils.runJobInTransaction(session, new ExportImportJob() {
@Override
public void run() throws IOException {
ImportUtils.importRealm(session, realmRep, strategy);
}
});
// Import users
for (ExtZipEntry entry : this.decrypter.getEntryList()) {
String name = entry.getName();
if ( (name.startsWith(realmName)) && (name.endsWith(".json")) && (name.substring(realmName.length()).contains("-users-")) ) {
bos = new ByteArrayOutputStream();
this.decrypter.extractEntry(entry, bos, this.password);
final ByteArrayInputStream bis2 = new ByteArrayInputStream(bos.toByteArray());
ExportImportUtils.runJobInTransaction(session, new ExportImportJob() {
@Override
public void run() throws IOException {
ImportUtils.importUsersFromStream(session, realmName, JsonSerialization.mapper, bis2);
}
});
}
}
} catch (DataFormatException dfe) {
throw new RuntimeException(dfe);
}
}
@Override
public void close() {
try {
this.decrypter.close();
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}

View file

@ -0,0 +1,41 @@
package org.keycloak.exportimport.zip;
import java.io.File;
import org.keycloak.Config;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.ImportProvider;
import org.keycloak.exportimport.ImportProviderFactory;
import org.keycloak.models.KeycloakSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ZipImportProviderFactory implements ImportProviderFactory {
@Override
public ImportProvider create(KeycloakSession session) {
String fileName = ExportImportConfig.getZipFile();
String password = ExportImportConfig.getZipPassword();
if (fileName == null) {
throw new IllegalArgumentException("ZIP file for import not provided");
}
if (password == null) {
throw new IllegalArgumentException("Password for decrypting ZIP not provided");
}
return new ZipImportProvider(new File(fileName), password);
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return ZipExportProviderFactory.PROVIDER_ID;
}
}

View file

@ -0,0 +1 @@
org.keycloak.exportimport.zip.ZipExportProviderFactory

View file

@ -0,0 +1 @@
org.keycloak.exportimport.zip.ZipImportProviderFactory

View file

@ -17,6 +17,9 @@
<modules>
<module>export-import-api</module>
<module>export-import-impl</module>
<module>export-import-dir</module>
<module>export-import-single-file</module>
<module>export-import-zip</module>
</modules>
</project>

View file

@ -30,6 +30,11 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View file

@ -3,6 +3,9 @@ package org.keycloak.models.utils;
import java.io.IOException;
import java.io.StringWriter;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Set;
@ -10,8 +13,11 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import org.bouncycastle.openssl.PEMWriter;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.util.PemUtils;
@ -65,6 +71,23 @@ public final class KeycloakModelUtils {
return PemUtils.removeBeginEnd(s);
}
public static void generateRealmKeys(RealmModel realm) {
KeyPair keyPair = null;
try {
keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
realm.setPrivateKey(keyPair.getPrivate());
realm.setPublicKey(keyPair.getPublic());
}
public static UserCredentialModel generateSecret(ClientModel app) {
UserCredentialModel secret = UserCredentialModel.generateSecret();
app.setSecret(secret.getValue());
return secret;
}
/**
* Deep search if given role is descendant of composite role
*

View file

@ -1,4 +1,4 @@
package org.keycloak.services.managers;
package org.keycloak.models.utils;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationProviderModel;
@ -13,9 +13,11 @@ import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.representations.idm.AuthenticationProviderRepresentation;
import org.keycloak.representations.idm.ClaimRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.OAuthClientRepresentation;
import org.keycloak.representations.idm.RealmAuditRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
@ -29,6 +31,7 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -201,4 +204,53 @@ public class ModelToRepresentation {
}
return rep;
}
public static ApplicationRepresentation toRepresentation(ApplicationModel applicationModel) {
ApplicationRepresentation rep = new ApplicationRepresentation();
rep.setId(applicationModel.getId());
rep.setName(applicationModel.getName());
rep.setEnabled(applicationModel.isEnabled());
rep.setAdminUrl(applicationModel.getManagementUrl());
rep.setPublicClient(applicationModel.isPublicClient());
rep.setBearerOnly(applicationModel.isBearerOnly());
rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
rep.setBaseUrl(applicationModel.getBaseUrl());
rep.setNotBefore(applicationModel.getNotBefore());
Set<String> redirectUris = applicationModel.getRedirectUris();
if (redirectUris != null) {
rep.setRedirectUris(new LinkedList<String>(redirectUris));
}
Set<String> webOrigins = applicationModel.getWebOrigins();
if (webOrigins != null) {
rep.setWebOrigins(new LinkedList<String>(webOrigins));
}
if (!applicationModel.getDefaultRoles().isEmpty()) {
rep.setDefaultRoles(applicationModel.getDefaultRoles().toArray(new String[0]));
}
return rep;
}
public static OAuthClientRepresentation toRepresentation(OAuthClientModel model) {
OAuthClientRepresentation rep = new OAuthClientRepresentation();
rep.setId(model.getId());
rep.setName(model.getClientId());
rep.setEnabled(model.isEnabled());
rep.setPublicClient(model.isPublicClient());
rep.setDirectGrantsOnly(model.isDirectGrantsOnly());
Set<String> redirectUris = model.getRedirectUris();
if (redirectUris != null) {
rep.setRedirectUris(new LinkedList<String>(redirectUris));
}
Set<String> webOrigins = model.getWebOrigins();
if (webOrigins != null) {
rep.setWebOrigins(new LinkedList<String>(webOrigins));
}
rep.setNotBefore(model.getNotBefore());
return rep;
}
}

View file

@ -0,0 +1,671 @@
package org.keycloak.models.utils;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.iharder.Base64;
import org.jboss.logging.Logger;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.AuthenticationProviderModel;
import org.keycloak.models.ClaimMask;
import org.keycloak.models.ClientModel;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.representations.idm.AuthenticationLinkRepresentation;
import org.keycloak.representations.idm.AuthenticationProviderRepresentation;
import org.keycloak.representations.idm.ClaimRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.OAuthClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.ScopeMappingRepresentation;
import org.keycloak.representations.idm.SocialLinkRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
public class RepresentationToModel {
private static Logger logger = Logger.getLogger(RepresentationToModel.class);
public static void importRealm(RealmRepresentation rep, RealmModel newRealm) {
newRealm.setName(rep.getRealm());
if (rep.isEnabled() != null) newRealm.setEnabled(rep.isEnabled());
if (rep.isSocial() != null) newRealm.setSocial(rep.isSocial());
if (rep.isBruteForceProtected() != null) newRealm.setBruteForceProtected(rep.isBruteForceProtected());
if (rep.getMaxFailureWaitSeconds() != null) newRealm.setMaxFailureWaitSeconds(rep.getMaxFailureWaitSeconds());
if (rep.getMinimumQuickLoginWaitSeconds() != null) newRealm.setMinimumQuickLoginWaitSeconds(rep.getMinimumQuickLoginWaitSeconds());
if (rep.getWaitIncrementSeconds() != null) newRealm.setWaitIncrementSeconds(rep.getWaitIncrementSeconds());
if (rep.getQuickLoginCheckMilliSeconds() != null) newRealm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
if (rep.getMaxDeltaTimeSeconds() != null) newRealm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
if (rep.getFailureFactor() != null) newRealm.setFailureFactor(rep.getFailureFactor());
if (rep.getNotBefore() != null) newRealm.setNotBefore(rep.getNotBefore());
if (rep.getAccessTokenLifespan() != null) newRealm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
else newRealm.setAccessTokenLifespan(300);
if (rep.getSsoSessionIdleTimeout() != null) newRealm.setSsoSessionIdleTimeout(rep.getSsoSessionIdleTimeout());
else newRealm.setSsoSessionIdleTimeout(600);
if (rep.getSsoSessionMaxLifespan() != null) newRealm.setSsoSessionMaxLifespan(rep.getSsoSessionMaxLifespan());
else newRealm.setSsoSessionMaxLifespan(36000);
if (rep.getAccessCodeLifespan() != null) newRealm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
else newRealm.setAccessCodeLifespan(60);
if (rep.getAccessCodeLifespanUserAction() != null)
newRealm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
else newRealm.setAccessCodeLifespanUserAction(300);
if (rep.isSslNotRequired() != null) newRealm.setSslNotRequired(rep.isSslNotRequired());
if (rep.isPasswordCredentialGrantAllowed() != null) newRealm.setPasswordCredentialGrantAllowed(rep.isPasswordCredentialGrantAllowed());
if (rep.isRegistrationAllowed() != null) newRealm.setRegistrationAllowed(rep.isRegistrationAllowed());
if (rep.isRememberMe() != null) newRealm.setRememberMe(rep.isRememberMe());
if (rep.isVerifyEmail() != null) newRealm.setVerifyEmail(rep.isVerifyEmail());
if (rep.isResetPasswordAllowed() != null) newRealm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
if (rep.isUpdateProfileOnInitialSocialLogin() != null)
newRealm.setUpdateProfileOnInitialSocialLogin(rep.isUpdateProfileOnInitialSocialLogin());
if (rep.getPrivateKey() == null || rep.getPublicKey() == null) {
KeycloakModelUtils.generateRealmKeys(newRealm);
} else {
newRealm.setPrivateKeyPem(rep.getPrivateKey());
newRealm.setPublicKeyPem(rep.getPublicKey());
}
if (rep.getLoginTheme() != null) newRealm.setLoginTheme(rep.getLoginTheme());
if (rep.getAccountTheme() != null) newRealm.setAccountTheme(rep.getAccountTheme());
if (rep.getAdminTheme() != null) newRealm.setAdminTheme(rep.getAdminTheme());
if (rep.getEmailTheme() != null) newRealm.setEmailTheme(rep.getEmailTheme());
if (rep.getRequiredCredentials() != null) {
for (String requiredCred : rep.getRequiredCredentials()) {
addRequiredCredential(newRealm, requiredCred);
}
} else {
addRequiredCredential(newRealm, CredentialRepresentation.PASSWORD);
}
if (rep.getPasswordPolicy() != null) newRealm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
if (rep.getApplications() != null) {
Map<String, ApplicationModel> appMap = createApplications(rep, newRealm);
}
if (rep.getRoles() != null) {
if (rep.getRoles().getRealm() != null) { // realm roles
for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
createRole(newRealm, roleRep);
}
}
if (rep.getRoles().getApplication() != null) {
for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getApplication().entrySet()) {
ApplicationModel app = newRealm.getApplicationByName(entry.getKey());
if (app == null) {
throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
}
for (RoleRepresentation roleRep : entry.getValue()) {
// Application role may already exists (for example if it is defaultRole)
RoleModel role = app.getRole(roleRep.getName());
if (role == null) {
role = app.addRole(roleRep.getName());
}
role.setDescription(roleRep.getDescription());
}
}
}
// now that all roles are created, re-iterate and set up composites
if (rep.getRoles().getRealm() != null) { // realm roles
for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
RoleModel role = newRealm.getRole(roleRep.getName());
addComposites(role, roleRep, newRealm);
}
}
if (rep.getRoles().getApplication() != null) {
for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getApplication().entrySet()) {
ApplicationModel app = newRealm.getApplicationByName(entry.getKey());
if (app == null) {
throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
}
for (RoleRepresentation roleRep : entry.getValue()) {
RoleModel role = app.getRole(roleRep.getName());
addComposites(role, roleRep, newRealm);
}
}
}
}
if (rep.getDefaultRoles() != null) {
for (String roleString : rep.getDefaultRoles()) {
newRealm.addDefaultRole(roleString.trim());
}
}
if (rep.getOauthClients() != null) {
createOAuthClients(rep, newRealm);
}
// Now that all possible roles and applications are created, create scope mappings
Map<String, ApplicationModel> appMap = newRealm.getApplicationNameMap();
if (rep.getApplicationScopeMappings() != null) {
for (Map.Entry<String, List<ScopeMappingRepresentation>> entry : rep.getApplicationScopeMappings().entrySet()) {
ApplicationModel app = appMap.get(entry.getKey());
if (app == null) {
throw new RuntimeException("Unable to find application role mappings for app: " + entry.getKey());
}
createApplicationScopeMappings(newRealm, app, entry.getValue());
}
}
if (rep.getScopeMappings() != null) {
for (ScopeMappingRepresentation scope : rep.getScopeMappings()) {
ClientModel client = newRealm.findClient(scope.getClient());
for (String roleString : scope.getRoles()) {
RoleModel role = newRealm.getRole(roleString.trim());
if (role == null) {
role = newRealm.addRole(roleString.trim());
}
client.addScopeMapping(role);
}
}
}
if (rep.getSmtpServer() != null) {
newRealm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
}
if (rep.getSocialProviders() != null) {
newRealm.setSocialConfig(new HashMap(rep.getSocialProviders()));
}
if (rep.getLdapServer() != null) {
newRealm.setLdapServerConfig(new HashMap(rep.getLdapServer()));
}
if (rep.getAuthenticationProviders() != null) {
List<AuthenticationProviderModel> authProviderModels = convertAuthenticationProviders(rep.getAuthenticationProviders());
newRealm.setAuthenticationProviders(authProviderModels);
} else {
List<AuthenticationProviderModel> authProviderModels = Arrays.asList(AuthenticationProviderModel.DEFAULT_PROVIDER);
newRealm.setAuthenticationProviders(authProviderModels);
}
// create users and their role mappings and social mappings
if (rep.getUsers() != null) {
for (UserRepresentation userRep : rep.getUsers()) {
UserModel user = createUser(newRealm, userRep, appMap);
}
}
}
public static void updateRealm(RealmRepresentation rep, RealmModel realm) {
if (rep.getRealm() != null) {
realm.setName(rep.getRealm());
}
if (rep.isEnabled() != null) realm.setEnabled(rep.isEnabled());
if (rep.isSocial() != null) realm.setSocial(rep.isSocial());
if (rep.isBruteForceProtected() != null) realm.setBruteForceProtected(rep.isBruteForceProtected());
if (rep.getMaxFailureWaitSeconds() != null) realm.setMaxFailureWaitSeconds(rep.getMaxFailureWaitSeconds());
if (rep.getMinimumQuickLoginWaitSeconds() != null) realm.setMinimumQuickLoginWaitSeconds(rep.getMinimumQuickLoginWaitSeconds());
if (rep.getWaitIncrementSeconds() != null) realm.setWaitIncrementSeconds(rep.getWaitIncrementSeconds());
if (rep.getQuickLoginCheckMilliSeconds() != null) realm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
if (rep.getMaxDeltaTimeSeconds() != null) realm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
if (rep.getFailureFactor() != null) realm.setFailureFactor(rep.getFailureFactor());
if (rep.isPasswordCredentialGrantAllowed() != null) realm.setPasswordCredentialGrantAllowed(rep.isPasswordCredentialGrantAllowed());
if (rep.isRegistrationAllowed() != null) realm.setRegistrationAllowed(rep.isRegistrationAllowed());
if (rep.isRememberMe() != null) realm.setRememberMe(rep.isRememberMe());
if (rep.isVerifyEmail() != null) realm.setVerifyEmail(rep.isVerifyEmail());
if (rep.isResetPasswordAllowed() != null) realm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
if (rep.isUpdateProfileOnInitialSocialLogin() != null)
realm.setUpdateProfileOnInitialSocialLogin(rep.isUpdateProfileOnInitialSocialLogin());
if (rep.isSslNotRequired() != null) realm.setSslNotRequired((rep.isSslNotRequired()));
if (rep.getAccessCodeLifespan() != null) realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
if (rep.getAccessCodeLifespanUserAction() != null)
realm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
if (rep.getNotBefore() != null) realm.setNotBefore(rep.getNotBefore());
if (rep.getAccessTokenLifespan() != null) realm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
if (rep.getSsoSessionIdleTimeout() != null) realm.setSsoSessionIdleTimeout(rep.getSsoSessionIdleTimeout());
if (rep.getSsoSessionMaxLifespan() != null) realm.setSsoSessionMaxLifespan(rep.getSsoSessionMaxLifespan());
if (rep.getRequiredCredentials() != null) {
realm.updateRequiredCredentials(rep.getRequiredCredentials());
}
if (rep.getLoginTheme() != null) realm.setLoginTheme(rep.getLoginTheme());
if (rep.getAccountTheme() != null) realm.setAccountTheme(rep.getAccountTheme());
if (rep.getAdminTheme() != null) realm.setAdminTheme(rep.getAdminTheme());
if (rep.getEmailTheme() != null) realm.setEmailTheme(rep.getEmailTheme());
if (rep.getPasswordPolicy() != null) realm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
if (rep.getDefaultRoles() != null) {
realm.updateDefaultRoles(rep.getDefaultRoles().toArray(new String[rep.getDefaultRoles().size()]));
}
if (rep.getSmtpServer() != null) {
realm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
}
if (rep.getSocialProviders() != null) {
realm.setSocialConfig(new HashMap(rep.getSocialProviders()));
}
if (rep.getLdapServer() != null) {
realm.setLdapServerConfig(new HashMap(rep.getLdapServer()));
}
if (rep.getAuthenticationProviders() != null) {
List<AuthenticationProviderModel> authProviderModels = convertAuthenticationProviders(rep.getAuthenticationProviders());
realm.setAuthenticationProviders(authProviderModels);
}
if ("GENERATE".equals(rep.getPublicKey())) {
KeycloakModelUtils.generateRealmKeys(realm);
}
}
// Basic realm stuff
public static void addRequiredCredential(RealmModel newRealm, String requiredCred) {
newRealm.addRequiredCredential(requiredCred);
}
private static List<AuthenticationProviderModel> convertAuthenticationProviders(List<AuthenticationProviderRepresentation> authenticationProviders) {
List<AuthenticationProviderModel> result = new ArrayList<AuthenticationProviderModel>();
for (AuthenticationProviderRepresentation representation : authenticationProviders) {
AuthenticationProviderModel model = new AuthenticationProviderModel(representation.getProviderName(),
representation.isPasswordUpdateSupported(), representation.getConfig());
result.add(model);
}
return result;
}
// Roles
public static void createRole(RealmModel newRealm, RoleRepresentation roleRep) {
RoleModel role = roleRep.getId()!=null ? newRealm.addRole(roleRep.getId(), roleRep.getName()) : newRealm.addRole(roleRep.getName());
if (roleRep.getDescription() != null) role.setDescription(roleRep.getDescription());
}
private static void addComposites(RoleModel role, RoleRepresentation roleRep, RealmModel realm) {
if (roleRep.getComposites() == null) return;
if (roleRep.getComposites().getRealm() != null) {
for (String roleStr : roleRep.getComposites().getRealm()) {
RoleModel realmRole = realm.getRole(roleStr);
if (realmRole == null) throw new RuntimeException("Unable to find composite realm role: " + roleStr);
role.addCompositeRole(realmRole);
}
}
if (roleRep.getComposites().getApplication() != null) {
for (Map.Entry<String, List<String>> entry : roleRep.getComposites().getApplication().entrySet()) {
ApplicationModel app = realm.getApplicationByName(entry.getKey());
if (app == null) {
throw new RuntimeException("App doesn't exist in role definitions: " + roleRep.getName());
}
for (String roleStr : entry.getValue()) {
RoleModel appRole = app.getRole(roleStr);
if (appRole == null) throw new RuntimeException("Unable to find composite app role: " + roleStr);
role.addCompositeRole(appRole);
}
}
}
}
// APPLICATIONS
private static Map<String, ApplicationModel> createApplications(RealmRepresentation rep, RealmModel realm) {
Map<String, ApplicationModel> appMap = new HashMap<String, ApplicationModel>();
for (ApplicationRepresentation resourceRep : rep.getApplications()) {
ApplicationModel app = createApplication(realm, resourceRep);
appMap.put(app.getName(), app);
}
return appMap;
}
/**
* Does not create scope or role mappings!
*
* @param realm
* @param resourceRep
* @return
*/
public static ApplicationModel createApplication(RealmModel realm, ApplicationRepresentation resourceRep) {
logger.debug("************ CREATE APPLICATION: {0}" + resourceRep.getName());
ApplicationModel applicationModel = resourceRep.getId()!=null ? realm.addApplication(resourceRep.getId(), resourceRep.getName()) : realm.addApplication(resourceRep.getName());
if (resourceRep.isEnabled() != null) applicationModel.setEnabled(resourceRep.isEnabled());
applicationModel.setManagementUrl(resourceRep.getAdminUrl());
if (resourceRep.isSurrogateAuthRequired() != null)
applicationModel.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
applicationModel.setBaseUrl(resourceRep.getBaseUrl());
if (resourceRep.isBearerOnly() != null) applicationModel.setBearerOnly(resourceRep.isBearerOnly());
if (resourceRep.isPublicClient() != null) applicationModel.setPublicClient(resourceRep.isPublicClient());
applicationModel.updateApplication();
if (resourceRep.getNotBefore() != null) {
applicationModel.setNotBefore(resourceRep.getNotBefore());
}
applicationModel.setSecret(resourceRep.getSecret());
if (applicationModel.getSecret() == null) {
KeycloakModelUtils.generateSecret(applicationModel);
}
if (resourceRep.getRedirectUris() != null) {
for (String redirectUri : resourceRep.getRedirectUris()) {
applicationModel.addRedirectUri(redirectUri);
}
}
if (resourceRep.getWebOrigins() != null) {
for (String webOrigin : resourceRep.getWebOrigins()) {
logger.debugv("Application: {0} webOrigin: {1}", resourceRep.getName(), webOrigin);
applicationModel.addWebOrigin(webOrigin);
}
} else {
// add origins from redirect uris
if (resourceRep.getRedirectUris() != null) {
Set<String> origins = new HashSet<String>();
for (String redirectUri : resourceRep.getRedirectUris()) {
logger.info("add redirectUri to origin: " + redirectUri);
if (redirectUri.startsWith("http:")) {
URI uri = URI.create(redirectUri);
String origin = uri.getScheme() + "://" + uri.getHost();
if (uri.getPort() != -1) {
origin += ":" + uri.getPort();
}
logger.debugv("adding default application origin: {0}" , origin);
origins.add(origin);
}
}
if (origins.size() > 0) {
applicationModel.setWebOrigins(origins);
}
}
}
if (resourceRep.getDefaultRoles() != null) {
applicationModel.updateDefaultRoles(resourceRep.getDefaultRoles());
}
if (resourceRep.getClaims() != null) {
setClaims(applicationModel, resourceRep.getClaims());
} else {
applicationModel.setAllowedClaimsMask(ClaimMask.USERNAME);
}
return applicationModel;
}
public static void updateApplication(ApplicationRepresentation rep, ApplicationModel resource) {
if (rep.getName() != null) resource.setName(rep.getName());
if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
if (rep.getAdminUrl() != null) resource.setManagementUrl(rep.getAdminUrl());
if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
resource.updateApplication();
if (rep.getNotBefore() != null) {
resource.setNotBefore(rep.getNotBefore());
}
if (rep.getDefaultRoles() != null) {
resource.updateDefaultRoles(rep.getDefaultRoles());
}
List<String> redirectUris = rep.getRedirectUris();
if (redirectUris != null) {
resource.setRedirectUris(new HashSet<String>(redirectUris));
}
List<String> webOrigins = rep.getWebOrigins();
if (webOrigins != null) {
resource.setWebOrigins(new HashSet<String>(webOrigins));
}
if (rep.getClaims() != null) {
setClaims(resource, rep.getClaims());
}
}
public static void setClaims(ClientModel model, ClaimRepresentation rep) {
long mask = model.getAllowedClaimsMask();
if (rep.getAddress()) {
mask |= ClaimMask.ADDRESS;
} else {
mask &= ~ClaimMask.ADDRESS;
}
if (rep.getEmail()) {
mask |= ClaimMask.EMAIL;
} else {
mask &= ~ClaimMask.EMAIL;
}
if (rep.getGender()) {
mask |= ClaimMask.GENDER;
} else {
mask &= ~ClaimMask.GENDER;
}
if (rep.getLocale()) {
mask |= ClaimMask.LOCALE;
} else {
mask &= ~ClaimMask.LOCALE;
}
if (rep.getName()) {
mask |= ClaimMask.NAME;
} else {
mask &= ~ClaimMask.NAME;
}
if (rep.getPhone()) {
mask |= ClaimMask.PHONE;
} else {
mask &= ~ClaimMask.PHONE;
}
if (rep.getPicture()) {
mask |= ClaimMask.PICTURE;
} else {
mask &= ~ClaimMask.PICTURE;
}
if (rep.getProfile()) {
mask |= ClaimMask.PROFILE;
} else {
mask &= ~ClaimMask.PROFILE;
}
if (rep.getUsername()) {
mask |= ClaimMask.USERNAME;
} else {
mask &= ~ClaimMask.USERNAME;
}
if (rep.getWebsite()) {
mask |= ClaimMask.WEBSITE;
} else {
mask &= ~ClaimMask.WEBSITE;
}
model.setAllowedClaimsMask(mask);
}
// OAuth clients
private static void createOAuthClients(RealmRepresentation realmRep, RealmModel realm) {
for (OAuthClientRepresentation rep : realmRep.getOauthClients()) {
createOAuthClient(rep, realm);
}
}
public static OAuthClientModel createOAuthClient(String id, String name, RealmModel realm) {
OAuthClientModel model = id!=null ? realm.addOAuthClient(id, name) : realm.addOAuthClient(name);
KeycloakModelUtils.generateSecret(model);
return model;
}
public static OAuthClientModel createOAuthClient(OAuthClientRepresentation rep, RealmModel realm) {
OAuthClientModel model = createOAuthClient(rep.getId(), rep.getName(), realm);
updateOAuthClient(rep, model);
return model;
}
public static void updateOAuthClient(OAuthClientRepresentation rep, OAuthClientModel model) {
if (rep.getName() != null) model.setClientId(rep.getName());
if (rep.isEnabled() != null) model.setEnabled(rep.isEnabled());
if (rep.isPublicClient() != null) model.setPublicClient(rep.isPublicClient());
if (rep.isDirectGrantsOnly() != null) model.setDirectGrantsOnly(rep.isDirectGrantsOnly());
if (rep.getClaims() != null) {
setClaims(model, rep.getClaims());
}
if (rep.getNotBefore() != null) {
model.setNotBefore(rep.getNotBefore());
}
if (rep.getSecret() != null) model.setSecret(rep.getSecret());
List<String> redirectUris = rep.getRedirectUris();
if (redirectUris != null) {
model.setRedirectUris(new HashSet<String>(redirectUris));
}
List<String> webOrigins = rep.getWebOrigins();
if (webOrigins != null) {
model.setWebOrigins(new HashSet<String>(webOrigins));
}
if (rep.getClaims() != null) {
setClaims(model, rep.getClaims());
}
if (rep.getNotBefore() != null) {
model.setNotBefore(rep.getNotBefore());
}
}
// Scope mappings
public static void createApplicationScopeMappings(RealmModel realm, ApplicationModel applicationModel, List<ScopeMappingRepresentation> mappings) {
for (ScopeMappingRepresentation mapping : mappings) {
ClientModel client = realm.findClient(mapping.getClient());
for (String roleString : mapping.getRoles()) {
RoleModel role = applicationModel.getRole(roleString.trim());
if (role == null) {
role = applicationModel.addRole(roleString.trim());
}
client.addScopeMapping(role);
}
}
}
// Users
public static UserModel createUser(RealmModel newRealm, UserRepresentation userRep, Map<String, ApplicationModel> appMap) {
UserModel user = newRealm.addUser(userRep.getId(), userRep.getUsername(), false);
user.setEnabled(userRep.isEnabled());
user.setEmail(userRep.getEmail());
user.setFirstName(userRep.getFirstName());
user.setLastName(userRep.getLastName());
if (userRep.getAttributes() != null) {
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
user.setAttribute(entry.getKey(), entry.getValue());
}
}
if (userRep.getRequiredActions() != null) {
for (String requiredAction : userRep.getRequiredActions()) {
user.addRequiredAction(UserModel.RequiredAction.valueOf(requiredAction));
}
}
if (userRep.getCredentials() != null) {
for (CredentialRepresentation cred : userRep.getCredentials()) {
updateCredential(user, cred);
}
}
if (userRep.getAuthenticationLink() != null) {
AuthenticationLinkRepresentation link = userRep.getAuthenticationLink();
AuthenticationLinkModel authLink = new AuthenticationLinkModel(link.getAuthProvider(), link.getAuthUserId());
user.setAuthenticationLink(authLink);
}
if (userRep.getSocialLinks() != null) {
for (SocialLinkRepresentation socialLink : userRep.getSocialLinks()) {
SocialLinkModel mappingModel = new SocialLinkModel(socialLink.getSocialProvider(), socialLink.getSocialUserId(), socialLink.getSocialUsername());
newRealm.addSocialLink(user, mappingModel);
}
}
if (userRep.getRealmRoles() != null) {
for (String roleString : userRep.getRealmRoles()) {
RoleModel role = newRealm.getRole(roleString.trim());
if (role == null) {
role = newRealm.addRole(roleString.trim());
}
user.grantRole(role);
}
}
if (userRep.getApplicationRoles() != null) {
for (Map.Entry<String, List<String>> entry : userRep.getApplicationRoles().entrySet()) {
ApplicationModel app = appMap.get(entry.getKey());
if (app == null) {
throw new RuntimeException("Unable to find application role mappings for app: " + entry.getKey());
}
createApplicationRoleMappings(app, user, entry.getValue());
}
}
return user;
}
// Detect if it is "plain-text" or "hashed" representation and update model according to it
private static void updateCredential(UserModel user, CredentialRepresentation cred) {
if (cred.getValue() != null) {
UserCredentialModel plainTextCred = convertCredential(cred);
user.updateCredential(plainTextCred);
} else {
UserCredentialValueModel hashedCred = new UserCredentialValueModel();
hashedCred.setType(cred.getType());
hashedCred.setDevice(cred.getDevice());
hashedCred.setHashIterations(cred.getHashIterations());
try {
hashedCred.setSalt(Base64.decode(cred.getSalt()));
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
hashedCred.setValue(cred.getHashedSaltedValue());
user.updateCredentialDirectly(hashedCred);
}
}
public static UserCredentialModel convertCredential(CredentialRepresentation cred) {
UserCredentialModel credential = new UserCredentialModel();
credential.setType(cred.getType());
credential.setValue(cred.getValue());
return credential;
}
// Role mappings
public static void createApplicationRoleMappings(ApplicationModel applicationModel, UserModel user, List<String> roleNames) {
if (user == null) {
throw new RuntimeException("User not found");
}
for (String roleName : roleNames) {
RoleModel role = applicationModel.getRole(roleName.trim());
if (role == null) {
role = applicationModel.addRole(roleName.trim());
}
user.grantRole(role);
}
}
}

View file

@ -5,7 +5,6 @@ import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.Constants;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.PasswordPolicy;
@ -16,10 +15,8 @@ import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.UserSessionProvider;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.OAuthClientManager;
import org.keycloak.services.managers.RealmManager;
import java.util.ArrayList;
@ -151,8 +148,9 @@ public class AdapterTest extends AbstractModelTest {
public void testOAuthClient() throws Exception {
test1CreateRealm();
OAuthClientModel oauth = new OAuthClientManager(realmModel).create("oauth-client");
oauth = realmModel.getOAuthClient("oauth-client");
RepresentationToModel.createOAuthClient(null, "oauth-client", realmModel);
OAuthClientModel oauth = realmModel.getOAuthClient("oauth-client");
Assert.assertNotNull(oauth);
}
@Test

View file

@ -7,6 +7,8 @@ import org.keycloak.models.ApplicationModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.services.managers.ApplicationManager;
@ -57,10 +59,10 @@ public class ApplicationModelTest extends AbstractModelTest {
@Test
public void json() {
ApplicationRepresentation representation = appManager.toRepresentation(application);
ApplicationRepresentation representation = ModelToRepresentation.toRepresentation(application);
RealmModel realm = realmManager.createRealm("copy");
ApplicationModel copy = appManager.createApplication(realm, representation);
ApplicationModel copy = RepresentationToModel.createApplication(realm, representation);
assertEquals(application, copy);
}

View file

@ -4,13 +4,10 @@ import org.junit.Assert;
import org.junit.Test;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
public class ModelTest extends AbstractModelTest {

View file

@ -37,7 +37,7 @@ public class LDAPKeycloakCredentialHandler extends LDAPPlainTextPasswordCredenti
@Override
public void setup(LDAPIdentityStore store) {
// TODO: Don't setup it here once PLIDM-508 is fixed
// TODO: Don't setup it here once PLINK-508 is fixed
if (store.getConfig().isActiveDirectory() || Boolean.getBoolean("keycloak.ldap.ad.skipUserAccountControlAfterPasswordUpdate")) {
String userAccountControlProp = System.getProperty("keycloak.ldap.ad.userAccountControlAfterPasswordUpdate");
this.userAccountControlAfterPasswordUpdate = userAccountControlProp!=null ? userAccountControlProp : "512";

View file

@ -12,6 +12,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.CredentialRepresentation;
import java.util.Arrays;
@ -58,7 +59,7 @@ public class ApplianceBootstrap {
realm.setAccessCodeLifespanUserAction(300);
realm.setSslNotRequired(true);
realm.setRegistrationAllowed(false);
manager.generateRealmKeys(realm);
KeycloakModelUtils.generateRealmKeys(realm);
realm.setAuthenticationProviders(Arrays.asList(AuthenticationProviderModel.DEFAULT_PROVIDER));
realm.setAuditListeners(Collections.singleton("jboss-logging"));

View file

@ -4,26 +4,15 @@ import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.annotate.JsonPropertyOrder;
import org.jboss.logging.Logger;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClaimMask;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionProvider;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.adapters.config.BaseRealmConfig;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.ScopeMappingRepresentation;
import org.keycloak.representations.idm.UserRoleMappingRepresentation;
import java.net.URI;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -41,112 +30,9 @@ public class ApplicationManager {
public ApplicationManager() {
}
/**
* Does not create scope or role mappings!
*
* @param realm
* @param resourceRep
* @return
*/
public ApplicationModel createApplication(RealmModel realm, ApplicationRepresentation resourceRep) {
logger.debug("************ CREATE APPLICATION: {0}" + resourceRep.getName());
ApplicationModel applicationModel = realm.addApplication(resourceRep.getName());
if (resourceRep.isEnabled() != null) applicationModel.setEnabled(resourceRep.isEnabled());
applicationModel.setManagementUrl(resourceRep.getAdminUrl());
if (resourceRep.isSurrogateAuthRequired() != null)
applicationModel.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
applicationModel.setBaseUrl(resourceRep.getBaseUrl());
if (resourceRep.isBearerOnly() != null) applicationModel.setBearerOnly(resourceRep.isBearerOnly());
if (resourceRep.isPublicClient() != null) applicationModel.setPublicClient(resourceRep.isPublicClient());
applicationModel.updateApplication();
if (resourceRep.getNotBefore() != null) {
applicationModel.setNotBefore(resourceRep.getNotBefore());
}
applicationModel.setSecret(resourceRep.getSecret());
if (applicationModel.getSecret() == null) {
generateSecret(applicationModel);
}
if (resourceRep.getRedirectUris() != null) {
for (String redirectUri : resourceRep.getRedirectUris()) {
applicationModel.addRedirectUri(redirectUri);
}
}
if (resourceRep.getWebOrigins() != null) {
for (String webOrigin : resourceRep.getWebOrigins()) {
logger.debugv("Application: {0} webOrigin: {1}", resourceRep.getName(), webOrigin);
applicationModel.addWebOrigin(webOrigin);
}
} else {
// add origins from redirect uris
if (resourceRep.getRedirectUris() != null) {
Set<String> origins = new HashSet<String>();
for (String redirectUri : resourceRep.getRedirectUris()) {
logger.info("add redirectUri to origin: " + redirectUri);
if (redirectUri.startsWith("http:")) {
URI uri = URI.create(redirectUri);
String origin = uri.getScheme() + "://" + uri.getHost();
if (uri.getPort() != -1) {
origin += ":" + uri.getPort();
}
logger.debugv("adding default application origin: {0}" , origin);
origins.add(origin);
}
}
if (origins.size() > 0) {
applicationModel.setWebOrigins(origins);
}
}
}
if (resourceRep.getDefaultRoles() != null) {
applicationModel.updateDefaultRoles(resourceRep.getDefaultRoles());
}
if (resourceRep.getClaims() != null) {
ClaimManager.setClaims(applicationModel, resourceRep.getClaims());
} else {
applicationModel.setAllowedClaimsMask(ClaimMask.USERNAME);
}
return applicationModel;
}
public void createRoleMappings(ApplicationModel applicationModel, UserModel user, List<String> roleNames) {
for (String roleName : roleNames) {
if (user == null) {
throw new RuntimeException("User not found");
}
RoleModel role = applicationModel.getRole(roleName.trim());
if (role == null) {
role = applicationModel.addRole(roleName.trim());
}
user.grantRole(role);
}
}
public void createScopeMappings(RealmModel realm, ApplicationModel applicationModel, List<ScopeMappingRepresentation> mappings) {
for (ScopeMappingRepresentation mapping : mappings) {
for (String roleString : mapping.getRoles()) {
RoleModel role = applicationModel.getRole(roleString.trim());
if (role == null) {
role = applicationModel.addRole(roleString.trim());
}
ClientModel client = realm.findClient(mapping.getClient());
client.addScopeMapping(role);
}
}
}
public ApplicationModel createApplication(RealmModel realm, String name) {
ApplicationModel app = realm.addApplication(name);
generateSecret(app);
KeycloakModelUtils.generateSecret(app);
return app;
}
@ -163,74 +49,6 @@ public class ApplicationManager {
}
}
public UserCredentialModel generateSecret(ApplicationModel app) {
UserCredentialModel secret = UserCredentialModel.generateSecret();
app.setSecret(secret.getValue());
return secret;
}
public void updateApplication(ApplicationRepresentation rep, ApplicationModel resource) {
if (rep.getName() != null) resource.setName(rep.getName());
if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
if (rep.getAdminUrl() != null) resource.setManagementUrl(rep.getAdminUrl());
if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
resource.updateApplication();
if (rep.getNotBefore() != null) {
resource.setNotBefore(rep.getNotBefore());
}
if (rep.getDefaultRoles() != null) {
resource.updateDefaultRoles(rep.getDefaultRoles());
}
List<String> redirectUris = rep.getRedirectUris();
if (redirectUris != null) {
resource.setRedirectUris(new HashSet<String>(redirectUris));
}
List<String> webOrigins = rep.getWebOrigins();
if (webOrigins != null) {
resource.setWebOrigins(new HashSet<String>(webOrigins));
}
if (rep.getClaims() != null) {
ClaimManager.setClaims(resource, rep.getClaims());
}
}
public ApplicationRepresentation toRepresentation(ApplicationModel applicationModel) {
ApplicationRepresentation rep = new ApplicationRepresentation();
rep.setId(applicationModel.getId());
rep.setName(applicationModel.getName());
rep.setEnabled(applicationModel.isEnabled());
rep.setAdminUrl(applicationModel.getManagementUrl());
rep.setPublicClient(applicationModel.isPublicClient());
rep.setBearerOnly(applicationModel.isBearerOnly());
rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
rep.setBaseUrl(applicationModel.getBaseUrl());
rep.setNotBefore(applicationModel.getNotBefore());
Set<String> redirectUris = applicationModel.getRedirectUris();
if (redirectUris != null) {
rep.setRedirectUris(new LinkedList<String>(redirectUris));
}
Set<String> webOrigins = applicationModel.getWebOrigins();
if (webOrigins != null) {
rep.setWebOrigins(new LinkedList<String>(webOrigins));
}
if (!applicationModel.getDefaultRoles().isEmpty()) {
rep.setDefaultRoles(applicationModel.getDefaultRoles().toArray(new String[0]));
}
return rep;
}
@JsonPropertyOrder({"realm", "realm-public-key", "bearer-only", "auth-server-url", "ssl-not-required",
"resource", "public-client", "credentials",
"use-resource-role-mappings"})

View file

@ -1,66 +0,0 @@
package org.keycloak.services.managers;
import org.keycloak.models.ClaimMask;
import org.keycloak.models.ClientModel;
import org.keycloak.representations.idm.ClaimRepresentation;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClaimManager {
public static void setClaims(ClientModel model, ClaimRepresentation rep) {
long mask = model.getAllowedClaimsMask();
if (rep.getAddress()) {
mask |= ClaimMask.ADDRESS;
} else {
mask &= ~ClaimMask.ADDRESS;
}
if (rep.getEmail()) {
mask |= ClaimMask.EMAIL;
} else {
mask &= ~ClaimMask.EMAIL;
}
if (rep.getGender()) {
mask |= ClaimMask.GENDER;
} else {
mask &= ~ClaimMask.GENDER;
}
if (rep.getLocale()) {
mask |= ClaimMask.LOCALE;
} else {
mask &= ~ClaimMask.LOCALE;
}
if (rep.getName()) {
mask |= ClaimMask.NAME;
} else {
mask &= ~ClaimMask.NAME;
}
if (rep.getPhone()) {
mask |= ClaimMask.PHONE;
} else {
mask &= ~ClaimMask.PHONE;
}
if (rep.getPicture()) {
mask |= ClaimMask.PICTURE;
} else {
mask &= ~ClaimMask.PICTURE;
}
if (rep.getProfile()) {
mask |= ClaimMask.PROFILE;
} else {
mask &= ~ClaimMask.PROFILE;
}
if (rep.getUsername()) {
mask |= ClaimMask.USERNAME;
} else {
mask &= ~ClaimMask.USERNAME;
}
if (rep.getWebsite()) {
mask |= ClaimMask.WEBSITE;
} else {
mask &= ~ClaimMask.WEBSITE;
}
model.setAllowedClaimsMask(mask);
}
}

View file

@ -2,22 +2,15 @@ package org.keycloak.services.managers;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.annotate.JsonPropertyOrder;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserSessionProvider;
import org.keycloak.representations.adapters.config.BaseRealmConfig;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.OAuthClientRepresentation;
import java.net.URI;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -26,35 +19,11 @@ import java.util.Set;
public class OAuthClientManager {
private RealmManager realmManager;
protected RealmModel realm;
public OAuthClientManager(RealmModel realm) {
this.realm = realm;
}
public OAuthClientManager(RealmManager realmManager) {
this.realmManager = realmManager;
}
public UserCredentialModel generateSecret(OAuthClientModel app) {
UserCredentialModel secret = UserCredentialModel.generateSecret();
app.setSecret(secret.getValue());
return secret;
}
public OAuthClientModel create(String name) {
OAuthClientModel model = realm.addOAuthClient(name);
generateSecret(model);
return model;
}
public OAuthClientModel create(OAuthClientRepresentation rep) {
OAuthClientModel model = create(rep.getName());
update(rep, model);
return model;
}
public boolean removeClient(RealmModel realm, OAuthClientModel client) {
if (realm.removeOAuthClient(client.getId())) {
UserSessionProvider sessions = realmManager.getSession().sessions();
@ -67,58 +36,6 @@ public class OAuthClientManager {
}
}
public void update(OAuthClientRepresentation rep, OAuthClientModel model) {
if (rep.getName() != null) model.setClientId(rep.getName());
if (rep.isEnabled() != null) model.setEnabled(rep.isEnabled());
if (rep.isPublicClient() != null) model.setPublicClient(rep.isPublicClient());
if (rep.isDirectGrantsOnly() != null) model.setDirectGrantsOnly(rep.isDirectGrantsOnly());
if (rep.getClaims() != null) {
ClaimManager.setClaims(model, rep.getClaims());
}
if (rep.getNotBefore() != null) {
model.setNotBefore(rep.getNotBefore());
}
if (rep.getSecret() != null) model.setSecret(rep.getSecret());
List<String> redirectUris = rep.getRedirectUris();
if (redirectUris != null) {
model.setRedirectUris(new HashSet<String>(redirectUris));
}
List<String> webOrigins = rep.getWebOrigins();
if (webOrigins != null) {
model.setWebOrigins(new HashSet<String>(webOrigins));
}
if (rep.getClaims() != null) {
ClaimManager.setClaims(model, rep.getClaims());
}
if (rep.getNotBefore() != null) {
model.setNotBefore(rep.getNotBefore());
}
}
public static OAuthClientRepresentation toRepresentation(OAuthClientModel model) {
OAuthClientRepresentation rep = new OAuthClientRepresentation();
rep.setId(model.getId());
rep.setName(model.getClientId());
rep.setEnabled(model.isEnabled());
rep.setPublicClient(model.isPublicClient());
rep.setDirectGrantsOnly(model.isDirectGrantsOnly());
Set<String> redirectUris = model.getRedirectUris();
if (redirectUris != null) {
rep.setRedirectUris(new LinkedList<String>(redirectUris));
}
Set<String> webOrigins = model.getWebOrigins();
if (webOrigins != null) {
rep.setWebOrigins(new LinkedList<String>(webOrigins));
}
rep.setNotBefore(model.getNotBefore());
return rep;
}
@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required",
"resource", "public-client", "credentials"})
public static class InstallationAdapterConfig extends BaseRealmConfig {

View file

@ -1,48 +1,25 @@
package org.keycloak.services.managers;
import org.jboss.logging.Logger;
import org.keycloak.exportimport.util.ExportImportUtils;
import org.keycloak.models.AccountRoles;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.AuthenticationProviderModel;
import org.keycloak.models.ClientModel;
import org.keycloak.Config;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelProvider;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserModel.RequiredAction;
import org.keycloak.models.UserSessionProvider;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.representations.idm.AuthenticationLinkRepresentation;
import org.keycloak.representations.idm.AuthenticationProviderRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.OAuthClientRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.RealmAuditRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.ScopeMappingRepresentation;
import org.keycloak.representations.idm.SocialLinkRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
/**
* Per request object
@ -128,10 +105,6 @@ public class RealmManager {
adminConsole.addScopeMapping(adminRole);
}
public String getMasterRealmAdminApplicationName(RealmModel realm) {
return realm.getName() + "-realm";
}
public String getRealmAdminApplicationName(RealmModel realm) {
return "realm-management";
}
@ -162,80 +135,6 @@ public class RealmManager {
return removed;
}
public void generateRealmKeys(RealmModel realm) {
KeyPair keyPair = null;
try {
keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
realm.setPrivateKey(keyPair.getPrivate());
realm.setPublicKey(keyPair.getPublic());
}
public void updateRealm(RealmRepresentation rep, RealmModel realm) {
if (rep.getRealm() != null) {
realm.setName(rep.getRealm());
}
if (rep.isEnabled() != null) realm.setEnabled(rep.isEnabled());
if (rep.isSocial() != null) realm.setSocial(rep.isSocial());
if (rep.isBruteForceProtected() != null) realm.setBruteForceProtected(rep.isBruteForceProtected());
if (rep.getMaxFailureWaitSeconds() != null) realm.setMaxFailureWaitSeconds(rep.getMaxFailureWaitSeconds());
if (rep.getMinimumQuickLoginWaitSeconds() != null) realm.setMinimumQuickLoginWaitSeconds(rep.getMinimumQuickLoginWaitSeconds());
if (rep.getWaitIncrementSeconds() != null) realm.setWaitIncrementSeconds(rep.getWaitIncrementSeconds());
if (rep.getQuickLoginCheckMilliSeconds() != null) realm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
if (rep.getMaxDeltaTimeSeconds() != null) realm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
if (rep.getFailureFactor() != null) realm.setFailureFactor(rep.getFailureFactor());
if (rep.isPasswordCredentialGrantAllowed() != null) realm.setPasswordCredentialGrantAllowed(rep.isPasswordCredentialGrantAllowed());
if (rep.isRegistrationAllowed() != null) realm.setRegistrationAllowed(rep.isRegistrationAllowed());
if (rep.isRememberMe() != null) realm.setRememberMe(rep.isRememberMe());
if (rep.isVerifyEmail() != null) realm.setVerifyEmail(rep.isVerifyEmail());
if (rep.isResetPasswordAllowed() != null) realm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
if (rep.isUpdateProfileOnInitialSocialLogin() != null)
realm.setUpdateProfileOnInitialSocialLogin(rep.isUpdateProfileOnInitialSocialLogin());
if (rep.isSslNotRequired() != null) realm.setSslNotRequired((rep.isSslNotRequired()));
if (rep.getAccessCodeLifespan() != null) realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
if (rep.getAccessCodeLifespanUserAction() != null)
realm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
if (rep.getNotBefore() != null) realm.setNotBefore(rep.getNotBefore());
if (rep.getAccessTokenLifespan() != null) realm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
if (rep.getSsoSessionIdleTimeout() != null) realm.setSsoSessionIdleTimeout(rep.getSsoSessionIdleTimeout());
if (rep.getSsoSessionMaxLifespan() != null) realm.setSsoSessionMaxLifespan(rep.getSsoSessionMaxLifespan());
if (rep.getRequiredCredentials() != null) {
realm.updateRequiredCredentials(rep.getRequiredCredentials());
}
if (rep.getLoginTheme() != null) realm.setLoginTheme(rep.getLoginTheme());
if (rep.getAccountTheme() != null) realm.setAccountTheme(rep.getAccountTheme());
if (rep.getAdminTheme() != null) realm.setAdminTheme(rep.getAdminTheme());
if (rep.getEmailTheme() != null) realm.setEmailTheme(rep.getEmailTheme());
if (rep.getPasswordPolicy() != null) realm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
if (rep.getDefaultRoles() != null) {
realm.updateDefaultRoles(rep.getDefaultRoles().toArray(new String[rep.getDefaultRoles().size()]));
}
if (rep.getSmtpServer() != null) {
realm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
}
if (rep.getSocialProviders() != null) {
realm.setSocialConfig(new HashMap(rep.getSocialProviders()));
}
if (rep.getLdapServer() != null) {
realm.setLdapServerConfig(new HashMap(rep.getLdapServer()));
}
if (rep.getAuthenticationProviders() != null) {
List<AuthenticationProviderModel> authProviderModels = convertAuthenticationProviders(rep.getAuthenticationProviders());
realm.setAuthenticationProviders(authProviderModels);
}
if ("GENERATE".equals(rep.getPublicKey())) {
generateRealmKeys(realm);
}
}
public void updateRealmAudit(RealmAuditRepresentation rep, RealmModel realm) {
realm.setAuditEnabled(rep.isAuditEnabled());
realm.setAuditExpiration(rep.getAuditExpiration() != null ? rep.getAuditExpiration() : 0);
@ -262,7 +161,7 @@ public class RealmManager {
ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
ApplicationModel realmAdminApp = applicationManager.createApplication(adminRealm, getMasterRealmAdminApplicationName(realm));
ApplicationModel realmAdminApp = applicationManager.createApplication(adminRealm, ExportImportUtils.getMasterRealmAdminApplicationName(realm));
realmAdminApp.setBearerOnly(true);
realm.setMasterAdminApp(realmAdminApp);
@ -319,273 +218,7 @@ public class RealmManager {
}
public void importRealm(RealmRepresentation rep, RealmModel newRealm) {
newRealm.setName(rep.getRealm());
if (rep.isEnabled() != null) newRealm.setEnabled(rep.isEnabled());
if (rep.isSocial() != null) newRealm.setSocial(rep.isSocial());
if (rep.isBruteForceProtected() != null) newRealm.setBruteForceProtected(rep.isBruteForceProtected());
if (rep.getMaxFailureWaitSeconds() != null) newRealm.setMaxFailureWaitSeconds(rep.getMaxFailureWaitSeconds());
if (rep.getMinimumQuickLoginWaitSeconds() != null) newRealm.setMinimumQuickLoginWaitSeconds(rep.getMinimumQuickLoginWaitSeconds());
if (rep.getWaitIncrementSeconds() != null) newRealm.setWaitIncrementSeconds(rep.getWaitIncrementSeconds());
if (rep.getQuickLoginCheckMilliSeconds() != null) newRealm.setQuickLoginCheckMilliSeconds(rep.getQuickLoginCheckMilliSeconds());
if (rep.getMaxDeltaTimeSeconds() != null) newRealm.setMaxDeltaTimeSeconds(rep.getMaxDeltaTimeSeconds());
if (rep.getFailureFactor() != null) newRealm.setFailureFactor(rep.getFailureFactor());
if (rep.getNotBefore() != null) newRealm.setNotBefore(rep.getNotBefore());
if (rep.getAccessTokenLifespan() != null) newRealm.setAccessTokenLifespan(rep.getAccessTokenLifespan());
else newRealm.setAccessTokenLifespan(300);
if (rep.getSsoSessionIdleTimeout() != null) newRealm.setSsoSessionIdleTimeout(rep.getSsoSessionIdleTimeout());
else newRealm.setSsoSessionIdleTimeout(600);
if (rep.getSsoSessionMaxLifespan() != null) newRealm.setSsoSessionMaxLifespan(rep.getSsoSessionMaxLifespan());
else newRealm.setSsoSessionMaxLifespan(36000);
if (rep.getAccessCodeLifespan() != null) newRealm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
else newRealm.setAccessCodeLifespan(60);
if (rep.getAccessCodeLifespanUserAction() != null)
newRealm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
else newRealm.setAccessCodeLifespanUserAction(300);
if (rep.isSslNotRequired() != null) newRealm.setSslNotRequired(rep.isSslNotRequired());
if (rep.isPasswordCredentialGrantAllowed() != null) newRealm.setPasswordCredentialGrantAllowed(rep.isPasswordCredentialGrantAllowed());
if (rep.isRegistrationAllowed() != null) newRealm.setRegistrationAllowed(rep.isRegistrationAllowed());
if (rep.isRememberMe() != null) newRealm.setRememberMe(rep.isRememberMe());
if (rep.isVerifyEmail() != null) newRealm.setVerifyEmail(rep.isVerifyEmail());
if (rep.isResetPasswordAllowed() != null) newRealm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
if (rep.isUpdateProfileOnInitialSocialLogin() != null)
newRealm.setUpdateProfileOnInitialSocialLogin(rep.isUpdateProfileOnInitialSocialLogin());
if (rep.getPrivateKey() == null || rep.getPublicKey() == null) {
generateRealmKeys(newRealm);
} else {
newRealm.setPrivateKeyPem(rep.getPrivateKey());
newRealm.setPublicKeyPem(rep.getPublicKey());
}
if (rep.getLoginTheme() != null) newRealm.setLoginTheme(rep.getLoginTheme());
if (rep.getAccountTheme() != null) newRealm.setAccountTheme(rep.getAccountTheme());
if (rep.getAdminTheme() != null) newRealm.setAdminTheme(rep.getAdminTheme());
if (rep.getEmailTheme() != null) newRealm.setEmailTheme(rep.getEmailTheme());
if (rep.getRequiredCredentials() != null) {
for (String requiredCred : rep.getRequiredCredentials()) {
addRequiredCredential(newRealm, requiredCred);
}
} else {
addRequiredCredential(newRealm, CredentialRepresentation.PASSWORD);
}
if (rep.getPasswordPolicy() != null) newRealm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
if (rep.getApplications() != null) {
Map<String, ApplicationModel> appMap = createApplications(rep, newRealm);
}
if (rep.getRoles() != null) {
if (rep.getRoles().getRealm() != null) { // realm roles
for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
createRole(newRealm, roleRep);
}
}
if (rep.getRoles().getApplication() != null) {
for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getApplication().entrySet()) {
ApplicationModel app = newRealm.getApplicationByName(entry.getKey());
if (app == null) {
throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
}
for (RoleRepresentation roleRep : entry.getValue()) {
RoleModel role = app.addRole(roleRep.getName());
role.setDescription(roleRep.getDescription());
}
}
}
// now that all roles are created, re-iterate and set up composites
if (rep.getRoles().getRealm() != null) { // realm roles
for (RoleRepresentation roleRep : rep.getRoles().getRealm()) {
RoleModel role = newRealm.getRole(roleRep.getName());
addComposites(role, roleRep, newRealm);
}
}
if (rep.getRoles().getApplication() != null) {
for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getApplication().entrySet()) {
ApplicationModel app = newRealm.getApplicationByName(entry.getKey());
if (app == null) {
throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
}
for (RoleRepresentation roleRep : entry.getValue()) {
RoleModel role = app.getRole(roleRep.getName());
addComposites(role, roleRep, newRealm);
}
}
}
}
if (rep.getDefaultRoles() != null) {
for (String roleString : rep.getDefaultRoles()) {
newRealm.addDefaultRole(roleString.trim());
}
}
if (rep.getOauthClients() != null) {
createOAuthClients(rep, newRealm);
}
// Now that all possible roles and applications are created, create scope mappings
Map<String, ApplicationModel> appMap = newRealm.getApplicationNameMap();
if (rep.getApplicationScopeMappings() != null) {
ApplicationManager manager = new ApplicationManager(this);
for (Map.Entry<String, List<ScopeMappingRepresentation>> entry : rep.getApplicationScopeMappings().entrySet()) {
ApplicationModel app = appMap.get(entry.getKey());
if (app == null) {
throw new RuntimeException("Unable to find application role mappings for app: " + entry.getKey());
}
manager.createScopeMappings(newRealm, app, entry.getValue());
}
}
if (rep.getScopeMappings() != null) {
for (ScopeMappingRepresentation scope : rep.getScopeMappings()) {
for (String roleString : scope.getRoles()) {
RoleModel role = newRealm.getRole(roleString.trim());
if (role == null) {
role = newRealm.addRole(roleString.trim());
}
ClientModel client = newRealm.findClient(scope.getClient());
client.addScopeMapping(role);
}
}
}
if (rep.getSmtpServer() != null) {
newRealm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
}
if (rep.getSocialProviders() != null) {
newRealm.setSocialConfig(new HashMap(rep.getSocialProviders()));
}
if (rep.getLdapServer() != null) {
newRealm.setLdapServerConfig(new HashMap(rep.getLdapServer()));
}
if (rep.getAuthenticationProviders() != null) {
List<AuthenticationProviderModel> authProviderModels = convertAuthenticationProviders(rep.getAuthenticationProviders());
newRealm.setAuthenticationProviders(authProviderModels);
} else {
List<AuthenticationProviderModel> authProviderModels = Arrays.asList(AuthenticationProviderModel.DEFAULT_PROVIDER);
newRealm.setAuthenticationProviders(authProviderModels);
}
// create users and their role mappings and social mappings
if (rep.getUsers() != null) {
for (UserRepresentation userRep : rep.getUsers()) {
UserModel user = createUser(newRealm, userRep, appMap);
}
}
}
public void addComposites(RoleModel role, RoleRepresentation roleRep, RealmModel realm) {
if (roleRep.getComposites() == null) return;
if (roleRep.getComposites().getRealm() != null) {
for (String roleStr : roleRep.getComposites().getRealm()) {
RoleModel realmRole = realm.getRole(roleStr);
if (realmRole == null) throw new RuntimeException("Unable to find composite realm role: " + roleStr);
role.addCompositeRole(realmRole);
}
}
if (roleRep.getComposites().getApplication() != null) {
for (Map.Entry<String, List<String>> entry : roleRep.getComposites().getApplication().entrySet()) {
ApplicationModel app = realm.getApplicationByName(entry.getKey());
if (app == null) {
throw new RuntimeException("App doesn't exist in role definitions: " + roleRep.getName());
}
for (String roleStr : entry.getValue()) {
RoleModel appRole = app.getRole(roleStr);
if (appRole == null) throw new RuntimeException("Unable to find composite app role: " + roleStr);
role.addCompositeRole(appRole);
}
}
}
}
public void createRole(RealmModel newRealm, RoleRepresentation roleRep) {
RoleModel role = newRealm.addRole(roleRep.getName());
if (roleRep.getDescription() != null) role.setDescription(roleRep.getDescription());
}
public void createRole(RealmModel newRealm, ApplicationModel app, RoleRepresentation roleRep) {
RoleModel role = app.addRole(roleRep.getName());
if (roleRep.getDescription() != null) role.setDescription(roleRep.getDescription());
}
public UserModel createUser(RealmModel newRealm, UserRepresentation userRep, Map<String, ApplicationModel> appMap) {
UserModel user = newRealm.addUser(userRep.getId(), userRep.getUsername(), false);
user.setEnabled(userRep.isEnabled());
user.setEmail(userRep.getEmail());
user.setFirstName(userRep.getFirstName());
user.setLastName(userRep.getLastName());
if (userRep.getAttributes() != null) {
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
user.setAttribute(entry.getKey(), entry.getValue());
}
}
if (userRep.getRequiredActions() != null) {
for (String requiredAction : userRep.getRequiredActions()) {
user.addRequiredAction(RequiredAction.valueOf(requiredAction));
}
}
if (userRep.getCredentials() != null) {
for (CredentialRepresentation cred : userRep.getCredentials()) {
UserCredentialModel credential = fromRepresentation(cred);
user.updateCredential(credential);
}
}
if (userRep.getAuthenticationLink() != null) {
AuthenticationLinkRepresentation link = userRep.getAuthenticationLink();
AuthenticationLinkModel authLink = new AuthenticationLinkModel(link.getAuthProvider(), link.getAuthUserId());
user.setAuthenticationLink(authLink);
}
if (userRep.getSocialLinks() != null) {
for (SocialLinkRepresentation socialLink : userRep.getSocialLinks()) {
SocialLinkModel mappingModel = new SocialLinkModel(socialLink.getSocialProvider(), socialLink.getSocialUserId(), socialLink.getSocialUsername());
newRealm.addSocialLink(user, mappingModel);
}
}
if (userRep.getRealmRoles() != null) {
for (String roleString : userRep.getRealmRoles()) {
RoleModel role = newRealm.getRole(roleString.trim());
if (role == null) {
role = newRealm.addRole(roleString.trim());
}
user.grantRole(role);
}
}
if (userRep.getApplicationRoles() != null) {
ApplicationManager manager = new ApplicationManager(this);
for (Map.Entry<String, List<String>> entry : userRep.getApplicationRoles().entrySet()) {
ApplicationModel app = appMap.get(entry.getKey());
if (app == null) {
throw new RuntimeException("Unable to find application role mappings for app: " + entry.getKey());
}
manager.createRoleMappings(app, user, entry.getValue());
}
}
return user;
}
public static UserCredentialModel fromRepresentation(CredentialRepresentation cred) {
UserCredentialModel credential = new UserCredentialModel();
credential.setType(cred.getType());
credential.setValue(cred.getValue());
return credential;
RepresentationToModel.importRealm(rep, newRealm);
}
/**
@ -606,37 +239,4 @@ public class RealmManager {
return realmModel.searchForUser(searchString.trim());
}
public void addRequiredCredential(RealmModel newRealm, String requiredCred) {
newRealm.addRequiredCredential(requiredCred);
}
protected Map<String, ApplicationModel> createApplications(RealmRepresentation rep, RealmModel realm) {
Map<String, ApplicationModel> appMap = new HashMap<String, ApplicationModel>();
ApplicationManager manager = new ApplicationManager(this);
for (ApplicationRepresentation resourceRep : rep.getApplications()) {
ApplicationModel app = manager.createApplication(realm, resourceRep);
appMap.put(app.getName(), app);
}
return appMap;
}
protected void createOAuthClients(RealmRepresentation realmRep, RealmModel realm) {
OAuthClientManager manager = new OAuthClientManager(realm);
for (OAuthClientRepresentation rep : realmRep.getOauthClients()) {
OAuthClientModel app = manager.create(rep);
}
}
protected List<AuthenticationProviderModel> convertAuthenticationProviders(List<AuthenticationProviderRepresentation> authenticationProviders) {
List<AuthenticationProviderModel> result = new ArrayList<AuthenticationProviderModel>();
for (AuthenticationProviderRepresentation representation : authenticationProviders) {
AuthenticationProviderModel model = new AuthenticationProviderModel(representation.getProviderName(),
representation.isPasswordUpdateSupported(), representation.getConfig());
result.add(model);
}
return result;
}
}

View file

@ -53,7 +53,7 @@ import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.OAuthRedirect;

View file

@ -7,7 +7,7 @@ import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.Config;
import org.keycloak.SkeletonKeyContextResolver;
import org.keycloak.exportimport.ExportImportProvider;
import org.keycloak.exportimport.ExportImportManager;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
@ -24,7 +24,6 @@ import org.keycloak.services.scheduled.ScheduledTaskRunner;
import org.keycloak.services.util.JsonConfigProvider;
import org.keycloak.timer.TimerProvider;
import org.keycloak.util.JsonSerialization;
import org.keycloak.util.ProviderLoader;
import javax.servlet.ServletContext;
import javax.ws.rs.core.Application;
@ -38,7 +37,6 @@ import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;
@ -81,7 +79,7 @@ public class KeycloakApplication extends Application {
classes.add(JsResource.class);
classes.add(WelcomeResource.class);
checkExportImportProvider();
new ExportImportManager().checkExportImport(this.sessionFactory);
setupDefaultRealm(context.getContextPath());
@ -235,16 +233,4 @@ public class KeycloakApplication extends Application {
}
}
protected void checkExportImportProvider() {
Iterator<ExportImportProvider> providers = ProviderLoader.load(ExportImportProvider.class).iterator();
if (providers.hasNext()) {
ExportImportProvider exportImport = providers.next();
exportImport.checkExportImport(sessionFactory);
} else {
log.warn("No ExportImportProvider found!");
}
}
}

View file

@ -10,13 +10,15 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.adapters.action.SessionStats;
import org.keycloak.representations.adapters.action.UserStats;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.UserSessionRepresentation;
import org.keycloak.services.managers.ApplicationManager;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.resources.KeycloakApplication;
@ -97,7 +99,7 @@ public class ApplicationResource {
ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
try {
applicationManager.updateApplication(rep, application);
RepresentationToModel.updateApplication(rep, application);
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Application " + rep.getName() + " already exists");
@ -116,8 +118,7 @@ public class ApplicationResource {
public ApplicationRepresentation getApplication() {
auth.requireView();
ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
return applicationManager.toRepresentation(application);
return ModelToRepresentation.toRepresentation(application);
}
@ -184,7 +185,7 @@ public class ApplicationResource {
auth.requireManage();
logger.debug("regenerateSecret");
UserCredentialModel cred = new ApplicationManager().generateSecret(application);
UserCredentialModel cred = KeycloakModelUtils.generateSecret(application);
CredentialRepresentation rep = ModelToRepresentation.toRepresentation(cred);
return rep;
}

View file

@ -8,6 +8,8 @@ import org.keycloak.models.ApplicationModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.services.managers.ApplicationManager;
import org.keycloak.services.managers.RealmManager;
@ -60,12 +62,11 @@ public class ApplicationsResource {
List<ApplicationRepresentation> rep = new ArrayList<ApplicationRepresentation>();
List<ApplicationModel> applicationModels = realm.getApplications();
ApplicationManager resourceManager = new ApplicationManager(new RealmManager(session));
boolean view = auth.hasView();
for (ApplicationModel applicationModel : applicationModels) {
if (view) {
rep.add(resourceManager.toRepresentation(applicationModel));
rep.add(ModelToRepresentation.toRepresentation(applicationModel));
} else {
ApplicationRepresentation app = new ApplicationRepresentation();
app.setName(applicationModel.getName());
@ -87,9 +88,8 @@ public class ApplicationsResource {
public Response createApplication(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) {
auth.requireManage();
ApplicationManager resourceManager = new ApplicationManager(new RealmManager(session));
try {
ApplicationModel applicationModel = resourceManager.createApplication(realm, rep);
ApplicationModel applicationModel = RepresentationToModel.createApplication(realm, rep);
return Response.created(uriInfo.getAbsolutePathBuilder().path(applicationModel.getName()).build()).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Application " + rep.getName() + " already exists");

View file

@ -1,9 +1,9 @@
package org.keycloak.services.resources.admin;
import org.keycloak.models.ClientModel;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.ClaimRepresentation;
import org.keycloak.services.managers.ClaimManager;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@ -47,6 +47,6 @@ public class ClaimResource {
@Consumes(MediaType.APPLICATION_JSON)
public void updateClaims(ClaimRepresentation rep) {
auth.requireManage();
ClaimManager.setClaims(model, rep);
RepresentationToModel.setClaims(model, rep);
}
}

View file

@ -8,9 +8,10 @@ import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.OAuthClientRepresentation;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.services.managers.OAuthClientManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication;
@ -82,9 +83,8 @@ public class OAuthClientResource {
public Response update(final OAuthClientRepresentation rep) {
auth.requireManage();
OAuthClientManager manager = new OAuthClientManager(realm);
try {
manager.update(rep, oauthClient);
RepresentationToModel.updateOAuthClient(rep, oauthClient);
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Client " + rep.getName() + " already exists");
@ -102,7 +102,7 @@ public class OAuthClientResource {
public OAuthClientRepresentation getOAuthClient() {
auth.requireView();
return OAuthClientManager.toRepresentation(oauthClient);
return ModelToRepresentation.toRepresentation(oauthClient);
}
/**
@ -118,7 +118,7 @@ public class OAuthClientResource {
public String getInstallation() throws IOException {
auth.requireView();
OAuthClientManager manager = new OAuthClientManager(realm);
OAuthClientManager manager = new OAuthClientManager();
Object rep = manager.toInstallationRepresentation(realm, oauthClient, getApplication().getBaseUri(uriInfo));
// TODO Temporary solution to pretty-print

View file

@ -8,6 +8,8 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.OAuthClientRepresentation;
import org.keycloak.services.managers.OAuthClientManager;
import org.keycloak.services.resources.flows.Flows;
@ -65,7 +67,7 @@ public class OAuthClientsResource {
boolean view = auth.hasView();
for (OAuthClientModel oauth : oauthModels) {
if (view) {
rep.add(OAuthClientManager.toRepresentation(oauth));
rep.add(ModelToRepresentation.toRepresentation(oauth));
} else {
OAuthClientRepresentation client = new OAuthClientRepresentation();
client.setName(oauth.getClientId());
@ -87,9 +89,8 @@ public class OAuthClientsResource {
public Response createOAuthClient(final @Context UriInfo uriInfo, final OAuthClientRepresentation rep) {
auth.requireManage();
OAuthClientManager resourceManager = new OAuthClientManager(realm);
try {
OAuthClientModel oauth = resourceManager.create(rep);
OAuthClientModel oauth = RepresentationToModel.createOAuthClient(rep, realm);
return Response.created(uriInfo.getAbsolutePathBuilder().path(oauth.getId()).build()).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Client " + rep.getName() + " already exists");

View file

@ -13,11 +13,12 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.adapters.action.SessionStats;
import org.keycloak.representations.idm.RealmAuditRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.LDAPConnectionTestManager;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.managers.TokenManager;
@ -138,7 +139,7 @@ public class RealmAdminResource {
logger.debug("updating realm: " + realm.getName());
try {
new RealmManager(session).updateRealm(rep, realm);
RepresentationToModel.updateRealm(rep, realm);
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Realm " + rep.getRealm() + " already exists");

View file

@ -14,7 +14,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.resources.KeycloakApplication;

View file

@ -2,13 +2,12 @@ package org.keycloak.services.resources.admin;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
import org.keycloak.models.Constants;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.services.resources.flows.Flows;
import javax.ws.rs.Consumes;

View file

@ -5,7 +5,7 @@ import org.keycloak.models.ApplicationModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import java.util.Collections;
import java.util.HashSet;

View file

@ -7,12 +7,10 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
import org.keycloak.representations.idm.MappingsRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.models.utils.ModelToRepresentation;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;

View file

@ -17,6 +17,7 @@ import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.adapters.action.UserStats;
import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
@ -26,7 +27,7 @@ import org.keycloak.representations.idm.SocialLinkRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.idm.UserSessionRepresentation;
import org.keycloak.services.managers.AccessCodeEntry;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.managers.TokenManager;
@ -760,7 +761,7 @@ public class UsersResource {
throw new BadRequestException("No password provided");
}
UserCredentialModel cred = RealmManager.fromRepresentation(pass);
UserCredentialModel cred = RepresentationToModel.convertCredential(pass);
user.updateCredential(cred);
user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
}

View file

@ -289,7 +289,17 @@
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-export-import-impl</artifactId>
<artifactId>keycloak-export-import-dir</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-export-import-single-file</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-export-import-zip</artifactId>
<version>${project.version}</version>
</dependency>

View file

@ -33,6 +33,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.AccessToken;
import org.keycloak.services.managers.ApplicationManager;
import org.keycloak.services.managers.RealmManager;
@ -59,7 +60,7 @@ public class CompositeRoleTest {
@Override
protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
RealmModel realm = manager.createRealm("Test");
manager.generateRealmKeys(realm);
KeycloakModelUtils.generateRealmKeys(realm);
realmPublicKey = realm.getPublicKey();
realm.setSsoSessionIdleTimeout(3000);
realm.setAccessTokenLifespan(10000);

View file

@ -0,0 +1,269 @@
package org.keycloak.testsuite.exportimport;
import java.io.File;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.Config;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.dir.DirExportProvider;
import org.keycloak.exportimport.dir.DirExportProviderFactory;
import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory;
import org.keycloak.exportimport.zip.ZipExportProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelProvider;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testutils.KeycloakServer;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ExportImportTest {
@ClassRule
public static KeycloakRule keycloakRule = new KeycloakRule( new KeycloakRule.KeycloakSetup() {
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
addUser(appRealm, "user1", "password");
addUser(appRealm, "user2", "password");
addUser(appRealm, "user3", "password");
addUser(adminstrationRealm, "admin2", "admin2");
}
});
@Test
public void testDirFullExportImport() throws Throwable {
ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
String targetDirPath = getExportImportTestDirectory() + File.separator + "dirExport";
DirExportProvider.recursiveDeleteDir(new File(targetDirPath));
ExportImportConfig.setDir(targetDirPath);
ExportImportConfig.setUsersPerFile(ExportImportConfig.DEFAULT_USERS_PER_FILE);
testFullExportImport();
// There should be 4 files in target directory (2 realm, 2 user)
Assert.assertEquals(4, new File(targetDirPath).listFiles().length);
}
@Test
public void testDirRealmExportImport() throws Throwable {
ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
String targetDirPath = getExportImportTestDirectory() + File.separator + "dirRealmExport";
DirExportProvider.recursiveDeleteDir(new File(targetDirPath));
ExportImportConfig.setDir(targetDirPath);
ExportImportConfig.setUsersPerFile(3);
testRealmExportImport();
// There should be 3 files in target directory (1 realm, 2 user)
Assert.assertEquals(3, new File(targetDirPath).listFiles().length);
}
@Test
public void testSingleFileFullExportImport() throws Throwable {
ExportImportConfig.setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
String targetFilePath = getExportImportTestDirectory() + File.separator + "singleFile-full.json";
ExportImportConfig.setFile(targetFilePath);
testFullExportImport();
}
@Test
public void testSingleFileRealmExportImport() throws Throwable {
ExportImportConfig.setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
String targetFilePath = getExportImportTestDirectory() + File.separator + "singleFile-realm.json";
ExportImportConfig.setFile(targetFilePath);
testRealmExportImport();
}
@Test
public void testZipFullExportImport() throws Throwable {
ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
String zipFilePath = getExportImportTestDirectory() + File.separator + "export-full.zip";
new File(zipFilePath).delete();
ExportImportConfig.setZipFile(zipFilePath);
ExportImportConfig.setZipPassword("encPassword");
ExportImportConfig.setUsersPerFile(ExportImportConfig.DEFAULT_USERS_PER_FILE);
testFullExportImport();
}
@Test
public void testZipRealmExportImport() throws Throwable {
ExportImportConfig.setProvider(ZipExportProviderFactory.PROVIDER_ID);
String zipFilePath = getExportImportTestDirectory() + File.separator + "export-realm.zip";
new File(zipFilePath).delete();
ExportImportConfig.setZipFile(zipFilePath);
ExportImportConfig.setZipPassword("encPassword");
ExportImportConfig.setUsersPerFile(3);
testRealmExportImport();
}
private void testFullExportImport() {
ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
ExportImportConfig.setRealmName(null);
// Restart server, which triggers export
keycloakRule.restartServer();
// Delete some realm (and some data in admin realm)
KeycloakSession session = keycloakRule.startSession();
try {
ModelProvider model = session.getModel();
model.removeRealm(model.getRealmByName("test").getId());
Assert.assertEquals(1, model.getRealms().size());
RealmModel master = model.getRealmByName(Config.getAdminRealm());
master.removeUser("admin2");
assertNotAuthenticated(model, Config.getAdminRealm(), "admin2", "admin2");
assertNotAuthenticated(model, "test", "test-user@localhost", "password");
assertNotAuthenticated(model, "test", "user1", "password");
assertNotAuthenticated(model, "test", "user2", "password");
assertNotAuthenticated(model, "test", "user3", "password");
} finally {
keycloakRule.stopSession(session, true);
}
// Configure import
ExportImportConfig.setAction(ExportImportConfig.ACTION_IMPORT);
// Restart server, which triggers import
keycloakRule.restartServer();
// Ensure data are imported back
session = keycloakRule.startSession();
try {
ModelProvider model = session.getModel();
Assert.assertEquals(2, model.getRealms().size());
assertAuthenticated(model, Config.getAdminRealm(), "admin2", "admin2");
assertAuthenticated(model, "test", "test-user@localhost", "password");
assertAuthenticated(model, "test", "user1", "password");
assertAuthenticated(model, "test", "user2", "password");
assertAuthenticated(model, "test", "user3", "password");
} finally {
keycloakRule.stopSession(session, true);
}
}
private void testRealmExportImport() {
ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
ExportImportConfig.setRealmName("test");
// Restart server, which triggers export
keycloakRule.restartServer();
// Delete some realm (and some data in admin realm)
KeycloakSession session = keycloakRule.startSession();
try {
ModelProvider model = session.getModel();
model.removeRealm(model.getRealmByName("test").getId());
Assert.assertEquals(1, model.getRealms().size());
RealmModel master = model.getRealmByName(Config.getAdminRealm());
master.removeUser("admin2");
assertNotAuthenticated(model, Config.getAdminRealm(), "admin2", "admin2");
assertNotAuthenticated(model, "test", "test-user@localhost", "password");
assertNotAuthenticated(model, "test", "user1", "password");
assertNotAuthenticated(model, "test", "user2", "password");
assertNotAuthenticated(model, "test", "user3", "password");
} finally {
keycloakRule.stopSession(session, true);
}
// Configure import
ExportImportConfig.setAction(ExportImportConfig.ACTION_IMPORT);
// Restart server, which triggers import
keycloakRule.restartServer();
// Ensure data are imported back, but just for "test" realm
session = keycloakRule.startSession();
try {
ModelProvider model = session.getModel();
Assert.assertEquals(2, model.getRealms().size());
assertNotAuthenticated(model, Config.getAdminRealm(), "admin2", "admin2");
assertAuthenticated(model, "test", "test-user@localhost", "password");
assertAuthenticated(model, "test", "user1", "password");
assertAuthenticated(model, "test", "user2", "password");
assertAuthenticated(model, "test", "user3", "password");
addUser(model.getRealmByName(Config.getAdminRealm()), "admin2", "admin2");
} finally {
keycloakRule.stopSession(session, true);
}
}
private void assertAuthenticated(ModelProvider model, String realmName, String username, String password) {
RealmModel realm = model.getRealmByName(realmName);
if (realm == null) {
Assert.fail("realm " + realmName + " not found");
}
UserModel user = realm.getUser(username);
if (user == null) {
Assert.fail("user " + username + " not found");
}
Assert.assertTrue(realm.validatePassword(user, password));
}
private void assertNotAuthenticated(ModelProvider model, String realmName, String username, String password) {
RealmModel realm = model.getRealmByName(realmName);
if (realm == null) {
return;
}
UserModel user = realm.getUser(username);
if (user == null) {
return;
}
Assert.assertFalse(realm.validatePassword(user, password));
}
private static void addUser(RealmModel appRealm, String username, String password) {
UserModel user = appRealm.addUser(username);
user.setEmail(username + "@test.com");
user.setEnabled(true);
UserCredentialModel creds = new UserCredentialModel();
creds.setType(CredentialRepresentation.PASSWORD);
creds.setValue(password);
user.updateCredential(creds);
}
private String getExportImportTestDirectory() {
String dirPath = null;
String relativeDirExportImportPath = "testsuite" + File.separator + "integration" + File.separator + "target" + File.separator + "export-import";
if (System.getProperties().containsKey("maven.home")) {
dirPath = System.getProperty("user.dir").replaceFirst("testsuite.integration.*", relativeDirExportImportPath);
} else {
for (String c : System.getProperty("java.class.path").split(File.pathSeparator)) {
if (c.contains(File.separator + "testsuite" + File.separator + "integration")) {
dirPath = c.replaceFirst("testsuite.integration.*", relativeDirExportImportPath);
}
}
}
String absolutePath = new File(dirPath).getAbsolutePath();
return absolutePath;
}
}

View file

@ -12,7 +12,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.ModelToRepresentation;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.testutils.KeycloakServer;
import org.keycloak.util.JsonSerialization;
@ -146,4 +146,13 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
}
session.close();
}
public void restartServer() {
try {
server.stop();
server.start();
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
}

View file

@ -1,7 +1,7 @@
package org.keycloak.test.tools;
import org.keycloak.exportimport.ExportImportConfig;
import org.keycloak.exportimport.ExportImportProvider;
import org.keycloak.exportimport.ExportProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
@ -231,10 +231,10 @@ public class PerfTools {
ExportImportConfig.setProvider("dir");
ExportImportConfig.setDir(dir);
Iterator<ExportImportProvider> providers = ProviderLoader.load(ExportImportProvider.class).iterator();
Iterator<ExportProvider> providers = ProviderLoader.load(ExportProvider.class).iterator();
if (providers.hasNext()) {
ExportImportProvider exportImport = providers.next();
ExportProvider exportImport = providers.next();
exportImport.checkExportImport(sessionFactory);
} else {
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);