diff --git a/ssl-config/src/main/java/com/palantir/remoting/ssl/KeyStoreConfiguration.java b/ssl-config/src/main/java/com/palantir/remoting/ssl/KeyStoreConfiguration.java deleted file mode 100644 index c35ef044a..000000000 --- a/ssl-config/src/main/java/com/palantir/remoting/ssl/KeyStoreConfiguration.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2015 Palantir Technologies, Inc. All rights reserved. - * - * Licensed 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 com.palantir.remoting.ssl; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import java.net.URI; -import org.immutables.value.Value; -import org.immutables.value.Value.Style.ImplementationVisibility; - -@JsonDeserialize(as = ImmutableKeyStoreConfiguration.class) -@JsonSerialize(as = ImmutableKeyStoreConfiguration.class) -@Value.Immutable -@Value.Style(visibility = ImplementationVisibility.PACKAGE) -public abstract class KeyStoreConfiguration { - - @Value.Parameter - public abstract URI uri(); - - @Value.Parameter - public abstract String password(); - - @SuppressWarnings("checkstyle:designforextension") - @Value.Default - public String type() { - return "JKS"; - } - - // alias of the key. If absent, first key returned by key store will be used. - public abstract Optional alias(); - - @Value.Check - protected final void check() { - Preconditions.checkArgument(!uri().equals(URI.create("")), "uri cannot be empty"); - Preconditions.checkArgument(!password().equals(""), "password cannot be empty"); - } - - public static KeyStoreConfiguration of(URI uri, String password) { - return ImmutableKeyStoreConfiguration.of(uri, password); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder extends ImmutableKeyStoreConfiguration.Builder {} - -} diff --git a/ssl-config/src/main/java/com/palantir/remoting/ssl/SslConfiguration.java b/ssl-config/src/main/java/com/palantir/remoting/ssl/SslConfiguration.java index 745fd1e74..84f108ee8 100644 --- a/ssl-config/src/main/java/com/palantir/remoting/ssl/SslConfiguration.java +++ b/ssl-config/src/main/java/com/palantir/remoting/ssl/SslConfiguration.java @@ -19,6 +19,8 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import java.nio.file.Path; import org.immutables.value.Value; import org.immutables.value.Value.Style.ImplementationVisibility; @@ -28,18 +30,51 @@ @Value.Style(visibility = ImplementationVisibility.PACKAGE) public abstract class SslConfiguration { - @Value.Parameter - public abstract TrustStoreConfiguration trust(); + private static final String DEFAULT_STORE_TYPE = "JKS"; - @Value.Parameter - public abstract Optional key(); + public abstract Path trustStorePath(); - public static SslConfiguration of(TrustStoreConfiguration trust) { - return ImmutableSslConfiguration.of(trust, Optional.absent()); + @SuppressWarnings("checkstyle:designforextension") + @Value.Default + public String trustStoreType() { + return DEFAULT_STORE_TYPE; } - public static SslConfiguration of(TrustStoreConfiguration trust, KeyStoreConfiguration key) { - return ImmutableSslConfiguration.of(trust, Optional.of(key)); + public abstract Optional keyStorePath(); + + public abstract Optional keyStorePassword(); + + @SuppressWarnings("checkstyle:designforextension") + @Value.Default + public String keyStoreType() { + return DEFAULT_STORE_TYPE; + } + + // alias of the key that should be used in the key store. + // If absent, first entry returned by key store is used. + public abstract Optional keyStoreKeyAlias(); + + @Value.Check + protected final void check() { + Preconditions.checkArgument( + keyStorePath().isPresent() == keyStorePassword().isPresent(), + "keyStorePath and keyStorePassword must both be present or both be absent"); + + Preconditions.checkArgument( + !keyStoreKeyAlias().isPresent() || keyStorePath().isPresent(), + "keyStorePath must be present if keyStoreKeyAlias is present"); + } + + public static SslConfiguration of(Path trustStorePath) { + return SslConfiguration.builder().trustStorePath(trustStorePath).build(); + } + + public static SslConfiguration of(Path trustStorePath, Path keyStorePath, String keyStorePassword) { + return SslConfiguration.builder() + .trustStorePath(trustStorePath) + .keyStorePath(keyStorePath) + .keyStorePassword(keyStorePassword) + .build(); } public static Builder builder() { diff --git a/ssl-config/src/main/java/com/palantir/remoting/ssl/SslSocketFactories.java b/ssl-config/src/main/java/com/palantir/remoting/ssl/SslSocketFactories.java index b3b4ce718..627ad1149 100644 --- a/ssl-config/src/main/java/com/palantir/remoting/ssl/SslSocketFactories.java +++ b/ssl-config/src/main/java/com/palantir/remoting/ssl/SslSocketFactories.java @@ -4,9 +4,12 @@ package com.palantir.remoting.ssl; +import com.google.common.base.Optional; import com.google.common.base.Throwables; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.security.GeneralSecurityException; import java.security.Key; import java.security.KeyStore; @@ -43,11 +46,17 @@ public static SSLSocketFactory createSslSocketFactory(SslConfiguration config) { * @return an {@link SSLContext} according to the input configuration */ public static SSLContext createSslContext(SslConfiguration config) { - TrustManager[] trustManagers = createTrustManagerFactory(config.trust()).getTrustManagers(); + TrustManager[] trustManagers = createTrustManagerFactory( + config.trustStorePath(), + config.trustStoreType()).getTrustManagers(); KeyManager[] keyManagers = null; - if (config.key().isPresent()) { - keyManagers = createKeyManagerFactory(config.key().get()).getKeyManagers(); + if (config.keyStorePath().isPresent()) { + keyManagers = createKeyManagerFactory( + config.keyStorePath().get(), + config.keyStorePassword().get(), + config.keyStoreType(), + config.keyStoreKeyAlias()).getKeyManagers(); } try { @@ -59,12 +68,12 @@ public static SSLContext createSslContext(SslConfiguration config) { } } - private static TrustManagerFactory createTrustManagerFactory(TrustStoreConfiguration trustStoreConfig) { + private static TrustManagerFactory createTrustManagerFactory(Path trustStorePath, String trustStoreType) { try { TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); - KeyStore keyStore = KeyStore.getInstance(trustStoreConfig.type()); - try (InputStream stream = trustStoreConfig.uri().toURL().openStream()) { + KeyStore keyStore = KeyStore.getInstance(trustStoreType); + try (InputStream stream = Files.newInputStream(trustStorePath)) { keyStore.load(stream, null); } trustManagerFactory.init(keyStore); @@ -75,23 +84,27 @@ private static TrustManagerFactory createTrustManagerFactory(TrustStoreConfigura } } - private static KeyManagerFactory createKeyManagerFactory(KeyStoreConfiguration keyStoreConfig) { + private static KeyManagerFactory createKeyManagerFactory( + Path keyStorePath, + String keyStorePassword, + String keyStoreType, + Optional keyStoreKeyAlias) { try { KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm()); - KeyStore keyStore = KeyStore.getInstance(keyStoreConfig.type()); - try (InputStream stream = keyStoreConfig.uri().toURL().openStream()) { - keyStore.load(stream, keyStoreConfig.password().toCharArray()); + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + try (InputStream stream = Files.newInputStream(keyStorePath)) { + keyStore.load(stream, keyStorePassword.toCharArray()); } - if (keyStoreConfig.alias().isPresent()) { + if (keyStoreKeyAlias.isPresent()) { // default KeyManagerFactory does not support referencing key by alias, so // if a key with a specific alias is desired, construct a new key store that // contains only the key and certificate with that alias - keyStore = newKeyStoreWithEntry(keyStore, keyStoreConfig.password(), keyStoreConfig.alias().get()); + keyStore = newKeyStoreWithEntry(keyStore, keyStorePassword, keyStoreKeyAlias.get()); } - keyManagerFactory.init(keyStore, keyStoreConfig.password().toCharArray()); + keyManagerFactory.init(keyStore, keyStorePassword.toCharArray()); return keyManagerFactory; } catch (GeneralSecurityException | IOException e) { diff --git a/ssl-config/src/main/java/com/palantir/remoting/ssl/TrustStoreConfiguration.java b/ssl-config/src/main/java/com/palantir/remoting/ssl/TrustStoreConfiguration.java deleted file mode 100644 index 32e10319e..000000000 --- a/ssl-config/src/main/java/com/palantir/remoting/ssl/TrustStoreConfiguration.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2015 Palantir Technologies, Inc. All rights reserved. - * - * Licensed 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 com.palantir.remoting.ssl; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.google.common.base.Preconditions; -import java.net.URI; -import org.immutables.value.Value; -import org.immutables.value.Value.Style.ImplementationVisibility; - -@JsonDeserialize(as = ImmutableTrustStoreConfiguration.class) -@JsonSerialize(as = ImmutableTrustStoreConfiguration.class) -@Value.Immutable -@Value.Style(visibility = ImplementationVisibility.PACKAGE) -public abstract class TrustStoreConfiguration { - - @Value.Parameter - public abstract URI uri(); - - @SuppressWarnings("checkstyle:designforextension") - @Value.Default - public String type() { - return "JKS"; - } - - @Value.Check - protected final void check() { - Preconditions.checkArgument(!uri().equals(URI.create("")), "uri cannot be empty"); - } - - public static TrustStoreConfiguration of(URI uri) { - return ImmutableTrustStoreConfiguration.of(uri); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder extends ImmutableTrustStoreConfiguration.Builder {} - -} diff --git a/ssl-config/src/test/java/com/palantir/ssl/DropwizardSslClientAuthTests.java b/ssl-config/src/test/java/com/palantir/ssl/DropwizardSslClientAuthTests.java index 8e3619bed..f7f137fc7 100644 --- a/ssl-config/src/test/java/com/palantir/ssl/DropwizardSslClientAuthTests.java +++ b/ssl-config/src/test/java/com/palantir/ssl/DropwizardSslClientAuthTests.java @@ -10,10 +10,8 @@ import com.google.common.base.Optional; import com.palantir.remoting.http.FeignClients; -import com.palantir.remoting.ssl.KeyStoreConfiguration; import com.palantir.remoting.ssl.SslConfiguration; import com.palantir.remoting.ssl.SslSocketFactories; -import com.palantir.remoting.ssl.TrustStoreConfiguration; import feign.RetryableException; import io.dropwizard.Application; import io.dropwizard.Configuration; @@ -48,7 +46,7 @@ public final class DropwizardSslClientAuthTests { @Test public void testConnectionFailsWithoutClientCerts() { - SslConfiguration sslConfig = SslConfiguration.of(TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH)); + SslConfiguration sslConfig = SslConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); TestEchoService service = createTestService(sslConfig); try { @@ -62,10 +60,9 @@ public void testConnectionFailsWithoutClientCerts() { @Test public void testConnectionWorksWithClientCerts() { SslConfiguration sslConfig = SslConfiguration.of( - TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH), - KeyStoreConfiguration.of( - TestConstants.CLIENT_KEY_STORE_JKS_PATH, - TestConstants.CLIENT_KEY_STORE_JKS_PASSWORD)); + TestConstants.CA_TRUST_STORE_PATH, + TestConstants.CLIENT_KEY_STORE_JKS_PATH, + TestConstants.CLIENT_KEY_STORE_JKS_PASSWORD); TestEchoService service = createTestService(sslConfig); assertThat(service.echo("foo"), is("foo")); diff --git a/ssl-config/src/test/java/com/palantir/ssl/SerializationTests.java b/ssl-config/src/test/java/com/palantir/ssl/SerializationTests.java index a189882c1..d5afb9fdf 100644 --- a/ssl-config/src/test/java/com/palantir/ssl/SerializationTests.java +++ b/ssl-config/src/test/java/com/palantir/ssl/SerializationTests.java @@ -23,23 +23,22 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.guava.GuavaModule; -import com.palantir.remoting.ssl.KeyStoreConfiguration; -import com.palantir.remoting.ssl.TrustStoreConfiguration; +import com.palantir.remoting.http.ObjectMappers; +import com.palantir.remoting.ssl.SslConfiguration; import java.io.IOException; -import java.net.URI; import org.junit.Test; public final class SerializationTests { @Test public void testJsonSerDe() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException { - ObjectMapper mapper = new ObjectMapper().registerModule(new GuavaModule()); - KeyStoreConfiguration keystore = KeyStoreConfiguration.of(URI.create("/path"), "password"); - TrustStoreConfiguration truststore = TrustStoreConfiguration.of(URI.create("/path")); + ObjectMapper mapper = ObjectMappers.guavaJdk7(); + SslConfiguration sslConfig = SslConfiguration.of( + TestConstants.CA_TRUST_STORE_PATH, + TestConstants.SERVER_KEY_STORE_JKS_PATH, + TestConstants.SERVER_KEY_STORE_JKS_PASSWORD); - assertThat(mapper.readValue(mapper.writeValueAsBytes(keystore), KeyStoreConfiguration.class), is(keystore)); - assertThat(mapper.readValue(mapper.writeValueAsBytes(truststore), TrustStoreConfiguration.class), - is(truststore)); + assertThat(mapper.readValue(mapper.writeValueAsBytes(sslConfig), SslConfiguration.class), is(sslConfig)); } + } diff --git a/ssl-config/src/test/java/com/palantir/ssl/SslSocketFactoriesConnectionTests.java b/ssl-config/src/test/java/com/palantir/ssl/SslSocketFactoriesConnectionTests.java index 14468b82a..2e40a610b 100644 --- a/ssl-config/src/test/java/com/palantir/ssl/SslSocketFactoriesConnectionTests.java +++ b/ssl-config/src/test/java/com/palantir/ssl/SslSocketFactoriesConnectionTests.java @@ -10,10 +10,8 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; -import com.palantir.remoting.ssl.KeyStoreConfiguration; import com.palantir.remoting.ssl.SslConfiguration; import com.palantir.remoting.ssl.SslSocketFactories; -import com.palantir.remoting.ssl.TrustStoreConfiguration; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -48,47 +46,40 @@ private enum ClientAuth { @Test public void testSslNoClientAuthenticationJks() { - TrustStoreConfiguration serverTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - KeyStoreConfiguration serverKeyStoreConfig = KeyStoreConfiguration.of( + SslConfiguration serverConfig = SslConfiguration.of( + TestConstants.CA_TRUST_STORE_PATH, TestConstants.SERVER_KEY_STORE_JKS_PATH, TestConstants.SERVER_KEY_STORE_JKS_PASSWORD); - SslConfiguration serverConfig = SslConfiguration.of(serverTrustStoreConfig, serverKeyStoreConfig); - TrustStoreConfiguration clientTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - SslConfiguration clientConfig = SslConfiguration.of(clientTrustStoreConfig); + SslConfiguration clientConfig = SslConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); runSslConnectionTest(serverConfig, clientConfig, ClientAuth.NO_CLIENT_AUTH); } @Test public void testSslNoClientAuthenticationPkcs12() { - TrustStoreConfiguration serverTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - KeyStoreConfiguration serverKeyStoreConfig = KeyStoreConfiguration.builder() - .uri(TestConstants.SERVER_KEY_STORE_P12_PATH) - .type(TestConstants.SERVER_KEY_STORE_P12_TYPE) - .password(TestConstants.SERVER_KEY_STORE_P12_PASSWORD) + SslConfiguration serverConfig = SslConfiguration.builder() + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.SERVER_KEY_STORE_P12_PATH) + .keyStoreType(TestConstants.SERVER_KEY_STORE_P12_TYPE) + .keyStorePassword(TestConstants.SERVER_KEY_STORE_P12_PASSWORD) .build(); - SslConfiguration serverConfig = SslConfiguration.of(serverTrustStoreConfig, serverKeyStoreConfig); - TrustStoreConfiguration clientTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - SslConfiguration clientConfig = SslConfiguration.of(clientTrustStoreConfig); + SslConfiguration clientConfig = SslConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); runSslConnectionTest(serverConfig, clientConfig, ClientAuth.NO_CLIENT_AUTH); } @Test public void testSslNoClientAuthenticationFailsWithoutProperClientTrustStore() { - TrustStoreConfiguration serverTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - KeyStoreConfiguration serverKeyStoreConfig = KeyStoreConfiguration.of( + SslConfiguration serverConfig = SslConfiguration.of( + TestConstants.CA_TRUST_STORE_PATH, TestConstants.SERVER_KEY_STORE_JKS_PATH, TestConstants.SERVER_KEY_STORE_JKS_PASSWORD); - SslConfiguration serverConfig = SslConfiguration.of(serverTrustStoreConfig, serverKeyStoreConfig); // bad configuration: client trust store does not contain any certificates // that can verify the server certificate - TrustStoreConfiguration clientTrustStoreConfig = TrustStoreConfiguration.of( - TestConstants.CLIENT_KEY_STORE_JKS_PATH); - SslConfiguration clientConfig = SslConfiguration.of(clientTrustStoreConfig); + SslConfiguration clientConfig = SslConfiguration.of(TestConstants.CLIENT_KEY_STORE_JKS_PATH); try { runSslConnectionTest(serverConfig, clientConfig, ClientAuth.NO_CLIENT_AUTH); @@ -103,109 +94,92 @@ public void testSslNoClientAuthenticationFailsWithoutProperClientTrustStore() { public void testSslWithNoClientAuthenticationWorksWithoutProperServerTrustStore() { // if no client authentication is present, doesn't matter that server trust store // cannot verify any certificates - TrustStoreConfiguration serverTrustStoreConfig = TrustStoreConfiguration.of( - TestConstants.SERVER_KEY_STORE_JKS_PATH); - KeyStoreConfiguration serverKeyStoreConfig = KeyStoreConfiguration.of( + SslConfiguration serverConfig = SslConfiguration.of( + TestConstants.SERVER_KEY_STORE_JKS_PATH, TestConstants.SERVER_KEY_STORE_JKS_PATH, TestConstants.SERVER_KEY_STORE_JKS_PASSWORD); - SslConfiguration serverConfig = SslConfiguration.of(serverTrustStoreConfig, serverKeyStoreConfig); - TrustStoreConfiguration clientTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - SslConfiguration clientConfig = SslConfiguration.of(clientTrustStoreConfig); + SslConfiguration clientConfig = SslConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); runSslConnectionTest(serverConfig, clientConfig, ClientAuth.NO_CLIENT_AUTH); } @Test public void testSslNoClientAuthenticationFailsWithMultipleKeyStoreSpecified() { - TrustStoreConfiguration serverTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - // specify that server key alias should be used - KeyStoreConfiguration serverKeyStoreConfig = KeyStoreConfiguration.builder() - .uri(TestConstants.MULTIPLE_KEY_STORE_JKS_PATH) - .password(TestConstants.MULTIPLE_KEY_STORE_JKS_PASSWORD) - .alias(TestConstants.MULTIPLE_KEY_STORE_SERVER_ALIAS) + SslConfiguration serverConfig = SslConfiguration.builder() + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.MULTIPLE_KEY_STORE_JKS_PATH) + .keyStorePassword(TestConstants.MULTIPLE_KEY_STORE_JKS_PASSWORD) + .keyStoreKeyAlias(TestConstants.MULTIPLE_KEY_STORE_SERVER_ALIAS) .build(); - SslConfiguration serverConfig = SslConfiguration.of(serverTrustStoreConfig, serverKeyStoreConfig); - TrustStoreConfiguration clientTrustStoreConfig = TrustStoreConfiguration.of( - TestConstants.SERVER_KEY_STORE_JKS_PATH); - SslConfiguration clientConfig = SslConfiguration.of(clientTrustStoreConfig); + SslConfiguration clientConfig = SslConfiguration.of(TestConstants.SERVER_KEY_STORE_JKS_PATH); runSslConnectionTest(serverConfig, clientConfig, ClientAuth.NO_CLIENT_AUTH); } @Test public void testSslWithClientAuthenticationJks() { - TrustStoreConfiguration serverTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - KeyStoreConfiguration serverKeyStoreConfig = KeyStoreConfiguration.of( + SslConfiguration serverConfig = SslConfiguration.of( + TestConstants.CA_TRUST_STORE_PATH, TestConstants.SERVER_KEY_STORE_JKS_PATH, TestConstants.SERVER_KEY_STORE_JKS_PASSWORD); - SslConfiguration serverConfig = SslConfiguration.of(serverTrustStoreConfig, serverKeyStoreConfig); - TrustStoreConfiguration clientTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - KeyStoreConfiguration clientKeyStoreConfig = KeyStoreConfiguration.of( + SslConfiguration clientConfig = SslConfiguration.of( + TestConstants.CA_TRUST_STORE_PATH, TestConstants.CLIENT_KEY_STORE_JKS_PATH, TestConstants.CLIENT_KEY_STORE_JKS_PASSWORD); - SslConfiguration clientConfig = SslConfiguration.of(clientTrustStoreConfig, clientKeyStoreConfig); runSslConnectionTest(serverConfig, clientConfig, ClientAuth.WITH_CLIENT_AUTH); } @Test public void testSslWithClientAuthenticationPkcs12() { - TrustStoreConfiguration serverTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - - KeyStoreConfiguration serverKeyStoreConfig = KeyStoreConfiguration.builder() - .uri(TestConstants.SERVER_KEY_STORE_P12_PATH) - .type(TestConstants.SERVER_KEY_STORE_P12_TYPE) - .password(TestConstants.SERVER_KEY_STORE_P12_PASSWORD) + SslConfiguration serverConfig = SslConfiguration.builder() + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.SERVER_KEY_STORE_P12_PATH) + .keyStoreType(TestConstants.SERVER_KEY_STORE_P12_TYPE) + .keyStorePassword(TestConstants.SERVER_KEY_STORE_P12_PASSWORD) .build(); - SslConfiguration serverConfig = SslConfiguration.of(serverTrustStoreConfig, serverKeyStoreConfig); - - TrustStoreConfiguration clientTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - KeyStoreConfiguration clientKeyStoreConfig = KeyStoreConfiguration.builder() - .uri(TestConstants.CLIENT_KEY_STORE_P12_PATH) - .type(TestConstants.CLIENT_KEY_STORE_P12_TYPE) - .password(TestConstants.CLIENT_KEY_STORE_P12_PASSWORD) + SslConfiguration clientConfig = SslConfiguration.builder() + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.CLIENT_KEY_STORE_P12_PATH) + .keyStoreType(TestConstants.CLIENT_KEY_STORE_P12_TYPE) + .keyStorePassword(TestConstants.CLIENT_KEY_STORE_P12_PASSWORD) .build(); - SslConfiguration clientConfig = SslConfiguration.of(clientTrustStoreConfig, clientKeyStoreConfig); runSslConnectionTest(serverConfig, clientConfig, ClientAuth.WITH_CLIENT_AUTH); } @Test public void testSslWithClientAuthenticationMixed() { - TrustStoreConfiguration serverTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - KeyStoreConfiguration serverKeyStoreConfig = KeyStoreConfiguration.of( + SslConfiguration serverConfig = SslConfiguration.of( + TestConstants.CA_TRUST_STORE_PATH, TestConstants.SERVER_KEY_STORE_JKS_PATH, TestConstants.SERVER_KEY_STORE_JKS_PASSWORD); - SslConfiguration serverConfig = SslConfiguration.of(serverTrustStoreConfig, serverKeyStoreConfig); - TrustStoreConfiguration clientTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - KeyStoreConfiguration clientKeyStoreConfig = KeyStoreConfiguration.builder() - .uri(TestConstants.CLIENT_KEY_STORE_P12_PATH) - .type(TestConstants.CLIENT_KEY_STORE_P12_TYPE) - .password(TestConstants.CLIENT_KEY_STORE_P12_PASSWORD) + SslConfiguration clientConfig = SslConfiguration.builder() + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.CLIENT_KEY_STORE_P12_PATH) + .keyStoreType(TestConstants.CLIENT_KEY_STORE_P12_TYPE) + .keyStorePassword(TestConstants.CLIENT_KEY_STORE_P12_PASSWORD) .build(); - SslConfiguration clientConfig = SslConfiguration.of(clientTrustStoreConfig, clientKeyStoreConfig); runSslConnectionTest(serverConfig, clientConfig, ClientAuth.WITH_CLIENT_AUTH); } @Test public void testSslWithClientAuthenticationFailsWithoutClientKeyStore() { - TrustStoreConfiguration serverTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - KeyStoreConfiguration serverKeyStoreConfig = KeyStoreConfiguration.of( + SslConfiguration serverConfig = SslConfiguration.of( + TestConstants.CA_TRUST_STORE_PATH, TestConstants.SERVER_KEY_STORE_JKS_PATH, TestConstants.SERVER_KEY_STORE_JKS_PASSWORD); - SslConfiguration serverConfig = SslConfiguration.of(serverTrustStoreConfig, serverKeyStoreConfig); - TrustStoreConfiguration clientTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); // bad configuration: client does not specify a key store for a connection // that requires client authentication - SslConfiguration clientConfig = SslConfiguration.of(clientTrustStoreConfig); + SslConfiguration clientConfig = SslConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); try { runSslConnectionTest(serverConfig, clientConfig, ClientAuth.WITH_CLIENT_AUTH); @@ -220,18 +194,15 @@ public void testSslWithClientAuthenticationFailsWithoutClientKeyStore() { public void testSslWithClientAuthenticationFailsWithoutProperServerTrustStore() { // bad configuration: server trust store does not contain any certificates // that can verify the client certificate - TrustStoreConfiguration serverTrustStoreConfig = TrustStoreConfiguration.of( - TestConstants.SERVER_KEY_STORE_JKS_PATH); - KeyStoreConfiguration serverKeyStoreConfig = KeyStoreConfiguration.of( + SslConfiguration serverConfig = SslConfiguration.of( + TestConstants.SERVER_KEY_STORE_JKS_PATH, TestConstants.SERVER_KEY_STORE_JKS_PATH, TestConstants.SERVER_KEY_STORE_JKS_PASSWORD); - SslConfiguration serverConfig = SslConfiguration.of(serverTrustStoreConfig, serverKeyStoreConfig); - TrustStoreConfiguration clientTrustStoreConfig = TrustStoreConfiguration.of(TestConstants.CA_TRUST_STORE_PATH); - KeyStoreConfiguration clientKeyStoreConfig = KeyStoreConfiguration.of( + SslConfiguration clientConfig = SslConfiguration.of( + TestConstants.CA_TRUST_STORE_PATH, TestConstants.CLIENT_KEY_STORE_JKS_PATH, TestConstants.CLIENT_KEY_STORE_JKS_PASSWORD); - SslConfiguration clientConfig = SslConfiguration.of(clientTrustStoreConfig, clientKeyStoreConfig); try { runSslConnectionTest(serverConfig, clientConfig, ClientAuth.WITH_CLIENT_AUTH); diff --git a/ssl-config/src/test/java/com/palantir/ssl/SslSocketFactoriesTests.java b/ssl-config/src/test/java/com/palantir/ssl/SslSocketFactoriesTests.java index f9813ea59..31907ce17 100644 --- a/ssl-config/src/test/java/com/palantir/ssl/SslSocketFactoriesTests.java +++ b/ssl-config/src/test/java/com/palantir/ssl/SslSocketFactoriesTests.java @@ -11,11 +11,11 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; -import com.palantir.remoting.ssl.KeyStoreConfiguration; import com.palantir.remoting.ssl.SslConfiguration; import com.palantir.remoting.ssl.SslSocketFactories; -import com.palantir.remoting.ssl.TrustStoreConfiguration; +import java.io.File; import java.io.IOException; +import java.nio.file.NoSuchFileException; import javax.net.ssl.SSLSocketFactory; import org.junit.Test; @@ -26,92 +26,67 @@ public final class SslSocketFactoriesTests { @Test public void testCreateSslSocketFactory_canCreateWithAllTrustStoreParams() { - TrustStoreConfiguration trustStoreConfig = TrustStoreConfiguration + SslConfiguration sslConfig = SslConfiguration .builder() - .uri(TestConstants.CA_TRUST_STORE_PATH) - .type(TestConstants.CA_TRUST_STORE_TYPE) + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .trustStoreType(TestConstants.CA_TRUST_STORE_TYPE) .build(); - SSLSocketFactory factory = SslSocketFactories.createSslSocketFactory(SslConfiguration - .builder() - .trust(trustStoreConfig) - .build()); + SSLSocketFactory factory = SslSocketFactories.createSslSocketFactory(sslConfig); assertThat(factory, notNullValue()); } @Test public void testCreateSslSocketFactory_canCreateWithAllTrustStoreParamsPkcs12Format() { - TrustStoreConfiguration trustStoreConfig = TrustStoreConfiguration + SslConfiguration sslConfig = SslConfiguration .builder() - .uri(TestConstants.SERVER_KEY_STORE_P12_PATH) - .type(TestConstants.SERVER_KEY_STORE_P12_TYPE) + .trustStorePath(TestConstants.SERVER_KEY_STORE_P12_PATH) + .trustStoreType(TestConstants.SERVER_KEY_STORE_P12_TYPE) .build(); - SSLSocketFactory factory = SslSocketFactories.createSslSocketFactory( - SslConfiguration.builder() - .trust(trustStoreConfig) - .build()); + SSLSocketFactory factory = SslSocketFactories.createSslSocketFactory(sslConfig); assertThat(factory, notNullValue()); } @Test public void testCreateSslSocketFactory_canCreateWithOnlyTrustStorePath() { - TrustStoreConfiguration trustStoreConfig = TrustStoreConfiguration + SslConfiguration sslConfig = SslConfiguration .builder() - .uri(TestConstants.CA_TRUST_STORE_PATH) + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) .build(); - SSLSocketFactory factory = SslSocketFactories.createSslSocketFactory( - SslConfiguration.builder() - .trust(trustStoreConfig) - .build()); + SSLSocketFactory factory = SslSocketFactories.createSslSocketFactory(sslConfig); assertThat(factory, notNullValue()); } @Test public void testCreateSslSocketFactory_canCreateWithAllKeyStoreParams() { - TrustStoreConfiguration trustStoreConfig = TrustStoreConfiguration - .builder() - .uri(TestConstants.CA_TRUST_STORE_PATH) - .build(); - - KeyStoreConfiguration keyStoreConfig = KeyStoreConfiguration + SslConfiguration sslConfig = SslConfiguration .builder() - .uri(TestConstants.SERVER_KEY_STORE_JKS_PATH) - .password(TestConstants.SERVER_KEY_STORE_JKS_PASSWORD) - .type(TestConstants.SERVER_KEY_STORE_JKS_TYPE) + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.SERVER_KEY_STORE_JKS_PATH) + .keyStorePassword(TestConstants.SERVER_KEY_STORE_JKS_PASSWORD) + .keyStoreType(TestConstants.SERVER_KEY_STORE_JKS_TYPE) .build(); - SSLSocketFactory factory = SslSocketFactories.createSslSocketFactory( - SslConfiguration.builder() - .trust(trustStoreConfig) - .key(keyStoreConfig) - .build()); + SSLSocketFactory factory = SslSocketFactories.createSslSocketFactory(sslConfig); assertThat(factory, notNullValue()); } @Test public void testCreateSslSocketFactory_canCreateWithoutKeyStoreTypeJks() { - TrustStoreConfiguration trustStoreConfig = TrustStoreConfiguration + SslConfiguration sslConfig = SslConfiguration .builder() - .uri(TestConstants.CA_TRUST_STORE_PATH) + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.SERVER_KEY_STORE_JKS_PATH) + .keyStorePassword(TestConstants.SERVER_KEY_STORE_JKS_PASSWORD) .build(); - KeyStoreConfiguration keyStoreConfig = KeyStoreConfiguration - .builder() - .uri(TestConstants.SERVER_KEY_STORE_JKS_PATH) - .password(TestConstants.SERVER_KEY_STORE_JKS_PASSWORD) - .build(); - - SSLSocketFactory factory = SslSocketFactories.createSslSocketFactory( - SslConfiguration.builder() - .trust(trustStoreConfig) - .key(keyStoreConfig) - .build()); + SSLSocketFactory factory = SslSocketFactories.createSslSocketFactory(sslConfig); assertThat(factory, notNullValue()); } @@ -119,25 +94,17 @@ public void testCreateSslSocketFactory_canCreateWithoutKeyStoreTypeJks() { @Test public void testCreateSslSocketFactory_jksKeyStoreTypeCannotBePkcs12Type() { try { - TrustStoreConfiguration trustStoreConfig = TrustStoreConfiguration - .builder() - .uri(TestConstants.CA_TRUST_STORE_PATH) - .build(); - - // bad configuration: key store is JKS format, but configuration specifies - // that it is in PKCS12 format - KeyStoreConfiguration keyStoreConfig = KeyStoreConfiguration + SslConfiguration sslConfig = SslConfiguration .builder() - .uri(TestConstants.SERVER_KEY_STORE_JKS_PATH) - .password(TestConstants.SERVER_KEY_STORE_JKS_PASSWORD) - .type(TestConstants.SERVER_KEY_STORE_P12_TYPE) + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.SERVER_KEY_STORE_JKS_PATH) + .keyStorePassword(TestConstants.SERVER_KEY_STORE_JKS_PASSWORD) + // bad configuration: key store is JKS format, but configuration specifies + // that it is in PKCS12 format + .keyStoreType(TestConstants.SERVER_KEY_STORE_P12_TYPE) .build(); - SslSocketFactories.createSslSocketFactory( - SslConfiguration.builder() - .trust(trustStoreConfig) - .key(keyStoreConfig) - .build()); + SslSocketFactories.createSslSocketFactory(sslConfig); fail(); } catch (RuntimeException ex) { @@ -148,23 +115,15 @@ public void testCreateSslSocketFactory_jksKeyStoreTypeCannotBePkcs12Type() { @Test public void testCreateSslSocketFactory_keyStorePasswordMustBeCorrectJks() { try { - TrustStoreConfiguration trustStoreConfig = TrustStoreConfiguration - .builder() - .uri(TestConstants.CA_TRUST_STORE_PATH) - .build(); - - // bad configuration: keyStorePassword is incorrect - KeyStoreConfiguration keyStoreConfig = KeyStoreConfiguration + SslConfiguration sslConfig = SslConfiguration .builder() - .uri(TestConstants.SERVER_KEY_STORE_JKS_PATH) - .password("a") + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.SERVER_KEY_STORE_JKS_PATH) + // bad configuration: keyStorePassword is incorrect + .keyStorePassword("a") .build(); - SslSocketFactories.createSslSocketFactory( - SslConfiguration.builder() - .trust(trustStoreConfig) - .key(keyStoreConfig) - .build()); + SslSocketFactories.createSslSocketFactory(sslConfig); fail(); } catch (RuntimeException ex) { @@ -176,23 +135,15 @@ public void testCreateSslSocketFactory_keyStorePasswordMustBeCorrectJks() { @Test public void testCreateSslSocketFactory_keyStorePasswordMustBeCorrectPkcs12() { try { - TrustStoreConfiguration trustStoreConfig = TrustStoreConfiguration - .builder() - .uri(TestConstants.CA_TRUST_STORE_PATH) - .build(); - - // bad configuration: keyStorePassword is incorrect - KeyStoreConfiguration keyStoreConfig = KeyStoreConfiguration + SslConfiguration sslConfig = SslConfiguration .builder() - .uri(TestConstants.SERVER_KEY_STORE_P12_PATH) - .password("a") + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.SERVER_KEY_STORE_P12_PATH) + // bad configuration: keyStorePassword is incorrect + .keyStorePassword("a") .build(); - SslSocketFactories.createSslSocketFactory( - SslConfiguration.builder() - .trust(trustStoreConfig) - .key(keyStoreConfig) - .build()); + SslSocketFactories.createSslSocketFactory(sslConfig); fail(); } catch (RuntimeException ex) { @@ -204,29 +155,103 @@ public void testCreateSslSocketFactory_keyStorePasswordMustBeCorrectPkcs12() { @Test public void testCreateSslSocketFactory_nonexistentKeyStoreAliasFails() { try { - TrustStoreConfiguration trustStoreConfig = TrustStoreConfiguration + SslConfiguration sslConfig = SslConfiguration .builder() - .uri(TestConstants.CA_TRUST_STORE_PATH) + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.MULTIPLE_KEY_STORE_JKS_PATH) + .keyStorePassword(TestConstants.MULTIPLE_KEY_STORE_JKS_PASSWORD) + // bad configuration: specified key alias does not exist in key store + .keyStoreKeyAlias("nonexistent") .build(); - // bad configuration: specified key alias does not exist in key store - KeyStoreConfiguration keyStoreConfig = KeyStoreConfiguration + SslSocketFactories.createSslSocketFactory(sslConfig); + + fail(); + } catch (IllegalStateException ex) { + assertThat(ex.getMessage(), containsString("Could not find key with alias")); + } + } + + @Test + public void testCreateSslSocketFactory_keystorePasswordRequiredIfUriPresent() { + try { + SslConfiguration sslConfig = SslConfiguration .builder() - .uri(TestConstants.MULTIPLE_KEY_STORE_JKS_PATH) - .password(TestConstants.MULTIPLE_KEY_STORE_JKS_PASSWORD) - .alias("nonexistent") + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePath(TestConstants.MULTIPLE_KEY_STORE_JKS_PATH) .build(); - SslSocketFactories.createSslSocketFactory( - SslConfiguration.builder() - .trust(trustStoreConfig) - .key(keyStoreConfig) - .build()); + SslSocketFactories.createSslSocketFactory(sslConfig); fail(); - } catch (IllegalStateException ex) { - assertThat(ex.getMessage(), containsString("Could not find key with alias")); + } catch (IllegalArgumentException ex) { + assertThat( + ex.getMessage(), + containsString("keyStorePath and keyStorePassword must both be present or both be absent")); + } + } + + @Test + public void testCreateSslSocketFactory_keyStorePathRequiredIfPasswordPresent() { + try { + SslConfiguration sslConfig = SslConfiguration + .builder() + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStorePassword(TestConstants.MULTIPLE_KEY_STORE_JKS_PASSWORD) + .build(); + + SslSocketFactories.createSslSocketFactory(sslConfig); + + fail(); + } catch (IllegalArgumentException ex) { + assertThat( + ex.getMessage(), + containsString("keyStorePath and keyStorePassword must both be present or both be absent")); + } + } + + @Test + public void testCreateSslSocketFactory_keyStorePathRequiredIfAliasPresent() { + try { + SslConfiguration sslConfig = SslConfiguration + .builder() + .trustStorePath(TestConstants.CA_TRUST_STORE_PATH) + .keyStoreKeyAlias(TestConstants.MULTIPLE_KEY_STORE_CLIENT_ALIAS) + .build(); + + SslSocketFactories.createSslSocketFactory(sslConfig); + + fail(); + } catch (IllegalArgumentException ex) { + assertThat(ex.getMessage(), containsString("keyStorePath must be present if keyStoreKeyAlias is present")); + } + } + + @Test + public void testCreateSslSocketFactory_failsWithInvalidPath() { + try { + SslConfiguration sslConfig = SslConfiguration + .builder() + .trustStorePath(new File("foo/bar").toPath()) + .build(); + + SslSocketFactories.createSslSocketFactory(sslConfig); + + fail(); + } catch (RuntimeException ex) { + assertThat(ex.getCause(), instanceOf(NoSuchFileException.class)); + assertThat(ex.getMessage(), containsString("foo/bar")); } } + @Test + public void testCreateSslSocketFactory_supportsRelativePath() { + SslConfiguration sslConfig = SslConfiguration + .builder() + .trustStorePath(new File("src/test/resources/testCA/testCATrustStore.jks").toPath()) + .build(); + + SslSocketFactories.createSslSocketFactory(sslConfig); + } + } diff --git a/ssl-config/src/test/java/com/palantir/ssl/TestConstants.java b/ssl-config/src/test/java/com/palantir/ssl/TestConstants.java index 77e1be50c..91aae4f5c 100644 --- a/ssl-config/src/test/java/com/palantir/ssl/TestConstants.java +++ b/ssl-config/src/test/java/com/palantir/ssl/TestConstants.java @@ -4,7 +4,6 @@ package com.palantir.ssl; -import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; @@ -13,54 +12,53 @@ */ final class TestConstants { - static final URI CA_TRUST_STORE_PATH = - Paths.get("src", "test", "resources", "testCA", "testCATrustStore.jks").toUri(); + static final Path CA_TRUST_STORE_PATH = Paths.get("src", "test", "resources", "testCA", "testCATrustStore.jks"); static final String CA_TRUST_STORE_TYPE = "JKS"; static final String CA_TRUST_STORE_PASSWORD = "testCA"; static final Path CA_CRL_PATH = Paths.get("src", "test", "resources", "crl.pem"); - static final URI SERVER_KEY_STORE_JKS_PATH = Paths.get( + static final Path SERVER_KEY_STORE_JKS_PATH = Paths.get( "src", "test", "resources", "testServer", - "testServerKeyStore.jks").toUri(); + "testServerKeyStore.jks"); static final String SERVER_KEY_STORE_JKS_TYPE = "JKS"; static final String SERVER_KEY_STORE_JKS_PASSWORD = "serverStore"; - static final URI SERVER_KEY_STORE_P12_PATH = Paths.get( + static final Path SERVER_KEY_STORE_P12_PATH = Paths.get( "src", "test", "resources", "testServer", - "testServerKeyStore.p12").toUri(); + "testServerKeyStore.p12"); static final String SERVER_KEY_STORE_P12_TYPE = "PKCS12"; static final String SERVER_KEY_STORE_P12_PASSWORD = "testServer"; - static final URI CLIENT_KEY_STORE_JKS_PATH = Paths.get( + static final Path CLIENT_KEY_STORE_JKS_PATH = Paths.get( "src", "test", "resources", "testClient", - "testClientKeyStore.jks").toUri(); + "testClientKeyStore.jks"); static final String CLIENT_KEY_STORE_JKS_TYPE = "JKS"; static final String CLIENT_KEY_STORE_JKS_PASSWORD = "clientStore"; - static final URI CLIENT_KEY_STORE_P12_PATH = Paths.get( + static final Path CLIENT_KEY_STORE_P12_PATH = Paths.get( "src", "test", "resources", "testClient", - "testClientKeyStore.p12").toUri(); + "testClientKeyStore.p12"); static final String CLIENT_KEY_STORE_P12_TYPE = "PKCS12"; static final String CLIENT_KEY_STORE_P12_PASSWORD = "testClient"; - static final URI MULTIPLE_KEY_STORE_JKS_PATH = Paths.get( + static final Path MULTIPLE_KEY_STORE_JKS_PATH = Paths.get( "src", "test", "resources", - "multiple.jks").toUri(); + "multiple.jks"); static final String MULTIPLE_KEY_STORE_JKS_PASSWORD = "multiple"; static final String MULTIPLE_KEY_STORE_CLIENT_ALIAS = "testClient"; static final String MULTIPLE_KEY_STORE_SERVER_ALIAS = "testServer";