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 }