mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
03.56.2007 846b9829d2dc1a05e18cb11a7b13f7373f6a6a6b
Implement support for config file change detection, which can detect external
edits to the server configuration (e.g., manually updating the file in a text
editor) with the server online. If the server detects that the configuration
file has been externally modified when it needs to rewrite it to apply a change
coming in through protocol, then it will attempt to copy the manually-edited
file off to the side and will generate an administrative alert and write a log
message to let administrators know what happened.

OpenDS Issue Number: 169
3 files modified
162 ■■■■■ changed files
opendj-sdk/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java 73 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/messages/ConfigMessages.java 39 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java 50 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
@@ -1928,6 +1928,75 @@
    // FIXME -- This needs support for encryption.
    // Calculate an archive for the current server configuration file and see if
    // it matches what we expect.  If not, then the file has been manually
    // edited with the server online which is a bad thing.  In that case, we'll
    // copy the current config off to the side before writing the new config
    // so that the manual changes don't get lost but also don't get applied.
    // Also, send an admin alert notifying administrators about the problem.
    try
    {
      byte[] currentDigest = calculateConfigDigest();
      if (! Arrays.equals(configurationDigest, currentDigest))
      {
        File existingCfg   = new File(configFile);
        File newConfigFile = new File(existingCfg.getParent(),
                                      "config.manualedit-" +
                                           TimeThread.getGMTTime() + ".ldif");
        int counter = 2;
        while (newConfigFile.exists())
        {
          newConfigFile = new File(newConfigFile.getAbsolutePath() + "." +
                                   counter++);
        }
        FileInputStream  inputStream  = new FileInputStream(existingCfg);
        FileOutputStream outputStream = new FileOutputStream(newConfigFile);
        byte[] buffer = new byte[8192];
        while (true)
        {
          int bytesRead = inputStream.read(buffer);
          if (bytesRead < 0)
          {
            break;
          }
          outputStream.write(buffer, 0, bytesRead);
        }
        inputStream.close();
        outputStream.close();
        int    msgID   = MSGID_CONFIG_MANUAL_CHANGES_DETECTED;
        String message = getMessage(msgID, configFile,
                                    newConfigFile.getAbsolutePath());
        logError(ErrorLogCategory.CONFIGURATION,
                 ErrorLogSeverity.SEVERE_WARNING, message, msgID);
        DirectoryServer.sendAlertNotification(this,
             ALERT_TYPE_MANUAL_CONFIG_EDIT_HANDLED, msgID, message);
      }
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        debugCaught(DebugLogLevel.ERROR, e);
      }
      int    msgID   = MSGID_CONFIG_MANUAL_CHANGES_LOST;
      String message = getMessage(msgID, configFile,
                                  stackTraceToSingleLineString(e));
      logError(ErrorLogCategory.CONFIGURATION,
               ErrorLogSeverity.SEVERE_ERROR, message, msgID);
      DirectoryServer.sendAlertNotification(this,
           ALERT_TYPE_MANUAL_CONFIG_EDIT_HANDLED, msgID, message);
    }
    // Write the new configuration to a temporary file.
    String tempConfig = configFile + ".tmp";
    try
@@ -3391,6 +3460,10 @@
    alerts.put(ALERT_TYPE_CANNOT_WRITE_CONFIGURATION,
               ALERT_DESCRIPTION_CANNOT_WRITE_CONFIGURATION);
    alerts.put(ALERT_TYPE_MANUAL_CONFIG_EDIT_HANDLED,
               ALERT_DESCRIPTION_MANUAL_CONFIG_EDIT_HANDLED);
    alerts.put(ALERT_TYPE_MANUAL_CONFIG_EDIT_LOST,
               ALERT_DESCRIPTION_MANUAL_CONFIG_EDIT_LOST);
    return alerts;
  }
opendj-sdk/opends/src/server/org/opends/server/messages/ConfigMessages.java
@@ -6595,6 +6595,32 @@
  /**
   * The message ID for the message that will be used if the server detects that
   * the configuration has been manually edited while the server is online, but
   * that the manual edits have been copied off into another file before the
   * configuration was updated by another change.  This takes two arguments,
   * which are the path to the live configuration file and the path to the file
   * containing the manual edits.
   */
  public static final int MSGID_CONFIG_MANUAL_CHANGES_DETECTED =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_WARNING | 655;
  /**
   * The message ID for the message that will be used if the server detects that
   * the configuration may have been manually edited while the server is online,
   * but a problem occurred that prevented the manual changes from being copied
   * before the configuration was overwritten.  This takes two arguments, which
   * are the path to the live configuration file and a string representation of
   * the exception that was caught.
   */
  public static final int MSGID_CONFIG_MANUAL_CHANGES_LOST =
       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 656;
  /**
   * Associates a set of generic messages with the message IDs defined in this
   * class.
   */
@@ -6917,6 +6943,19 @@
    registerMessage(MSGID_CONFIG_FILE_CANNOT_WRITE_CONFIG_ARCHIVE,
                    "An error occurred while trying to write the current " +
                    "configuration to the configuration archive:  %s");
    registerMessage(MSGID_CONFIG_MANUAL_CHANGES_DETECTED,
                    "The Directory Server has detected that one or more " +
                    "external changes have been made to the configuration " +
                    "file %s while the server was online, but another change " +
                    "has caused the server configuration to be overwritten.  " +
                    "The manual changes have not been applied, but they have " +
                    "been preserved in file %s");
    registerMessage(MSGID_CONFIG_MANUAL_CHANGES_LOST,
                    "The Directory Server encountered an error while " +
                    "attempting to determine whether the configuration file " +
                    "%s has been externally edited with the server online, " +
                    "and/or trying to preserve such changes:  %s.  Any " +
                    "manual changes made to that file may have been lost");
    registerMessage(MSGID_CONFIG_FILE_WRITE_CANNOT_EXPORT_NEW_CONFIG,
                    "An error occurred while attempting to export the new " +
                    "Directory Server configuration to file %s:  %s");
opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -1326,6 +1326,56 @@
  /**
   * The description for the alert type that will be used for the alert
   * notification generated if the server detects that the configuration has
   * been manually edited with the server online and those edits would have been
   * lost by an online config change.
   */
  public static final String ALERT_DESCRIPTION_MANUAL_CONFIG_EDIT_HANDLED =
      "This alert type will be used to notify administrators if the " +
      "Directory Server detects that its configuration has been manually " +
      "edited with the server online and those changes were overwritten by " +
      "another change made through the server.  The manually-edited " +
      "configuration will be copied off to another location.";
  /**
   * The alert type string that will be used for the alert notification
   * generated if a problem occurs while attempting to write the Directory
   * Server configuration to disk.
   */
  public static final String ALERT_TYPE_MANUAL_CONFIG_EDIT_HANDLED =
       "org.opends.server.ManualConfigEditHandled";
  /**
   * The description for the alert type that will be used for the alert
   * notification generated if the server detects that the configuration has
   * been manually edited with the server online, but a problem occurred while
   * trying to preserve the manual changes that may have caused them to be lost.
   */
  public static final String ALERT_DESCRIPTION_MANUAL_CONFIG_EDIT_LOST =
      "This alert type will be used to notify administrators if the " +
      "Directory Server detects that its configuration has been manually " +
      "edited with the server online and those changes were overwritten by " +
      "another change made through the server.  The manually-edited " +
      "configuration could not be preserved due to an unexpected error.";
  /**
   * The alert type string that will be used for the alert notification
   * generated if a problem occurs while attempting to write the Directory
   * Server configuration to disk.
   */
  public static final String ALERT_TYPE_MANUAL_CONFIG_EDIT_LOST =
       "org.opends.server.ManualConfigEditLost";
  /**
   * The description for the alert type that will be used for the alert
   * notification generated if an error occurs while attempting to write the
   * tasks backing file.
   */