Skip to content

Commit

Permalink
Merge pull request #59 from nmiyake/matchDropwizardConfig
Browse files Browse the repository at this point in the history
Flatten configuration and match Dropwizard names
  • Loading branch information
uschi2000 committed Feb 20, 2016
2 parents fd493e6 + f48fa58 commit d6c7b70
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 d6c7b70

Please sign in to comment.