001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.support.jsse; 018 019import java.io.IOException; 020import java.security.GeneralSecurityException; 021import java.security.SecureRandom; 022import java.security.Security; 023import java.util.List; 024 025import javax.net.ssl.KeyManager; 026import javax.net.ssl.SSLContext; 027import javax.net.ssl.SSLEngine; 028import javax.net.ssl.SSLServerSocketFactory; 029import javax.net.ssl.SSLSocketFactory; 030import javax.net.ssl.TrustManager; 031import javax.net.ssl.X509KeyManager; 032 033import org.apache.camel.CamelContext; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037/** 038 * Represents {@link SSLContext} configuration options used in instantiating an 039 * {@code SSLContext} instance. 040 */ 041public class SSLContextParameters extends BaseSSLContextParameters { 042 043 // TODO : switch to TLSv1.3 when we fully upgrade to JDK11 044 protected static final String DEFAULT_SECURE_SOCKET_PROTOCOL = "TLSv1.2"; 045 046 private static final Logger LOG = LoggerFactory.getLogger(SSLContextParameters.class); 047 048 /** 049 * The optional key manager configuration for creating the 050 * {@link KeyManager}s used in constructing an {@link SSLContext}. 051 */ 052 private KeyManagersParameters keyManagers; 053 054 /** 055 * The optional trust manager configuration for creating the 056 * {@link TrustManager}s used in constructing an {@link SSLContext}. 057 */ 058 private TrustManagersParameters trustManagers; 059 060 /** 061 * The optional secure random configuration options to use for constructing 062 * the {@link SecureRandom} used in the creation of an {@link SSLContext]. 063 */ 064 private SecureRandomParameters secureRandom; 065 066 /** 067 * The optional configuration options to be applied purely to the client side settings 068 * of the {@link SSLContext}. Settings specified here override any duplicate settings 069 * provided at the overall level by this class. These parameters apply to 070 * {@link SSLSocketFactory}s and {@link SSLEngine}s produced by the {@code SSLContext} 071 * produced from this class as well as to the {@code SSLContext} itself. 072 */ 073 private SSLContextClientParameters clientParameters; 074 075 /** 076 * The optional configuration options to be applied purely to the server side settings 077 * of the {@link SSLContext}. Settings specified here override any duplicate settings 078 * provided at the overall level by this class. These parameters apply to 079 * {@link SSLServerSocketFactory}s and {@link SSLEngine}s produced by the {@code SSLContext} 080 * produced from this class as well as to the {@code SSLContext} itself. 081 */ 082 private SSLContextServerParameters serverParameters; 083 084 /** 085 * The optional provider identifier for the JSSE implementation to use when 086 * constructing an {@link SSLContext}. 087 */ 088 private String provider; 089 090 /** 091 * The optional protocol for the secure sockets created by the {@link SSLContext} 092 * represented by this instance's configuration. See Appendix A in the <a 093 * href="http://download.oracle.com/javase/6/docs/technotes/guides//security/jsse/JSSERefGuide.html#AppA" 094 * >Java Secure Socket Extension Reference Guide</a> for information about 095 * standard protocol names. 096 */ 097 private String secureSocketProtocol; 098 099 /** 100 * An optional certificate alias to use. This is useful when the keystore has multiple 101 * certificates. 102 */ 103 private String certAlias; 104 105 public KeyManagersParameters getKeyManagers() { 106 return keyManagers; 107 } 108 109 /** 110 * Sets the optional key manager configuration for creating the 111 * {@link KeyManager}s used in constructing an {@link SSLContext}. 112 * 113 * @param keyManagers the options or {@code null} to provide no 114 * {@code KeyManager}s 115 */ 116 public void setKeyManagers(KeyManagersParameters keyManagers) { 117 this.keyManagers = keyManagers; 118 } 119 120 public TrustManagersParameters getTrustManagers() { 121 return trustManagers; 122 } 123 124 /** 125 * Sets the optional trust manager configuration for creating the 126 * {@link TrustManager}s used in constructing an {@link SSLContext}. 127 * 128 * @param trustManagers the options or {@code null} to provide no 129 * {@code TrustManager}s 130 */ 131 public void setTrustManagers(TrustManagersParameters trustManagers) { 132 this.trustManagers = trustManagers; 133 } 134 135 public SecureRandomParameters getSecureRandom() { 136 return secureRandom; 137 } 138 139 /** 140 * Sets the optional secure random configuration options to use for 141 * constructing the {@link SecureRandom} used in the creation of an {@link SSLContext}. 142 * 143 * @param secureRandom the options or {@code null} to use the default 144 */ 145 public void setSecureRandom(SecureRandomParameters secureRandom) { 146 this.secureRandom = secureRandom; 147 } 148 149 public SSLContextClientParameters getClientParameters() { 150 return clientParameters; 151 } 152 153 /** 154 * The optional configuration options to be applied purely to the client side settings 155 * of the {@link SSLContext}. Settings specified here override any duplicate settings 156 * provided at the overall level by this class. These parameters apply to 157 * {@link SSLSocketFactory}s and {@link SSLEngine}s produced by the {@code SSLContext} 158 * produced from this class as well as to the {@code SSLContext} itself. 159 * 160 * @param clientParameters the optional additional client-side parameters 161 */ 162 public void setClientParameters(SSLContextClientParameters clientParameters) { 163 this.clientParameters = clientParameters; 164 } 165 166 public SSLContextServerParameters getServerParameters() { 167 return serverParameters; 168 } 169 170 /** 171 * The optional configuration options to be applied purely to the server side settings 172 * of the {@link SSLContext}. Settings specified here override any duplicate settings 173 * provided at the overall level by this class. These parameters apply to 174 * {@link SSLServerSocketFactory}s and {@link SSLEngine}s produced by the {@code SSLContext} 175 * produced from this class as well as to the {@code SSLContext} itself. 176 * 177 * @param serverParameters the optional additional client-side parameters 178 */ 179 public void setServerParameters(SSLContextServerParameters serverParameters) { 180 this.serverParameters = serverParameters; 181 } 182 183 public String getProvider() { 184 return provider; 185 } 186 187 /** 188 * Sets the optional provider identifier to use when constructing an 189 * {@link SSLContext}. 190 * 191 * @param provider the identifier (from the list of available providers 192 * returned by {@link Security#getProviders()}) or {@code null} 193 * to use the highest priority provider implementing the secure 194 * socket protocol 195 * 196 * @see Security#getProviders(java.util.Map) 197 * @see #setSecureSocketProtocol(String) 198 */ 199 public void setProvider(String provider) { 200 this.provider = provider; 201 } 202 203 public String getSecureSocketProtocol() { 204 if (this.secureSocketProtocol == null) { 205 return DEFAULT_SECURE_SOCKET_PROTOCOL; 206 } 207 return this.secureSocketProtocol; 208 } 209 210 /** 211 * Sets the optional protocol for the secure sockets created by the 212 * {@link SSLContext} represented by this instance's configuration. Defaults 213 * to TLS. See Appendix A in the <a href= 214 * "http://download.oracle.com/javase/6/docs/technotes/guides//security/jsse/JSSERefGuide.html#AppA" 215 * >Java Secure Socket Extension Reference Guide</a> for information about 216 * standard protocol names. 217 * 218 * @param secureSocketProtocol the name of the protocol or {@code null} to 219 * use the default (TLS) 220 */ 221 public void setSecureSocketProtocol(String secureSocketProtocol) { 222 this.secureSocketProtocol = secureSocketProtocol; 223 } 224 225 public String getCertAlias() { 226 return certAlias; 227 } 228 229 /** 230 * An optional certificate alias to use. This is useful when the keystore has multiple 231 * certificates. 232 * @param certAlias an optional certificate alias to use 233 */ 234 public void setCertAlias(String certAlias) { 235 this.certAlias = certAlias; 236 } 237 238 //////////////////////////////////////////// 239 240 /** 241 * Creates an {@link SSLContext} based on the related configuration options 242 * of this instance. Namely, {@link #keyManagers}, {@link #trustManagers}, and 243 * {@link #secureRandom}, but also respecting the chosen provider and secure 244 * socket protocol as well. 245 * 246 * @param camelContext The camel context 247 * 248 * @return a newly configured instance 249 * 250 * @throws GeneralSecurityException if there is a problem in this instances 251 * configuration or that of its nested configuration options 252 * @throws IOException if there is an error reading a key/trust store 253 */ 254 public SSLContext createSSLContext(CamelContext camelContext) throws GeneralSecurityException, IOException { 255 if (camelContext != null) { 256 // setup CamelContext before creating SSLContext 257 setCamelContext(camelContext); 258 if (keyManagers != null) { 259 keyManagers.setCamelContext(camelContext); 260 } 261 if (trustManagers != null) { 262 trustManagers.setCamelContext(camelContext); 263 } 264 if (secureRandom != null) { 265 secureRandom.setCamelContext(camelContext); 266 } 267 if (clientParameters != null) { 268 clientParameters.setCamelContext(camelContext); 269 } 270 if (serverParameters != null) { 271 serverParameters.setCamelContext(camelContext); 272 } 273 } 274 275 LOG.trace("Creating SSLContext from SSLContextParameters [{}].", this); 276 277 LOG.info("Available providers: {}.", Security.getProviders()); 278 279 KeyManager[] keyManagers = this.keyManagers == null ? null : this.keyManagers.createKeyManagers(); 280 TrustManager[] trustManagers = this.trustManagers == null ? null : this.trustManagers.createTrustManagers(); 281 SecureRandom secureRandom = this.secureRandom == null ? null : this.secureRandom.createSecureRandom(); 282 283 SSLContext context; 284 if (this.getProvider() == null) { 285 context = SSLContext.getInstance(this.parsePropertyValue(this.getSecureSocketProtocol())); 286 } else { 287 context = SSLContext.getInstance(this.parsePropertyValue(this.getSecureSocketProtocol()), 288 this.parsePropertyValue(this.getProvider())); 289 } 290 291 if (this.getCertAlias() != null && keyManagers != null) { 292 for (int idx = 0; idx < keyManagers.length; idx++) { 293 if (keyManagers[idx] instanceof X509KeyManager) { 294 try { 295 keyManagers[idx] = new AliasedX509ExtendedKeyManager(this.getCertAlias(), 296 (X509KeyManager)keyManagers[idx]); 297 } catch (Exception e) { 298 throw new GeneralSecurityException(e); 299 } 300 } 301 } 302 } 303 304 LOG.debug("SSLContext [{}], initialized from [{}], is using provider [{}], protocol [{}], key managers {}, trust managers {}, and secure random [{}].", 305 new Object[] {context, this, context.getProvider(), context.getProtocol(), keyManagers, trustManagers, secureRandom}); 306 307 context.init(keyManagers, trustManagers, secureRandom); 308 309 this.configureSSLContext(context); 310 311 // Decorate the context. 312 context = new SSLContextDecorator( 313 new SSLContextSpiDecorator( 314 context, 315 this.getSSLEngineConfigurers(context), 316 this.getSSLSocketFactoryConfigurers(context), 317 this.getSSLServerSocketFactoryConfigurers(context))); 318 319 return context; 320 } 321 322 @Override 323 protected void configureSSLContext(SSLContext context) throws GeneralSecurityException { 324 LOG.trace("Configuring client and server side SSLContext parameters on SSLContext [{}]...", context); 325 super.configureSSLContext(context); 326 327 if (this.getClientParameters() != null) { 328 LOG.trace("Overriding client-side SSLContext parameters on SSLContext [{}] with configured client parameters.", 329 context); 330 this.getClientParameters().configureSSLContext(context); 331 } 332 333 if (this.getServerParameters() != null) { 334 LOG.trace("Overriding server-side SSLContext parameters on SSLContext [{}] with configured server parameters.", 335 context); 336 this.getServerParameters().configureSSLContext(context); 337 } 338 339 LOG.trace("Configured client and server side SSLContext parameters on SSLContext [{}].", context); 340 } 341 342 @Override 343 protected List<Configurer<SSLEngine>> getSSLEngineConfigurers(SSLContext context) { 344 LOG.trace("Collecting client and server side SSLEngine configurers on SSLContext [{}]...", context); 345 List<Configurer<SSLEngine>> configurers = super.getSSLEngineConfigurers(context); 346 347 if (this.getClientParameters() != null) { 348 LOG.trace("Augmenting SSLEngine configurers with configurers from client parameters on SSLContext [{}].", 349 context); 350 configurers.addAll(this.getClientParameters().getSSLEngineConfigurers(context)); 351 } 352 353 if (this.getServerParameters() != null) { 354 LOG.trace("Augmenting SSLEngine configurers with configurers from server parameters on SSLContext [{}].", 355 context); 356 configurers.addAll(this.getServerParameters().getSSLEngineConfigurers(context)); 357 } 358 359 LOG.trace("Collected client and server side SSLEngine configurers on SSLContext [{}].", context); 360 361 return configurers; 362 } 363 364 @Override 365 protected List<Configurer<SSLSocketFactory>> getSSLSocketFactoryConfigurers(SSLContext context) { 366 LOG.trace("Collecting SSLSocketFactory configurers on SSLContext [{}]...", context); 367 List<Configurer<SSLSocketFactory>> configurers = super.getSSLSocketFactoryConfigurers(context); 368 369 if (this.getClientParameters() != null) { 370 LOG.trace("Augmenting SSLSocketFactory configurers with configurers from client parameters on SSLContext [{}].", 371 context); 372 configurers.addAll(this.getClientParameters().getSSLSocketFactoryConfigurers(context)); 373 } 374 375 LOG.trace("Collected SSLSocketFactory configurers on SSLContext [{}].", context); 376 377 return configurers; 378 } 379 380 @Override 381 protected List<Configurer<SSLServerSocketFactory>> getSSLServerSocketFactoryConfigurers(SSLContext context) { 382 LOG.trace("Collecting SSLServerSocketFactory configurers for SSLContext [{}]...", context); 383 List<Configurer<SSLServerSocketFactory>> configurers = super.getSSLServerSocketFactoryConfigurers(context); 384 385 if (this.getServerParameters() != null) { 386 LOG.trace("Augmenting SSLServerSocketFactory configurers with configurers from server parameters for SSLContext [{}].", 387 context); 388 configurers.addAll(this.getServerParameters().getSSLServerSocketFactoryConfigurers(context)); 389 } 390 391 LOG.trace("Collected client and server side SSLServerSocketFactory configurers for SSLContext [{}].", context); 392 393 return configurers; 394 } 395 396 @Override 397 public String toString() { 398 StringBuilder builder = new StringBuilder(); 399 builder.append("SSLContextParameters[keyManagers="); 400 builder.append(keyManagers); 401 builder.append(", trustManagers="); 402 builder.append(trustManagers); 403 builder.append(", secureRandom="); 404 builder.append(secureRandom); 405 builder.append(", clientParameters="); 406 builder.append(clientParameters); 407 builder.append(", serverParameters="); 408 builder.append(serverParameters); 409 builder.append(", provider="); 410 builder.append(provider); 411 builder.append(", secureSocketProtocol="); 412 builder.append(secureSocketProtocol); 413 builder.append(", certAlias="); 414 builder.append(certAlias); 415 builder.append(", getCipherSuites()="); 416 builder.append(getCipherSuites()); 417 builder.append(", getCipherSuitesFilter()="); 418 builder.append(getCipherSuitesFilter()); 419 builder.append(", getSecureSocketProtocols()="); 420 builder.append(getSecureSocketProtocols()); 421 builder.append(", getSecureSocketProtocolsFilter()="); 422 builder.append(getSecureSocketProtocolsFilter()); 423 builder.append(", getSessionTimeout()="); 424 builder.append(getSessionTimeout()); 425 builder.append("]"); 426 return builder.toString(); 427 } 428 429}