1 package edu.internet2.middleware.grouper.pspng;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.io.IOException;
20 import java.io.Reader;
21 import java.io.StringReader;
22 import java.util.*;
23
24 import com.unboundid.ldap.sdk.Filter;
25 import com.unboundid.ldap.sdk.LDAPException;
26 import org.apache.commons.lang.StringUtils;
27 import org.ldaptive.*;
28 import org.ldaptive.io.LdifReader;
29
30 import edu.internet2.middleware.subject.Subject;
31 import static edu.internet2.middleware.grouper.pspng.PspUtils.*;
32
33
34
35
36
37
38
39
40
41
42 public class LdapGroupProvisioner extends LdapProvisioner<LdapGroupProvisionerConfiguration> {
43
44 public LdapGroupProvisioner(String provisionerName, LdapGroupProvisionerConfiguration config, boolean fullSyncMode) {
45 super(provisionerName, config, fullSyncMode);
46
47 LOG.debug("Constructing LdapGroupProvisioner: {}", provisionerName);
48 }
49
50 public static Class<? extends ProvisionerConfiguration> getPropertyClass() {
51 return LdapGroupProvisionerConfiguration.class;
52 }
53
54
55 @Override
56 protected void addMembership(GrouperGroupInfo grouperGroupInfo, LdapGroup ldapGroup,
57 Subject subject, LdapUser ldapUser) throws PspException {
58
59
60
61
62
63 if ( ldapUser == null && config.needsTargetSystemUsers() ) {
64 LOG.warn("{}: Skipping adding membership to group {} because ldap user does not exist: {}",
65 new Object[]{getDisplayName(), grouperGroupInfo, subject});
66 return;
67 }
68
69 if ( ldapGroup == null ) {
70
71
72
73
74
75 ldapGroup = createGroup(grouperGroupInfo, Arrays.asList(subject));
76 cacheGroup(grouperGroupInfo, ldapGroup);
77 }
78 else {
79 String membershipAttributeValue = evaluateJexlExpression("MemberAttributeValue", config.getMemberAttributeValueFormat(), subject, ldapUser, grouperGroupInfo, ldapGroup);
80 if ( membershipAttributeValue != null ) {
81 scheduleGroupModification(grouperGroupInfo, ldapGroup, AttributeModificationType.ADD, Arrays.asList(membershipAttributeValue));
82 JobStatistics jobStatistics = this.getJobStatistics();
83 if (jobStatistics != null) {
84 jobStatistics.insertCount.addAndGet(1);
85 }
86 }
87 }
88 }
89
90
91 protected void scheduleGroupModification(GrouperGroupInfo grouperGroupInfo, LdapGroup ldapGroup, AttributeModificationType modType, Collection<String> membershipValuesToChange) {
92 String attributeName = config.getMemberAttributeName();
93
94 for ( String value : membershipValuesToChange )
95
96 LOG.info("Will change LDAP: {} {} {} {} of {}",
97 new Object[] {modType, value,
98 modType == AttributeModificationType.ADD ? "to" : "from",
99 attributeName, ldapGroup});
100
101 scheduleLdapModification(
102 new ModifyRequest(
103 ldapGroup.getLdapObject().getDn(),
104 new AttributeModification(
105 modType,
106 new LdapAttribute(attributeName, membershipValuesToChange.toArray(new String[0])))));
107 }
108
109 @Override
110 protected void deleteMembership(GrouperGroupInfo grouperGroupInfo, LdapGroup ldapGroup ,
111 Subject subject, LdapUser ldapUser) throws PspException {
112 if ( ldapGroup == null ) {
113 LOG.warn("{}: Ignoring request to remove {} from a group that doesn't exist: {}",
114 new Object[]{getDisplayName(), subject.getId(), grouperGroupInfo});
115 return;
116 }
117
118 if ( ldapUser == null && config.needsTargetSystemUsers() ) {
119 LOG.warn("{}: Skipping removing membership from group {} because ldap user does not exist: {}",
120 new Object[]{getDisplayName(), grouperGroupInfo, subject});
121 return;
122 }
123
124
125
126
127
128 String membershipAttributeValue = evaluateJexlExpression("MemberAttributeValue", config.getMemberAttributeValueFormat(), subject, ldapUser, grouperGroupInfo, ldapGroup);
129
130 if ( membershipAttributeValue != null ) {
131 JobStatistics jobStatistics = this.getJobStatistics();
132 if (jobStatistics != null) {
133 jobStatistics.deleteCount.addAndGet(1);
134 }
135 scheduleGroupModification(grouperGroupInfo, ldapGroup, AttributeModificationType.REMOVE, Arrays.asList(membershipAttributeValue));
136 }
137 }
138
139 @Override
140 protected boolean doFullSync(
141 GrouperGroupInfo grouperGroupInfo, LdapGroup ldapGroup ,
142 Set<Subject> correctSubjects, Map<Subject, LdapUser> tsUserMap,
143 Set<LdapUser> correctTSUsers,
144 JobStatistics stats) throws PspException {
145
146 stats.totalCount.set(correctSubjects.size());
147
148
149
150 if ( ldapGroup != null )
151 ldapGroup.getLdapObject().getStringValues(config.getMemberAttributeName());
152
153
154 if ( ldapGroup == null ) {
155
156
157 if ( config.areEmptyGroupsSupported() ) {
158 if ( correctSubjects.size() == 0 ) {
159 LOG.info("{}: Nothing to do because empty group already not present in ldap system", getDisplayName() );
160 return false;
161 }
162 }
163
164 ldapGroup = createGroup(grouperGroupInfo, correctSubjects);
165 stats.insertCount.addAndGet(correctSubjects.size());
166
167
168 if ( ldapGroup != null ) {
169 cacheGroup(grouperGroupInfo, ldapGroup);
170 }
171 return true;
172 } else {
173
174 ldapGroup = updateGroupFromTemplate(grouperGroupInfo, ldapGroup);
175 cacheGroup(grouperGroupInfo, ldapGroup);
176 }
177
178
179 if ( !config.areEmptyGroupsSupported() && correctSubjects.size() == 0 ) {
180 LOG.info("{}: Deleting empty group because schema requires its member attribute", getDisplayName());
181 deleteGroup(grouperGroupInfo, ldapGroup);
182
183
184 Collection<String> membershipValues = ldapGroup.getLdapObject().getStringValues(config.getMemberAttributeName());
185 stats.deleteCount.addAndGet(membershipValues.size());
186
187 return true;
188 }
189
190 Set<String> correctMembershipValues = getStringSet(config.isMemberAttributeCaseSensitive());
191
192 for ( Subject correctSubject: correctSubjects ) {
193 String membershipAttributeValue = evaluateJexlExpression("MemberAttributeValue", config.getMemberAttributeValueFormat(), correctSubject, tsUserMap.get(correctSubject), grouperGroupInfo, ldapGroup);
194
195 if ( membershipAttributeValue != null ) {
196 correctMembershipValues.add(membershipAttributeValue);
197 }
198 }
199
200 Collection<String> currentMembershipValues = getStringSet(config.isMemberAttributeCaseSensitive(), ldapGroup.getLdapObject().getStringValues(config.getMemberAttributeName()));
201
202
203
204
205
206
207 if(config.allowEmptyDnAttributeValues()) {
208 if(config.getMemberAttributeName().equals("member")) {
209 currentMembershipValues.removeIf(v -> v.equals(""));
210 }
211 }
212
213 LOG.info("{}: Full-sync comparison for {}: Target-subject count: Correct/Actual: {}/{}",
214 new Object[] {getDisplayName(), grouperGroupInfo, correctMembershipValues.size(), currentMembershipValues.size()});
215
216 LOG.debug("{}: Full-sync comparison: Correct: {}", getDisplayName(), correctMembershipValues);
217 LOG.debug("{}: Full-sync comparison: Actual: {}", getDisplayName(), currentMembershipValues);
218
219
220 Collection<String> extraValues = subtractStringCollections(
221 config.isMemberAttributeCaseSensitive(), currentMembershipValues, correctMembershipValues);
222
223 stats.deleteCount.addAndGet(extraValues.size());
224
225 LOG.info("{}: Group {} has {} extra values",
226 new Object[] {getDisplayName(), grouperGroupInfo, extraValues.size()});
227 if ( extraValues.size() > 0 ) {
228 getLdapSystem().performLdapModify(
229 new ModifyRequest(
230 ldapGroup.dn,
231 new AttributeModification(
232 AttributeModificationType.REMOVE,
233 new LdapAttribute(config.getMemberAttributeName(),extraValues.toArray(new String[0])))),
234 config.isMemberAttributeCaseSensitive(),
235 true);
236 }
237
238
239 Collection<String> missingValues = subtractStringCollections(
240 config.isMemberAttributeCaseSensitive(), correctMembershipValues, currentMembershipValues);
241
242 stats.insertCount.addAndGet(missingValues.size());
243
244 LOG.info("{}: Group {} has {} missing values",
245 new Object[]{getDisplayName(), grouperGroupInfo, missingValues.size()});
246 if ( missingValues.size() > 0 ) {
247 getLdapSystem().performLdapModify(
248 new ModifyRequest(
249 ldapGroup.dn,
250 new AttributeModification(
251 AttributeModificationType.ADD,
252 new LdapAttribute(config.getMemberAttributeName(),missingValues.toArray(new String[0])))),
253 config.isMemberAttributeCaseSensitive(),
254 true);
255
256 }
257
258 return extraValues.size()>0 || missingValues.size()>0;
259 }
260
261
262
263
264
265
266
267
268 protected LdapGroupg/LdapGroup.html#LdapGroup">LdapGroup updateGroupFromTemplate(GrouperGroupInfo grouperGroupInfo, LdapGroup existingLdapGroup) throws PspException {
269 LOG.debug("{}: Making sure (non-membership) attributes of group are up to date: {}", getDisplayName(), existingLdapGroup.dn);
270
271 try {
272 String ldifFromTemplate = getGroupLdifFromTemplate(grouperGroupInfo, config.removeNullDnFromGroupLdifCreationTemplate());
273 LdapEntry ldapEntryFromTemplate = getLdapEntryFromLdif(ldifFromTemplate);
274
275 ensureLdapOusExist(ldapEntryFromTemplate.getDn(), false);
276 if ( getLdapSystem().makeLdapObjectCorrect(ldapEntryFromTemplate, existingLdapGroup.ldapObject.ldapEntry, config.isMemberAttributeCaseSensitive()) ) {
277 LdapGroup result = fetchTargetSystemGroup(grouperGroupInfo);
278 return result;
279 }
280 else {
281 return existingLdapGroup;
282 }
283 }
284 catch (PspException e) {
285 LOG.error("{}: Problem checking and updating group's template attributes", getDisplayName(), e);
286 throw e;
287 }
288 catch (IOException e) {
289 LOG.error("{}: Problem checking and updating group's tempalte attributes", getDisplayName(), e);
290 throw new PspException("IO Exception while checking and updating group's template attributes", e);
291 }
292 }
293
294
295
296 @Override
297 protected void doFullSync_cleanupExtraGroups(JobStatistics stats) throws PspException {
298
299
300 String filterString = config.getAllGroupSearchFilter();
301 if ( StringUtils.isEmpty(filterString) ) {
302 LOG.error("{}: Cannot cleanup extra groups without a configured all-group search filter", getDisplayName());
303 return;
304 }
305
306 String baseDn = config.getGroupSearchBaseDn();
307
308 if ( StringUtils.isEmpty(baseDn)) {
309 LOG.error("{}: Cannot cleanup extra groups without a configured group-search base dn", getDisplayName());
310 return;
311 }
312
313
314 List<LdapObject> allProvisionedGroups
315 = getLdapSystem().performLdapSearchRequest(
316 -1, baseDn, SearchScope.SUBTREE,
317 Arrays.asList(getLdapAttributesToFetch()), filterString);
318
319
320
321
322 Collection<GrouperGroupInfo> groupsThatShouldBeProvisioned = getAllGroupsForProvisioner();
323 Map<GrouperGroupInfo, LdapGroup> ldapGroupsThatShouldBeProvisioned = fetchTargetSystemGroupsInBatches(groupsThatShouldBeProvisioned);
324
325 Set<String> correctGroupDNs = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
326 for(LdapGroup correctLdapGroup : ldapGroupsThatShouldBeProvisioned.values()) {
327 String correctLdapGroupDn = correctLdapGroup.getLdapObject().getDn();
328 correctGroupDNs.add(correctLdapGroupDn);
329 }
330
331
332 List<LdapObject> groupsToDelete = new ArrayList<LdapObject>();
333 for (LdapObject aProvisionedGroup : allProvisionedGroups) {
334 if ( ! correctGroupDNs.contains(aProvisionedGroup.getDn()) ) {
335 groupsToDelete.add(aProvisionedGroup);
336 }
337 }
338
339 LOG.info("{}: There are {} groups that we should delete", getDisplayName(), groupsToDelete.size());
340
341 for ( LdapObject groupToRemove : groupsToDelete ) {
342 int numMembershipsBeingDeleted = groupToRemove.getStringValues(config.getMemberAttributeName()).size();
343 stats.deleteCount.addAndGet(numMembershipsBeingDeleted);
344
345 getLdapSystem().performLdapDelete(groupToRemove.getDn());
346 }
347
348 }
349
350
351 @Override
352 protected LdapGroup createGroup(GrouperGroupInfo grouperGroup, Collection<Subject> initialMembers) throws PspException {
353 if ( !config.areEmptyGroupsSupported() && initialMembers.size() == 0 ) {
354 LOG.warn("Not Creating LDAP group because empty groups are not supported: {}", grouperGroup);
355 return null;
356 }
357
358 LOG.info("Creating LDAP group for GrouperGroup: {} ", grouperGroup);
359 String ldif = getGroupLdifFromTemplate(grouperGroup);
360
361
362 if ( initialMembers != null && initialMembers.size() > 0 ) {
363
364
365 Collection<String> membershipValues = new HashSet<String>(initialMembers.size());
366
367 for ( Subject subject : initialMembers ) {
368 LdapUser ldapUser;
369 String membershipAttributeValue = null;
370 if (!config.needsTargetSystemUsers()) {
371 membershipAttributeValue = evaluateJexlExpression("MemberAttributeValue", config.getMemberAttributeValueFormat(), subject, null, grouperGroup, null);
372 }
373 else {
374 ldapUser = getTargetSystemUser(subject);
375 if ( ldapUser != null ) {
376 membershipAttributeValue = evaluateJexlExpression("MemberAttributeValue", config.getMemberAttributeValueFormat(), subject, ldapUser, grouperGroup, null);
377 }
378 }
379
380 if ( membershipAttributeValue != null ) {
381 membershipValues.add(membershipAttributeValue);
382 }
383 }
384
385 JobStatistics jobStatistics = this.getJobStatistics();
386 if (jobStatistics != null) {
387 jobStatistics.insertCount.addAndGet(membershipValues.size());
388 }
389
390 StringBuilder ldifForMemberships = new StringBuilder();
391 for ( String attributeValue : membershipValues ) {
392 ldifForMemberships.append(String.format("%s: %s\n", config.getMemberAttributeName(), attributeValue));
393 }
394 ldif = ldif.concat("\n");
395 ldif = ldif.concat(ldifForMemberships.toString());
396 }
397
398 Connection conn = getLdapSystem().getLdapConnection();
399 try {
400 LOG.debug("{}: LDIF for new group (with partial DN): {}", getDisplayName(), ldif.replaceAll("\\n", "||"));
401 LdapEntry ldifEntry = getLdapEntryFromLdif(ldif);
402
403
404 for ( String attributeName : ldifEntry.getAttributeNames() ) {
405
406
407
408 if(config.allowEmptyDnAttributeValues()) {
409 List<String> attributeDnSyntaxList = Arrays.asList(config.getAttributesNeededingDnEscaping());
410 if(attributeDnSyntaxList.contains(attributeName)) {
411 LOG.debug("{}: attribute {} requires DN syntax but is allowed to hold the null DN", getDisplayName(), attributeName);
412 continue;
413 }
414 }
415 LdapAttribute attribute = ldifEntry.getAttribute(attributeName);
416 if ( LdapSystem.attributeHasNoValues(attribute) ) {
417 LOG.warn("{}: LDIF for new group did not define any values for {}", getDisplayName(), attributeName);
418 ldifEntry.removeAttribute(attributeName);
419 }
420 }
421 LOG.debug("{}: Adding group: {}", getDisplayName(), ldifEntry);
422
423 performLdapAdd(ldifEntry);
424
425
426 LOG.debug("Reading group that was just added to ldap server: {}", grouperGroup);
427 LdapGroup result = fetchTargetSystemGroup(grouperGroup);
428
429 if ( result == null ) {
430 LOG.error("{}: Group could not be found after it was created: {}", getDisplayName(), grouperGroup);
431 }
432 return result;
433 } catch (PspException e) {
434 LOG.error("Problem while creating new group: {}", ldif, e);
435 throw e;
436 } catch ( IOException e ) {
437 LOG.error("IO problem while creating group: {}", ldif, e);
438 throw new PspException("IO problem while creating group: %s", e.getMessage());
439 }
440 finally {
441 conn.close();
442 }
443 }
444
445
446
447
448
449
450
451
452
453 private LdapEntry getLdapEntryFromLdif(String ldif) throws IOException {
454 Reader reader = new StringReader(ldif);
455 LdifReader ldifReader = new LdifReader(reader);
456 SearchResult ldifResult = ldifReader.read();
457 LdapEntry ldifEntry = ldifResult.getEntry();
458
459
460 String actualDn = String.format("%s,%s", ldifEntry.getDn(),config.getGroupCreationBaseDn());
461 ldifEntry.setDn(actualDn);
462 return ldifEntry;
463 }
464
465
466
467
468
469
470
471
472 private String getGroupLdifFromTemplate(GrouperGroupInfo grouperGroup, boolean stripMembershipAttributeWithNullDn) throws PspException {
473 String ldif = config.getGroupCreationLdifTemplate();
474
475 if(stripMembershipAttributeWithNullDn) {
476 LOG.debug("Stripping membership attribute {} with null DN value. LDIF string before is: {}", config.getMemberAttributeName(), ldif);
477 ldif = ldif.replaceAll(config.getMemberAttributeName() + ":\\|\\|", "");
478 LOG.debug("LDIF string after is: {}", ldif);
479 }
480
481 ldif = ldif.replaceAll("\\|\\|", "\n");
482 ldif = evaluateJexlExpression("GroupTemplate", ldif, null, null, grouperGroup, null);
483 ldif = sanityCheckDnAttributesOfLdif(ldif, "Group ldif for %s", grouperGroup);
484
485 return ldif;
486 }
487
488 private String getGroupLdifFromTemplate(GrouperGroupInfo grouperGroup) throws PspException {
489 return getGroupLdifFromTemplate(grouperGroup, false);
490 }
491
492 @Override
493 protected Map<GrouperGroupInfo, LdapGroup> fetchTargetSystemGroups(
494 Collection<GrouperGroupInfo> grouperGroupsToFetch) throws PspException {
495 if ( grouperGroupsToFetch.size() > config.getGroupSearch_batchSize() )
496 throw new IllegalArgumentException("LdapGroupProvisioner.fetchTargetSystemGroups: invoked with too many groups to fetch");
497
498
499
500 String[] returnAttributes = getLdapAttributesToFetch();
501
502 if ( grouperGroupsToFetch.size() > 1 && config.isBulkGroupSearchingEnabled() ) {
503 StringBuilder combinedLdapFilter = new StringBuilder();
504
505
506 combinedLdapFilter.append("(|");
507
508 for (GrouperGroupInfo grouperGroup : grouperGroupsToFetch) {
509 SearchFilter f = getGroupLdapFilter(grouperGroup);
510 String groupFilterString = f.format();
511
512
513 if (groupFilterString.startsWith("("))
514 combinedLdapFilter.append(groupFilterString);
515 else
516 combinedLdapFilter.append('(').append(groupFilterString).append(')');
517 }
518 combinedLdapFilter.append(')');
519
520
521 List<LdapObject> searchResult;
522
523 LOG.debug("{}: Searching for {} groups with:: {}",
524 new Object[]{getDisplayName(), grouperGroupsToFetch.size(), combinedLdapFilter});
525
526 try {
527 searchResult = getLdapSystem().performLdapSearchRequest(
528 -1, config.getGroupSearchBaseDn(), SearchScope.SUBTREE,
529 Arrays.asList(returnAttributes),
530 combinedLdapFilter.toString());
531 } catch (PspException e) {
532 LOG.error("Problem fetching groups with filter '{}' on base '{}'",
533 new Object[]{combinedLdapFilter, config.getGroupSearchBaseDn(), e});
534 throw e;
535 }
536
537 LOG.debug("{}: Group search returned {} groups", getDisplayName(), searchResult.size());
538
539
540
541
542 Map<GrouperGroupInfo, LdapGroup> result = new HashMap<GrouperGroupInfo, LdapGroup>();
543
544 Set<LdapObject> matchedFetchResults = new HashSet<LdapObject>();
545
546
547 for (GrouperGroupInfo groupToFetch : grouperGroupsToFetch) {
548 SearchFilter f = getGroupLdapFilter(groupToFetch);
549
550 for (LdapObject aFetchedLdapObject : searchResult) {
551 if (aFetchedLdapObject.matchesLdapFilter(f)) {
552 result.put(groupToFetch, new LdapGroup(aFetchedLdapObject));
553 matchedFetchResults.add(aFetchedLdapObject);
554 break;
555 }
556 }
557 }
558
559 Set<LdapObject> unmatchedFetchResults = new HashSet<LdapObject>(searchResult);
560 unmatchedFetchResults.removeAll(matchedFetchResults);
561
562
563 if ( unmatchedFetchResults.size() == 0 ) {
564 return result;
565 }
566 else {
567 for (LdapObject unmatchedFetchResult : unmatchedFetchResults) {
568 LOG.warn("{}: Bulk fetch failed (returned unmatchable group data). "
569 + "This can be caused by searching for a DN with escaping or by singleGroupSearchFilter ({}) that are not included "
570 + "in groupSearchAttributes ({})?): {}",
571 new Object[]{getDisplayName(), config.getSingleGroupSearchFilter(), config.getGroupSearchAttributes(), unmatchedFetchResult.getDn()});
572 }
573 LOG.warn("{}: Slower fetching will be attempted", getDisplayName());
574
575
576
577 }
578 }
579
580
581 Map<GrouperGroupInfo, LdapGroup> result = new HashMap<GrouperGroupInfo, LdapGroup>();
582
583 for (GrouperGroupInfo grouperGroup : grouperGroupsToFetch) {
584 SearchFilter groupLdapFilter = null;
585 if (grouperGroup == null) {
586 continue;
587 }
588 try {
589 groupLdapFilter = getGroupLdapFilter(grouperGroup);
590 } catch (DeletedGroupException dge) {
591 LOG.debug("{}: " + dge.getMessage(), getDisplayName());
592
593 continue;
594 }
595 try {
596 LOG.debug("{}: Searching for group {} with:: {}",
597 new Object[]{getDisplayName(), grouperGroup, groupLdapFilter});
598
599
600 List<LdapObject> searchResult = getLdapSystem().performLdapSearchRequest(
601 -1, config.getGroupSearchBaseDn(), SearchScope.SUBTREE,
602 Arrays.asList(returnAttributes),
603 groupLdapFilter);
604
605 if (searchResult.size() == 1) {
606 LdapObject ldapObject = searchResult.iterator().next();
607 LOG.debug("{}: Group search returned {}", getDisplayName(), ldapObject.getDn());
608 result.put(grouperGroup, new LdapGroup(ldapObject));
609 }
610 else if ( searchResult.size() > 1 ){
611 LOG.error("{}: Search for group {} with '{}' returned multiple matches: {}",
612 new Object[]{getDisplayName(), grouperGroup, groupLdapFilter, searchResult});
613 throw new PspException("Search for ldap group returned multiple matches");
614 }
615 else if ( searchResult.size() == 0 ) {
616
617 LOG.debug("{}: Group search did not return any results", getDisplayName());
618 }
619 } catch (PspException e) {
620 LOG.error("{}: Problem fetching group with filter '{}' on base '{}'",
621 new Object[]{getDisplayName(), groupLdapFilter, config.getGroupSearchBaseDn(), e});
622 throw e;
623 }
624 }
625
626 return result;
627 }
628
629 private String[] getLdapAttributesToFetch() {
630 String returnAttributes[] = config.getGroupSearchAttributes();
631 if ( fullSyncMode ) {
632 LOG.debug("Fetching membership attribute, too");
633
634 returnAttributes = Arrays.copyOf(returnAttributes, returnAttributes.length + 1);
635 returnAttributes[returnAttributes.length-1] = config.getMemberAttributeName();
636 } else {
637 LOG.debug("Fetching without membership attribute");
638 }
639 return returnAttributes;
640 }
641
642
643 private SearchFilter getGroupLdapFilter(GrouperGroupInfo grouperGroup) throws PspException {
644 String result = evaluateJexlExpression("SingleGroupSearchFilter", config.getSingleGroupSearchFilter(), null, null, grouperGroup, null);
645 if ( StringUtils.isEmpty(result) )
646 throw new RuntimeException("Group searching requires singleGroupSearchFilter to be configured correctly");
647
648
649 String filterPieces[] = result.split("\\|\\|");
650 SearchFilter filter = new SearchFilter(filterPieces[0]);
651
652 if ( filterPieces.length == 1 ) {
653 try {
654
655 Filter.create(result);
656 }
657 catch (LDAPException e) {
658 LOG.warn("{}: Group ldap filter was invalid. " +
659 "Perhaps its filter clauses needed to be escaped with utils.escapeLdapFilter or use ldap-filter positional parameters. " +
660 "Group={}. Bad filter={}. ",
661 new Object[]{getDisplayName(), grouperGroup, result});
662
663
664
665 }
666 } else {
667
668
669 for (int i = 1; i < filterPieces.length; i++)
670 filter.setParameter(i - 1, filterPieces[i].trim());
671 }
672
673 LOG.trace("{}: Filter for group {}: {}",
674 new Object[] {getDisplayName(), grouperGroup, filter});
675
676 return filter;
677 }
678
679
680 @Override
681 protected void deleteGroup(GrouperGroupInfo grouperGroupInfo, LdapGroup ldapGroup)
682 throws PspException {
683 if ( ldapGroup == null ) {
684 LOG.warn("Nothing to do: Unable to delete group {} because the group wasn't found on target system", grouperGroupInfo);
685 return;
686 }
687
688 String dn = ldapGroup.getLdapObject().getDn();
689
690 LOG.info("Deleting group {} by deleting DN {}", grouperGroupInfo, dn);
691 JobStatistics jobStatistics = this.getJobStatistics();
692 if (jobStatistics != null) {
693 jobStatistics.deleteCount.addAndGet(1);
694 }
695
696 getLdapSystem().performLdapDelete(dn);
697 }
698 }