001/* 002 * Copyright 2016-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2016-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2016-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.unboundidds.tools; 037 038 039 040import java.io.BufferedReader; 041import java.io.File; 042import java.io.FileOutputStream; 043import java.io.FileReader; 044import java.io.OutputStream; 045import java.util.ArrayList; 046import java.util.Arrays; 047import java.util.LinkedHashMap; 048import java.util.concurrent.atomic.AtomicBoolean; 049 050import com.unboundid.ldap.sdk.DN; 051import com.unboundid.ldap.sdk.ExtendedResult; 052import com.unboundid.ldap.sdk.Filter; 053import com.unboundid.ldap.sdk.LDAPConnection; 054import com.unboundid.ldap.sdk.LDAPConnectionOptions; 055import com.unboundid.ldap.sdk.LDAPConnectionPool; 056import com.unboundid.ldap.sdk.LDAPException; 057import com.unboundid.ldap.sdk.ResultCode; 058import com.unboundid.ldap.sdk.UnsolicitedNotificationHandler; 059import com.unboundid.ldap.sdk.Version; 060import com.unboundid.ldif.LDIFWriter; 061import com.unboundid.util.Debug; 062import com.unboundid.util.DNFileReader; 063import com.unboundid.util.LDAPCommandLineTool; 064import com.unboundid.util.FilterFileReader; 065import com.unboundid.util.FixedRateBarrier; 066import com.unboundid.util.NotNull; 067import com.unboundid.util.Nullable; 068import com.unboundid.util.RateAdjustor; 069import com.unboundid.util.StaticUtils; 070import com.unboundid.util.ThreadSafety; 071import com.unboundid.util.ThreadSafetyLevel; 072import com.unboundid.util.args.ArgumentException; 073import com.unboundid.util.args.ArgumentParser; 074import com.unboundid.util.args.BooleanArgument; 075import com.unboundid.util.args.BooleanValueArgument; 076import com.unboundid.util.args.DNArgument; 077import com.unboundid.util.args.FileArgument; 078import com.unboundid.util.args.FilterArgument; 079import com.unboundid.util.args.IPAddressArgumentValueValidator; 080import com.unboundid.util.args.IntegerArgument; 081import com.unboundid.util.args.StringArgument; 082import com.unboundid.util.args.TimestampArgument; 083import com.unboundid.util.args.SubCommand; 084 085import static com.unboundid.ldap.sdk.unboundidds.tools.ToolMessages.*; 086 087 088 089/** 090 * This class provides a tool that can be used to perform a variety of account 091 * management functions against user entries in the Ping Identity, UnboundID, 092 * or Nokia/Alcatel-Lucent 8661 Directory Server. It primarily uses the 093 * password policy state extended operation for its processing. 094 * <BR> 095 * <BLOCKQUOTE> 096 * <B>NOTE:</B> This class, and other classes within the 097 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 098 * supported for use against Ping Identity, UnboundID, and 099 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 100 * for proprietary functionality or for external specifications that are not 101 * considered stable or mature enough to be guaranteed to work in an 102 * interoperable way with other types of LDAP servers. 103 * </BLOCKQUOTE> 104 */ 105@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 106public final class ManageAccount 107 extends LDAPCommandLineTool 108 implements UnsolicitedNotificationHandler 109{ 110 /** 111 * The column at which to wrap long lines. 112 */ 113 private static final int WRAP_COLUMN = StaticUtils.TERMINAL_WIDTH_COLUMNS - 1; 114 115 116 117 /** 118 * The primary name of the argument used to indicate that the tool should 119 * append to the reject file rather than overwrite it. 120 */ 121 @NotNull private static final String ARG_APPEND_TO_REJECT_FILE = 122 "appendToRejectFile"; 123 124 125 126 /** 127 * The primary name of the argument used to specify a base DN to use for 128 * searches. 129 */ 130 @NotNull static final String ARG_BASE_DN = "baseDN"; 131 132 133 134 /** 135 * The primary name of the argument used to specify the path to a file to a 136 * sample variable rate data file to create. 137 */ 138 @NotNull private static final String ARG_GENERATE_SAMPLE_RATE_FILE = 139 "generateSampleRateFile"; 140 141 142 143 /** 144 * The primary name of the argument used to specify the path to a file 145 * containing the DNs of the users on which to operate. 146 */ 147 @NotNull private static final String ARG_DN_INPUT_FILE = "dnInputFile"; 148 149 150 151 /** 152 * The primary name of the argument used to specify the path to a file 153 * containing search filters to use to identify users. 154 */ 155 @NotNull private static final String ARG_FILTER_INPUT_FILE = 156 "filterInputFile"; 157 158 159 160 /** 161 * The primary name of the argument used to specify the number of threads to 162 * use to process search operations to identify which users to target. 163 */ 164 @NotNull static final String ARG_NUM_SEARCH_THREADS = "numSearchThreads"; 165 166 167 168 /** 169 * The primary name of the argument used to specify the number of threads to 170 * use to perform manage-account processing. 171 */ 172 @NotNull static final String ARG_NUM_THREADS = "numThreads"; 173 174 175 176 /** 177 * The primary name of the argument used to specify the target rate of 178 * operations per second. 179 */ 180 @NotNull private static final String ARG_RATE_PER_SECOND = "ratePerSecond"; 181 182 183 184 /** 185 * The primary name of the argument used to specify the path to a reject file 186 * to create. 187 */ 188 @NotNull private static final String ARG_REJECT_FILE = "rejectFile"; 189 190 191 192 /** 193 * The primary name of the argument used to specify the simple page size to 194 * use when performing searches. 195 */ 196 @NotNull static final String ARG_SIMPLE_PAGE_SIZE = "simplePageSize"; 197 198 199 200 /** 201 * The primary name of the argument used to suppress result operation types 202 * without values. 203 */ 204 @NotNull static final String ARG_SUPPRESS_EMPTY_RESULT_OPERATIONS = 205 "suppressEmptyResultOperations"; 206 207 208 209 /** 210 * The primary name of the argument used to specify the DN of the user on 211 * which to operate. 212 */ 213 @NotNull private static final String ARG_TARGET_DN = "targetDN"; 214 215 216 217 /** 218 * The primary name of the argument used to specify a search filter to use to 219 * identify users. 220 */ 221 @NotNull private static final String ARG_TARGET_FILTER = "targetFilter"; 222 223 224 225 /** 226 * The primary name of the argument used to specify the user IDs of target 227 * users. 228 */ 229 @NotNull private static final String ARG_TARGET_USER_ID = "targetUserID"; 230 231 232 233 /** 234 * The primary name of the argument used to specify the name of the attribute 235 * to identify which user has a given user ID. 236 */ 237 @NotNull static final String ARG_USER_ID_ATTRIBUTE = "userIDAttribute"; 238 239 240 241 /** 242 * The primary name of the argument used to specify the path to a file 243 * containing the user IDs of the target users. 244 */ 245 @NotNull private static final String ARG_USER_ID_INPUT_FILE = 246 "userIDInputFile"; 247 248 249 250 /** 251 * The primary name of the argument used to specify the path to a variable 252 * rate data file. 253 */ 254 @NotNull private static final String ARG_VARIABLE_RATE_DATA = 255 "variableRateData"; 256 257 258 259 /** 260 * The default search base DN. 261 */ 262 @NotNull private static final DN DEFAULT_BASE_DN = DN.NULL_DN; 263 264 265 266 /** 267 * The default user ID attribute. 268 */ 269 @NotNull private static final String DEFAULT_USER_ID_ATTRIBUTE = "uid"; 270 271 272 273 /** 274 * A target user DN to use in examples. 275 */ 276 @NotNull private static final String EXAMPLE_TARGET_USER_DN = 277 "uid=jdoe,ou=People,dc=example,dc=com"; 278 279 280 281 // The argument parser for this tool. 282 @Nullable private volatile ArgumentParser parser; 283 284 // Indicates whether all DNs have been provided to the manage-account 285 // processor. 286 @NotNull private final AtomicBoolean allDNsProvided; 287 288 // Indicates whether all filters have been provided to the manage-account 289 // search processor. 290 @NotNull private final AtomicBoolean allFiltersProvided; 291 292 // Indicates whether a request has been made to cancel processing. 293 @NotNull private final AtomicBoolean cancelRequested; 294 295 // The rate limiter to use for this tool. 296 @Nullable private volatile FixedRateBarrier rateLimiter; 297 298 // The LDAP connection options to use for connections created by this tool. 299 @NotNull private final LDAPConnectionOptions connectionOptions; 300 301 // The LDIF writer to use to write information about successful and failed 302 // operations. 303 @Nullable private volatile LDIFWriter outputWriter; 304 305 // The LDIF writer to use to write information about failed operations. 306 @Nullable private volatile LDIFWriter rejectWriter; 307 308 // The search processor for this tool. 309 @Nullable private volatile ManageAccountSearchProcessor searchProcessor; 310 311 // The rate adjustor to use to vary the load over time. 312 @Nullable private volatile RateAdjustor rateAdjustor; 313 314 315 316 /** 317 * Invokes the tool with the provided set of arguments. 318 * 319 * @param args The command-line arguments provided to this tool. 320 */ 321 public static void main(@NotNull final String... args) 322 { 323 final ResultCode resultCode = main(System.out, System.err, args); 324 if (resultCode != ResultCode.SUCCESS) 325 { 326 System.exit(resultCode.intValue()); 327 } 328 } 329 330 331 332 /** 333 * Invokes the tool with the provided set of arguments. 334 * 335 * @param out The output stream to use for standard out. It may be 336 * {@code null} if standard out should be suppressed. 337 * @param err The output stream to use for standard error. It may be 338 * {@code null} if standard error should be suppressed. 339 * @param args The command-line arguments provided to this tool. 340 * 341 * @return A result code with the status of the tool processing. Any result 342 * code other than {@link ResultCode#SUCCESS} should be considered a 343 * failure. 344 */ 345 @NotNull() 346 public static ResultCode main(@Nullable final OutputStream out, 347 @Nullable final OutputStream err, 348 @NotNull final String... args) 349 { 350 final ManageAccount tool = new ManageAccount(out, err); 351 352 final boolean origCommentAboutBase64EncodedValues = 353 LDIFWriter.commentAboutBase64EncodedValues(); 354 LDIFWriter.setCommentAboutBase64EncodedValues(true); 355 try 356 { 357 return tool.runTool(args); 358 } 359 finally 360 { 361 LDIFWriter.setCommentAboutBase64EncodedValues( 362 origCommentAboutBase64EncodedValues); 363 } 364 } 365 366 367 368 /** 369 * Creates a new instance of this tool with the provided arguments. 370 * 371 * @param out The output stream to use for standard out. It may be 372 * {@code null} if standard out should be suppressed. 373 * @param err The output stream to use for standard error. It may be 374 * {@code null} if standard error should be suppressed. 375 */ 376 public ManageAccount(@Nullable final OutputStream out, 377 @Nullable final OutputStream err) 378 { 379 super(out, err); 380 381 connectionOptions = new LDAPConnectionOptions(); 382 connectionOptions.setUnsolicitedNotificationHandler(this); 383 384 allDNsProvided = new AtomicBoolean(false); 385 allFiltersProvided = new AtomicBoolean(false); 386 cancelRequested = new AtomicBoolean(false); 387 388 parser = null; 389 rateLimiter = null; 390 rateAdjustor = null; 391 outputWriter = null; 392 rejectWriter = null; 393 searchProcessor = null; 394 } 395 396 397 398 /** 399 * {@inheritDoc} 400 */ 401 @Override() 402 @NotNull() 403 public String getToolName() 404 { 405 return "manage-account"; 406 } 407 408 409 410 /** 411 * {@inheritDoc} 412 */ 413 @Override() 414 @NotNull() 415 public String getToolDescription() 416 { 417 return INFO_MANAGE_ACCT_TOOL_DESC.get(); 418 } 419 420 421 422 /** 423 * {@inheritDoc} 424 */ 425 @Override() 426 @NotNull() 427 public String getToolVersion() 428 { 429 return Version.NUMERIC_VERSION_STRING; 430 } 431 432 433 434 /** 435 * {@inheritDoc} 436 */ 437 @Override() 438 public boolean supportsInteractiveMode() 439 { 440 return true; 441 } 442 443 444 445 /** 446 * {@inheritDoc} 447 */ 448 @Override() 449 public boolean defaultsToInteractiveMode() 450 { 451 return true; 452 } 453 454 455 456 /** 457 * {@inheritDoc} 458 */ 459 @Override() 460 public boolean supportsPropertiesFile() 461 { 462 return true; 463 } 464 465 466 467 /** 468 * {@inheritDoc} 469 */ 470 @Override() 471 protected boolean supportsOutputFile() 472 { 473 return true; 474 } 475 476 477 478 /** 479 * {@inheritDoc} 480 */ 481 @Override() 482 protected boolean supportsDebugLogging() 483 { 484 return true; 485 } 486 487 488 489 /** 490 * {@inheritDoc} 491 */ 492 @Override() 493 protected boolean supportsAuthentication() 494 { 495 return true; 496 } 497 498 499 500 /** 501 * {@inheritDoc} 502 */ 503 @Override() 504 protected boolean defaultToPromptForBindPassword() 505 { 506 return true; 507 } 508 509 510 511 /** 512 * {@inheritDoc} 513 */ 514 @Override() 515 protected boolean supportsSASLHelp() 516 { 517 return true; 518 } 519 520 521 522 /** 523 * {@inheritDoc} 524 */ 525 @Override() 526 protected boolean includeAlternateLongIdentifiers() 527 { 528 return true; 529 } 530 531 532 533 /** 534 * {@inheritDoc} 535 */ 536 @Override() 537 protected boolean supportsSSLDebugging() 538 { 539 return true; 540 } 541 542 543 544 /** 545 * {@inheritDoc} 546 */ 547 @Override() 548 protected boolean supportsMultipleServers() 549 { 550 return true; 551 } 552 553 554 555 /** 556 * {@inheritDoc} 557 */ 558 @Override() 559 protected boolean logToolInvocationByDefault() 560 { 561 return true; 562 } 563 564 565 566 /** 567 * {@inheritDoc} 568 */ 569 @Override() 570 public void addNonLDAPArguments(@NotNull final ArgumentParser parser) 571 throws ArgumentException 572 { 573 // Get a copy of the argument parser for later use. 574 this.parser = parser; 575 576 577 // Get the current time formatted as a generalized time. 578 final String currentGeneralizedTime = 579 StaticUtils.encodeGeneralizedTime(System.currentTimeMillis()); 580 final String olderGeneralizedTime = 581 StaticUtils.encodeGeneralizedTime( 582 System.currentTimeMillis() - 12_345L); 583 584 585 // Define the global arguments used to indicate which users to target. 586 final DNArgument targetDN = new DNArgument('b', ARG_TARGET_DN, false, 0, 587 null, INFO_MANAGE_ACCT_ARG_DESC_TARGET_DN.get()); 588 targetDN.addLongIdentifier("userDN", true); 589 targetDN.addLongIdentifier("target-dn", true); 590 targetDN.addLongIdentifier("user-dn", true); 591 targetDN.setArgumentGroupName( 592 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 593 parser.addArgument(targetDN); 594 595 final FileArgument dnInputFile = new FileArgument(null, ARG_DN_INPUT_FILE, 596 false, 0, null, INFO_MANAGE_ACCT_ARG_DESC_DN_FILE.get(), true, 597 true, true, false); 598 dnInputFile.addLongIdentifier("targetDNFile", true); 599 dnInputFile.addLongIdentifier("userDNFile", true); 600 dnInputFile.addLongIdentifier("dn-input-file", true); 601 dnInputFile.addLongIdentifier("target-dn-file", true); 602 dnInputFile.addLongIdentifier("user-dn-file", true); 603 dnInputFile.setArgumentGroupName( 604 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 605 parser.addArgument(dnInputFile); 606 607 final FilterArgument targetFilter = new FilterArgument(null, 608 ARG_TARGET_FILTER, false, 0, null, 609 INFO_MANAGE_ACCT_ARG_DESC_TARGET_FILTER.get(ARG_BASE_DN)); 610 targetFilter.addLongIdentifier("target-filter", true); 611 targetFilter.setArgumentGroupName( 612 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 613 parser.addArgument(targetFilter); 614 615 final FileArgument filterInputFile = new FileArgument(null, 616 ARG_FILTER_INPUT_FILE, false, 0, null, 617 INFO_MANAGE_ACCT_ARG_DESC_FILTER_INPUT_FILE.get(ARG_BASE_DN), 618 true, true, true, false); 619 filterInputFile.addLongIdentifier("targetFilterFile", true); 620 filterInputFile.addLongIdentifier("filter-input-file", true); 621 filterInputFile.addLongIdentifier("target-filter-file", true); 622 filterInputFile.setArgumentGroupName( 623 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 624 parser.addArgument(filterInputFile); 625 626 final StringArgument targetUserID = new StringArgument(null, 627 ARG_TARGET_USER_ID, false, 0, null, 628 INFO_MANAGE_ACCT_ARG_DESC_TARGET_USER_ID.get(ARG_BASE_DN, 629 ARG_USER_ID_ATTRIBUTE)); 630 targetUserID.addLongIdentifier("userID", true); 631 targetUserID.addLongIdentifier("target-user-id", true); 632 targetUserID.addLongIdentifier("user-id", true); 633 targetUserID.setArgumentGroupName( 634 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 635 parser.addArgument(targetUserID); 636 637 final FileArgument userIDInputFile = new FileArgument(null, 638 ARG_USER_ID_INPUT_FILE, false, 0, null, 639 INFO_MANAGE_ACCT_ARG_DESC_USER_ID_INPUT_FILE.get(ARG_BASE_DN, 640 ARG_USER_ID_ATTRIBUTE), 641 true, true, true, false); 642 userIDInputFile.addLongIdentifier("targetUserIDFile", true); 643 userIDInputFile.addLongIdentifier("user-id-input-file", true); 644 userIDInputFile.addLongIdentifier("target-user-id-file", true); 645 userIDInputFile.setArgumentGroupName( 646 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 647 parser.addArgument(userIDInputFile); 648 649 final StringArgument userIDAttribute = new StringArgument(null, 650 ARG_USER_ID_ATTRIBUTE, false, 1, null, 651 INFO_MANAGE_ACCT_ARG_DESC_USER_ID_ATTR.get( 652 ARG_TARGET_USER_ID, ARG_USER_ID_INPUT_FILE, 653 DEFAULT_USER_ID_ATTRIBUTE), 654 DEFAULT_USER_ID_ATTRIBUTE); 655 userIDAttribute.addLongIdentifier("user-id-attribute", true); 656 userIDAttribute.setArgumentGroupName( 657 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 658 parser.addArgument(userIDAttribute); 659 660 final DNArgument baseDN = new DNArgument(null, ARG_BASE_DN, false, 1, null, 661 INFO_MANAGE_ACCT_ARG_DESC_BASE_DN.get(ARG_TARGET_FILTER, 662 ARG_FILTER_INPUT_FILE, ARG_TARGET_USER_ID, 663 ARG_USER_ID_INPUT_FILE), 664 DEFAULT_BASE_DN); 665 baseDN.addLongIdentifier("base-dn", true); 666 baseDN.setArgumentGroupName( 667 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 668 parser.addArgument(baseDN); 669 670 final IntegerArgument simplePageSize = new IntegerArgument('z', 671 ARG_SIMPLE_PAGE_SIZE, false, 1, null, 672 INFO_MANAGE_ACCT_ARG_DESC_SIMPLE_PAGE_SIZE.get(getToolName()), 1, 673 Integer.MAX_VALUE); 674 simplePageSize.addLongIdentifier("simple-page-size", true); 675 simplePageSize.setArgumentGroupName( 676 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get(getToolName())); 677 parser.addArgument(simplePageSize); 678 679 680 // Ensure that the user will be required ot provide at least one of the 681 // arguments to specify which users to target. 682 parser.addRequiredArgumentSet(targetDN, dnInputFile, targetFilter, 683 filterInputFile, targetUserID, userIDInputFile); 684 685 686 // Define the global arguments used to control the amount of load the tool 687 // should be permitted to generate. 688 final IntegerArgument numThreads = new IntegerArgument('t', ARG_NUM_THREADS, 689 false, 1, null, 690 INFO_MANAGE_ACCT_ARG_DESC_NUM_THREADS.get(getToolName()), 1, 691 Integer.MAX_VALUE, 1); 692 numThreads.addLongIdentifier("num-threads", true); 693 numThreads.setArgumentGroupName( 694 INFO_MANAGE_ACCT_ARG_GROUP_PERFORMANCE.get()); 695 parser.addArgument(numThreads); 696 697 final IntegerArgument numSearchThreads = new IntegerArgument(null, 698 ARG_NUM_SEARCH_THREADS, false, 1, null, 699 INFO_MANAGE_ACCT_ARG_DESC_NUM_SEARCH_THREADS.get(getToolName()), 1, 700 Integer.MAX_VALUE, 1); 701 numSearchThreads.addLongIdentifier("num-search-threads", true); 702 numSearchThreads.setArgumentGroupName( 703 INFO_MANAGE_ACCT_ARG_GROUP_PERFORMANCE.get()); 704 parser.addArgument(numSearchThreads); 705 706 final IntegerArgument ratePerSecond = new IntegerArgument('r', 707 ARG_RATE_PER_SECOND, false, 1, null, 708 INFO_MANAGE_ACCT_ARG_DESC_RATE_PER_SECOND.get( 709 ARG_VARIABLE_RATE_DATA), 710 1, Integer.MAX_VALUE); 711 ratePerSecond.addLongIdentifier("rate-per-second", true); 712 ratePerSecond.setArgumentGroupName( 713 INFO_MANAGE_ACCT_ARG_GROUP_PERFORMANCE.get()); 714 parser.addArgument(ratePerSecond); 715 716 final FileArgument variableRateData = new FileArgument(null, 717 ARG_VARIABLE_RATE_DATA, false, 1, null, 718 INFO_MANAGE_ACCT_ARG_DESC_VARIABLE_RATE_DATA.get( 719 ARG_RATE_PER_SECOND), 720 true, true, true, false); 721 variableRateData.addLongIdentifier("variable-rate-data", true); 722 variableRateData.setArgumentGroupName( 723 INFO_MANAGE_ACCT_ARG_GROUP_PERFORMANCE.get()); 724 parser.addArgument(variableRateData); 725 726 final FileArgument generateSampleRateFile = new FileArgument(null, 727 ARG_GENERATE_SAMPLE_RATE_FILE, false, 1, null, 728 INFO_MANAGE_ACCT_ARG_DESC_GENERATE_SAMPLE_RATE_FILE.get( 729 ARG_VARIABLE_RATE_DATA), 730 false, true, true, false); 731 generateSampleRateFile.addLongIdentifier("generate-sample-rate-file", true); 732 generateSampleRateFile.setArgumentGroupName( 733 INFO_MANAGE_ACCT_ARG_GROUP_PERFORMANCE.get()); 734 generateSampleRateFile.setUsageArgument(true); 735 parser.addArgument(generateSampleRateFile); 736 737 738 // Define the global arguments tht pertain to the reject file. 739 final FileArgument rejectFile = new FileArgument('R', ARG_REJECT_FILE, 740 false, 1, null, INFO_MANAGE_ACCT_ARG_DESC_REJECT_FILE.get(), 741 false, true, true, false); 742 rejectFile.addLongIdentifier("reject-file", true); 743 parser.addArgument(rejectFile); 744 745 final BooleanArgument appendToRejectFile = new BooleanArgument(null, 746 ARG_APPEND_TO_REJECT_FILE, 1, 747 INFO_MANAGE_ACCT_ARG_DESC_APPEND_TO_REJECT_FILE.get( 748 rejectFile.getIdentifierString())); 749 appendToRejectFile.addLongIdentifier("append-to-reject-file", true); 750 parser.addArgument(appendToRejectFile); 751 752 parser.addDependentArgumentSet(appendToRejectFile, rejectFile); 753 754 755 // Define the argument used to suppress result operations without values. 756 final BooleanArgument suppressEmptyResultOperations = 757 new BooleanArgument(null, ARG_SUPPRESS_EMPTY_RESULT_OPERATIONS, 758 1, 759 INFO_MANAGE_ACCT_ARG_DESC_SUPPRESS_EMPTY_RESULT_OPERATIONS.get( 760 getToolName())); 761 parser.addArgument(suppressEmptyResultOperations); 762 763 764 // Define the subcommand used to retrieve all state information for a user. 765 createSubCommand(ManageAccountSubCommandType.GET_ALL, 766 INFO_MANAGE_ACCT_SC_GET_ALL_EXAMPLE.get(EXAMPLE_TARGET_USER_DN)); 767 768 769 // Define the subcommand used to retrieve the password policy DN for a user. 770 createSubCommand(ManageAccountSubCommandType.GET_PASSWORD_POLICY_DN, 771 INFO_MANAGE_ACCT_SC_GET_POLICY_DN_EXAMPLE.get(EXAMPLE_TARGET_USER_DN)); 772 773 774 // Define the subcommand to determine whether the account is usable. 775 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_IS_USABLE, 776 INFO_MANAGE_ACCT_SC_GET_IS_USABLE_EXAMPLE.get(EXAMPLE_TARGET_USER_DN)); 777 778 779 // Define the subcommand to retrieve the set of password policy state 780 // account usability notice messages. 781 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_USABILITY_NOTICES, 782 INFO_MANAGE_ACCT_SC_GET_USABILITY_NOTICES_EXAMPLE.get( 783 EXAMPLE_TARGET_USER_DN)); 784 785 786 // Define the subcommand to retrieve the set of password policy state 787 // account usability warning messages. 788 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_USABILITY_WARNINGS, 789 INFO_MANAGE_ACCT_SC_GET_USABILITY_WARNINGS_EXAMPLE.get( 790 EXAMPLE_TARGET_USER_DN)); 791 792 793 // Define the subcommand to retrieve the set of password policy state 794 // account usability error messages. 795 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_USABILITY_ERRORS, 796 INFO_MANAGE_ACCT_SC_GET_USABILITY_ERRORS_EXAMPLE.get( 797 EXAMPLE_TARGET_USER_DN)); 798 799 800 // Define the subcommand to retrieve the password changed time for a user. 801 createSubCommand(ManageAccountSubCommandType.GET_PASSWORD_CHANGED_TIME, 802 INFO_MANAGE_ACCT_SC_GET_PW_CHANGED_TIME_EXAMPLE.get( 803 EXAMPLE_TARGET_USER_DN)); 804 805 806 // Define the subcommand to set the password changed time for a user. 807 final ArgumentParser setPWChangedTimeParser = 808 createSubCommandParser( 809 ManageAccountSubCommandType.SET_PASSWORD_CHANGED_TIME); 810 811 final TimestampArgument setPWChangedTimeValueArg = new TimestampArgument( 812 'O', "passwordChangedTime", false, 1, null, 813 INFO_MANAGE_ACCT_SC_SET_PW_CHANGED_TIME_ARG_VALUE.get()); 814 setPWChangedTimeValueArg.addLongIdentifier("operationValue", true); 815 setPWChangedTimeValueArg.addLongIdentifier("password-changed-time", true); 816 setPWChangedTimeValueArg.addLongIdentifier("operation-value", true); 817 setPWChangedTimeParser.addArgument(setPWChangedTimeValueArg); 818 819 createSubCommand(ManageAccountSubCommandType.SET_PASSWORD_CHANGED_TIME, 820 setPWChangedTimeParser, 821 createSubCommandExample( 822 ManageAccountSubCommandType.SET_PASSWORD_CHANGED_TIME, 823 INFO_MANAGE_ACCT_SC_SET_PW_CHANGED_TIME_EXAMPLE.get( 824 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 825 "--passwordChangedTime", currentGeneralizedTime)); 826 827 828 // Define the subcommand to clear the password changed time for a user. 829 createSubCommand(ManageAccountSubCommandType.CLEAR_PASSWORD_CHANGED_TIME, 830 INFO_MANAGE_ACCT_SC_CLEAR_PW_CHANGED_TIME_EXAMPLE.get( 831 EXAMPLE_TARGET_USER_DN)); 832 833 834 // Define the subcommand to determine whether a user account is disabled. 835 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_IS_DISABLED, 836 INFO_MANAGE_ACCT_SC_GET_IS_DISABLED_EXAMPLE.get( 837 EXAMPLE_TARGET_USER_DN)); 838 839 840 // Define the subcommand to specify whether a user's account is disabled. 841 final ArgumentParser setAcctDisabledParser = 842 createSubCommandParser( 843 ManageAccountSubCommandType.SET_ACCOUNT_IS_DISABLED); 844 845 final BooleanValueArgument setAcctDisabledValueArg = 846 new BooleanValueArgument('O', "accountIsDisabled", true, null, 847 INFO_MANAGE_ACCT_SC_SET_IS_DISABLED_ARG_VALUE.get()); 848 setAcctDisabledValueArg.addLongIdentifier("operationValue", true); 849 setAcctDisabledValueArg.addLongIdentifier("account-is-disabled", true); 850 setAcctDisabledValueArg.addLongIdentifier("operation-value", true); 851 setAcctDisabledParser.addArgument(setAcctDisabledValueArg); 852 853 createSubCommand(ManageAccountSubCommandType.SET_ACCOUNT_IS_DISABLED, 854 setAcctDisabledParser, 855 createSubCommandExample( 856 ManageAccountSubCommandType.SET_ACCOUNT_IS_DISABLED, 857 INFO_MANAGE_ACCT_SC_SET_IS_DISABLED_EXAMPLE.get( 858 EXAMPLE_TARGET_USER_DN), 859 "--accountIsDisabled", "true")); 860 861 862 // Define the subcommand to clear the account disabled state. 863 createSubCommand(ManageAccountSubCommandType.CLEAR_ACCOUNT_IS_DISABLED, 864 INFO_MANAGE_ACCT_SC_CLEAR_IS_DISABLED_EXAMPLE.get( 865 EXAMPLE_TARGET_USER_DN)); 866 867 868 // Define the subcommand to retrieve the account activation time for a user. 869 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_ACTIVATION_TIME, 870 INFO_MANAGE_ACCT_SC_GET_ACCT_ACT_TIME_EXAMPLE.get( 871 EXAMPLE_TARGET_USER_DN)); 872 873 874 // Define the subcommand to set the account activation time for a user. 875 final ArgumentParser setAcctActivationTimeParser = 876 createSubCommandParser( 877 ManageAccountSubCommandType.SET_ACCOUNT_ACTIVATION_TIME); 878 879 final TimestampArgument setAcctActivationTimeValueArg = 880 new TimestampArgument('O', "accountActivationTime", false, 1, null, 881 INFO_MANAGE_ACCT_SC_SET_ACCT_ACT_TIME_ARG_VALUE.get()); 882 setAcctActivationTimeValueArg.addLongIdentifier("operationValue", true); 883 setAcctActivationTimeValueArg.addLongIdentifier("account-activation-time", 884 true); 885 setAcctActivationTimeValueArg.addLongIdentifier("operation-value", true); 886 setAcctActivationTimeParser.addArgument(setAcctActivationTimeValueArg); 887 888 createSubCommand(ManageAccountSubCommandType.SET_ACCOUNT_ACTIVATION_TIME, 889 setAcctActivationTimeParser, 890 createSubCommandExample( 891 ManageAccountSubCommandType.SET_ACCOUNT_ACTIVATION_TIME, 892 INFO_MANAGE_ACCT_SC_SET_ACCT_ACT_TIME_EXAMPLE.get( 893 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 894 "--accountActivationTime", currentGeneralizedTime)); 895 896 897 // Define the subcommand to clear the account activation time for a user. 898 createSubCommand(ManageAccountSubCommandType.CLEAR_ACCOUNT_ACTIVATION_TIME, 899 INFO_MANAGE_ACCT_SC_CLEAR_ACCT_ACT_TIME_EXAMPLE.get( 900 EXAMPLE_TARGET_USER_DN)); 901 902 903 // Define the subcommand to retrieve the length of time until a user's 904 // account is activated. 905 createSubCommand( 906 ManageAccountSubCommandType.GET_SECONDS_UNTIL_ACCOUNT_ACTIVATION, 907 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_ACCT_ACT_EXAMPLE.get( 908 EXAMPLE_TARGET_USER_DN)); 909 910 911 // Define the subcommand to determine whether a user's account is not yet 912 // active. 913 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_IS_NOT_YET_ACTIVE, 914 INFO_MANAGE_ACCT_SC_GET_ACCT_NOT_YET_ACTIVE_EXAMPLE.get( 915 EXAMPLE_TARGET_USER_DN)); 916 917 918 // Define the subcommand to retrieve the account expiration time for a user. 919 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_EXPIRATION_TIME, 920 INFO_MANAGE_ACCT_SC_GET_ACCT_EXP_TIME_EXAMPLE.get( 921 EXAMPLE_TARGET_USER_DN)); 922 923 924 // Define the subcommand to set the account expiration time for a user. 925 final ArgumentParser setAcctExpirationTimeParser = 926 createSubCommandParser( 927 ManageAccountSubCommandType.SET_ACCOUNT_EXPIRATION_TIME); 928 929 final TimestampArgument setAcctExpirationTimeValueArg = 930 new TimestampArgument('O', "accountExpirationTime", false, 1, null, 931 INFO_MANAGE_ACCT_SC_SET_ACCT_EXP_TIME_ARG_VALUE.get()); 932 setAcctExpirationTimeValueArg.addLongIdentifier("operationValue", true); 933 setAcctExpirationTimeValueArg.addLongIdentifier("account-expiration-time", 934 true); 935 setAcctExpirationTimeValueArg.addLongIdentifier("operation-value", true); 936 setAcctExpirationTimeParser.addArgument(setAcctExpirationTimeValueArg); 937 938 createSubCommand(ManageAccountSubCommandType.SET_ACCOUNT_EXPIRATION_TIME, 939 setAcctExpirationTimeParser, 940 createSubCommandExample( 941 ManageAccountSubCommandType.SET_ACCOUNT_EXPIRATION_TIME, 942 INFO_MANAGE_ACCT_SC_SET_ACCT_EXP_TIME_EXAMPLE.get( 943 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 944 "--accountExpirationTime", currentGeneralizedTime)); 945 946 947 // Define the subcommand to clear the account expiration time for a user. 948 createSubCommand(ManageAccountSubCommandType.CLEAR_ACCOUNT_EXPIRATION_TIME, 949 INFO_MANAGE_ACCT_SC_CLEAR_ACCT_EXP_TIME_EXAMPLE.get( 950 EXAMPLE_TARGET_USER_DN)); 951 952 953 // Define the subcommand to retrieve the length of time until a user's 954 // account is expired. 955 createSubCommand( 956 ManageAccountSubCommandType.GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION, 957 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_ACCT_EXP_EXAMPLE.get( 958 EXAMPLE_TARGET_USER_DN)); 959 960 961 // Define the subcommand to determine whether a user's account is expired. 962 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_IS_EXPIRED, 963 INFO_MANAGE_ACCT_SC_GET_ACCT_IS_EXPIRED_EXAMPLE.get( 964 EXAMPLE_TARGET_USER_DN)); 965 966 967 // Define the subcommand to retrieve a user's password expiration warned 968 // time. 969 createSubCommand( 970 ManageAccountSubCommandType.GET_PASSWORD_EXPIRATION_WARNED_TIME, 971 INFO_MANAGE_ACCT_SC_GET_PW_EXP_WARNED_TIME_EXAMPLE.get( 972 EXAMPLE_TARGET_USER_DN)); 973 974 975 // Define the subcommand to set a user's password expiration warned time. 976 final ArgumentParser setPWExpWarnedTimeParser = 977 createSubCommandParser( 978 ManageAccountSubCommandType.SET_PASSWORD_EXPIRATION_WARNED_TIME); 979 980 final TimestampArgument setPWExpWarnedTimeValueArg = 981 new TimestampArgument('O', "passwordExpirationWarnedTime", false, 1, 982 null, INFO_MANAGE_ACCT_SC_SET_PW_EXP_WARNED_TIME_ARG_VALUE.get()); 983 setPWExpWarnedTimeValueArg.addLongIdentifier("operationValue", true); 984 setPWExpWarnedTimeValueArg.addLongIdentifier( 985 "password-expiration-warned-time", true); 986 setPWExpWarnedTimeValueArg.addLongIdentifier("operation-value", true); 987 setPWExpWarnedTimeParser.addArgument(setPWExpWarnedTimeValueArg); 988 989 createSubCommand( 990 ManageAccountSubCommandType.SET_PASSWORD_EXPIRATION_WARNED_TIME, 991 setPWExpWarnedTimeParser, 992 createSubCommandExample( 993 ManageAccountSubCommandType.SET_PASSWORD_EXPIRATION_WARNED_TIME, 994 INFO_MANAGE_ACCT_SC_SET_PW_EXP_WARNED_TIME_EXAMPLE.get( 995 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 996 "--passwordExpirationWarnedTime", currentGeneralizedTime)); 997 998 999 // Define the subcommand to clear a user's password expiration warned time. 1000 createSubCommand( 1001 ManageAccountSubCommandType.CLEAR_PASSWORD_EXPIRATION_WARNED_TIME, 1002 INFO_MANAGE_ACCT_SC_CLEAR_PW_EXP_WARNED_TIME_EXAMPLE.get( 1003 EXAMPLE_TARGET_USER_DN)); 1004 1005 1006 // Define the subcommand to get the number of seconds until a user is 1007 // eligible to receive a password expiration warning. 1008 createSubCommand( 1009 ManageAccountSubCommandType. 1010 GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING, 1011 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_PW_EXP_WARNING_EXAMPLE.get( 1012 EXAMPLE_TARGET_USER_DN)); 1013 1014 1015 // Define the subcommand to retrieve a user's password expiration time. 1016 createSubCommand(ManageAccountSubCommandType.GET_PASSWORD_EXPIRATION_TIME, 1017 INFO_MANAGE_ACCT_SC_GET_PW_EXP_TIME_EXAMPLE.get( 1018 EXAMPLE_TARGET_USER_DN)); 1019 1020 1021 // Define the subcommand to get the number of seconds until a user's 1022 // password expires. 1023 createSubCommand( 1024 ManageAccountSubCommandType.GET_SECONDS_UNTIL_PASSWORD_EXPIRATION, 1025 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_PW_EXP_EXAMPLE.get( 1026 EXAMPLE_TARGET_USER_DN)); 1027 1028 1029 // Define the subcommand to determine whether a user's password is expired. 1030 createSubCommand(ManageAccountSubCommandType.GET_PASSWORD_IS_EXPIRED, 1031 INFO_MANAGE_ACCT_SC_GET_PW_IS_EXPIRED_EXAMPLE.get( 1032 EXAMPLE_TARGET_USER_DN)); 1033 1034 1035 // Define the subcommand to determine whether an account is failure locked. 1036 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_IS_FAILURE_LOCKED, 1037 INFO_MANAGE_ACCT_SC_GET_ACCT_FAILURE_LOCKED_EXAMPLE.get( 1038 EXAMPLE_TARGET_USER_DN)); 1039 1040 1041 // Define the subcommand to specify whether an account is failure locked. 1042 final ArgumentParser setIsFailureLockedParser = 1043 createSubCommandParser( 1044 ManageAccountSubCommandType.SET_ACCOUNT_IS_FAILURE_LOCKED); 1045 1046 final BooleanValueArgument setIsFailureLockedValueArg = 1047 new BooleanValueArgument('O', "accountIsFailureLocked", true, null, 1048 INFO_MANAGE_ACCT_SC_SET_ACCT_FAILURE_LOCKED_ARG_VALUE.get()); 1049 setIsFailureLockedValueArg.addLongIdentifier("operationValue", true); 1050 setIsFailureLockedValueArg.addLongIdentifier("account-is-failure-locked", 1051 true); 1052 setIsFailureLockedValueArg.addLongIdentifier("operation-value", true); 1053 setIsFailureLockedParser.addArgument(setIsFailureLockedValueArg); 1054 1055 createSubCommand(ManageAccountSubCommandType.SET_ACCOUNT_IS_FAILURE_LOCKED, 1056 setIsFailureLockedParser, 1057 createSubCommandExample( 1058 ManageAccountSubCommandType.SET_ACCOUNT_IS_FAILURE_LOCKED, 1059 INFO_MANAGE_ACCT_SC_SET_ACCT_FAILURE_LOCKED_EXAMPLE.get( 1060 EXAMPLE_TARGET_USER_DN), 1061 "--accountIsFailureLocked", "true")); 1062 1063 1064 // Define the subcommand to get the time an account was failure locked. 1065 createSubCommand(ManageAccountSubCommandType.GET_FAILURE_LOCKOUT_TIME, 1066 INFO_MANAGE_ACCT_SC_GET_FAILURE_LOCKED_TIME_EXAMPLE.get( 1067 EXAMPLE_TARGET_USER_DN)); 1068 1069 1070 // Define the subcommand to get the length of time until a failure-locked 1071 // account will be automatically unlocked. 1072 createSubCommand( 1073 ManageAccountSubCommandType. 1074 GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK, 1075 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_FAILURE_UNLOCK_EXAMPLE.get( 1076 EXAMPLE_TARGET_USER_DN)); 1077 1078 1079 // Define the subcommand to determine the authentication failure times. 1080 createSubCommand( 1081 ManageAccountSubCommandType.GET_AUTHENTICATION_FAILURE_TIMES, 1082 INFO_MANAGE_ACCT_SC_GET_AUTH_FAILURE_TIMES_EXAMPLE.get( 1083 EXAMPLE_TARGET_USER_DN)); 1084 1085 1086 // Define the subcommand to add values to the set of authentication failure 1087 // times. 1088 final ArgumentParser addAuthFailureTimeParser = 1089 createSubCommandParser( 1090 ManageAccountSubCommandType.ADD_AUTHENTICATION_FAILURE_TIME); 1091 1092 final TimestampArgument addAuthFailureTimeValueArg = 1093 new TimestampArgument('O', "authenticationFailureTime", false, 0, null, 1094 INFO_MANAGE_ACCT_SC_ADD_AUTH_FAILURE_TIME_ARG_VALUE.get()); 1095 addAuthFailureTimeValueArg.addLongIdentifier("operationValue", true); 1096 addAuthFailureTimeValueArg.addLongIdentifier( 1097 "authentication-failure-time", true); 1098 addAuthFailureTimeValueArg.addLongIdentifier("operation-value", true); 1099 addAuthFailureTimeParser.addArgument(addAuthFailureTimeValueArg); 1100 1101 createSubCommand( 1102 ManageAccountSubCommandType.ADD_AUTHENTICATION_FAILURE_TIME, 1103 addAuthFailureTimeParser, 1104 createSubCommandExample( 1105 ManageAccountSubCommandType.ADD_AUTHENTICATION_FAILURE_TIME, 1106 INFO_MANAGE_ACCT_SC_ADD_AUTH_FAILURE_TIME_EXAMPLE.get( 1107 EXAMPLE_TARGET_USER_DN))); 1108 1109 1110 // Define the subcommand to replace the authentication failure times. 1111 final ArgumentParser setAuthFailureTimesParser = 1112 createSubCommandParser( 1113 ManageAccountSubCommandType.SET_AUTHENTICATION_FAILURE_TIMES); 1114 1115 final TimestampArgument setAuthFailureTimesValueArg = 1116 new TimestampArgument('O', "authenticationFailureTime", false, 0, null, 1117 INFO_MANAGE_ACCT_SC_SET_AUTH_FAILURE_TIMES_ARG_VALUE.get()); 1118 setAuthFailureTimesValueArg.addLongIdentifier("operationValue", true); 1119 setAuthFailureTimesValueArg.addLongIdentifier( 1120 "authentication-failure-time", true); 1121 setAuthFailureTimesValueArg.addLongIdentifier("operation-value", true); 1122 setAuthFailureTimesParser.addArgument(setAuthFailureTimesValueArg); 1123 1124 createSubCommand( 1125 ManageAccountSubCommandType.SET_AUTHENTICATION_FAILURE_TIMES, 1126 setAuthFailureTimesParser, 1127 createSubCommandExample( 1128 ManageAccountSubCommandType.SET_AUTHENTICATION_FAILURE_TIMES, 1129 INFO_MANAGE_ACCT_SC_SET_AUTH_FAILURE_TIMES_EXAMPLE.get( 1130 EXAMPLE_TARGET_USER_DN, olderGeneralizedTime, 1131 currentGeneralizedTime), 1132 "--authenticationFailureTime", olderGeneralizedTime, 1133 "--authenticationFailureTime", currentGeneralizedTime)); 1134 1135 1136 // Define the subcommand to clear the authentication failure times. 1137 createSubCommand( 1138 ManageAccountSubCommandType.CLEAR_AUTHENTICATION_FAILURE_TIMES, 1139 INFO_MANAGE_ACCT_SC_CLEAR_AUTH_FAILURE_TIMES_EXAMPLE.get( 1140 EXAMPLE_TARGET_USER_DN)); 1141 1142 1143 // Define the subcommand to get the remaining authentication failure count. 1144 createSubCommand( 1145 ManageAccountSubCommandType.GET_REMAINING_AUTHENTICATION_FAILURE_COUNT, 1146 INFO_MANAGE_ACCT_SC_GET_REMAINING_FAILURE_COUNT_EXAMPLE.get( 1147 EXAMPLE_TARGET_USER_DN)); 1148 1149 1150 // Define the subcommand to determine whether the account is idle locked. 1151 createSubCommand(ManageAccountSubCommandType.GET_ACCOUNT_IS_IDLE_LOCKED, 1152 INFO_MANAGE_ACCT_SC_GET_ACCT_IDLE_LOCKED_EXAMPLE.get( 1153 EXAMPLE_TARGET_USER_DN)); 1154 1155 1156 // Define the subcommand to get the length of time until the account is 1157 // idle locked. 1158 createSubCommand(ManageAccountSubCommandType.GET_SECONDS_UNTIL_IDLE_LOCKOUT, 1159 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_IDLE_LOCKOUT_EXAMPLE.get( 1160 EXAMPLE_TARGET_USER_DN)); 1161 1162 1163 // Define the subcommand to get the idle lockout time for an account. 1164 createSubCommand(ManageAccountSubCommandType.GET_IDLE_LOCKOUT_TIME, 1165 INFO_MANAGE_ACCT_SC_GET_IDLE_LOCKOUT_TIME_EXAMPLE.get( 1166 EXAMPLE_TARGET_USER_DN)); 1167 1168 1169 // Define the subcommand to determine whether a user's password has been 1170 // reset. 1171 createSubCommand(ManageAccountSubCommandType.GET_MUST_CHANGE_PASSWORD, 1172 INFO_MANAGE_ACCT_SC_GET_MUST_CHANGE_PW_EXAMPLE.get( 1173 EXAMPLE_TARGET_USER_DN)); 1174 1175 1176 // Define the subcommand to specify whether a user's password has been 1177 // reset. 1178 final ArgumentParser setPWIsResetParser = 1179 createSubCommandParser( 1180 ManageAccountSubCommandType.SET_MUST_CHANGE_PASSWORD); 1181 1182 final BooleanValueArgument setPWIsResetValueArg = 1183 new BooleanValueArgument('O', "mustChangePassword", true, null, 1184 INFO_MANAGE_ACCT_SC_SET_MUST_CHANGE_PW_ARG_VALUE.get()); 1185 setPWIsResetValueArg.addLongIdentifier("passwordIsReset", true); 1186 setPWIsResetValueArg.addLongIdentifier("operationValue", true); 1187 setPWIsResetValueArg.addLongIdentifier("must-change-password", true); 1188 setPWIsResetValueArg.addLongIdentifier("password-is-reset", true); 1189 setPWIsResetValueArg.addLongIdentifier("operation-value", true); 1190 setPWIsResetParser.addArgument(setPWIsResetValueArg); 1191 1192 createSubCommand(ManageAccountSubCommandType.SET_MUST_CHANGE_PASSWORD, 1193 setPWIsResetParser, 1194 createSubCommandExample( 1195 ManageAccountSubCommandType.SET_MUST_CHANGE_PASSWORD, 1196 INFO_MANAGE_ACCT_SC_SET_MUST_CHANGE_PW_EXAMPLE.get( 1197 EXAMPLE_TARGET_USER_DN), 1198 "--mustChangePassword", "true")); 1199 1200 1201 // Define the subcommand to clear the password reset state information. 1202 createSubCommand(ManageAccountSubCommandType.CLEAR_MUST_CHANGE_PASSWORD, 1203 INFO_MANAGE_ACCT_SC_CLEAR_MUST_CHANGE_PW_EXAMPLE.get( 1204 EXAMPLE_TARGET_USER_DN)); 1205 1206 1207 // Define the subcommand to determine whether the account is reset locked. 1208 createSubCommand( 1209 ManageAccountSubCommandType.GET_ACCOUNT_IS_PASSWORD_RESET_LOCKED, 1210 INFO_MANAGE_ACCT_SC_GET_ACCT_IS_RESET_LOCKED_EXAMPLE.get( 1211 EXAMPLE_TARGET_USER_DN)); 1212 1213 1214 // Define the subcommand to get the length of time until the password is 1215 // reset locked. 1216 createSubCommand( 1217 ManageAccountSubCommandType.GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT, 1218 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_RESET_LOCKOUT_EXAMPLE.get( 1219 EXAMPLE_TARGET_USER_DN)); 1220 1221 1222 // Define the subcommand to get the password reset lockout time. 1223 createSubCommand( 1224 ManageAccountSubCommandType.GET_PASSWORD_RESET_LOCKOUT_TIME, 1225 INFO_MANAGE_ACCT_SC_GET_RESET_LOCKOUT_TIME_EXAMPLE.get( 1226 EXAMPLE_TARGET_USER_DN)); 1227 1228 1229 // Define the subcommand to get the last login time. 1230 createSubCommand(ManageAccountSubCommandType.GET_LAST_LOGIN_TIME, 1231 INFO_MANAGE_ACCT_SC_GET_LAST_LOGIN_TIME_EXAMPLE.get( 1232 EXAMPLE_TARGET_USER_DN)); 1233 1234 1235 // Define the subcommand to set the last login time. 1236 final ArgumentParser setLastLoginTimeParser = 1237 createSubCommandParser( 1238 ManageAccountSubCommandType.SET_LAST_LOGIN_TIME); 1239 1240 final TimestampArgument setLastLoginTimeValueArg = new TimestampArgument( 1241 'O', "lastLoginTime", false, 1, null, 1242 INFO_MANAGE_ACCT_SC_SET_LAST_LOGIN_TIME_ARG_VALUE.get()); 1243 setLastLoginTimeValueArg.addLongIdentifier("operationValue", true); 1244 setLastLoginTimeValueArg.addLongIdentifier("last-login-time", true); 1245 setLastLoginTimeValueArg.addLongIdentifier("operation-value", true); 1246 setLastLoginTimeParser.addArgument(setLastLoginTimeValueArg); 1247 1248 createSubCommand(ManageAccountSubCommandType.SET_LAST_LOGIN_TIME, 1249 setLastLoginTimeParser, 1250 createSubCommandExample( 1251 ManageAccountSubCommandType.SET_LAST_LOGIN_TIME, 1252 INFO_MANAGE_ACCT_SC_SET_LAST_LOGIN_TIME_EXAMPLE.get( 1253 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 1254 "--lastLoginTime", currentGeneralizedTime)); 1255 1256 1257 // Define the subcommand to clear the last login time. 1258 createSubCommand(ManageAccountSubCommandType.CLEAR_LAST_LOGIN_TIME, 1259 INFO_MANAGE_ACCT_SC_CLEAR_LAST_LOGIN_TIME_EXAMPLE.get( 1260 EXAMPLE_TARGET_USER_DN)); 1261 1262 1263 // Define the subcommand to get the last login IP address. 1264 createSubCommand(ManageAccountSubCommandType.GET_LAST_LOGIN_IP_ADDRESS, 1265 INFO_MANAGE_ACCT_SC_GET_LAST_LOGIN_IP_EXAMPLE.get( 1266 EXAMPLE_TARGET_USER_DN)); 1267 1268 1269 // Define the subcommand to set the last login IP address. 1270 final ArgumentParser setLastLoginIPParser = 1271 createSubCommandParser( 1272 ManageAccountSubCommandType.SET_LAST_LOGIN_IP_ADDRESS); 1273 1274 final StringArgument setLastLoginIPValueArg = new StringArgument('O', 1275 "lastLoginIPAddress", true, 1, null, 1276 INFO_MANAGE_ACCT_SC_SET_LAST_LOGIN_IP_ARG_VALUE.get()); 1277 setLastLoginIPValueArg.addLongIdentifier("operationValue", true); 1278 setLastLoginIPValueArg.addLongIdentifier("last-login-ip-address", true); 1279 setLastLoginIPValueArg.addLongIdentifier("operation-value", true); 1280 setLastLoginIPValueArg.addValueValidator( 1281 new IPAddressArgumentValueValidator()); 1282 setLastLoginIPParser.addArgument(setLastLoginIPValueArg); 1283 1284 1285 createSubCommand(ManageAccountSubCommandType.SET_LAST_LOGIN_IP_ADDRESS, 1286 setLastLoginIPParser, 1287 createSubCommandExample( 1288 ManageAccountSubCommandType.SET_LAST_LOGIN_IP_ADDRESS, 1289 INFO_MANAGE_ACCT_SC_SET_LAST_LOGIN_IP_EXAMPLE.get( 1290 EXAMPLE_TARGET_USER_DN, "1.2.3.4"), 1291 "--lastLoginIPAddress", "1.2.3.4")); 1292 1293 1294 // Define the subcommand to clear the last login IP address. 1295 createSubCommand(ManageAccountSubCommandType.CLEAR_LAST_LOGIN_IP_ADDRESS, 1296 INFO_MANAGE_ACCT_SC_CLEAR_LAST_LOGIN_IP_EXAMPLE.get( 1297 EXAMPLE_TARGET_USER_DN)); 1298 1299 1300 // Define the subcommand to get the grace login use times. 1301 createSubCommand(ManageAccountSubCommandType.GET_GRACE_LOGIN_USE_TIMES, 1302 INFO_MANAGE_ACCT_SC_GET_GRACE_LOGIN_TIMES_EXAMPLE.get( 1303 EXAMPLE_TARGET_USER_DN)); 1304 1305 1306 // Define the subcommand to add values to the set of grace login use times. 1307 final ArgumentParser addGraceLoginTimeParser = 1308 createSubCommandParser( 1309 ManageAccountSubCommandType.ADD_GRACE_LOGIN_USE_TIME); 1310 1311 final TimestampArgument addGraceLoginTimeValueArg = 1312 new TimestampArgument('O', "graceLoginUseTime", false, 0, null, 1313 INFO_MANAGE_ACCT_SC_ADD_GRACE_LOGIN_TIME_ARG_VALUE.get()); 1314 addGraceLoginTimeValueArg.addLongIdentifier("operationValue", true); 1315 addGraceLoginTimeValueArg.addLongIdentifier("grace-login-use-time", true); 1316 addGraceLoginTimeValueArg.addLongIdentifier("operation-value", true); 1317 addGraceLoginTimeParser.addArgument(addGraceLoginTimeValueArg); 1318 1319 createSubCommand(ManageAccountSubCommandType.ADD_GRACE_LOGIN_USE_TIME, 1320 addGraceLoginTimeParser, 1321 createSubCommandExample( 1322 ManageAccountSubCommandType.ADD_GRACE_LOGIN_USE_TIME, 1323 INFO_MANAGE_ACCT_SC_ADD_GRACE_LOGIN_TIME_EXAMPLE.get( 1324 EXAMPLE_TARGET_USER_DN))); 1325 1326 1327 // Define the subcommand to replace the set of grace login use times. 1328 final ArgumentParser setGraceLoginTimesParser = 1329 createSubCommandParser( 1330 ManageAccountSubCommandType.SET_GRACE_LOGIN_USE_TIMES); 1331 1332 final TimestampArgument setGraceLoginTimesValueArg = 1333 new TimestampArgument('O', "graceLoginUseTime", false, 0, null, 1334 INFO_MANAGE_ACCT_SC_SET_GRACE_LOGIN_TIMES_ARG_VALUE.get()); 1335 setGraceLoginTimesValueArg.addLongIdentifier("operationValue", true); 1336 setGraceLoginTimesValueArg.addLongIdentifier("grace-login-use-time", true); 1337 setGraceLoginTimesValueArg.addLongIdentifier("operation-value", true); 1338 setGraceLoginTimesParser.addArgument(setGraceLoginTimesValueArg); 1339 1340 createSubCommand(ManageAccountSubCommandType.SET_GRACE_LOGIN_USE_TIMES, 1341 setGraceLoginTimesParser, 1342 createSubCommandExample( 1343 ManageAccountSubCommandType.SET_GRACE_LOGIN_USE_TIMES, 1344 INFO_MANAGE_ACCT_SC_SET_GRACE_LOGIN_TIMES_EXAMPLE.get( 1345 EXAMPLE_TARGET_USER_DN, olderGeneralizedTime, 1346 currentGeneralizedTime), 1347 "--graceLoginUseTime", olderGeneralizedTime, 1348 "--graceLoginUseTime", currentGeneralizedTime)); 1349 1350 1351 // Define the subcommand to clear the grace login use times. 1352 createSubCommand(ManageAccountSubCommandType.CLEAR_GRACE_LOGIN_USE_TIMES, 1353 INFO_MANAGE_ACCT_SC_CLEAR_GRACE_LOGIN_TIMES_EXAMPLE.get( 1354 EXAMPLE_TARGET_USER_DN)); 1355 1356 1357 // Define the subcommand to get the remaining grace login count. 1358 createSubCommand( 1359 ManageAccountSubCommandType.GET_REMAINING_GRACE_LOGIN_COUNT, 1360 INFO_MANAGE_ACCT_SC_GET_REMAINING_GRACE_LOGIN_COUNT_EXAMPLE.get( 1361 EXAMPLE_TARGET_USER_DN)); 1362 1363 1364 // Define the subcommand to get the password changed by required time value. 1365 createSubCommand( 1366 ManageAccountSubCommandType.GET_PASSWORD_CHANGED_BY_REQUIRED_TIME, 1367 INFO_MANAGE_ACCT_SC_GET_PW_CHANGED_BY_REQ_TIME_EXAMPLE.get( 1368 EXAMPLE_TARGET_USER_DN)); 1369 1370 1371 // Define the subcommand to set the password changed by required time value. 1372 final ArgumentParser setPWChangedByReqTimeParser = 1373 createSubCommandParser(ManageAccountSubCommandType. 1374 SET_PASSWORD_CHANGED_BY_REQUIRED_TIME); 1375 1376 final TimestampArgument setPWChangedByReqTimeValueArg = 1377 new TimestampArgument('O', "passwordChangedByRequiredTime", false, 1, 1378 null, 1379 INFO_MANAGE_ACCT_SC_SET_PW_CHANGED_BY_REQ_TIME_ARG_VALUE.get()); 1380 setPWChangedByReqTimeValueArg.addLongIdentifier("operationValue", true); 1381 setPWChangedByReqTimeValueArg.addLongIdentifier( 1382 "password-changed-by-required-time", true); 1383 setPWChangedByReqTimeValueArg.addLongIdentifier("operation-value", true); 1384 setPWChangedByReqTimeParser.addArgument( 1385 setPWChangedByReqTimeValueArg); 1386 1387 createSubCommand( 1388 ManageAccountSubCommandType.SET_PASSWORD_CHANGED_BY_REQUIRED_TIME, 1389 setPWChangedByReqTimeParser, 1390 createSubCommandExample( 1391 ManageAccountSubCommandType.SET_PASSWORD_CHANGED_BY_REQUIRED_TIME, 1392 INFO_MANAGE_ACCT_SC_SET_PW_CHANGED_BY_REQ_TIME_EXAMPLE.get( 1393 EXAMPLE_TARGET_USER_DN))); 1394 1395 1396 // Define the subcommand to clear the password changed by required time 1397 // value. 1398 createSubCommand( 1399 ManageAccountSubCommandType.CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME, 1400 INFO_MANAGE_ACCT_SC_CLEAR_PW_CHANGED_BY_REQ_TIME_EXAMPLE.get( 1401 EXAMPLE_TARGET_USER_DN)); 1402 1403 1404 // Define the subcommand to get the length of time until the required change 1405 // time. 1406 createSubCommand( 1407 ManageAccountSubCommandType. 1408 GET_SECONDS_UNTIL_REQUIRED_PASSWORD_CHANGE_TIME, 1409 INFO_MANAGE_ACCT_SC_GET_SECS_UNTIL_REQ_CHANGE_TIME_EXAMPLE.get( 1410 EXAMPLE_TARGET_USER_DN)); 1411 1412 1413 // Define the subcommand to get the password history count. 1414 createSubCommand(ManageAccountSubCommandType.GET_PASSWORD_HISTORY_COUNT, 1415 INFO_MANAGE_ACCT_SC_GET_PW_HISTORY_COUNT_EXAMPLE.get( 1416 EXAMPLE_TARGET_USER_DN)); 1417 1418 1419 // Define the subcommand to clear a user's password history. 1420 createSubCommand(ManageAccountSubCommandType.CLEAR_PASSWORD_HISTORY, 1421 INFO_MANAGE_ACCT_SC_CLEAR_PW_HISTORY_EXAMPLE.get( 1422 EXAMPLE_TARGET_USER_DN)); 1423 1424 1425 // Define the subcommand to determine whether a user has a retired password. 1426 createSubCommand(ManageAccountSubCommandType.GET_HAS_RETIRED_PASSWORD, 1427 INFO_MANAGE_ACCT_SC_GET_HAS_RETIRED_PW_EXAMPLE.get( 1428 EXAMPLE_TARGET_USER_DN)); 1429 1430 1431 // Define the subcommand to retrieve the time that a user's former password 1432 // was retired. 1433 createSubCommand(ManageAccountSubCommandType.GET_PASSWORD_RETIRED_TIME, 1434 INFO_MANAGE_ACCT_SC_GET_PW_RETIRED_TIME_EXAMPLE.get( 1435 EXAMPLE_TARGET_USER_DN)); 1436 1437 1438 // Define the subcommand to retrieve the retired password expiration time. 1439 createSubCommand( 1440 ManageAccountSubCommandType.GET_RETIRED_PASSWORD_EXPIRATION_TIME, 1441 INFO_MANAGE_ACCT_SC_GET_RETIRED_PW_EXP_TIME_EXAMPLE.get( 1442 EXAMPLE_TARGET_USER_DN)); 1443 1444 1445 // Define the subcommand to purge a retired password. 1446 createSubCommand(ManageAccountSubCommandType.CLEAR_RETIRED_PASSWORD, 1447 INFO_MANAGE_ACCT_SC_PURGE_RETIRED_PW_EXAMPLE.get( 1448 EXAMPLE_TARGET_USER_DN)); 1449 1450 1451 // Define the subcommand to get the available SASL mechanisms for a user. 1452 createSubCommand(ManageAccountSubCommandType.GET_AVAILABLE_SASL_MECHANISMS, 1453 INFO_MANAGE_ACCT_SC_GET_AVAILABLE_SASL_MECHS_EXAMPLE.get( 1454 EXAMPLE_TARGET_USER_DN)); 1455 1456 1457 // Define the subcommand to get the available OTP delivery mechanisms for a 1458 // user. 1459 createSubCommand( 1460 ManageAccountSubCommandType.GET_AVAILABLE_OTP_DELIVERY_MECHANISMS, 1461 INFO_MANAGE_ACCT_SC_GET_AVAILABLE_OTP_MECHS_EXAMPLE.get( 1462 EXAMPLE_TARGET_USER_DN)); 1463 1464 1465 // Define the subcommand to determine whether a user has at least one TOTP 1466 // shared secret. 1467 createSubCommand(ManageAccountSubCommandType.GET_HAS_TOTP_SHARED_SECRET, 1468 INFO_MANAGE_ACCT_SC_GET_HAS_TOTP_SHARED_SECRET_EXAMPLE.get( 1469 EXAMPLE_TARGET_USER_DN)); 1470 1471 1472 // Define the subcommand to add a value to the set of TOTP shared secrets 1473 // for a user. 1474 final ArgumentParser addTOTPSharedSecretParser = 1475 createSubCommandParser( 1476 ManageAccountSubCommandType.ADD_TOTP_SHARED_SECRET); 1477 1478 final StringArgument addTOTPSharedSecretValueArg = 1479 new StringArgument('O', "totpSharedSecret", true, 0, null, 1480 INFO_MANAGE_ACCT_SC_ADD_YUBIKEY_ID_ARG_VALUE.get()); 1481 addTOTPSharedSecretValueArg.addLongIdentifier("operationValue", true); 1482 addTOTPSharedSecretValueArg.addLongIdentifier("totp-shared-secret", true); 1483 addTOTPSharedSecretValueArg.addLongIdentifier("operation-value", true); 1484 addTOTPSharedSecretValueArg.setSensitive(true); 1485 addTOTPSharedSecretParser.addArgument( 1486 addTOTPSharedSecretValueArg); 1487 1488 createSubCommand(ManageAccountSubCommandType.ADD_TOTP_SHARED_SECRET, 1489 addTOTPSharedSecretParser, 1490 createSubCommandExample( 1491 ManageAccountSubCommandType.ADD_TOTP_SHARED_SECRET, 1492 INFO_MANAGE_ACCT_SC_ADD_TOTP_SHARED_SECRET_EXAMPLE.get( 1493 "abcdefghijklmnop", EXAMPLE_TARGET_USER_DN), 1494 "--totpSharedSecret", "abcdefghijklmnop")); 1495 1496 1497 // Define the subcommand to remove a value from the set of TOTP shared 1498 // secrets for a user. 1499 final ArgumentParser removeTOTPSharedSecretParser = 1500 createSubCommandParser( 1501 ManageAccountSubCommandType.REMOVE_TOTP_SHARED_SECRET); 1502 1503 final StringArgument removeTOTPSharedSecretValueArg = 1504 new StringArgument('O', "totpSharedSecret", true, 0, null, 1505 INFO_MANAGE_ACCT_SC_REMOVE_YUBIKEY_ID_ARG_VALUE.get()); 1506 removeTOTPSharedSecretValueArg.addLongIdentifier("operationValue", true); 1507 removeTOTPSharedSecretValueArg.addLongIdentifier("totp-shared-secret", 1508 true); 1509 removeTOTPSharedSecretValueArg.addLongIdentifier("operation-value", true); 1510 removeTOTPSharedSecretValueArg.setSensitive(true); 1511 removeTOTPSharedSecretParser.addArgument( 1512 removeTOTPSharedSecretValueArg); 1513 1514 createSubCommand(ManageAccountSubCommandType.REMOVE_TOTP_SHARED_SECRET, 1515 removeTOTPSharedSecretParser, 1516 createSubCommandExample( 1517 ManageAccountSubCommandType.REMOVE_TOTP_SHARED_SECRET, 1518 INFO_MANAGE_ACCT_SC_REMOVE_TOTP_SHARED_SECRET_EXAMPLE.get( 1519 "abcdefghijklmnop", EXAMPLE_TARGET_USER_DN), 1520 "--totpSharedSecret", "abcdefghijklmnop")); 1521 1522 1523 // Define the subcommand to replace set of TOTP shared secrets for a user. 1524 final ArgumentParser setTOTPSharedSecretsParser = 1525 createSubCommandParser( 1526 ManageAccountSubCommandType.SET_TOTP_SHARED_SECRETS); 1527 1528 final StringArgument setTOTPSharedSecretsValueArg = 1529 new StringArgument('O', "totpSharedSecret", true, 0, null, 1530 INFO_MANAGE_ACCT_SC_SET_TOTP_SHARED_SECRETS_ARG_VALUE.get()); 1531 setTOTPSharedSecretsValueArg.addLongIdentifier("operationValue", true); 1532 setTOTPSharedSecretsValueArg.addLongIdentifier("totp-shared-secret", true); 1533 setTOTPSharedSecretsValueArg.addLongIdentifier("operation-value", true); 1534 setTOTPSharedSecretsValueArg.setSensitive(true); 1535 setTOTPSharedSecretsParser.addArgument( 1536 setTOTPSharedSecretsValueArg); 1537 1538 createSubCommand(ManageAccountSubCommandType.SET_TOTP_SHARED_SECRETS, 1539 setTOTPSharedSecretsParser, 1540 createSubCommandExample( 1541 ManageAccountSubCommandType.SET_TOTP_SHARED_SECRETS, 1542 INFO_MANAGE_ACCT_SC_SET_TOTP_SHARED_SECRETS_EXAMPLE.get( 1543 EXAMPLE_TARGET_USER_DN, "abcdefghijklmnop"), 1544 "--totpSharedSecret", "abcdefghijklmnop")); 1545 1546 1547 // Define the subcommand to clear the set of TOTP shared secrets for a user. 1548 createSubCommand( 1549 ManageAccountSubCommandType.CLEAR_TOTP_SHARED_SECRETS, 1550 INFO_MANAGE_ACCT_SC_CLEAR_TOTP_SHARED_SECRETS_EXAMPLE.get( 1551 EXAMPLE_TARGET_USER_DN)); 1552 1553 1554 // Define the subcommand to determine whether a user has at least one 1555 // registered YubiKey OTP device public ID. 1556 createSubCommand( 1557 ManageAccountSubCommandType.GET_HAS_REGISTERED_YUBIKEY_PUBLIC_ID, 1558 INFO_MANAGE_ACCT_SC_GET_HAS_YUBIKEY_ID_EXAMPLE.get( 1559 EXAMPLE_TARGET_USER_DN)); 1560 1561 1562 // Define the subcommand to get the set of registered YubiKey OTP device 1563 // public IDs for a user. 1564 createSubCommand( 1565 ManageAccountSubCommandType.GET_REGISTERED_YUBIKEY_PUBLIC_IDS, 1566 INFO_MANAGE_ACCT_SC_GET_YUBIKEY_IDS_EXAMPLE.get( 1567 EXAMPLE_TARGET_USER_DN)); 1568 1569 1570 // Define the subcommand to add a value to the set of registered YubiKey OTP 1571 // device public IDs for a user. 1572 final ArgumentParser addRegisteredYubiKeyPublicIDParser = 1573 createSubCommandParser( 1574 ManageAccountSubCommandType.ADD_REGISTERED_YUBIKEY_PUBLIC_ID); 1575 1576 final StringArgument addRegisteredYubiKeyPublicIDValueArg = 1577 new StringArgument('O', "publicID", true, 0, null, 1578 INFO_MANAGE_ACCT_SC_ADD_YUBIKEY_ID_ARG_VALUE.get()); 1579 addRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operationValue", 1580 true); 1581 addRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("public-id", true); 1582 addRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operation-value", 1583 true); 1584 addRegisteredYubiKeyPublicIDParser.addArgument( 1585 addRegisteredYubiKeyPublicIDValueArg); 1586 1587 createSubCommand( 1588 ManageAccountSubCommandType.ADD_REGISTERED_YUBIKEY_PUBLIC_ID, 1589 addRegisteredYubiKeyPublicIDParser, 1590 createSubCommandExample( 1591 ManageAccountSubCommandType.ADD_REGISTERED_YUBIKEY_PUBLIC_ID, 1592 INFO_MANAGE_ACCT_SC_ADD_YUBIKEY_ID_EXAMPLE.get( 1593 "abcdefghijkl", EXAMPLE_TARGET_USER_DN), 1594 "--publicID", "abcdefghijkl")); 1595 1596 1597 // Define the subcommand to remove a value from the set of registered 1598 // YubiKey OTP device public IDs for a user. 1599 final ArgumentParser removeRegisteredYubiKeyPublicIDParser = 1600 createSubCommandParser( 1601 ManageAccountSubCommandType.REMOVE_REGISTERED_YUBIKEY_PUBLIC_ID); 1602 1603 final StringArgument removeRegisteredYubiKeyPublicIDValueArg = 1604 new StringArgument('O', "publicID", true, 0, null, 1605 INFO_MANAGE_ACCT_SC_REMOVE_YUBIKEY_ID_ARG_VALUE.get()); 1606 removeRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operationValue", 1607 true); 1608 removeRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("public-id", 1609 true); 1610 removeRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operation-value", 1611 true); 1612 removeRegisteredYubiKeyPublicIDParser.addArgument( 1613 removeRegisteredYubiKeyPublicIDValueArg); 1614 1615 createSubCommand( 1616 ManageAccountSubCommandType.REMOVE_REGISTERED_YUBIKEY_PUBLIC_ID, 1617 removeRegisteredYubiKeyPublicIDParser, 1618 createSubCommandExample( 1619 ManageAccountSubCommandType.REMOVE_REGISTERED_YUBIKEY_PUBLIC_ID, 1620 INFO_MANAGE_ACCT_SC_REMOVE_YUBIKEY_ID_EXAMPLE.get( 1621 "abcdefghijkl", EXAMPLE_TARGET_USER_DN), 1622 "--publicID", "abcdefghijkl")); 1623 1624 1625 // Define the subcommand to replace set of registered YubiKey OTP device 1626 // public IDs for a user. 1627 final ArgumentParser setRegisteredYubiKeyPublicIDParser = 1628 createSubCommandParser( 1629 ManageAccountSubCommandType.SET_REGISTERED_YUBIKEY_PUBLIC_IDS); 1630 1631 final StringArgument setRegisteredYubiKeyPublicIDValueArg = 1632 new StringArgument('O', "publicID", true, 0, null, 1633 INFO_MANAGE_ACCT_SC_SET_YUBIKEY_IDS_ARG_VALUE.get()); 1634 setRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operationValue", 1635 true); 1636 setRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("public-id", true); 1637 setRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operation-value", 1638 true); 1639 setRegisteredYubiKeyPublicIDParser.addArgument( 1640 setRegisteredYubiKeyPublicIDValueArg); 1641 1642 createSubCommand( 1643 ManageAccountSubCommandType.SET_REGISTERED_YUBIKEY_PUBLIC_IDS, 1644 setRegisteredYubiKeyPublicIDParser, 1645 createSubCommandExample( 1646 ManageAccountSubCommandType.SET_REGISTERED_YUBIKEY_PUBLIC_IDS, 1647 INFO_MANAGE_ACCT_SC_SET_YUBIKEY_IDS_EXAMPLE.get( 1648 EXAMPLE_TARGET_USER_DN, "abcdefghijkl"), 1649 "--publicID", "abcdefghijkl")); 1650 1651 1652 // Define the subcommand to clear the set of registered YubiKey OTP device 1653 // public IDs for a user. 1654 createSubCommand( 1655 ManageAccountSubCommandType.CLEAR_REGISTERED_YUBIKEY_PUBLIC_IDS, 1656 INFO_MANAGE_ACCT_SC_CLEAR_YUBIKEY_IDS_EXAMPLE.get( 1657 EXAMPLE_TARGET_USER_DN)); 1658 1659 1660 // Define the subcommand to determine whether a user has at least one static 1661 // password. 1662 createSubCommand(ManageAccountSubCommandType.GET_HAS_STATIC_PASSWORD, 1663 INFO_MANAGE_ACCT_SC_GET_HAS_STATIC_PW_EXAMPLE.get( 1664 EXAMPLE_TARGET_USER_DN)); 1665 1666 1667 // Define the subcommand to retrieve the last bind password validation time 1668 // for a user. 1669 createSubCommand( 1670 ManageAccountSubCommandType.GET_LAST_BIND_PASSWORD_VALIDATION_TIME, 1671 INFO_MANAGE_ACCT_SC_GET_LAST_BIND_PW_VALIDATION_TIME_EXAMPLE.get( 1672 EXAMPLE_TARGET_USER_DN)); 1673 1674 1675 // Define the subcommand to retrieve the length of time since the last bind 1676 // password validation for a user. 1677 createSubCommand( 1678 ManageAccountSubCommandType. 1679 GET_SECONDS_SINCE_LAST_BIND_PASSWORD_VALIDATION, 1680 INFO_MANAGE_ACCT_SC_GET_SECS_SINCE_LAST_BIND_PW_VALIDATION_EXAMPLE.get( 1681 EXAMPLE_TARGET_USER_DN)); 1682 1683 1684 // Define the subcommand to set the last bind password validation time for a 1685 // user. 1686 final ArgumentParser setLastBindPasswordValidationTimeParser = 1687 createSubCommandParser(ManageAccountSubCommandType. 1688 SET_LAST_BIND_PASSWORD_VALIDATION_TIME); 1689 1690 final TimestampArgument setLastBindPasswordValidationTimeValueArg = 1691 new TimestampArgument('O', "validationTime", false, 1, null, 1692 INFO_MANAGE_ACCT_SC_SET_LAST_BIND_PW_VALIDATION_TIME_ARG_VALUE. 1693 get()); 1694 setLastBindPasswordValidationTimeValueArg.addLongIdentifier( 1695 "operationValue", true); 1696 setLastBindPasswordValidationTimeValueArg.addLongIdentifier( 1697 "validation-time", true); 1698 setLastBindPasswordValidationTimeValueArg.addLongIdentifier( 1699 "operation-value", true); 1700 setLastBindPasswordValidationTimeParser.addArgument( 1701 setLastBindPasswordValidationTimeValueArg); 1702 1703 createSubCommand( 1704 ManageAccountSubCommandType.SET_LAST_BIND_PASSWORD_VALIDATION_TIME, 1705 setLastBindPasswordValidationTimeParser, 1706 createSubCommandExample( 1707 ManageAccountSubCommandType. 1708 SET_LAST_BIND_PASSWORD_VALIDATION_TIME, 1709 INFO_MANAGE_ACCT_SC_SET_LAST_BIND_PW_VALIDATION_TIME_EXAMPLE.get( 1710 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 1711 "--validationTime", currentGeneralizedTime)); 1712 1713 1714 // Define the subcommand to clear the last bind password validation time for 1715 // a user. 1716 createSubCommand( 1717 ManageAccountSubCommandType.CLEAR_LAST_BIND_PASSWORD_VALIDATION_TIME, 1718 INFO_MANAGE_ACCT_SC_CLEAR_LAST_BIND_PW_VALIDATION_TIME_EXAMPLE.get( 1719 EXAMPLE_TARGET_USER_DN)); 1720 1721 1722 // Define the subcommand to determine whether an account is locked because 1723 // it contains a password that does not satisfy all of the configured 1724 // password validators. 1725 createSubCommand( 1726 ManageAccountSubCommandType.GET_ACCOUNT_IS_VALIDATION_LOCKED, 1727 INFO_MANAGE_ACCT_SC_GET_ACCT_VALIDATION_LOCKED_EXAMPLE.get( 1728 EXAMPLE_TARGET_USER_DN)); 1729 1730 1731 // Define the subcommand to specify whether an account is locked because it 1732 // contains a password that does not satisfy all of the configured password 1733 // validators. 1734 final ArgumentParser setIsValidationLockedParser = 1735 createSubCommandParser( 1736 ManageAccountSubCommandType.SET_ACCOUNT_IS_VALIDATION_LOCKED); 1737 1738 final BooleanValueArgument setIsValidationLockedValueArg = 1739 new BooleanValueArgument('O', "accountIsValidationLocked", true, null, 1740 INFO_MANAGE_ACCT_SC_SET_ACCT_VALIDATION_LOCKED_ARG_VALUE.get()); 1741 setIsValidationLockedValueArg.addLongIdentifier("operationValue", true); 1742 setIsValidationLockedValueArg.addLongIdentifier( 1743 "account-is-validation-locked", true); 1744 setIsValidationLockedValueArg.addLongIdentifier("operation-value", true); 1745 setIsValidationLockedParser.addArgument(setIsValidationLockedValueArg); 1746 1747 createSubCommand( 1748 ManageAccountSubCommandType.SET_ACCOUNT_IS_VALIDATION_LOCKED, 1749 setIsValidationLockedParser, 1750 createSubCommandExample( 1751 ManageAccountSubCommandType.SET_ACCOUNT_IS_VALIDATION_LOCKED, 1752 INFO_MANAGE_ACCT_SC_SET_ACCT_VALIDATION_LOCKED_EXAMPLE.get( 1753 EXAMPLE_TARGET_USER_DN), 1754 "--accountIsValidationLocked", "true")); 1755 1756 1757 // Define the subcommand to retrieve a user's recent login history. 1758 createSubCommand( 1759 ManageAccountSubCommandType.GET_RECENT_LOGIN_HISTORY, 1760 INFO_MANAGE_ACCT_SC_GET_RECENT_LOGIN_HISTORY_EXAMPLE.get( 1761 EXAMPLE_TARGET_USER_DN)); 1762 1763 1764 // Define the subcommand to retrieve a user's recent login history. 1765 createSubCommand( 1766 ManageAccountSubCommandType.CLEAR_RECENT_LOGIN_HISTORY, 1767 INFO_MANAGE_ACCT_SC_CLEAR_RECENT_LOGIN_HISTORY_EXAMPLE.get( 1768 EXAMPLE_TARGET_USER_DN)); 1769 } 1770 1771 1772 1773 /** 1774 * Creates an argument parser for the provided subcommand type. It will not 1775 * have any arguments associated with it. 1776 * 1777 * @param type The subcommand type for which to create the argument parser. 1778 * 1779 * @return The created argument parser. 1780 * 1781 * @throws ArgumentException If a problem is encountered while creating the 1782 * argument parser. 1783 */ 1784 @NotNull() 1785 private static ArgumentParser createSubCommandParser( 1786 @NotNull final ManageAccountSubCommandType type) 1787 throws ArgumentException 1788 { 1789 return new ArgumentParser(type.getPrimaryName(), type.getDescription()); 1790 } 1791 1792 1793 1794 /** 1795 * Generates an example usage map for a specified subcommand. 1796 * 1797 * @param t The subcommand type. 1798 * @param description The description to use for the example. 1799 * @param args The set of arguments to include in the example, 1800 * excluding the subcommand name and the arguments used 1801 * to connect and authenticate to the server. This may 1802 * be empty if no additional arguments are needed. 1803 * 1804 * @return The generated example usage map. 1805 */ 1806 @NotNull() 1807 private static LinkedHashMap<String[],String> createSubCommandExample( 1808 @NotNull final ManageAccountSubCommandType t, 1809 @NotNull final String description, 1810 @NotNull final String... args) 1811 { 1812 final LinkedHashMap<String[], String> examples = 1813 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 1814 createSubCommandExample(examples, t, description, args); 1815 return examples; 1816 } 1817 1818 1819 1820 /** 1821 * Adds an example for a specified subcommand to the given map. 1822 * 1823 * @param examples The map to which the example should be added. 1824 * @param t The subcommand type. 1825 * @param description The description to use for the example. 1826 * @param args The set of arguments to include in the example, 1827 * excluding the subcommand name and the arguments used 1828 * to connect and authenticate to the server. This may 1829 * be empty if no additional arguments are needed. 1830 */ 1831 private static void createSubCommandExample( 1832 @NotNull final LinkedHashMap<String[], String> examples, 1833 @NotNull final ManageAccountSubCommandType t, final 1834 @NotNull String description, 1835 @NotNull final String... args) 1836 { 1837 final ArrayList<String> argList = new ArrayList<>(10 + args.length); 1838 argList.add(t.getPrimaryName()); 1839 argList.add("--hostname"); 1840 argList.add("server.example.com"); 1841 argList.add("--port"); 1842 argList.add("389"); 1843 argList.add("--bindDN"); 1844 argList.add("uid=admin,dc=example,dc=com"); 1845 argList.add("--promptForBindPassword"); 1846 argList.add("--targetDN"); 1847 argList.add("uid=jdoe,ou=People,dc=example,dc=com"); 1848 1849 if (args.length > 0) 1850 { 1851 argList.addAll(Arrays.asList(args)); 1852 } 1853 1854 final String[] argArray = new String[argList.size()]; 1855 argList.toArray(argArray); 1856 1857 examples.put(argArray, description); 1858 } 1859 1860 1861 1862 /** 1863 * Creates a subcommand with the provided information. 1864 * 1865 * @param subcommandType The subcommand type. 1866 * @param exampleDescription The description to use for the 1867 * automatically-generated example. 1868 * 1869 * @throws ArgumentException If a problem is encountered while creating the 1870 * subcommand. 1871 */ 1872 private void createSubCommand( 1873 @NotNull final ManageAccountSubCommandType subcommandType, 1874 @NotNull final String exampleDescription) 1875 throws ArgumentException 1876 { 1877 final ArgumentParser subcommandParser = 1878 createSubCommandParser(subcommandType); 1879 1880 final LinkedHashMap<String[],String> examples = 1881 createSubCommandExample(subcommandType, exampleDescription); 1882 1883 createSubCommand(subcommandType, subcommandParser, examples); 1884 } 1885 1886 1887 1888 /** 1889 * Creates a subcommand with the provided information. 1890 * 1891 * @param subcommandType The subcommand type. 1892 * @param subcommandParser The argument parser for the subcommand-specific 1893 * arguments. 1894 * @param examples The example usages for the subcommand. 1895 * 1896 * @throws ArgumentException If a problem is encountered while creating the 1897 * subcommand. 1898 */ 1899 private void createSubCommand( 1900 @NotNull final ManageAccountSubCommandType subcommandType, 1901 @NotNull final ArgumentParser subcommandParser, 1902 @NotNull final LinkedHashMap<String[],String> examples) 1903 throws ArgumentException 1904 { 1905 final SubCommand subCommand = new SubCommand( 1906 subcommandType.getPrimaryName(), subcommandType.getDescription(), 1907 subcommandParser, examples); 1908 1909 for (final String alternateName : subcommandType.getAlternateNames()) 1910 { 1911 subCommand.addName(alternateName, true); 1912 } 1913 1914 parser.addSubCommand(subCommand); 1915 } 1916 1917 1918 1919 /** 1920 * {@inheritDoc} 1921 */ 1922 @Override() 1923 @NotNull() 1924 public LDAPConnectionOptions getConnectionOptions() 1925 { 1926 return connectionOptions; 1927 } 1928 1929 1930 1931 /** 1932 * {@inheritDoc} 1933 */ 1934 @Override() 1935 @NotNull() 1936 public ResultCode doToolProcessing() 1937 { 1938 // If we should just generate a sample rate data file, then do that now. 1939 final FileArgument generateSampleRateFile = 1940 parser.getFileArgument(ARG_GENERATE_SAMPLE_RATE_FILE); 1941 if (generateSampleRateFile.isPresent()) 1942 { 1943 try 1944 { 1945 RateAdjustor.writeSampleVariableRateFile( 1946 generateSampleRateFile.getValue()); 1947 return ResultCode.SUCCESS; 1948 } 1949 catch (final Exception e) 1950 { 1951 Debug.debugException(e); 1952 wrapErr(0, WRAP_COLUMN, 1953 ERR_MANAGE_ACCT_CANNOT_GENERATE_SAMPLE_RATE_FILE.get( 1954 generateSampleRateFile.getValue().getAbsolutePath(), 1955 StaticUtils.getExceptionMessage(e))); 1956 return ResultCode.LOCAL_ERROR; 1957 } 1958 } 1959 1960 1961 // If we need to create a fixed-rate barrier and/or use a variable rate 1962 // definition, then set that up. 1963 final IntegerArgument ratePerSecond = 1964 parser.getIntegerArgument(ARG_RATE_PER_SECOND); 1965 final FileArgument variableRateData = 1966 parser.getFileArgument(ARG_VARIABLE_RATE_DATA); 1967 if (ratePerSecond.isPresent() || variableRateData.isPresent()) 1968 { 1969 if (ratePerSecond.isPresent()) 1970 { 1971 rateLimiter = new FixedRateBarrier(1000L, ratePerSecond.getValue()); 1972 } 1973 else 1974 { 1975 rateLimiter = new FixedRateBarrier(1000L, Integer.MAX_VALUE); 1976 } 1977 1978 if (variableRateData.isPresent()) 1979 { 1980 try 1981 { 1982 rateAdjustor = RateAdjustor.newInstance(rateLimiter, 1983 ratePerSecond.getValue(), variableRateData.getValue()); 1984 } 1985 catch (final Exception e) 1986 { 1987 Debug.debugException(e); 1988 wrapErr(0, WRAP_COLUMN, 1989 ERR_MANAGE_ACCT_CANNOT_CREATE_RATE_ADJUSTOR.get( 1990 variableRateData.getValue().getAbsolutePath(), 1991 StaticUtils.getExceptionMessage(e))); 1992 return ResultCode.PARAM_ERROR; 1993 } 1994 } 1995 } 1996 1997 1998 // Create the connection pool to use for all processing. 1999 final LDAPConnectionPool pool; 2000 final int numSearchThreads = 2001 parser.getIntegerArgument(ARG_NUM_SEARCH_THREADS).getValue(); 2002 try 2003 { 2004 final int numOperationThreads = 2005 parser.getIntegerArgument(ARG_NUM_THREADS).getValue(); 2006 pool = getConnectionPool(numOperationThreads, 2007 (numOperationThreads + numSearchThreads)); 2008 2009 // Explicitly disable automatic retry, since it probably won't work 2010 // reliably for extended operations anyway. We'll handle retry manually. 2011 pool.setRetryFailedOperationsDueToInvalidConnections(false); 2012 2013 // Set a maximum connection age of 30 minutes. 2014 pool.setMaxConnectionAgeMillis(1_800_000L); 2015 } 2016 catch (final LDAPException le) 2017 { 2018 Debug.debugException(le); 2019 2020 wrapErr(0, WRAP_COLUMN, 2021 ERR_MANAGE_ACCT_CANNOT_CREATE_CONNECTION_POOL.get(getToolName(), 2022 le.getMessage())); 2023 return le.getResultCode(); 2024 } 2025 2026 2027 try 2028 { 2029 // Create the output writer. This should always succeed. 2030 outputWriter = new LDIFWriter(getOut()); 2031 2032 2033 2034 // Create the reject writer if appropriate. 2035 final FileArgument rejectFile = parser.getFileArgument(ARG_REJECT_FILE); 2036 if (rejectFile.isPresent()) 2037 { 2038 final BooleanArgument appendToRejectFile = 2039 parser.getBooleanArgument(ARG_APPEND_TO_REJECT_FILE); 2040 2041 try 2042 { 2043 rejectWriter = new LDIFWriter(new FileOutputStream( 2044 rejectFile.getValue(), appendToRejectFile.isPresent())); 2045 } 2046 catch (final Exception e) 2047 { 2048 Debug.debugException(e); 2049 wrapErr(0, WRAP_COLUMN, 2050 ERR_MANAGE_ACCT_CANNOT_CREATE_REJECT_WRITER.get( 2051 rejectFile.getValue().getAbsolutePath(), 2052 StaticUtils.getExceptionMessage(e))); 2053 return ResultCode.LOCAL_ERROR; 2054 } 2055 } 2056 2057 2058 // Create the processor that will be used to actually perform the 2059 // manage-account operation processing for each entry. 2060 final ManageAccountProcessor processor; 2061 try 2062 { 2063 processor = new ManageAccountProcessor(this, pool, rateLimiter, 2064 outputWriter, rejectWriter); 2065 } 2066 catch (final LDAPException le) 2067 { 2068 Debug.debugException(le); 2069 wrapErr(0, WRAP_COLUMN, 2070 ERR_MANAGE_ACCT_CANNOT_CREATE_PROCESSOR.get( 2071 StaticUtils.getExceptionMessage(le))); 2072 return le.getResultCode(); 2073 } 2074 2075 2076 // If we should use a rate adjustor, then start it now. 2077 if (rateAdjustor != null) 2078 { 2079 rateAdjustor.start(); 2080 } 2081 2082 2083 // If any targetDN values were provided, then process them now. 2084 final DNArgument targetDN = parser.getDNArgument(ARG_TARGET_DN); 2085 if (targetDN.isPresent()) 2086 { 2087 for (final DN dn : targetDN.getValues()) 2088 { 2089 if (cancelRequested()) 2090 { 2091 return ResultCode.USER_CANCELED; 2092 } 2093 2094 processor.process(dn.toString()); 2095 } 2096 } 2097 2098 2099 // If any DN input files were specified, then process them now. 2100 final FileArgument dnInputFile = 2101 parser.getFileArgument(ARG_DN_INPUT_FILE); 2102 if (dnInputFile.isPresent()) 2103 { 2104 for (final File f : dnInputFile.getValues()) 2105 { 2106 DNFileReader reader = null; 2107 try 2108 { 2109 reader = new DNFileReader(f); 2110 while (true) 2111 { 2112 if (cancelRequested()) 2113 { 2114 return ResultCode.USER_CANCELED; 2115 } 2116 2117 final DN dn; 2118 try 2119 { 2120 dn = reader.readDN(); 2121 } 2122 catch (final LDAPException le) 2123 { 2124 Debug.debugException(le); 2125 processor.handleMessage(le.getMessage(), true); 2126 continue; 2127 } 2128 2129 if (dn == null) 2130 { 2131 break; 2132 } 2133 2134 processor.process(dn.toString()); 2135 } 2136 } 2137 catch (final Exception e) 2138 { 2139 Debug.debugException(e); 2140 processor.handleMessage( 2141 ERR_MANAGE_ACCT_ERROR_READING_DN_FILE.get( 2142 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 2143 true); 2144 } 2145 finally 2146 { 2147 if (reader != null) 2148 { 2149 try 2150 { 2151 reader.close(); 2152 } 2153 catch (final Exception e2) 2154 { 2155 Debug.debugException(e2); 2156 } 2157 } 2158 } 2159 } 2160 } 2161 2162 2163 // If any target filters were specified, then process them now. 2164 final FilterArgument targetFilter = 2165 parser.getFilterArgument(ARG_TARGET_FILTER); 2166 if (targetFilter.isPresent()) 2167 { 2168 searchProcessor = 2169 new ManageAccountSearchProcessor(this, processor, pool); 2170 for (final Filter f : targetFilter.getValues()) 2171 { 2172 searchProcessor.processFilter(f); 2173 } 2174 } 2175 2176 2177 // If any filter input files were specified, then process them now. 2178 final FileArgument filterInputFile = 2179 parser.getFileArgument(ARG_FILTER_INPUT_FILE); 2180 if (filterInputFile.isPresent()) 2181 { 2182 if (searchProcessor == null) 2183 { 2184 searchProcessor = 2185 new ManageAccountSearchProcessor(this, processor, pool); 2186 } 2187 2188 for (final File f : filterInputFile.getValues()) 2189 { 2190 FilterFileReader reader = null; 2191 try 2192 { 2193 reader = new FilterFileReader(f); 2194 while (true) 2195 { 2196 if (cancelRequested()) 2197 { 2198 return ResultCode.USER_CANCELED; 2199 } 2200 2201 final Filter filter; 2202 try 2203 { 2204 filter = reader.readFilter(); 2205 } 2206 catch (final LDAPException le) 2207 { 2208 Debug.debugException(le); 2209 processor.handleMessage(le.getMessage(), true); 2210 continue; 2211 } 2212 2213 if (filter == null) 2214 { 2215 break; 2216 } 2217 2218 searchProcessor.processFilter(filter); 2219 } 2220 } 2221 catch (final Exception e) 2222 { 2223 Debug.debugException(e); 2224 processor.handleMessage( 2225 ERR_MANAGE_ACCT_ERROR_READING_FILTER_FILE.get( 2226 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 2227 true); 2228 } 2229 finally 2230 { 2231 if (reader != null) 2232 { 2233 try 2234 { 2235 reader.close(); 2236 } 2237 catch (final Exception e2) 2238 { 2239 Debug.debugException(e2); 2240 } 2241 } 2242 } 2243 } 2244 } 2245 2246 2247 // If any target user IDs were specified, then process them now. 2248 final StringArgument targetUserID = 2249 parser.getStringArgument(ARG_TARGET_USER_ID); 2250 if (targetUserID.isPresent()) 2251 { 2252 if (searchProcessor == null) 2253 { 2254 searchProcessor = 2255 new ManageAccountSearchProcessor(this, processor, pool); 2256 } 2257 2258 for (final String userID : targetUserID.getValues()) 2259 { 2260 searchProcessor.processUserID(userID); 2261 } 2262 } 2263 2264 2265 // If any user ID input files were specified, then process them now. 2266 final FileArgument userIDInputFile = 2267 parser.getFileArgument(ARG_USER_ID_INPUT_FILE); 2268 if (userIDInputFile.isPresent()) 2269 { 2270 if (searchProcessor == null) 2271 { 2272 searchProcessor = 2273 new ManageAccountSearchProcessor(this, processor, pool); 2274 } 2275 2276 for (final File f : userIDInputFile.getValues()) 2277 { 2278 BufferedReader reader = null; 2279 try 2280 { 2281 reader = new BufferedReader(new FileReader(f)); 2282 while (true) 2283 { 2284 if (cancelRequested()) 2285 { 2286 return ResultCode.USER_CANCELED; 2287 } 2288 2289 final String line = reader.readLine(); 2290 if (line == null) 2291 { 2292 break; 2293 } 2294 2295 if ((line.length() == 0) || line.startsWith("#")) 2296 { 2297 continue; 2298 } 2299 2300 searchProcessor.processUserID(line.trim()); 2301 } 2302 } 2303 catch (final Exception e) 2304 { 2305 Debug.debugException(e); 2306 processor.handleMessage( 2307 ERR_MANAGE_ACCT_ERROR_READING_USER_ID_FILE.get( 2308 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 2309 true); 2310 } 2311 finally 2312 { 2313 if (reader != null) 2314 { 2315 try 2316 { 2317 reader.close(); 2318 } 2319 catch (final Exception e2) 2320 { 2321 Debug.debugException(e2); 2322 } 2323 } 2324 } 2325 } 2326 } 2327 2328 2329 allFiltersProvided.set(true); 2330 if (searchProcessor != null) 2331 { 2332 searchProcessor.waitForCompletion(); 2333 } 2334 2335 allDNsProvided.set(true); 2336 processor.waitForCompletion(); 2337 } 2338 finally 2339 { 2340 pool.close(); 2341 2342 if (rejectWriter != null) 2343 { 2344 try 2345 { 2346 rejectWriter.close(); 2347 } 2348 catch (final Exception e) 2349 { 2350 Debug.debugException(e); 2351 } 2352 } 2353 } 2354 2355 2356 // If we've gotten here, then we can consider the command successful, even 2357 // if some of the operations failed. 2358 return ResultCode.SUCCESS; 2359 } 2360 2361 2362 2363 /** 2364 * Retrieves the argument parser for this tool. 2365 * 2366 * @return The argument parser for this tool. 2367 */ 2368 @Nullable() 2369 ArgumentParser getArgumentParser() 2370 { 2371 return parser; 2372 } 2373 2374 2375 2376 /** 2377 * Indicates whether the tool should cancel its processing. 2378 * 2379 * @return {@code true} if the tool should cancel its processing, or 2380 * {@code false} if not. 2381 */ 2382 boolean cancelRequested() 2383 { 2384 return cancelRequested.get(); 2385 } 2386 2387 2388 2389 /** 2390 * Indicates whether the manage-account processor has been provided with all 2391 * of the DNs of all of the entries to process. 2392 * 2393 * @return {@code true} if the manage-account processor has been provided 2394 * with all of the DNs of all of the entries to process, or 2395 * {@code false} if not. 2396 */ 2397 boolean allDNsProvided() 2398 { 2399 return allDNsProvided.get(); 2400 } 2401 2402 2403 2404 /** 2405 * Indicates whether the manage-account search processor has been provided 2406 * with all of the filters to use to identify entries to process. 2407 * 2408 * @return {@code true} if the manage-account search processor has been 2409 * provided with all of the filters to use to identify entries to 2410 * process, or {@code false} if not. 2411 */ 2412 boolean allFiltersProvided() 2413 { 2414 return allFiltersProvided.get(); 2415 } 2416 2417 2418 2419 /** 2420 * {@inheritDoc} 2421 */ 2422 @Override() 2423 protected boolean registerShutdownHook() 2424 { 2425 return true; 2426 } 2427 2428 2429 2430 /** 2431 * {@inheritDoc} 2432 */ 2433 @Override() 2434 protected void doShutdownHookProcessing( 2435 @Nullable final ResultCode resultCode) 2436 { 2437 cancelRequested.set(true); 2438 2439 if (rateLimiter != null) 2440 { 2441 rateLimiter.shutdownRequested(); 2442 } 2443 2444 if (searchProcessor != null) 2445 { 2446 searchProcessor.cancelSearches(); 2447 } 2448 } 2449 2450 2451 2452 /** 2453 * Performs any processing that may be necessary in response to the provided 2454 * unsolicited notification that has been received from the server. 2455 * 2456 * @param connection The connection on which the unsolicited notification 2457 * was received. 2458 * @param notification The unsolicited notification that has been received 2459 * from the server. 2460 */ 2461 @Override() 2462 public void handleUnsolicitedNotification( 2463 @NotNull final LDAPConnection connection, 2464 @NotNull final ExtendedResult notification) 2465 { 2466 final String message = INFO_MANAGE_ACCT_UNSOLICITED_NOTIFICATION.get( 2467 String.valueOf(connection), String.valueOf(notification)); 2468 if (outputWriter == null) 2469 { 2470 err(); 2471 err("* " + message); 2472 err(); 2473 } 2474 else 2475 { 2476 try 2477 { 2478 outputWriter.writeComment(message, true, true); 2479 outputWriter.flush(); 2480 } 2481 catch (final Exception e) 2482 { 2483 // We can't really do anything about this. 2484 Debug.debugException(e); 2485 } 2486 } 2487 } 2488 2489 2490 2491 /** 2492 * {@inheritDoc} 2493 */ 2494 @Override() 2495 @NotNull() 2496 public LinkedHashMap<String[],String> getExampleUsages() 2497 { 2498 final LinkedHashMap<String[],String> examples = 2499 new LinkedHashMap<>(StaticUtils.computeMapCapacity(4)); 2500 2501 createSubCommandExample(examples, 2502 ManageAccountSubCommandType.GET_ALL, 2503 INFO_MANAGE_ACCT_SC_GET_ALL_EXAMPLE.get(EXAMPLE_TARGET_USER_DN)); 2504 2505 createSubCommandExample(examples, 2506 ManageAccountSubCommandType.GET_ACCOUNT_USABILITY_ERRORS, 2507 INFO_MANAGE_ACCT_SC_GET_USABILITY_ERRORS_EXAMPLE.get( 2508 EXAMPLE_TARGET_USER_DN)); 2509 2510 createSubCommandExample(examples, 2511 ManageAccountSubCommandType.SET_ACCOUNT_IS_DISABLED, 2512 INFO_MANAGE_ACCT_SC_SET_IS_DISABLED_EXAMPLE.get( 2513 EXAMPLE_TARGET_USER_DN), 2514 "--accountIsDisabled", "true"); 2515 2516 createSubCommandExample(examples, 2517 ManageAccountSubCommandType.CLEAR_AUTHENTICATION_FAILURE_TIMES, 2518 INFO_MANAGE_ACCT_SC_CLEAR_AUTH_FAILURE_TIMES_EXAMPLE.get( 2519 EXAMPLE_TARGET_USER_DN)); 2520 2521 return examples; 2522 } 2523}