UnboundID Server SDK

Ping Identity
UnboundID Server SDK Documentation

ExampleDataSecurityAuditor.java

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * docs/licenses/cddl.txt
 * or http://www.opensource.org/licenses/cddl1.php.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * docs/licenses/cddl.txt.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2022-2023 Ping Identity Corporation
 */
package com.unboundid.directory.sdk.examples;



import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

import com.unboundid.directory.sdk.common.types.Entry;
import com.unboundid.directory.sdk.ds.api.DataSecurityAuditor;
import com.unboundid.directory.sdk.ds.config.DataSecurityAuditorConfig;
import com.unboundid.directory.sdk.ds.types.AuditSeverity;
import com.unboundid.directory.sdk.ds.types.DataSecurityAuditorEntryReporter;
import com.unboundid.directory.sdk.ds.types.DataSecurityAuditorSummaryReporter;
import com.unboundid.directory.sdk.ds.types.DirectoryServerContext;
import com.unboundid.ldap.sdk.Attribute;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.unboundidds.PasswordPolicyStateJSON;
import com.unboundid.util.NotNull;
import com.unboundid.util.Nullable;
import com.unboundid.util.args.ArgumentException;
import com.unboundid.util.args.ArgumentParser;



/**
 * This class provides a simple example of a data security auditor that can be
 * used to identify accounts with outstanding authentication failures (that is,
 * one or more failed bind attempts since the most recent successful attempt).
 * This auditor requires failure lockout to be enabled in the associated
 * password policy, as that enables tracking of outstanding authentication
 * failures.  It does not require any special configuration properties.
 */
public final class ExampleDataSecurityAuditor
       extends DataSecurityAuditor
{
  /**
   * The name of the attribute that will be included in report entries to
   * indicate the number of outstanding authentication failures for the
   * associated entry.
   */
  @NotNull private static final String REPORT_ATTR_NUM_OUTSTANDING_FAILURES =
       "ds-audit-report-number-of-outstanding-authentication-failures";



  /**
   * The name of the attribute that will be included in summary entries to
   * indicate the total number of entries with outstanding authentication
   * failures.
   */
  @NotNull private static final String
       SUMMARY_ATTR_ENTRIES_WITH_OUTSTANDING_FAILURES =
       "ds-audit-summary-entries-with-outstanding-authentication-failures";



  /**
   * The set of object classes that will be included in report entries generated
   * by this data security auditor.
   */
  @NotNull private static final String[] REPORT_ENTRY_OBJECT_CLASSES =
  {
    "ds-audit-report-outstanding-authentication-failures",
    "extensibleObject"
  };



  /**
   * The set of object classes that will be included in summary entries
   * generated by this data security auditor.
   */
  @NotNull private static final String[] SUMMARY_ENTRY_OBJECT_CLASSES =
  {
    "ds-audit-summary-outstanding-authentication-failures",
    "extensibleObject"
  };



  // A counter that will be used to keep track of the number of entries with
  // outstanding authentication failures.
  @NotNull private final AtomicLong entriesWithOustandingAuthFailures;



  /**
   * Creates a new instance of this data security auditor.  All data security
   * auditor implementations must include a default constructor, but any
   * initialization should generally be done in the
   * {@code initializeDataSecurityAuditor} method.
   */
  public ExampleDataSecurityAuditor()
  {
    entriesWithOustandingAuthFailures = new AtomicLong(0L);
  }



  /**
   * Retrieves a human-readable name for this extension.
   *
   * @return  A human-readable name for this extension.
   */
  @Override()
  @NotNull()
  public String getExtensionName()
  {
    return "Example Data Security Auditor";
  }



  /**
   * Retrieves a human-readable description for this extension.  Each element
   * of the array that is returned will be considered a separate paragraph in
   * generated documentation.
   *
   * @return  A human-readable description for this extension, or {@code null}
   *          or an empty array if no description should be available.
   */
  @Override()
  @Nullable()
  public String[] getExtensionDescription()
  {
    return new String[]
    {
      "This data security auditor can be used to identify user accounts with " +
           "outstanding authentication failures."
    };
  }



  /**
   * Updates the provided argument parser to define any configuration arguments
   * which may be used by this extension.  The argument parser may also be
   * updated to define relationships between arguments (e.g., to specify
   * required, exclusive, or dependent argument sets).
   *
   * @param  parser  The argument parser to be updated with the configuration
   *                 arguments which may be used by this extension.
   *
   * @throws  ArgumentException  If a problem is encountered while updating the
   *                             provided argument parser.
   */
  @Override()
  public void defineConfigArguments(@NotNull final ArgumentParser parser)
         throws ArgumentException
  {
    // No arguments will be allowed by default.
  }



  /**
   * Initializes this data security auditor before beginning processing in the
   * specified backend.
   *
   * @param  serverContext  A handle to the server context for the server in
   *                        which this extension is running.
   * @param  config         The general configuration for this data security
   *                        auditor.
   * @param  parser         The argument parser which has been initialized from
   *                        the configuration for this data security auditor.
   * @param  backendID      The backend ID for the backend in which processing
   *                        will be performed.
   *
   * @throws  LDAPException  If a problem occurs while initializing this data
   *                         security auditor.
   */
  @Override()
  public void initializeDataSecurityAuditorForBackend(
                   @NotNull final DirectoryServerContext serverContext,
                   @NotNull final DataSecurityAuditorConfig config,
                   @NotNull final ArgumentParser parser,
                   @NotNull final String backendID)
         throws LDAPException
  {
    entriesWithOustandingAuthFailures.set(0L);
  }



  /**
   * Performs any cleanup that may be necessary when this data security auditor
   * ends processing in a backend.
   */
  @Override()
  public void finalizeDataSecurityAuditor()
  {
    // No implementation is required.
  }



  /**
   * Examines the provided entry to determine whether any data security issues
   * should be reported.  If any such issues are found, then the provided
   * reporter should be used to report them.
   *
   * @param  entry                The entry to examine.
   * @param  passwordPolicyState  The password policy state for the account
   *                              with which the provided entry is associated.
   * @param  reporter             A reporter whose {@code reportEntry} method
   *                              may be used to indicate that the provided
   *                              entry has one or more identified issues.
   *
   * @throws  IOException  If a problem is encountered while the reporter is
   *                       attempting to add an entry to the report file.
   */
  @Override()
  public void examineEntry(
              @NotNull final Entry entry,
              @NotNull final PasswordPolicyStateJSON passwordPolicyState,
              @NotNull final DataSecurityAuditorEntryReporter reporter)
         throws IOException
  {
    final Integer outstandingAuthenticationFailures =
         passwordPolicyState.getCurrentAuthenticationFailureCount();
    if ((outstandingAuthenticationFailures != null) &&
         (outstandingAuthenticationFailures > 0))
    {
      entriesWithOustandingAuthFailures.incrementAndGet();

      reporter.reportEntry(entry, AuditSeverity.WARNING,
           REPORT_ENTRY_OBJECT_CLASSES,
           new Attribute(REPORT_ATTR_NUM_OUTSTANDING_FAILURES,
                outstandingAuthenticationFailures.toString()));
    }
  }



  /**
   * Reports a summary of the results obtained from processing this data
   * security auditor in the associated backend.
   *
   * @param  reporter  The reporter that may be used to provide the summary of
   *                   processing performed by this data security auditor in the
   *                   associated backend.
   *
   * @throws  IOException  If a problem is encountered while the reporter is
   *                       attempting to add an entry to the report file.
   */
  @Override()
  public void reportSummary(
              @NotNull final DataSecurityAuditorSummaryReporter reporter)
         throws IOException
  {
    reporter.reportSummary(SUMMARY_ENTRY_OBJECT_CLASSES,
         new Attribute(SUMMARY_ATTR_ENTRIES_WITH_OUTSTANDING_FAILURES,
              entriesWithOustandingAuthFailures.toString()));
  }



  /**
   * Retrieves a map containing examples of configurations that may be used for
   * this extension.  The map key should be a list of sample arguments, and the
   * corresponding value should be a description of the behavior that will be
   * exhibited by the extension when used with that configuration.
   *
   * @return  A map containing examples of configurations that may be used for
   *          this extension.  It may be {@code null} or empty if there should
   *          not be any example argument sets.
   */
  @Nullable()
  public Map<List<String>,String> getExamplesArgumentSets()
  {
    return Collections.emptyMap();
  }
}