| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.ignite.ssl; |
| |
| import java.security.KeyManagementException; |
| import java.security.NoSuchAlgorithmException; |
| import java.util.concurrent.atomic.AtomicReference; |
| import javax.cache.configuration.Factory; |
| import javax.net.ssl.KeyManager; |
| import javax.net.ssl.SSLContext; |
| import javax.net.ssl.SSLException; |
| import javax.net.ssl.SSLParameters; |
| import javax.net.ssl.TrustManager; |
| import org.apache.ignite.IgniteException; |
| import org.apache.ignite.internal.util.typedef.internal.A; |
| |
| /** |
| * Represents abstract implementation of SSL Context Factory that caches the result of the first successful |
| * attempt to create an {@link SSLContext} and always returns it as a result of further invocations of the |
| * {@link AbstractSslContextFactory#create()}} method. |
| */ |
| public abstract class AbstractSslContextFactory implements Factory<SSLContext> { |
| /** */ |
| private static final long serialVersionUID = 0L; |
| |
| /** Default SSL protocol. */ |
| public static final String DFLT_SSL_PROTOCOL = "TLS"; |
| |
| /** SSL protocol. */ |
| protected String proto = DFLT_SSL_PROTOCOL; |
| |
| /** Enabled cipher suites. */ |
| protected String[] cipherSuites; |
| |
| /** Enabled protocols. */ |
| protected String[] protocols; |
| |
| /** Cached instance of an {@link SSLContext}. */ |
| protected final AtomicReference<SSLContext> sslCtx = new AtomicReference<>(); |
| |
| /** |
| * Gets protocol for secure transport. |
| * |
| * @return SSL protocol name. |
| */ |
| public String getProtocol() { |
| return proto; |
| } |
| |
| /** |
| * Sets protocol for secure transport. If not specified, {@link #DFLT_SSL_PROTOCOL} will be used. |
| * |
| * @param proto SSL protocol name. |
| */ |
| public void setProtocol(String proto) { |
| A.notNull(proto, "proto"); |
| |
| this.proto = proto; |
| } |
| |
| /** |
| * Sets enabled cipher suites. |
| * |
| * @param cipherSuites enabled cipher suites. |
| */ |
| public void setCipherSuites(String... cipherSuites) { |
| this.cipherSuites = cipherSuites; |
| } |
| |
| /** |
| * Gets enabled cipher suites. |
| * |
| * @return enabled cipher suites |
| */ |
| public String[] getCipherSuites() { |
| return cipherSuites; |
| } |
| |
| /** |
| * Gets enabled protocols. |
| * |
| * @return Enabled protocols. |
| */ |
| public String[] getProtocols() { |
| return protocols; |
| } |
| |
| /** |
| * Sets enabled protocols. |
| * |
| * @param protocols Enabled protocols. |
| */ |
| public void setProtocols(String... protocols) { |
| this.protocols = protocols; |
| } |
| |
| /** |
| * Creates SSL context based on factory settings. |
| * |
| * @return Initialized SSL context. |
| * @throws SSLException If SSL context could not be created. |
| */ |
| private SSLContext createSslContext() throws SSLException { |
| checkParameters(); |
| |
| KeyManager[] keyMgrs = createKeyManagers(); |
| |
| TrustManager[] trustMgrs = createTrustManagers(); |
| |
| try { |
| SSLContext ctx = SSLContext.getInstance(proto); |
| |
| if (cipherSuites != null || protocols != null) { |
| SSLParameters sslParameters = new SSLParameters(); |
| |
| if (cipherSuites != null) |
| sslParameters.setCipherSuites(cipherSuites); |
| |
| if (protocols != null) |
| sslParameters.setProtocols(protocols); |
| |
| ctx = new SSLContextWrapper(ctx, sslParameters); |
| } |
| |
| ctx.init(keyMgrs, trustMgrs, null); |
| |
| return ctx; |
| } |
| catch (NoSuchAlgorithmException e) { |
| throw new SSLException("Unsupported SSL protocol: " + proto, e); |
| } |
| catch (KeyManagementException e) { |
| throw new SSLException("Failed to initialized SSL context.", e); |
| } |
| } |
| |
| /** |
| * @param param Value. |
| * @param name Name. |
| * @throws SSLException If {@code null}. |
| */ |
| protected void checkNullParameter(Object param, String name) throws SSLException { |
| if (param == null) |
| throw new SSLException("Failed to initialize SSL context (parameter cannot be null): " + name); |
| } |
| |
| /** |
| * Checks that all required parameters are set. |
| * |
| * @throws SSLException If any of required parameters is missing. |
| */ |
| protected abstract void checkParameters() throws SSLException; |
| |
| /** |
| * @return Created Key Managers. |
| * @throws SSLException If Key Managers could not be created. |
| */ |
| protected abstract KeyManager[] createKeyManagers() throws SSLException; |
| |
| /** |
| * @return Created Trust Managers. |
| * @throws SSLException If Trust Managers could not be created. |
| */ |
| protected abstract TrustManager[] createTrustManagers() throws SSLException; |
| |
| /** {@inheritDoc} */ |
| @Override public SSLContext create() { |
| SSLContext ctx = sslCtx.get(); |
| |
| if (ctx == null) { |
| try { |
| ctx = createSslContext(); |
| |
| if (!sslCtx.compareAndSet(null, ctx)) |
| ctx = sslCtx.get(); |
| } |
| catch (SSLException e) { |
| throw new IgniteException(e); |
| } |
| } |
| |
| return ctx; |
| } |
| } |