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 legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2008 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.server.core; 028 029import org.forgerock.i18n.LocalizableMessage; 030import org.forgerock.i18n.slf4j.LocalizedLogger; 031import org.forgerock.util.Utils; 032 033import java.util.ArrayList; 034import java.util.List; 035import java.util.concurrent.ConcurrentHashMap; 036 037import org.opends.server.admin.ClassPropertyDefinition; 038import org.opends.server.admin.server.ConfigurationAddListener; 039import org.opends.server.admin.server.ConfigurationChangeListener; 040import org.opends.server.admin.server.ConfigurationDeleteListener; 041import org.opends.server.admin.std.meta.KeyManagerProviderCfgDefn; 042import org.opends.server.admin.std.server.KeyManagerProviderCfg; 043import org.opends.server.admin.std.server.RootCfg; 044import org.opends.server.admin.server.ServerManagementContext; 045import org.opends.server.api.KeyManagerProvider; 046import org.forgerock.opendj.config.server.ConfigException; 047import org.forgerock.opendj.config.server.ConfigChangeResult; 048import org.opends.server.types.DN; 049import org.opends.server.types.InitializationException; 050import org.forgerock.opendj.ldap.ResultCode; 051 052import static org.opends.messages.ConfigMessages.*; 053import static org.opends.server.util.StaticUtils.*; 054 055/** 056 * This class defines a utility that will be used to manage the set of key 057 * manager providers defined in the Directory Server. It will initialize the 058 * key manager providers when the server starts, and then will manage any 059 * additions, removals, or modifications to any key manager providers while 060 * the server is running. 061 */ 062public class KeyManagerProviderConfigManager 063 implements ConfigurationChangeListener<KeyManagerProviderCfg>, 064 ConfigurationAddListener<KeyManagerProviderCfg>, 065 ConfigurationDeleteListener<KeyManagerProviderCfg> 066 067{ 068 069 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 070 071 /** 072 * A mapping between the DNs of the config entries and the associated key 073 * manager providers. 074 */ 075 private final ConcurrentHashMap<DN,KeyManagerProvider> providers; 076 077 private final ServerContext serverContext; 078 079 /** 080 * Creates a new instance of this key manager provider config manager. 081 * 082 * @param serverContext 083 * The server context. 084 */ 085 public KeyManagerProviderConfigManager(ServerContext serverContext) 086 { 087 this.serverContext = serverContext; 088 providers = new ConcurrentHashMap<>(); 089 } 090 091 /** 092 * Initializes all key manager providers currently defined in the Directory 093 * Server configuration. This should only be called at Directory Server 094 * startup. 095 * 096 * @throws ConfigException If a configuration problem causes the key 097 * manager provider initialization process to fail. 098 * 099 * @throws InitializationException If a problem occurs while initializing 100 * the key manager providers that is not 101 * related to the server configuration. 102 */ 103 public void initializeKeyManagerProviders() 104 throws ConfigException, InitializationException 105 { 106 // Get the root configuration object. 107 ServerManagementContext managementContext = 108 ServerManagementContext.getInstance(); 109 RootCfg rootConfiguration = 110 managementContext.getRootConfiguration(); 111 112 113 // Register as an add and delete listener with the root configuration so we 114 // can be notified if any key manager provider entries are added or removed. 115 rootConfiguration.addKeyManagerProviderAddListener(this); 116 rootConfiguration.addKeyManagerProviderDeleteListener(this); 117 118 119 //Initialize the existing key manager providers. 120 for (String name : rootConfiguration.listKeyManagerProviders()) 121 { 122 KeyManagerProviderCfg providerConfig = 123 rootConfiguration.getKeyManagerProvider(name); 124 providerConfig.addChangeListener(this); 125 126 if (providerConfig.isEnabled()) 127 { 128 String className = providerConfig.getJavaClass(); 129 try 130 { 131 KeyManagerProvider provider = 132 loadProvider(className, providerConfig, true); 133 providers.put(providerConfig.dn(), provider); 134 DirectoryServer.registerKeyManagerProvider(providerConfig.dn(), 135 provider); 136 } 137 catch (InitializationException ie) 138 { 139 logger.error(ie.getMessageObject()); 140 continue; 141 } 142 } 143 } 144 } 145 146 147 148 /** {@inheritDoc} */ 149 public boolean isConfigurationAddAcceptable( 150 KeyManagerProviderCfg configuration, 151 List<LocalizableMessage> unacceptableReasons) 152 { 153 if (configuration.isEnabled()) 154 { 155 // Get the name of the class and make sure we can instantiate it as a 156 // key manager provider. 157 String className = configuration.getJavaClass(); 158 try 159 { 160 loadProvider(className, configuration, false); 161 } 162 catch (InitializationException ie) 163 { 164 unacceptableReasons.add(ie.getMessageObject()); 165 return false; 166 } 167 } 168 169 // If we've gotten here, then it's fine. 170 return true; 171 } 172 173 174 175 /** {@inheritDoc} */ 176 public ConfigChangeResult applyConfigurationAdd( 177 KeyManagerProviderCfg configuration) 178 { 179 final ConfigChangeResult ccr = new ConfigChangeResult(); 180 181 configuration.addChangeListener(this); 182 183 if (! configuration.isEnabled()) 184 { 185 return ccr; 186 } 187 188 KeyManagerProvider provider = null; 189 190 // Get the name of the class and make sure we can instantiate it as a key 191 // manager provider. 192 String className = configuration.getJavaClass(); 193 try 194 { 195 provider = loadProvider(className, configuration, true); 196 } 197 catch (InitializationException ie) 198 { 199 ccr.setResultCodeIfSuccess(DirectoryServer.getServerErrorResultCode()); 200 ccr.addMessage(ie.getMessageObject()); 201 } 202 203 if (ccr.getResultCode() == ResultCode.SUCCESS) 204 { 205 providers.put(configuration.dn(), provider); 206 DirectoryServer.registerKeyManagerProvider(configuration.dn(), provider); 207 } 208 209 return ccr; 210 } 211 212 213 214 /** {@inheritDoc} */ 215 public boolean isConfigurationDeleteAcceptable( 216 KeyManagerProviderCfg configuration, 217 List<LocalizableMessage> unacceptableReasons) 218 { 219 // FIXME -- We should try to perform some check to determine whether the 220 // provider is in use. 221 return true; 222 } 223 224 225 226 /** {@inheritDoc} */ 227 public ConfigChangeResult applyConfigurationDelete( 228 KeyManagerProviderCfg configuration) 229 { 230 final ConfigChangeResult ccr = new ConfigChangeResult(); 231 232 DirectoryServer.deregisterKeyManagerProvider(configuration.dn()); 233 234 KeyManagerProvider provider = providers.remove(configuration.dn()); 235 if (provider != null) 236 { 237 provider.finalizeKeyManagerProvider(); 238 } 239 240 return ccr; 241 } 242 243 244 245 /** {@inheritDoc} */ 246 public boolean isConfigurationChangeAcceptable( 247 KeyManagerProviderCfg configuration, 248 List<LocalizableMessage> unacceptableReasons) 249 { 250 if (configuration.isEnabled()) 251 { 252 // Get the name of the class and make sure we can instantiate it as a key 253 // manager provider. 254 String className = configuration.getJavaClass(); 255 try 256 { 257 loadProvider(className, configuration, false); 258 } 259 catch (InitializationException ie) 260 { 261 unacceptableReasons.add(ie.getMessageObject()); 262 return false; 263 } 264 } 265 266 // If we've gotten here, then it's fine. 267 return true; 268 } 269 270 271 272 /** {@inheritDoc} */ 273 public ConfigChangeResult applyConfigurationChange( 274 KeyManagerProviderCfg configuration) 275 { 276 final ConfigChangeResult ccr = new ConfigChangeResult(); 277 278 279 // Get the existing provider if it's already enabled. 280 KeyManagerProvider existingProvider = providers.get(configuration.dn()); 281 282 283 // If the new configuration has the provider disabled, then disable it if it 284 // is enabled, or do nothing if it's already disabled. 285 if (! configuration.isEnabled()) 286 { 287 if (existingProvider != null) 288 { 289 DirectoryServer.deregisterKeyManagerProvider(configuration.dn()); 290 291 KeyManagerProvider provider = providers.remove(configuration.dn()); 292 if (provider != null) 293 { 294 provider.finalizeKeyManagerProvider(); 295 } 296 } 297 298 return ccr; 299 } 300 301 302 // Get the class for the key manager provider. If the provider is already 303 // enabled, then we shouldn't do anything with it although if the class has 304 // changed then we'll at least need to indicate that administrative action 305 // is required. If the provider is disabled, then instantiate the class and 306 // initialize and register it as a key manager provider. 307 String className = configuration.getJavaClass(); 308 if (existingProvider != null) 309 { 310 if (! className.equals(existingProvider.getClass().getName())) 311 { 312 ccr.setAdminActionRequired(true); 313 } 314 315 return ccr; 316 } 317 318 KeyManagerProvider provider = null; 319 try 320 { 321 provider = loadProvider(className, configuration, true); 322 } 323 catch (InitializationException ie) 324 { 325 ccr.setResultCodeIfSuccess(DirectoryServer.getServerErrorResultCode()); 326 ccr.addMessage(ie.getMessageObject()); 327 } 328 329 if (ccr.getResultCode() == ResultCode.SUCCESS) 330 { 331 providers.put(configuration.dn(), provider); 332 DirectoryServer.registerKeyManagerProvider(configuration.dn(), provider); 333 } 334 335 return ccr; 336 } 337 338 339 340 /** 341 * Loads the specified class, instantiates it as a key manager provider, and 342 * optionally initializes that instance. 343 * 344 * @param className The fully-qualified name of the key manager 345 * provider class to load, instantiate, and initialize. 346 * @param configuration The configuration to use to initialize the key 347 * manager provider. It must not be {@code null}. 348 * @param initialize Indicates whether the key manager provider instance 349 * should be initialized. 350 * 351 * @return The possibly initialized key manager provider. 352 * 353 * @throws InitializationException If the provided configuration is not 354 * acceptable, or if a problem occurred 355 * while attempting to initialize the key 356 * manager provider using that 357 * configuration. 358 */ 359 private KeyManagerProvider loadProvider(String className, 360 KeyManagerProviderCfg configuration, 361 boolean initialize) 362 throws InitializationException 363 { 364 try 365 { 366 KeyManagerProviderCfgDefn definition = 367 KeyManagerProviderCfgDefn.getInstance(); 368 ClassPropertyDefinition propertyDefinition = 369 definition.getJavaClassPropertyDefinition(); 370 Class<? extends KeyManagerProvider> providerClass = 371 propertyDefinition.loadClass(className, KeyManagerProvider.class); 372 KeyManagerProvider provider = providerClass.newInstance(); 373 374 375 if (initialize) 376 { 377 provider.initializeKeyManagerProvider(configuration); 378 } 379 else 380 { 381 List<LocalizableMessage> unacceptableReasons = new ArrayList<>(); 382 if (!provider.isConfigurationAcceptable(configuration, unacceptableReasons)) 383 { 384 String reasons = Utils.joinAsString(". ", unacceptableReasons); 385 throw new InitializationException( 386 ERR_CONFIG_KEYMANAGER_CONFIG_NOT_ACCEPTABLE.get(configuration.dn(), reasons)); 387 } 388 } 389 390 return provider; 391 } 392 catch (InitializationException ie) 393 { 394 throw ie; 395 } 396 catch (Exception e) 397 { 398 LocalizableMessage message = ERR_CONFIG_KEYMANAGER_INITIALIZATION_FAILED. 399 get(className, configuration.dn(), stackTraceToSingleLineString(e)); 400 throw new InitializationException(message, e); 401 } 402 } 403} 404