spring-attic / spring-cloud-etcd

Apache License 2.0
144 stars 60 forks source link

Support communication with etcd via SSL #28

Open yorksen opened 8 years ago

yorksen commented 8 years ago

Hi, we need to make etcd listen on 3379 and 4001 through https protocol. how to configure the spring-cloud-etcd ? and how to setup the SSL certificates(truststore) to spring-cloud-etcd?

spencergibb commented 8 years ago

It's currently not supported: https://github.com/spring-cloud-incubator/spring-cloud-etcd/blob/master/spring-cloud-etcd-core/src/main/java/org/springframework/cloud/etcd/EtcdAutoConfiguration.java#L38. PR's welcome.

yorksen commented 8 years ago

Recently, I am trying to make spring-cloud-etcd support SSL. I don't know how to make it report to https://localhost:4001 (default is http://xxxx). It seams class EtcdProperties can do the customization:

@ConfigurationProperties("spring.cloud.etcd") @Data public class EtcdProperties { @NotNull private List uris = Arrays.asList(URI.create("http://localhost:4001"));

private boolean enabled = true;

}

But I don't know how to assign a List value to uris property in application.properties file, the expression below doesn't work: spring.cloud.etcd.uris=https://localhost:4001,http://localhost:4001

Or if there is no way, I'll try to change the type of uris from List to String and its value will be URIs split by ','.

spencergibb commented 8 years ago

@yorksen as I mentioned before, it isn't supported yet.

yorksen commented 8 years ago

Yes, I know.

Nowadays, I am tring to modify spring-cloud-etcd source code to make it support SSL, If it works, I'll push my code to you.

But I have a little problem, how to specify the etcd address such as https://localhost:4001 via spring.cloud.etcd.uris property.

yorksen commented 8 years ago

Hi, the modification below will make spring-cloud-etcd support SSL. it just passed the tests, but need some refactoring before commit:

@Bean @ConditionalOnMissingBean public EtcdClient etcdClient() throws IOException,KeyStoreException,NoSuchAlgorithmException,CertificateException,UnrecoverableKeyException {

if (etcdProperties().isSslEnable())
{
    String trustStoreFile = etcdProperties().getTrustStoreFile();
    String trustStorePassword = etcdProperties().getTrustStorePassword();
    String keystoreFile = etcdProperties().getKeyStoreFile();
    String keystorePassword = etcdProperties().getKeyStorePassword();

    SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();
    if ((trustStoreFile != null) && (trustStorePassword != null)) {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        try (FileInputStream instreamTrustStore = new FileInputStream(new File(trustStoreFile))) {
            trustStore.load(instreamTrustStore, trustStorePassword.toCharArray());
        }

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);
        sslContextBuilder = sslContextBuilder.trustManager(trustManagerFactory);
    }

    if ((keystoreFile != null) && (keystorePassword != null)) {
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        try (FileInputStream instreamKeyStore = new FileInputStream(new File(keystoreFile))) {
                keyStore.load(instreamKeyStore, keystorePassword.toCharArray());
        }

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(keyStore, keystorePassword.toCharArray());
            sslContextBuilder = sslContextBuilder.keyManager(keyManagerFactory);
    }

    SslContext sslContext = sslContextBuilder.build();
    return new EtcdClient(sslContext, etcdProperties().getSecureUris().toArray(new URI[] {}));
}
else
{
    return new EtcdClient(etcdProperties().getUris().toArray(new URI[] {}));
}

}

yorksen commented 8 years ago

After the modification the class EtcdProperties looks like this:

@ConfigurationProperties("spring.cloud.etcd") @Data public class EtcdProperties {

@NotNull
private List<URI> uris = Arrays.asList(URI.create("http://localhost:4001"));

@NotNull
private List<URI> secureUris = Arrays.asList(URI.create("https://localhost:4001"));

private boolean enabled = true;

private String trustStoreFile;

private String trustStorePassword;

private String keyStoreFile;

private String keyStorePassword;

private boolean sslEnable = false;

}

the yml file will be like this: spring: cloud: etcd: sslEnable: true trustStoreFile: server.keystore trustStorePassword: Changeit

Finally, Launch etcd in this way to enable the https: ./etcd -cert-file=./server.pem -key-file=./server-key.pem -advertise-client-urls=https://127.0.0.1:2379,https://127.0.0.1:4001 -listen-client-urls https://127.0.0.1:2379,https://127.0.0.1:4001

yorksen commented 8 years ago

By the way, why not change the etcd service report port number from 4001 to 2379? the official documents mentioned that the port 4001 is a deprecated port number which assigned from etcd 1.0, when etcd 2.0 came, they use 2379 instead. https://coreos.com/etcd/docs/latest/configuration.html