use of org.keycloak.services.managers.UserStorageSyncManager in project keycloak by keycloak.
the class KeycloakApplication method setupScheduledTasks.
public static void setupScheduledTasks(final KeycloakSessionFactory sessionFactory) {
long interval = Config.scope("scheduled").getLong("interval", 900L) * 1000;
KeycloakSession session = sessionFactory.create();
try {
TimerProvider timer = session.getProvider(TimerProvider.class);
timer.schedule(new ClusterAwareScheduledTaskRunner(sessionFactory, new ClearExpiredEvents(), interval), interval, "ClearExpiredEvents");
timer.schedule(new ClusterAwareScheduledTaskRunner(sessionFactory, new ClearExpiredClientInitialAccessTokens(), interval), interval, "ClearExpiredClientInitialAccessTokens");
timer.schedule(new ScheduledTaskRunner(sessionFactory, new ClearExpiredUserSessions()), interval, ClearExpiredUserSessions.TASK_NAME);
new UserStorageSyncManager().bootstrapPeriodic(sessionFactory, timer);
} finally {
session.close();
}
}
use of org.keycloak.services.managers.UserStorageSyncManager in project keycloak by keycloak.
the class SyncFederationTest method test01PeriodicSyncOnCreate.
/**
* Test that period sync is triggered when creating a synchronized User Storage Provider
*/
@Test
public void test01PeriodicSyncOnCreate() {
final Map<String, Integer> state = testingClient.server().fetch(session -> {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
DummyUserFederationProviderFactory dummyFedFactory = (DummyUserFederationProviderFactory) sessionFactory.getProviderFactory(UserStorageProvider.class, DummyUserFederationProviderFactory.PROVIDER_NAME);
int full = dummyFedFactory.getFullSyncCounter();
int changed = dummyFedFactory.getChangedSyncCounter();
Map<String, Integer> state1 = new HashMap<>();
state1.put("full", full);
state1.put("changed", changed);
return state1;
}, Map.class);
// Enable timer for SyncDummyUserFederationProvider
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel model = new UserStorageProviderModel();
model.setProviderId(DummyUserFederationProviderFactory.PROVIDER_NAME);
model.setPriority(1);
model.setName("test-sync-dummy");
model.setFullSyncPeriod(-1);
model.setChangedSyncPeriod(1);
model.setLastSync(0);
ComponentModel dummyModel = new UserStorageProviderModel(appRealm.addComponentModel(model));
});
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel dummyModel = findDummyProviderModel(appRealm);
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
DummyUserFederationProviderFactory dummyFedFactory = (DummyUserFederationProviderFactory) sessionFactory.getProviderFactory(UserStorageProvider.class, DummyUserFederationProviderFactory.PROVIDER_NAME);
// Assert that after some period was DummyUserFederationProvider triggered
UserStorageSyncManager usersSyncManager = new UserStorageSyncManager();
sleep(1800);
// Cancel timer
usersSyncManager.notifyToRefreshPeriodicSync(session, appRealm, dummyModel, true);
log.infof("Notified sync manager about cancel periodic sync");
// This sync is here just to ensure that we have lock (doublecheck that periodic sync, which was possibly triggered before canceling timer is finished too)
while (true) {
SynchronizationResult result = usersSyncManager.syncChangedUsers(session.getKeycloakSessionFactory(), appRealm.getId(), dummyModel);
if (result.isIgnored()) {
log.infof("Still waiting for lock before periodic sync is finished", result.toString());
sleep(1000);
} else {
break;
}
}
int full = state.get("full");
int changed = state.get("changed");
// Assert that DummyUserFederationProviderFactory.syncChangedUsers was invoked at least 2 times (once periodically and once for us)
int newChanged = dummyFedFactory.getChangedSyncCounter();
Assert.assertEquals(full, dummyFedFactory.getFullSyncCounter());
Assert.assertTrue("Assertion failed. newChanged=" + newChanged + ", changed=" + changed, newChanged > (changed + 1));
// Assert that dummy provider won't be invoked anymore
sleep(1800);
Assert.assertEquals(full, dummyFedFactory.getFullSyncCounter());
int newestChanged = dummyFedFactory.getChangedSyncCounter();
Assert.assertEquals("Assertion failed. newChanged=" + newChanged + ", newestChanged=" + newestChanged, newChanged, newestChanged);
});
// remove dummyProvider
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel dummyModel = findDummyProviderModel(appRealm);
appRealm.removeComponent(dummyModel);
});
}
use of org.keycloak.services.managers.UserStorageSyncManager in project keycloak by keycloak.
the class SyncFederationTest method test02PeriodicSyncOnUpdate.
/**
* Test that period sync is triggered when updating a synchronized User Storage Provider to have a non-negative sync period
*/
@Test
public void test02PeriodicSyncOnUpdate() {
final Map<String, Integer> state = testingClient.server().fetch(session -> {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
DummyUserFederationProviderFactory dummyFedFactory = (DummyUserFederationProviderFactory) sessionFactory.getProviderFactory(UserStorageProvider.class, DummyUserFederationProviderFactory.PROVIDER_NAME);
int full = dummyFedFactory.getFullSyncCounter();
int changed = dummyFedFactory.getChangedSyncCounter();
Map<String, Integer> state1 = new HashMap<>();
state1.put("full", full);
state1.put("changed", changed);
return state1;
}, Map.class);
// Configure sync without timer for SyncDummyUserFederationProvider
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel model = new UserStorageProviderModel();
model.setProviderId(DummyUserFederationProviderFactory.PROVIDER_NAME);
model.setPriority(1);
model.setName("test-sync-dummy");
model.setFullSyncPeriod(-1);
model.setChangedSyncPeriod(-1);
model.setLastSync(0);
ComponentModel dummyModel = new UserStorageProviderModel(appRealm.addComponentModel(model));
});
testingClient.server().run(session -> {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
DummyUserFederationProviderFactory dummyFedFactory = (DummyUserFederationProviderFactory) sessionFactory.getProviderFactory(UserStorageProvider.class, DummyUserFederationProviderFactory.PROVIDER_NAME);
// Assert that after some period was DummyUserFederationProvider triggered
UserStorageSyncManager usersSyncManager = new UserStorageSyncManager();
// Assert that dummy provider wasn't invoked anymore
sleep(1800);
int full = state.get("full");
int changed = state.get("changed");
Assert.assertEquals(full, dummyFedFactory.getFullSyncCounter());
int newChanged = dummyFedFactory.getChangedSyncCounter();
Assert.assertEquals("Assertion failed. changed=" + changed + ", newChanged=" + newChanged, changed, newChanged);
});
// Re-enable periodic sync for changed users
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel dummyModel = findDummyProviderModel(appRealm);
dummyModel.setChangedSyncPeriod(1);
appRealm.updateComponent(dummyModel);
});
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel dummyModel = findDummyProviderModel(appRealm);
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
DummyUserFederationProviderFactory dummyFedFactory = (DummyUserFederationProviderFactory) sessionFactory.getProviderFactory(UserStorageProvider.class, DummyUserFederationProviderFactory.PROVIDER_NAME);
// Assert that after some period was DummyUserFederationProvider triggered
UserStorageSyncManager usersSyncManager = new UserStorageSyncManager();
sleep(1800);
// Cancel timer
usersSyncManager.notifyToRefreshPeriodicSync(session, appRealm, dummyModel, true);
log.infof("Notified sync manager about cancel periodic sync");
// This sync is here just to ensure that we have lock (doublecheck that periodic sync, which was possibly triggered before canceling timer is finished too)
while (true) {
SynchronizationResult result = usersSyncManager.syncChangedUsers(session.getKeycloakSessionFactory(), appRealm.getId(), dummyModel);
if (result.isIgnored()) {
log.infof("Still waiting for lock before periodic sync is finished", result.toString());
sleep(1000);
} else {
break;
}
}
int full = state.get("full");
int changed = state.get("changed");
// Assert that DummyUserFederationProviderFactory.syncChangedUsers was invoked at least 1 time
int newChanged = dummyFedFactory.getChangedSyncCounter();
Assert.assertEquals(full, dummyFedFactory.getFullSyncCounter());
log.info("Asserting. newChanged=" + newChanged + " > changed=" + changed);
Assert.assertTrue("Assertion failed. newChanged=" + newChanged + ", changed=" + changed, newChanged > (changed + 1));
// Assert that dummy provider won't be invoked anymore
sleep(1800);
Assert.assertEquals(full, dummyFedFactory.getFullSyncCounter());
int newestChanged = dummyFedFactory.getChangedSyncCounter();
Assert.assertEquals("Assertion failed. newChanged=" + newChanged + ", newestChanged=" + newestChanged, newChanged, newestChanged);
});
// remove dummyProvider
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(AuthRealm.TEST);
UserStorageProviderModel dummyModel = findDummyProviderModel(appRealm);
appRealm.removeComponent(dummyModel);
});
}
use of org.keycloak.services.managers.UserStorageSyncManager in project keycloak by keycloak.
the class RealmAdminResource method updateRealm.
/**
* Update the top-level information of the realm
*
* Any user, roles or client information in the representation
* will be ignored. This will only update top-level attributes of the realm.
*
* @param rep
* @return
*/
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response updateRealm(final RealmRepresentation rep) {
auth.realm().requireManageRealm();
logger.debug("updating realm: " + realm.getName());
if (Config.getAdminRealm().equals(realm.getName()) && (rep.getRealm() != null && !rep.getRealm().equals(Config.getAdminRealm()))) {
return ErrorResponse.error("Can't rename master realm", Status.BAD_REQUEST);
}
ReservedCharValidator.validate(rep.getRealm());
ReservedCharValidator.validateLocales(rep.getSupportedLocales());
try {
if (!Constants.GENERATE.equals(rep.getPublicKey()) && (rep.getPrivateKey() != null && rep.getPublicKey() != null)) {
try {
KeyPairVerifier.verify(rep.getPrivateKey(), rep.getPublicKey());
} catch (VerificationException e) {
return ErrorResponse.error(e.getMessage(), Status.BAD_REQUEST);
}
}
if (!Constants.GENERATE.equals(rep.getPublicKey()) && (rep.getCertificate() != null)) {
try {
X509Certificate cert = PemUtils.decodeCertificate(rep.getCertificate());
if (cert == null) {
return ErrorResponse.error("Failed to decode certificate", Status.BAD_REQUEST);
}
} catch (Exception e) {
return ErrorResponse.error("Failed to decode certificate", Status.BAD_REQUEST);
}
}
boolean wasDuplicateEmailsAllowed = realm.isDuplicateEmailsAllowed();
RepresentationToModel.updateRealm(rep, realm, session);
// Refresh periodic sync tasks for configured federationProviders
UserStorageSyncManager usersSyncManager = new UserStorageSyncManager();
realm.getUserStorageProvidersStream().forEachOrdered(fedProvider -> usersSyncManager.notifyToRefreshPeriodicSync(session, realm, fedProvider, false));
// This populates the map in DefaultKeycloakContext to be used when treating the event
session.getContext().getUri();
adminEvent.operation(OperationType.UPDATE).representation(StripSecretsUtils.strip(rep)).success();
if (rep.isDuplicateEmailsAllowed() != null && rep.isDuplicateEmailsAllowed() != wasDuplicateEmailsAllowed) {
UserCache cache = session.getProvider(UserCache.class);
if (cache != null)
cache.clear();
}
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return ErrorResponse.exists("Realm with same name exists");
} catch (ModelException e) {
return ErrorResponse.error(e.getMessage(), Status.BAD_REQUEST);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return ErrorResponse.error("Failed to update realm", Response.Status.INTERNAL_SERVER_ERROR);
}
}
use of org.keycloak.services.managers.UserStorageSyncManager in project keycloak by keycloak.
the class LDAPRoleMappingsTest method test04_syncRoleMappings.
/**
* KEYCLOAK-5698
*/
@Test
public void test04_syncRoleMappings() {
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ctx.getLdapModel());
LDAPObject john = LDAPTestUtils.addLDAPUser(ldapProvider, appRealm, "johnrolemapper", "John", "RoleMapper", "johnrolemapper@email.org", null, "1234");
LDAPTestUtils.updateLDAPPassword(ldapProvider, john, "Password1");
LDAPTestUtils.addOrUpdateRoleLDAPMappers(appRealm, ctx.getLdapModel(), LDAPGroupMapperMode.LDAP_ONLY);
UserStorageSyncManager usersSyncManager = new UserStorageSyncManager();
SynchronizationResult syncResult = usersSyncManager.syncChangedUsers(session.getKeycloakSessionFactory(), appRealm.getId(), new UserStorageProviderModel(ctx.getLdapModel()));
syncResult.getAdded();
});
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
// make sure user is cached.
UserModel johnRoleMapper = session.users().getUserByUsername(appRealm, "johnrolemapper");
Assert.assertNotNull(johnRoleMapper);
Assert.assertEquals(0, johnRoleMapper.getRealmRoleMappingsStream().count());
});
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
// Add some role mappings directly in LDAP
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ctx.getLdapModel());
ComponentModel roleMapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "realmRolesMapper");
RoleLDAPStorageMapper roleMapper = LDAPTestUtils.getRoleMapper(roleMapperModel, ldapProvider, appRealm);
LDAPObject johnLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "johnrolemapper");
roleMapper.addRoleMappingInLDAP("realmRole1", johnLdap);
roleMapper.addRoleMappingInLDAP("realmRole2", johnLdap);
// Get user and check that he has requested roles from LDAP
UserModel johnRoleMapper = session.users().getUserByUsername(appRealm, "johnrolemapper");
RoleModel realmRole1 = appRealm.getRole("realmRole1");
RoleModel realmRole2 = appRealm.getRole("realmRole2");
Set<RoleModel> johnRoles = johnRoleMapper.getRealmRoleMappingsStream().collect(Collectors.toSet());
Assert.assertFalse(johnRoles.contains(realmRole1));
Assert.assertFalse(johnRoles.contains(realmRole2));
});
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
// Add some role mappings directly in LDAP
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ctx.getLdapModel());
ComponentModel roleMapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "realmRolesMapper");
RoleLDAPStorageMapper roleMapper = LDAPTestUtils.getRoleMapper(roleMapperModel, ldapProvider, appRealm);
LDAPObject johnLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "johnrolemapper");
// not sure why it is here for second time, but it is failing for Active directory - mapping already exists
if (!ctx.getLdapProvider().getLdapIdentityStore().getConfig().isActiveDirectory()) {
roleMapper.addRoleMappingInLDAP("realmRole1", johnLdap);
roleMapper.addRoleMappingInLDAP("realmRole2", johnLdap);
}
UserStorageSyncManager usersSyncManager = new UserStorageSyncManager();
SynchronizationResult syncResult = usersSyncManager.syncChangedUsers(session.getKeycloakSessionFactory(), appRealm.getId(), new UserStorageProviderModel(ctx.getLdapModel()));
});
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
// Get user and check that he has requested roles from LDAP
UserModel johnRoleMapper = session.users().getUserByUsername(appRealm, "johnrolemapper");
RoleModel realmRole1 = appRealm.getRole("realmRole1");
RoleModel realmRole2 = appRealm.getRole("realmRole2");
Set<RoleModel> johnRoles = johnRoleMapper.getRealmRoleMappingsStream().collect(Collectors.toSet());
Assert.assertTrue(johnRoles.contains(realmRole1));
Assert.assertTrue(johnRoles.contains(realmRole2));
});
}
Aggregations