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