001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * docs/licenses/cddl.txt
011 * or http://www.opensource.org/licenses/cddl1.php.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * docs/licenses/cddl.txt.  If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 *      Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 *      Portions Copyright 2011-2024 Ping Identity Corporation
026 */
027package com.unboundid.directory.sdk.ds.api;
028
029
030
031import java.io.InputStream;
032import java.io.OutputStream;
033import java.util.Collections;
034import java.util.List;
035import java.util.Map;
036import javax.crypto.CipherInputStream;
037import javax.crypto.CipherOutputStream;
038
039import com.unboundid.directory.sdk.broker.internal.BrokerExtension;
040import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
041import com.unboundid.directory.sdk.common.internal.Reconfigurable;
042import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
043import com.unboundid.directory.sdk.ds.config.CipherStreamProviderConfig;
044import com.unboundid.directory.sdk.ds.types.DirectoryServerContext;
045import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
046import com.unboundid.ldap.sdk.LDAPException;
047import com.unboundid.ldap.sdk.ResultCode;
048import com.unboundid.util.Extensible;
049import com.unboundid.util.ThreadSafety;
050import com.unboundid.util.ThreadSafetyLevel;
051import com.unboundid.util.args.ArgumentException;
052import com.unboundid.util.args.ArgumentParser;
053
054
055
056/**
057 * This class defines an API that must be implemented by extensions which
058 * provide access to cipher input streams and cipher output streams to be used
059 * by the server in order to read and write encrypted data.
060 * <BR>
061 * <H2>Configuring Cipher Stream Providers</H2>
062 * In order to configure a cipher stream provider created using this API, use a
063 * command like:
064 * <PRE>
065 *      dsconfig create-cipher-stream-provider \
066 *           --provider-name "<I>{provider-name}</I>" \
067 *           --type third-party \
068 *           --set enabled:true \
069 *           --set "extension-class:<I>{class-name}</I>" \
070 *           --set "extension-argument:<I>{name=value}</I>"
071 * </PRE>
072 * where "<I>{provider-name}</I>" is the name to use for the cipher stream
073 * provider instance, "<I>{class-name}</I>" is the fully-qualified name of the
074 * Java class that extends
075 * {@code com.unboundid.directory.sdk.ds.api.CipherStreamProvider},
076 * and "<I>{name=value}</I>" represents name-value pairs for any arguments to
077 * provide to the cipher stream provider.  If multiple arguments should be
078 * provided to the cipher stream provider, then the
079 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
080 * provided multiple times.
081 */
082@Extensible()
083@DirectoryServerExtension()
084@BrokerExtension()
085@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
086public abstract class CipherStreamProvider
087       implements UnboundIDExtension,
088                  Reconfigurable<CipherStreamProviderConfig>,
089                  ExampleUsageProvider
090{
091  /**
092   * Creates a new instance of this cipher stream provider.  All cipher stream
093   * provider implementations must include a default constructor, but any
094   * initialization should generally be done in the
095   * {@code initializeCipherStreamProvider} method.
096   */
097  public CipherStreamProvider()
098  {
099    // No implementation is required.
100  }
101
102
103
104  /**
105   * {@inheritDoc}
106   */
107  public abstract String getExtensionName();
108
109
110
111  /**
112   * {@inheritDoc}
113   */
114  public abstract String[] getExtensionDescription();
115
116
117
118  /**
119   * {@inheritDoc}
120   */
121  public void defineConfigArguments(final ArgumentParser parser)
122         throws ArgumentException
123  {
124    // No arguments will be allowed by default.
125  }
126
127
128
129  /**
130   * Initializes this cipher stream provider.
131   *
132   * @param  serverContext  A handle to the server context for the server in
133   *                        which this extension is running.
134   * @param  config         The general configuration for this cipher stream
135   *                        provider.
136   * @param  parser         The argument parser which has been initialized from
137   *                        the configuration for this cipher stream provider.
138   *
139   * @throws  LDAPException  If a problem occurs while initializing this cipher
140   *                         stream provider.
141   */
142  public void initializeCipherStreamProvider(
143                   final DirectoryServerContext serverContext,
144                   final CipherStreamProviderConfig config,
145                   final ArgumentParser parser)
146         throws LDAPException
147  {
148    // No initialization will be performed by default.
149  }
150
151
152
153  /**
154   * {@inheritDoc}
155   */
156  public boolean isConfigurationAcceptable(
157                      final CipherStreamProviderConfig config,
158                      final ArgumentParser parser,
159                      final List<String> unacceptableReasons)
160  {
161    // No extended validation will be performed by default.
162    return true;
163  }
164
165
166
167  /**
168   * {@inheritDoc}
169   */
170  public ResultCode applyConfiguration(final CipherStreamProviderConfig config,
171                                       final ArgumentParser parser,
172                                       final List<String> adminActionsRequired,
173                                       final List<String> messages)
174  {
175    // By default, no configuration changes will be applied.  If there are any
176    // arguments, then add an admin action message indicating that the extension
177    // needs to be restarted for any changes to take effect.
178    if (! parser.getNamedArguments().isEmpty())
179    {
180      adminActionsRequired.add(
181           "No configuration change has actually been applied.  The new " +
182                "configuration will not take effect until this cipher stream " +
183                "provider is disabled and re-enabled or until the server is " +
184                "restarted.");
185    }
186
187    return ResultCode.SUCCESS;
188  }
189
190
191
192  /**
193   * Performs any cleanup which may be necessary when this cipher stream
194   * provider is to be taken out of service.
195   */
196  public void finalizeCipherStreamProvider()
197  {
198    // No implementation is required.
199  }
200
201
202
203  /**
204   * Wraps the provided input stream in a cipher input stream that can be used
205   * to decrypt data read from the given stream.
206   *
207   * @param  source  The input stream to be wrapped with a cipher input stream.
208   *
209   * @return  The cipher input stream which wraps the provided input stream.
210   *
211   * @throws  LDAPException  If a problem occurs while creating the cipher input
212   *                         stream.
213   */
214  public abstract CipherInputStream createCipherInputStream(
215                                         final InputStream source)
216         throws LDAPException;
217
218
219
220  /**
221   * Wraps the provided output stream in a cipher output stream that can be used
222   * to encrypt data written to the given stream.
223   *
224   * @param  target  The output stream to be wrapped with a cipher output
225   *                 stream.
226   *
227   * @return  The cipher output stream which wraps the provided output stream.
228   *
229   * @throws  LDAPException  If a problem occurs while creating the cipher
230   *                         output stream.
231   */
232  public abstract CipherOutputStream createCipherOutputStream(
233                                          final OutputStream target)
234         throws LDAPException;
235
236
237
238  /**
239   * Retrieves a map with information about any backup compatibility properties
240   * that are specific to this cipher stream provider.
241   *
242   * @return  A map with information about any backup compatibility properties
243   *          that are specific to this cipher stream provider.  It may be
244   *          {@code null} or empty if there are no provider-specific
245   *          properties.
246   */
247  public Map<String,String> getBackupCompatibilityProperties()
248  {
249    // No properties will be added by default.
250    return null;
251  }
252
253
254
255  /**
256   * Examines the provided set of backup compatibility properties to determine
257   * whether there might be any warning or error conditions that may interfere
258   * with the ability to restore a backup of the encryption settings database.
259   * The default implementation does not do anything, but subclasses may
260   * override this method to provide any appropriate warning and error messages.
261   *
262   * @param  sourceProperties  A map of properties (obtained from the
263   *                           {@link #getBackupCompatibilityProperties} method)
264   *                           from the backup to be restore.  The contents of
265   *                           this map must not be altered.
266   * @param  targetProperties  A map of properties (obtained from the
267   *                           {@link #getBackupCompatibilityProperties} method)
268   *                           from the server in which the backup is to be
269   *                           restored.  The contents of this map must not be
270   *                           altered.
271   * @param  errorMessages     A list that may be updated with messages about
272   *                           any compatibility errors that have been
273   *                           identified.  If any compatibility errors are
274   *                           identified, the restore will be aborted.
275   * @param  warningMessages   A list that may be updated with messages about
276   *                           any compatibility warnings that have been
277   *                           identified.  If any compatibility warnings are
278   *                           identified, they will be presented to a user
279   *                           attempting a restore, but the user may choose to
280   *                           ignore them if they are certain that the issue
281   *                           will not cause any problems.
282   */
283  public void identifyBackupCompatibilityProblems(
284                   final Map<String,String> sourceProperties,
285                   final Map<String,String> targetProperties,
286                   final List<CharSequence> errorMessages,
287                   final List<CharSequence> warningMessages)
288  {
289    // No processing will be performed by default.
290  }
291
292
293
294  /**
295   * Retrieves a list of human-readable string representations for the
296   * provided cipher-stream-provider-specific backup compatibility properties.
297   * The list returned does not need to have a one-to-one mapping with the
298   * properties (e.g., it may omit information about some properties, or it may
299   * combine information from multiple properties into a single string, or it
300   * may convert one property into multiple strings).  It may also be
301   * {@code null} if this cipher stream provider does not expect to have any
302   * provider-specific properties.
303   *
304   * @param  propertyMap  A map of the property names and the associated values
305   *                      to use in obtaining the human-readable string
306   *                      representations.
307   *
308   * @return  A list of human-readable string representations for the
309   *          provider-specific backup compatibility properties, or {@code null}
310   *          if this cipher stream provider does not expect to have any
311   *          provider-specific properties.
312   */
313  public List<String> getBackupCompatibilityPropertyStrings(
314                           final Map<String,String> propertyMap)
315  {
316    // No property strings will be returned by default.
317    return null;
318  }
319
320
321
322  /**
323   * Retrieves a list of messages that should be logged (and made available in
324   * the output) when backing up an encryption settings database protected with
325   * this cipher stream provider.  For example, this may be used to warn about
326   * additional files that may also need to be backed up separately (e.g., an
327   * encryption key stored in a separate file).
328   *
329   * @return  A list of messages that should be logged when backing up an
330   *          encryption settings database protected with this cipher stream
331   *          provider.  It may be {@code null} or empty if no log messages are
332   *          needed.
333   */
334  public List<String> getBackupLogMessages()
335  {
336    // No messages will be logged by default.
337    return null;
338  }
339
340
341
342  /**
343   * {@inheritDoc}
344   */
345  public Map<List<String>,String> getExamplesArgumentSets()
346  {
347    return Collections.emptyMap();
348  }
349}