001 /*
002 * Copyright 2011-2015 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2015 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021 package com.unboundid.ldap.sdk.unboundidds.tasks;
022
023
024
025 import java.util.ArrayList;
026 import java.util.Arrays;
027 import java.util.Collections;
028 import java.util.Date;
029 import java.util.LinkedHashMap;
030 import java.util.LinkedList;
031 import java.util.List;
032 import java.util.Map;
033
034 import com.unboundid.ldap.sdk.Attribute;
035 import com.unboundid.ldap.sdk.Entry;
036 import com.unboundid.ldap.sdk.Filter;
037 import com.unboundid.ldap.sdk.LDAPException;
038 import com.unboundid.util.NotMutable;
039 import com.unboundid.util.StaticUtils;
040 import com.unboundid.util.ThreadSafety;
041 import com.unboundid.util.ThreadSafetyLevel;
042
043 import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*;
044 import static com.unboundid.util.Validator.*;
045
046
047
048 /**
049 * <BLOCKQUOTE>
050 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID
051 * LDAP SDK for Java. It is not available for use in applications that
052 * include only the Standard Edition of the LDAP SDK, and is not supported for
053 * use in conjunction with non-UnboundID products.
054 * </BLOCKQUOTE>
055 * This class defines a Directory Server task that can be used to cause the
056 * server to initiate a data security audit, which can look for potential
057 * issues in the environment that can impact the security of the directory
058 * environment.
059 * <BR><BR>
060 * The properties that are available for use with this type of task include:
061 * <UL>
062 * <LI>The names of the auditors to include or exclude from the audit. This
063 * is optional, and if it is not provided, then all enabled auditors will
064 * be used.</LI>
065 * <LI>The backend IDs for the backends containing the data to be audited.
066 * This is optional, and if it is not provided then the server will run
067 * the audit in all backends that support this capability.</LI>
068 * <LI>A set of filters which identify the entries that should be examined by
069 * the audit. This is optional, and if it is not provided, then all
070 * entries in the selected backends will be included.</LI>
071 * <LI>The path to the directory in which the output files should be
072 * generated. This is optional, and if it is not provided then the server
073 * will use a default output directory.</LI>
074 * </UL>
075 */
076 @NotMutable()
077 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
078 public final class AuditDataSecurityTask
079 extends Task
080 {
081 /**
082 * The fully-qualified name of the Java class that is used for the audit data
083 * security task.
084 */
085 static final String AUDIT_DATA_SECURITY_TASK_CLASS =
086 "com.unboundid.directory.server.tasks.AuditDataSecurityTask";
087
088
089
090 /**
091 * The name of the attribute used to specify the set of auditors to use to
092 * examine the data.
093 */
094 private static final String ATTR_INCLUDE_AUDITOR =
095 "ds-task-audit-data-security-include-auditor";
096
097
098
099 /**
100 * The name of the attribute used to specify the set of auditors that should
101 * not be used when examining the data.
102 */
103 private static final String ATTR_EXCLUDE_AUDITOR =
104 "ds-task-audit-data-security-exclude-auditor";
105
106
107
108 /**
109 * The name of the attribute used to the backend IDs for the backends in which
110 * the audit should be performed.
111 */
112 private static final String ATTR_BACKEND_ID =
113 "ds-task-audit-data-security-backend-id";
114
115
116
117 /**
118 * The name of the attribute used to specify a set of filters that should be
119 * used to identify entries to include in the audit.
120 */
121 private static final String ATTR_REPORT_FILTER =
122 "ds-task-audit-data-security-report-filter";
123
124
125
126 /**
127 * The name of the attribute used to specify the directory in which the report
128 * output files should be written.
129 */
130 private static final String ATTR_OUTPUT_DIRECTORY =
131 "ds-task-audit-data-security-output-directory";
132
133
134
135 /**
136 * The name of the object class used in audit data security task entries.
137 */
138 private static final String OC_AUDIT_DATA_SECURITY_TASK =
139 "ds-task-audit-data-security";
140
141
142
143 /**
144 * The task property that will be used for the included set of auditors.
145 */
146 private static final TaskProperty PROPERTY_INCLUDE_AUDITOR =
147 new TaskProperty(ATTR_INCLUDE_AUDITOR,
148 INFO_AUDIT_DATA_SECURITY_DISPLAY_NAME_INCLUDE_AUDITOR.get(),
149 INFO_AUDIT_DATA_SECURITY_DESCRIPTION_INCLUDE_AUDITOR.get(),
150 String.class, false, true, false);
151
152
153
154 /**
155 * The task property that will be used for the excluded set of auditors.
156 */
157 private static final TaskProperty PROPERTY_EXCLUDE_AUDITOR =
158 new TaskProperty(ATTR_EXCLUDE_AUDITOR,
159 INFO_AUDIT_DATA_SECURITY_DISPLAY_NAME_EXCLUDE_AUDITOR.get(),
160 INFO_AUDIT_DATA_SECURITY_DESCRIPTION_EXCLUDE_AUDITOR.get(),
161 String.class, false, true, false);
162
163
164
165 /**
166 * The task property that will be used for the backend IDs.
167 */
168 private static final TaskProperty PROPERTY_BACKEND_ID =
169 new TaskProperty(ATTR_BACKEND_ID,
170 INFO_AUDIT_DATA_SECURITY_DISPLAY_NAME_BACKEND_ID.get(),
171 INFO_AUDIT_DATA_SECURITY_DESCRIPTION_BACKEND_ID.get(),
172 String.class, false, true, false);
173
174
175
176 /**
177 * The task property that will be used for the report filters.
178 */
179 private static final TaskProperty PROPERTY_REPORT_FILTER =
180 new TaskProperty(ATTR_REPORT_FILTER,
181 INFO_AUDIT_DATA_SECURITY_DISPLAY_NAME_REPORT_FILTER.get(),
182 INFO_AUDIT_DATA_SECURITY_DESCRIPTION_REPORT_FILTER.get(),
183 String.class, false, true, false);
184
185
186
187 /**
188 * The task property that will be used for the output directory.
189 */
190 private static final TaskProperty PROPERTY_OUTPUT_DIRECTORY =
191 new TaskProperty(ATTR_OUTPUT_DIRECTORY,
192 INFO_AUDIT_DATA_SECURITY_DISPLAY_NAME_OUTPUT_DIR.get(),
193 INFO_AUDIT_DATA_SECURITY_DESCRIPTION_OUTPUT_DIR.get(),
194 String.class, false, false, false);
195
196
197
198 /**
199 * The serial version UID for this serializable class.
200 */
201 private static final long serialVersionUID = -4994621474763299632L;
202
203
204
205 // The backend IDs of the backends in which the audit should be performed.
206 private final List<String> backendIDs;
207
208 // The names of the excluded auditors to use in the audit.
209 private final List<String> excludeAuditors;
210
211 // The names of the included auditors to use in the audit.
212 private final List<String> includeAuditors;
213
214 // The report filters to select entries to audit.
215 private final List<String> reportFilters;
216
217 // The path of the output directory to use for report data files.
218 private final String outputDirectory;
219
220
221
222 /**
223 * Creates a new uninitialized audit data security task instance which should
224 * only be used for obtaining general information about this task, including
225 * the task name, description, and supported properties. Attempts to use a
226 * task created with this constructor for any other reason will likely fail.
227 */
228 public AuditDataSecurityTask()
229 {
230 excludeAuditors = null;
231 includeAuditors = null;
232 backendIDs = null;
233 reportFilters = null;
234 outputDirectory = null;
235 }
236
237
238
239 /**
240 * Creates a new audit data security task with the provided information and
241 * default settings for all general task properties.
242 *
243 * @param includeAuditors The names of the auditors that should be used to
244 * examine the data. It may be {@code null} or empty
245 * if an exclude list should be provided, or if all
246 * enabled auditors should be invoked. You must not
247 * provide both include and exclude auditors.
248 * @param excludeAuditors The names of the auditors that should be excluded
249 * when examining the data. It may be {@code null}
250 * or empty if an include list should be provided, or
251 * if all enabled auditors should be invoked. You
252 * must not provide both include and exclude
253 * auditors.
254 * @param backendIDs The backend IDs of the backends containing the
255 * data to examine. It may be {@code null} or empty
256 * if all supported backends should be selected.
257 * @param reportFilters A set of filters which identify entries that
258 * should be examined. It may be {@code null} or
259 * empty if all entries should be examined.
260 * @param outputDirectory The path to the output directory (on the server
261 * filesystem) in which report data files should be
262 * written. It may be {@code null} if a default
263 * output directory should be used.
264 */
265 public AuditDataSecurityTask(final List<String> includeAuditors,
266 final List<String> excludeAuditors,
267 final List<String> backendIDs,
268 final List<String> reportFilters,
269 final String outputDirectory)
270 {
271 this(null, includeAuditors, excludeAuditors, backendIDs, reportFilters,
272 outputDirectory, null, null, null, null, null);
273 }
274
275
276
277 /**
278 * Creates a new audit data security task with the provided information.
279 *
280 * @param taskID The task ID to use for this task. If it is
281 * {@code null} then a UUID will be generated
282 * for use as the task ID.
283 * @param includeAuditors The names of the auditors that should be
284 * used to examine the data. It may be
285 * {@code null} or empty if an exclude list
286 * should be provided, or if all enabled
287 * auditors should be invoked. You must not
288 * provide both include and exclude auditors.
289 * @param excludeAuditors The names of the auditors that should be
290 * excluded when examining the data. It may
291 * be {@code null} or empty if an include list
292 * should be provided, or if all enabled
293 * auditors should be invoked. You must not
294 * provide both include and exclude auditors.
295 * @param backendIDs The backend IDs of the backends containing
296 * the data to examine. It may be
297 * {@code null} or empty if all supported
298 * backends should be selected.
299 * @param reportFilters A set of filters which identify entries
300 * that should be examined. It may be
301 * {@code null} or empty if all entries should
302 * be examined.
303 * @param outputDirectory The path to the output directory (on the
304 * server filesystem) in which report data
305 * files should be written. It may be
306 * {@code null} if a default output directory
307 * should be used.
308 * @param scheduledStartTime The time that this task should start
309 * running.
310 * @param dependencyIDs The list of task IDs that will be required
311 * to complete before this task will be
312 * eligible to start.
313 * @param failedDependencyAction Indicates what action should be taken if
314 * any of the dependencies for this task do
315 * not complete successfully.
316 * @param notifyOnCompletion The list of e-mail addresses of individuals
317 * that should be notified when this task
318 * completes.
319 * @param notifyOnError The list of e-mail addresses of individuals
320 * that should be notified if this task does
321 * not complete successfully.
322 */
323 public AuditDataSecurityTask(final String taskID,
324 final List<String> includeAuditors,
325 final List<String> excludeAuditors, final List<String> backendIDs,
326 final List<String> reportFilters, final String outputDirectory,
327 final Date scheduledStartTime, final List<String> dependencyIDs,
328 final FailedDependencyAction failedDependencyAction,
329 final List<String> notifyOnCompletion,
330 final List<String> notifyOnError)
331 {
332 super(taskID, AUDIT_DATA_SECURITY_TASK_CLASS, scheduledStartTime,
333 dependencyIDs, failedDependencyAction, notifyOnCompletion,
334 notifyOnError);
335
336 this.includeAuditors = getStringList(includeAuditors);
337 this.excludeAuditors = getStringList(excludeAuditors);
338 this.backendIDs = getStringList(backendIDs);
339 this.reportFilters = getStringList(reportFilters);
340 this.outputDirectory = outputDirectory;
341
342 ensureTrue(
343 (this.includeAuditors.isEmpty() || this.excludeAuditors.isEmpty()),
344 "You cannot request both include and exclude auditors.");
345 }
346
347
348
349 /**
350 * Creates a new audit data security task from the provided entry.
351 *
352 * @param entry The entry to use to create this audit data security task.
353 *
354 * @throws TaskException If the provided entry cannot be parsed as an audit
355 * data security task entry.
356 */
357 public AuditDataSecurityTask(final Entry entry)
358 throws TaskException
359 {
360 super(entry);
361
362 includeAuditors = Collections.unmodifiableList(StaticUtils.toNonNullList(
363 entry.getAttributeValues(ATTR_INCLUDE_AUDITOR)));
364 excludeAuditors = Collections.unmodifiableList(StaticUtils.toNonNullList(
365 entry.getAttributeValues(ATTR_EXCLUDE_AUDITOR)));
366 backendIDs = Collections.unmodifiableList(StaticUtils.toNonNullList(
367 entry.getAttributeValues(ATTR_BACKEND_ID)));
368 reportFilters = Collections.unmodifiableList(StaticUtils.toNonNullList(
369 entry.getAttributeValues(ATTR_REPORT_FILTER)));
370 outputDirectory = entry.getAttributeValue(ATTR_OUTPUT_DIRECTORY);
371 }
372
373
374
375 /**
376 * Creates a new audit data security task from the provided set of task
377 * properties.
378 *
379 * @param properties The set of task properties and their corresponding
380 * values to use for the task. It must not be
381 * {@code null}.
382 *
383 * @throws TaskException If the provided set of properties cannot be used to
384 * create a valid audit data security task.
385 */
386 public AuditDataSecurityTask(final Map<TaskProperty,List<Object>> properties)
387 throws TaskException
388 {
389 super(AUDIT_DATA_SECURITY_TASK_CLASS, properties);
390
391 String outputDir = null;
392 final LinkedList<String> includeAuditorsList = new LinkedList<String>();
393 final LinkedList<String> excludeAuditorsList = new LinkedList<String>();
394 final LinkedList<String> backendIDList = new LinkedList<String>();
395 final LinkedList<String> reportFilterList = new LinkedList<String>();
396 for (final Map.Entry<TaskProperty,List<Object>> entry :
397 properties.entrySet())
398 {
399 final TaskProperty p = entry.getKey();
400 final String attrName = StaticUtils.toLowerCase(p.getAttributeName());
401 final List<Object> values = entry.getValue();
402
403 if (attrName.equals(ATTR_INCLUDE_AUDITOR))
404 {
405 final String[] s = parseStrings(p, values, null);
406 if (s != null)
407 {
408 includeAuditorsList.addAll(Arrays.asList(s));
409 }
410 }
411 else if (attrName.equals(ATTR_EXCLUDE_AUDITOR))
412 {
413 final String[] s = parseStrings(p, values, null);
414 if (s != null)
415 {
416 excludeAuditorsList.addAll(Arrays.asList(s));
417 }
418 }
419 else if (attrName.equals(ATTR_BACKEND_ID))
420 {
421 final String[] s = parseStrings(p, values, null);
422 if (s != null)
423 {
424 backendIDList.addAll(Arrays.asList(s));
425 }
426 }
427 else if (attrName.equals(ATTR_REPORT_FILTER))
428 {
429 final String[] s = parseStrings(p, values, null);
430 if (s != null)
431 {
432 reportFilterList.addAll(Arrays.asList(s));
433 }
434 }
435 else if (attrName.equals(ATTR_OUTPUT_DIRECTORY))
436 {
437 outputDir = parseString(p, values, null);
438 }
439 }
440
441 includeAuditors = Collections.unmodifiableList(includeAuditorsList);
442 excludeAuditors = Collections.unmodifiableList(excludeAuditorsList);
443 backendIDs = Collections.unmodifiableList(backendIDList);
444 reportFilters = Collections.unmodifiableList(reportFilterList);
445 outputDirectory = outputDir;
446
447 if ((! includeAuditors.isEmpty()) && (! excludeAuditors.isEmpty()))
448 {
449 throw new TaskException(
450 ERR_AUDIT_DATA_SECURITY_BOTH_INCLUDE_AND_EXCLUDE_AUDITORS.get());
451 }
452 }
453
454
455
456 /**
457 * {@inheritDoc}
458 */
459 @Override()
460 public String getTaskName()
461 {
462 return INFO_TASK_NAME_AUDIT_DATA_SECURITY.get();
463 }
464
465
466
467 /**
468 * {@inheritDoc}
469 */
470 @Override()
471 public String getTaskDescription()
472 {
473 return INFO_TASK_DESCRIPTION_AUDIT_DATA_SECURITY.get();
474 }
475
476
477
478 /**
479 * Retrieves the names of the auditors that should be invoked during the
480 * data security audit.
481 *
482 * @return The names of the include auditors that should be used for the
483 * task, or an empty list if either an exclude list should be used or
484 * all enabled auditors should be used.
485 */
486 public List<String> getIncludeAuditors()
487 {
488 return includeAuditors;
489 }
490
491
492
493 /**
494 * Retrieves the names of the auditors that should not be invoked during the
495 * audit.
496 *
497 * @return The names of the exclude auditors that should be used for the
498 * task, or an empty list if either an include list should be used or
499 * all enabled auditors should be used.
500 */
501 public List<String> getExcludeAuditors()
502 {
503 return excludeAuditors;
504 }
505
506
507
508 /**
509 * Retrieves the backend IDs of the backends that should be examined during
510 * the course of the audit.
511 *
512 * @return The backend IDs of the backends that should be examined during the
513 * course of the audit, or an empty list if all backends that support
514 * this capability should be used.
515 */
516 public List<String> getBackendIDs()
517 {
518 return backendIDs;
519 }
520
521
522
523 /**
524 * Retrieves the string representations of the report filters that should be
525 * used to identify which entries should be examined during the course of the
526 * audit.
527 *
528 * @return The string representations of the report filters that should be
529 * used to identify which entries should be examined during the
530 * course of the audit, or an empty list if all entries should be
531 * examined.
532 */
533 public List<String> getReportFilterStrings()
534 {
535 return reportFilters;
536 }
537
538
539
540 /**
541 * Retrieves the parsed report filters that should be used to identify which
542 * entries should be examined during the course of the audit.
543 *
544 * @return The parsed report filters that should be used to identify which
545 * entries should be examined during the course of the audit, or an
546 * empty list if all entries should be examined.
547 *
548 * @throws LDAPException If any of the filter strings cannot be parsed as a
549 * valid filter.
550 */
551 public List<Filter> getReportFilters()
552 throws LDAPException
553 {
554 if (reportFilters.isEmpty())
555 {
556 return Collections.emptyList();
557 }
558
559 final ArrayList<Filter> filterList =
560 new ArrayList<Filter>(reportFilters.size());
561 for (final String filter : reportFilters)
562 {
563 filterList.add(Filter.create(filter));
564 }
565 return Collections.unmodifiableList(filterList);
566 }
567
568
569
570 /**
571 * Retrieves the path to the directory on the server filesystem in which the
572 * report output files should be written.
573 *
574 * @return The path to the directory on the server filesystem in which the
575 * report output files should be written.
576 */
577 public String getOutputDirectory()
578 {
579 return outputDirectory;
580 }
581
582
583
584 /**
585 * {@inheritDoc}
586 */
587 @Override()
588 protected List<String> getAdditionalObjectClasses()
589 {
590 return Arrays.asList(OC_AUDIT_DATA_SECURITY_TASK);
591 }
592
593
594
595 /**
596 * {@inheritDoc}
597 */
598 @Override()
599 protected List<Attribute> getAdditionalAttributes()
600 {
601 final LinkedList<Attribute> attrList = new LinkedList<Attribute>();
602
603 if (! includeAuditors.isEmpty())
604 {
605 attrList.add(new Attribute(ATTR_INCLUDE_AUDITOR, includeAuditors));
606 }
607
608 if (! excludeAuditors.isEmpty())
609 {
610 attrList.add(new Attribute(ATTR_EXCLUDE_AUDITOR, excludeAuditors));
611 }
612
613 if (! backendIDs.isEmpty())
614 {
615 attrList.add(new Attribute(ATTR_BACKEND_ID, backendIDs));
616 }
617
618 if (! reportFilters.isEmpty())
619 {
620 attrList.add(new Attribute(ATTR_REPORT_FILTER, reportFilters));
621 }
622
623 if (outputDirectory != null)
624 {
625 attrList.add(new Attribute(ATTR_OUTPUT_DIRECTORY, outputDirectory));
626 }
627
628 return attrList;
629 }
630
631
632
633 /**
634 * {@inheritDoc}
635 */
636 @Override()
637 public List<TaskProperty> getTaskSpecificProperties()
638 {
639 return Collections.unmodifiableList(Arrays.asList(
640 PROPERTY_INCLUDE_AUDITOR,
641 PROPERTY_EXCLUDE_AUDITOR,
642 PROPERTY_BACKEND_ID,
643 PROPERTY_REPORT_FILTER,
644 PROPERTY_OUTPUT_DIRECTORY));
645 }
646
647
648
649 /**
650 * {@inheritDoc}
651 */
652 @Override()
653 public Map<TaskProperty,List<Object>> getTaskPropertyValues()
654 {
655 final LinkedHashMap<TaskProperty,List<Object>> props =
656 new LinkedHashMap<TaskProperty,List<Object>>(5);
657
658 if (! includeAuditors.isEmpty())
659 {
660 props.put(PROPERTY_INCLUDE_AUDITOR,
661 Collections.<Object>unmodifiableList(includeAuditors));
662 }
663
664 if (! excludeAuditors.isEmpty())
665 {
666 props.put(PROPERTY_EXCLUDE_AUDITOR,
667 Collections.<Object>unmodifiableList(excludeAuditors));
668 }
669
670 if (! backendIDs.isEmpty())
671 {
672 props.put(PROPERTY_BACKEND_ID,
673 Collections.<Object>unmodifiableList(backendIDs));
674 }
675
676 if (! reportFilters.isEmpty())
677 {
678 props.put(PROPERTY_REPORT_FILTER,
679 Collections.<Object>unmodifiableList(reportFilters));
680 }
681
682 if (outputDirectory != null)
683 {
684 props.put(PROPERTY_OUTPUT_DIRECTORY,
685 Collections.<Object>unmodifiableList(Arrays.asList(
686 outputDirectory)));
687 }
688
689 return Collections.unmodifiableMap(props);
690 }
691
692
693
694 /**
695 * Retrieves an unmodifiable list using information from the provided list.
696 * If the given list is {@code null}, then an empty list will be returned.
697 * Otherwise, an unmodifiable version of the provided list will be returned.
698 *
699 * @param l The list to be processed.
700 *
701 * @return The resulting string list.
702 */
703 private static List<String> getStringList(final List<String> l)
704 {
705 if (l == null)
706 {
707 return Collections.emptyList();
708 }
709 else
710 {
711 return Collections.unmodifiableList(l);
712 }
713 }
714 }