private static void append(@NotNull List<String> list, @Nullable SyncedIdentity syncedIdentity, @NotNull String op, @Nullable String msg) { String uid = JsonUtil.getJsonString((syncedIdentity == null ? null : syncedIdentity.getId())); ExternalIdentityRef externalIdentityRef = (syncedIdentity == null) ? null : syncedIdentity.getExternalIdRef(); String eid = (externalIdentityRef == null) ? "\"\"" : JsonUtil.getJsonString(externalIdentityRef.getString()); if (msg == null) { list.add(String.format("{op:\"%s\",uid:%s,eid:%s}", op, uid, eid)); } else { list.add(String.format("{op:\"%s\",uid:%s,eid:%s,msg:%s}", op, uid, eid, JsonUtil.getJsonString(msg))); } }
@Nullable @Override public String apply(@Nullable SyncedIdentity syncedIdentity) { if (syncedIdentity != null && isMyIDP(syncedIdentity)) { ExternalIdentityRef ref = syncedIdentity.getExternalIdRef(); try { ExternalIdentity extId = (ref == null) ? null : idp.getIdentity(ref); if (extId == null) { return syncedIdentity.getId(); } } catch (ExternalIdentityException e) { log.error("Error while fetching external identity {}", syncedIdentity, e); } } return null; } }), Predicates.notNull());
/** * @see SynchronizationMBean#syncAllUsers(boolean) */ @NotNull String[] syncAllUsers(boolean purge) { try { List<String> list = new ArrayList<>(); context.setKeepMissing(!purge) .setForceGroupSync(true) .setForceUserSync(true); Iterator<SyncedIdentity> it = handler.listIdentities(userMgr); List<SyncResult> results = new ArrayList<>(batchSize); while (it.hasNext()) { SyncedIdentity id = it.next(); if (isMyIDP(id)) { results = syncUser(id.getId(), false, results, list); } } commit(list, results, NO_BATCH_SIZE); return list.toArray(new String[0]); } catch (RepositoryException e) { throw new IllegalStateException("Error retrieving users for syncing", e); } }
private boolean ignore(@Nullable SyncedIdentity syncedIdentity, @Nullable PreAuthenticatedLogin preAuthLogin) { if (syncedIdentity != null) { ExternalIdentityRef externalIdRef = syncedIdentity.getExternalIdRef(); if (externalIdRef == null) { debug("ignoring local user: {}", syncedIdentity.getId()); return true; } else if (!idp.getName().equals(externalIdRef.getProviderName())) { debug("ignoring foreign identity: {} (idp={})", externalIdRef.getString(), idp.getName()); return true; } if (preAuthLogin != null && !syncHandler.requiresSync(syncedIdentity)) { debug("pre-authenticated external user {} does not require syncing.", syncedIdentity.toString()); return true; } } return false; }
@Test public void testListIdentitiesAfterSync() throws Exception { sync(USER_ID, false); // membership-nesting is 1 => expect only 'USER_ID' plus the declared group-membership Set<String> expected = Sets.newHashSet(USER_ID); for (ExternalIdentityRef extRef : idp.getUser(USER_ID).getDeclaredGroups()) { expected.add(extRef.getId()); } Iterator<SyncedIdentity> identities = syncHandler.listIdentities(userManager); while (identities.hasNext()) { SyncedIdentity si = identities.next(); if (expected.contains(si.getId())) { expected.remove(si.getId()); assertNotNull(si.getExternalIdRef()); } else { fail("Sync handler returned unexpected identity: " + si); } } assertTrue(expected.isEmpty()); }
@Test public void testSyncAutoMembership() throws Exception { Group gr = createTestGroup(); syncConfig.user().setAutoMembership(gr.getID()); SyncResult result = syncCtx.sync(idp.listUsers().next()); assertEquals(SyncResult.Status.ADD, result.getStatus()); Authorizable a = userManager.getAuthorizable(result.getIdentity().getId()); assertTrue(gr.isDeclaredMember(a)); }
@Test public void testCreateSyncedIdentitySyncedUser() throws Exception { ExternalIdentity externalUser = idp.listUsers().next(); sync(externalUser); Authorizable a = userManager.getAuthorizable(externalUser.getId()); SyncedIdentity si = DefaultSyncContext.createSyncedIdentity(a); assertNotNull(si); assertEquals(a.getID(), si.getId()); assertNotNull(si.getExternalIdRef()); assertFalse(si.isGroup()); assertEquals(syncCtx.now, si.lastSynced()); }
@Test public void testCreateSyncedIdentitySyncedGroup() throws Exception { ExternalIdentity externalGroup = idp.listGroups().next(); sync(externalGroup); Authorizable a = userManager.getAuthorizable(externalGroup.getId()); SyncedIdentity si = DefaultSyncContext.createSyncedIdentity(a); assertNotNull(si); assertEquals(a.getID(), si.getId()); assertNotNull(si.getExternalIdRef()); assertTrue(si.isGroup()); assertEquals(syncCtx.now, si.lastSynced()); }
@Test public void testCreateSyncedIdentityLocalUser() throws Exception { User u = getTestUser(); SyncedIdentity si = DefaultSyncContext.createSyncedIdentity(u); assertNotNull(si); assertEquals(u.getID(), si.getId()); assertNull(si.getExternalIdRef()); assertFalse(si.isGroup()); assertEquals(-1, si.lastSynced()); }
@Test public void testCreateSyncedIdentityLocalGroup() throws Exception { Group gr = createTestGroup(); SyncedIdentity si = DefaultSyncContext.createSyncedIdentity(gr); assertNotNull(si); assertEquals(gr.getID(), si.getId()); assertNull(si.getExternalIdRef()); assertTrue(si.isGroup()); assertEquals(-1, si.lastSynced()); }
private void assertRepExternalId(@NotNull SyncResult result) throws Exception { assertSame(SyncResult.Status.ADD, result.getStatus()); SyncedIdentity si = result.getIdentity(); assertNotNull(si); Authorizable authorizable = userManager.getAuthorizable(si.getId()); assertNotNull(authorizable); Tree userTree = r.getTree(authorizable.getPath()); assertTrue(userTree.hasProperty(DefaultSyncContext.REP_EXTERNAL_ID)); PropertyState ps = userTree.getProperty(DefaultSyncContext.REP_EXTERNAL_ID); assertNotNull(ps); assertFalse(ps.isArray()); assertSame(Type.STRING, ps.getType()); assertEquals(si.getExternalIdRef(), ExternalIdentityRef.fromString(ps.getValue(Type.STRING))); }
@Test public void testLostMembershipDifferentIDP() throws Exception { // create a group in the repository which is marked as being external // and associated with another IPD. Group gr = createTestGroup(); setExternalID(gr, "differentIDP"); // sync an external user from the IDP into the repo and make it member // of the test group SyncResult result = syncCtx.sync(idp.listUsers().next()); User user = userManager.getAuthorizable(result.getIdentity().getId(), User.class); gr.addMember(user); root.commit(); // enforce synchronization of the user and it's group membership syncCtx.setForceUserSync(true); syncConfig.user().setMembershipExpirationTime(-1); syncConfig.user().setMembershipNestingDepth(1); assertEquals(SyncResult.Status.UPDATE, syncCtx.sync(user.getID()).getStatus()); // since the group is not associated with the test-IDP the group-membership // must NOT be modified during the sync. assertTrue(gr.isDeclaredMember(user)); }
@Test public void testLostMembershipWithExpirationSet() throws Exception { long expTime = 2; syncConfig.user().setMembershipNestingDepth(1).setMembershipExpirationTime(expTime).setExpirationTime(expTime); Group gr = createTestGroup(); setExternalID(gr, idp.getName()); SyncResult result = syncCtx.sync(idp.listUsers().next()); User user = (User) userManager.getAuthorizable(result.getIdentity().getId()); gr.addMember(user); root.commit(); waitUntilExpired(user, root, expTime); DefaultSyncContext newCtx = new DefaultSyncContext(syncConfig, idp, userManager, valueFactory); result = newCtx.sync(user.getID()); root.commit(); assertSame(SyncResult.Status.UPDATE, result.getStatus()); gr = (Group) userManager.getAuthorizable(gr.getID()); assertFalse(gr.isDeclaredMember(userManager.getAuthorizable(user.getID()))); }
@Test public void testSyncForeignExternalGroup() throws Exception { ExternalGroup foreign = new TestIdentityProvider.ForeignExternalGroup(); SyncResult res = syncContext.sync(foreign); assertNotNull(res); assertSame(SyncResult.Status.FOREIGN, res.getStatus()); // expect {@code SyncedIdentity} in accordance with {@code sync(String userId)}, // where the authorizable is found to be linked to a different IDP. SyncedIdentity si = res.getIdentity(); assertNotNull(si); assertEquals(foreign.getId(), si.getId()); ExternalIdentityRef ref = si.getExternalIdRef(); assertNotNull(ref); assertEquals(foreign.getExternalId(), ref); assertTrue(si.isGroup()); assertEquals(-1, si.lastSynced()); assertFalse(r.hasPendingChanges()); }
@Test public void testSyncForeignExternalUser() throws Exception { ExternalIdentity foreign = new TestIdentityProvider.ForeignExternalUser(); SyncResult res = syncCtx.sync(foreign); assertNotNull(res); assertSame(SyncResult.Status.FOREIGN, res.getStatus()); // expect {@code SyncedIdentity} in accordance with {@code sync(String userId)}, // where the authorizable is found to be linked to a different IDP. SyncedIdentity si = res.getIdentity(); assertNotNull(si); assertEquals(foreign.getId(), si.getId()); ExternalIdentityRef ref = si.getExternalIdRef(); assertNotNull(ref); assertEquals(foreign.getExternalId(), ref); assertFalse(si.isGroup()); assertEquals(-1, si.lastSynced()); assertFalse(root.hasPendingChanges()); }
@Test public void testSyncForeignExternalGroup() throws Exception { ExternalIdentity foreign = new TestIdentityProvider.ForeignExternalGroup(); SyncResult res = syncCtx.sync(foreign); assertNotNull(res); assertSame(SyncResult.Status.FOREIGN, res.getStatus()); // expect {@code SyncedIdentity} in accordance with {@code sync(String userId)}, // where the authorizable is found to be linked to a different IDP. SyncedIdentity si = res.getIdentity(); assertNotNull(si); assertEquals(foreign.getId(), si.getId()); ExternalIdentityRef ref = si.getExternalIdRef(); assertNotNull(ref); assertEquals(foreign.getExternalId(), ref); assertTrue(si.isGroup()); assertEquals(-1, si.lastSynced()); assertFalse(root.hasPendingChanges()); }
@Test public void testLostMembership() throws Exception { // create a group in the repository which is marked as being external // and associated with the test-IDP to setup the situation that a // repository group is no longer listed in the IDP. Group gr = createTestGroup(); setExternalID(gr, idp.getName()); // sync an external user from the IDP into the repo and make it member // of the test group SyncResult result = syncCtx.sync(idp.listUsers().next()); User user = userManager.getAuthorizable(result.getIdentity().getId(), User.class); gr.addMember(user); root.commit(); // enforce synchronization of the user and it's group membership syncCtx.setForceUserSync(true); syncConfig.user().setMembershipExpirationTime(-1); // 1. membership nesting is < 0 => membership not synchronized syncConfig.user().setMembershipNestingDepth(-1); syncCtx.sync(user.getID()).getStatus(); assertTrue(gr.isDeclaredMember(user)); // 2. membership nesting is > 0 => membership gets synchronized syncConfig.user().setMembershipNestingDepth(1); assertEquals(SyncResult.Status.UPDATE, syncCtx.sync(user.getID()).getStatus()); assertFalse(gr.isDeclaredMember(user)); }