blob: d7a1bdbb474a8f790b906434205f5bf082a6bb87 [file] [log] [blame]
/*
* 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.client;
import java.util.concurrent.Callable;
import javax.net.ssl.SSLHandshakeException;
import org.apache.ignite.Ignition;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.ClientConfiguration;
import org.apache.ignite.configuration.ClientConnectorConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.ssl.SslContextFactory;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.jetbrains.annotations.NotNull;
import org.junit.Ignore;
import org.junit.Test;
/**
* Tests cases when node connects to cluster with different set of cipher suites.
*/
public class SslParametersTest extends GridCommonAbstractTest {
/** */
public static final String TEST_CACHE_NAME = "TEST";
/** */
private volatile String[] cipherSuites;
/** */
private volatile String[] protocols;
/** {@inheritDoc} */
@SuppressWarnings("rawtypes")
@Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(gridName);
cfg.setClientConnectorConfiguration(new ClientConnectorConfiguration()
.setSslEnabled(true)
.setUseIgniteSslContextFactory(true));
cfg.setSslContextFactory(createSslFactory());
CacheConfiguration ccfg = new CacheConfiguration(TEST_CACHE_NAME);
cfg.setCacheConfiguration(ccfg);
return cfg;
}
/**
* @return Client config.
*/
protected ClientConfiguration getClientConfiguration() {
return new ClientConfiguration()
.setAddresses("127.0.0.1:10800")
.setSslMode(SslMode.REQUIRED)
.setSslContextFactory(createSslFactory())
.setPartitionAwarenessEnabled(false);
}
/**
* @return SSL factory.
*/
@NotNull private SslContextFactory createSslFactory() {
SslContextFactory factory = (SslContextFactory)GridTestUtils.sslTrustedFactory("node01", "trustone");
factory.setCipherSuites(cipherSuites);
factory.setProtocols(protocols);
return factory;
}
/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
stopAllGrids();
protocols = null;
cipherSuites = null;
}
/**
* @throws Exception If failed.
*/
@Test
public void testSameCipherSuite() throws Exception {
cipherSuites = new String[] {
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"
};
startGrid();
checkSuccessfulClientStart(
new String[] {
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"
},
null
);
}
/**
* @throws Exception If failed.
*/
@Test
public void testOneCommonCipherSuite() throws Exception {
cipherSuites = new String[] {
"TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"
};
startGrid();
checkSuccessfulClientStart(
new String[] {
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"
},
null
);
}
/**
* @throws Exception If failed.
*/
@Test
public void testNoCommonCipherSuite() throws Exception {
cipherSuites = new String[] {
"TLS_RSA_WITH_AES_128_GCM_SHA256"
};
startGrid();
checkClientStartFailure(
new String[] {
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"
},
null
);
}
/**
* @throws Exception If failed.
*/
@Test
public void testNonExistentCipherSuite() throws Exception {
cipherSuites = new String[] {
"TLS_RSA_WITH_AES_128_GCM_SHA256"
};
startGrid();
checkClientStartFailure(
new String[] {
"TLC_FAKE_CIPHER",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"
},
null,
IllegalArgumentException.class,
"TLC_FAKE_CIPHER"
);
}
/**
* @throws Exception If failed.
*/
@Test
public void testNoCommonProtocols() throws Exception {
protocols = new String[] {
"TLSv1.1",
"SSLv3"
};
startGrid();
checkClientStartFailure(
null,
new String[] {
"TLSv1",
"TLSv1.2"
}
);
}
/**
* @throws Exception If failed.
*/
@Test
public void testNonExistentProtocol() throws Exception {
protocols = new String[] {
"SSLv3"
};
startGrid();
checkClientStartFailure(
null,
new String[] {
"SSLv3",
"SSLvDoesNotExist"
},
IllegalArgumentException.class,
"SSLvDoesNotExist"
);
}
/**
* @throws Exception If failed.
*/
@Test
@Ignore("Outdated machines do not consider TLS 1.1 deprecated.")
public void testDeprecatedProtocolThrows() throws Exception {
protocols = new String[] {
"TLSv1.1",
"TLSv1.2"
};
startGrid();
checkClientStartFailure(
null,
new String[] {
"TLSv1.1",
},
SSLHandshakeException.class,
"No appropriate protocol (protocol is disabled or cipher suites are inappropriate)"
);
}
/**
* @throws Exception If failed.
*/
@Test
public void testSameProtocols() throws Exception {
protocols = new String[] {
"TLSv1.1",
"TLSv1.2"
};
startGrid();
checkSuccessfulClientStart(null,
new String[] {
"TLSv1.1",
"TLSv1.2"
}
);
}
/**
* @throws Exception If failed.
*/
@Test
public void testOneCommonProtocol() throws Exception {
protocols = new String[] {
"TLSv1",
"TLSv1.1",
"TLSv1.2"
};
startGrid();
checkSuccessfulClientStart(null,
new String[] {
"TLSv1.2",
"SSLv3"
}
);
}
/**
* @param cipherSuites list of cipher suites
* @param protocols list of protocols
*/
private void checkSuccessfulClientStart(String[] cipherSuites, String[] protocols) {
this.cipherSuites = F.isEmpty(cipherSuites) ? null : cipherSuites;
this.protocols = F.isEmpty(protocols) ? null : protocols;
try (IgniteClient client = Ignition.startClient(getClientConfiguration())) {
client.getOrCreateCache(TEST_CACHE_NAME);
}
}
/**
* @param cipherSuites list of cipher suites
* @param protocols list of protocols
*/
private void checkClientStartFailure(String[] cipherSuites, String[] protocols) {
checkClientStartFailure(
cipherSuites,
protocols,
ClientConnectionException.class,
"SSL handshake failed"
);
}
/**
* @param cipherSuites list of cipher suites
* @param protocols list of protocols
* @param ex expected exception class
* @param msg exception message
*/
private void checkClientStartFailure(
String[] cipherSuites,
String[] protocols,
Class<? extends Throwable> ex,
String msg
) {
this.cipherSuites = F.isEmpty(cipherSuites) ? null : cipherSuites;
this.protocols = F.isEmpty(protocols) ? null : protocols;
GridTestUtils.assertThrowsAnyCause(
null,
new Callable<Object>() {
@Override public Object call() {
Ignition.startClient(getClientConfiguration());
return null;
}
},
ex,
msg
);
}
}