Skip to content

Commit

Permalink
Flatten configuration and match Dropwizard names
Browse files Browse the repository at this point in the history
Remove TrustStoreConfiguration and KeyStoreConfiguration
and move all settings directly to SslConfiguration.
  • Loading branch information
nmiyake committed Feb 20, 2016
1 parent fd493e6 commit f48fa58
Show file tree
Hide file tree
Showing 9 changed files with 274 additions and 356 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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<KeyStoreConfiguration> key();
public abstract Path trustStorePath();

public static SslConfiguration of(TrustStoreConfiguration trust) {
return ImmutableSslConfiguration.of(trust, Optional.<KeyStoreConfiguration>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<Path> keyStorePath();

public abstract Optional<String> 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<String> 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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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);
Expand All @@ -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<String> 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) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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"));
Expand Down
19 changes: 9 additions & 10 deletions ssl-config/src/test/java/com/palantir/ssl/SerializationTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

}
Loading

0 comments on commit f48fa58

Please sign in to comment.