summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorValerij Fredriksen <valerijf@oath.com>2018-01-23 09:45:22 +0100
committerValerij Fredriksen <valerijf@oath.com>2018-01-23 09:51:34 +0100
commit522ed8a6a042e6ebae19af7047bce26739b03315 (patch)
treed3535534eadfe25d2737ee87818255401129f85c
parent193dcf4fdfdb0501cfe0e7d7198180185db1192f (diff)
Add node-admin hostname verifier
-rw-r--r--node-admin/pom.xml6
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/DockerAdminComponent.java6
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/util/ConfigServerHttpRequestExecutor.java25
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/util/Environment.java29
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java2
5 files changed, 57 insertions, 11 deletions
diff --git a/node-admin/pom.xml b/node-admin/pom.xml
index 7b3b787b503..a982a192b51 100644
--- a/node-admin/pom.xml
+++ b/node-admin/pom.xml
@@ -86,6 +86,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>vespa-athenz</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
<dependency>
<groupId>org.hamcrest</groupId>
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/DockerAdminComponent.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/DockerAdminComponent.java
index db0313583db..0450229eae6 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/DockerAdminComponent.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/DockerAdminComponent.java
@@ -64,7 +64,11 @@ public class DockerAdminComponent implements AdminComponent {
Environment environment = new Environment(configServerConfig);
requestExecutor = ConfigServerHttpRequestExecutor.create(
- environment.getConfigServerUris(), environment.getKeyStoreOptions(), environment.getTrustStoreOptions());
+ environment.getConfigServerUris(),
+ environment.getKeyStoreOptions(),
+ environment.getTrustStoreOptions(),
+ environment.getAthenzIdentity());
+
NodeRepository nodeRepository = new NodeRepositoryImpl(requestExecutor);
Orchestrator orchestrator = new OrchestratorImpl(requestExecutor);
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/util/ConfigServerHttpRequestExecutor.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/util/ConfigServerHttpRequestExecutor.java
index 954de4b271a..010fd99f124 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/util/ConfigServerHttpRequestExecutor.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/util/ConfigServerHttpRequestExecutor.java
@@ -4,6 +4,8 @@ package com.yahoo.vespa.hosted.node.admin.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yahoo.concurrent.ThreadFactoryFactory;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.tls.AthenzIdentityVerifier;
import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
@@ -13,11 +15,11 @@ import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.ssl.SSLContextBuilder;
+import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -61,8 +63,11 @@ public class ConfigServerHttpRequestExecutor implements AutoCloseable {
private volatile SelfCloseableHttpClient client;
public static ConfigServerHttpRequestExecutor create(
- Collection<URI> configServerUris, Optional<KeyStoreOptions> keyStoreOptions, Optional<KeyStoreOptions> trustStoreOptions) {
- Supplier<SelfCloseableHttpClient> clientSupplier = () -> createHttpClient(keyStoreOptions, trustStoreOptions);
+ Collection<URI> configServerUris,
+ Optional<KeyStoreOptions> keyStoreOptions,
+ Optional<KeyStoreOptions> trustStoreOptions,
+ Optional<AthenzIdentity> athenzIdentity) {
+ Supplier<SelfCloseableHttpClient> clientSupplier = () -> createHttpClient(keyStoreOptions, trustStoreOptions, athenzIdentity);
ConfigServerHttpRequestExecutor requestExecutor = new ConfigServerHttpRequestExecutor(
randomizeConfigServerUris(configServerUris), clientSupplier.get());
@@ -178,11 +183,13 @@ public class ConfigServerHttpRequestExecutor implements AutoCloseable {
}
private static SelfCloseableHttpClient createHttpClient(Optional<KeyStoreOptions> keyStoreOptions,
- Optional<KeyStoreOptions> trustStoreOptions) {
+ Optional<KeyStoreOptions> trustStoreOptions,
+ Optional<AthenzIdentity> athenzIdentity) {
NODE_ADMIN_LOGGER.info("Creating new HTTP client");
try {
- SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
- makeSslContext(keyStoreOptions, trustStoreOptions), NoopHostnameVerifier.INSTANCE);
+ SSLContext sslContext = makeSslContext(keyStoreOptions, trustStoreOptions);
+ HostnameVerifier hostnameVerifier = makeHostnameVerifier(athenzIdentity);
+ SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
return new SelfCloseableHttpClient(sslSocketFactory);
} catch (Exception e) {
NODE_ADMIN_LOGGER.error("Failed to create HTTP client with custom SSL Context, proceeding with default", e);
@@ -212,6 +219,12 @@ public class ConfigServerHttpRequestExecutor implements AutoCloseable {
return sslContextBuilder.build();
}
+ private static HostnameVerifier makeHostnameVerifier(Optional<AthenzIdentity> athenzIdentity) {
+ return athenzIdentity
+ .map(identity -> (HostnameVerifier) new AthenzIdentityVerifier(Collections.singleton(identity)))
+ .orElse(SSLConnectionSocketFactory.getDefaultHostnameVerifier());
+ }
+
@Override
public void close() {
clientRefresherScheduler.shutdown();
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/util/Environment.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/util/Environment.java
index 72996e438b7..d4e790b941e 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/util/Environment.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/util/Environment.java
@@ -2,6 +2,8 @@
package com.yahoo.vespa.hosted.node.admin.util;
import com.google.common.base.Strings;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.defaults.Defaults;
import com.yahoo.vespa.hosted.dockerapi.ContainerName;
import com.yahoo.vespa.hosted.node.admin.ConfigServerConfig;
@@ -47,6 +49,7 @@ public class Environment {
private final String feedEndpoint;
private final Optional<KeyStoreOptions> keyStoreOptions;
private final Optional<KeyStoreOptions> trustStoreOptions;
+ private final Optional<AthenzIdentity> athenzIdentity;
static {
filenameFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
@@ -73,7 +76,10 @@ public class Environment {
createKeyStoreOptions(
configServerConfig.trustStoreConfig().path(),
configServerConfig.trustStoreConfig().password().toCharArray(),
- configServerConfig.trustStoreConfig().type().name())
+ configServerConfig.trustStoreConfig().type().name()),
+ createAthenzIdentity(
+ configServerConfig.athenzDomain(),
+ configServerConfig.serviceName())
);
}
@@ -86,7 +92,8 @@ public class Environment {
List<String> logstashNodes,
String feedEndpoint,
Optional<KeyStoreOptions> keyStoreOptions,
- Optional<KeyStoreOptions> trustStoreOptions) {
+ Optional<KeyStoreOptions> trustStoreOptions,
+ Optional<AthenzIdentity> athenzIdentity) {
this.configServerHosts = configServerHosts;
this.environment = environment;
this.region = region;
@@ -97,6 +104,7 @@ public class Environment {
this.feedEndpoint = feedEndpoint;
this.keyStoreOptions = keyStoreOptions;
this.trustStoreOptions = trustStoreOptions;
+ this.athenzIdentity = athenzIdentity;
}
public List<URI> getConfigServerUris() { return configServerHosts; }
@@ -145,6 +153,11 @@ public class Environment {
.map(path -> new KeyStoreOptions(Paths.get(path), password, type));
}
+ private static Optional<AthenzIdentity> createAthenzIdentity(String athenzDomain, String serviceName) {
+ if (Strings.isNullOrEmpty(athenzDomain) || Strings.isNullOrEmpty(serviceName)) return Optional.empty();
+ return Optional.of(new AthenzService(athenzDomain, serviceName));
+ }
+
public InetAddress getInetAddressForHost(String hostname) throws UnknownHostException {
return inetAddressResolver.getInetAddressForHost(hostname);
}
@@ -219,6 +232,10 @@ public class Environment {
return trustStoreOptions;
}
+ public Optional<AthenzIdentity> getAthenzIdentity() {
+ return athenzIdentity;
+ }
+
public static class Builder {
private List<URI> configServerHosts = Collections.emptyList();
@@ -231,6 +248,7 @@ public class Environment {
private String feedEndpoint;
private KeyStoreOptions keyStoreOptions;
private KeyStoreOptions trustStoreOptions;
+ private AthenzIdentity athenzIdentity;
public Builder configServerUris(String... hosts) {
configServerHosts = Arrays.stream(hosts)
@@ -284,11 +302,16 @@ public class Environment {
return this;
}
+ public Builder athenzIdentity(AthenzIdentity athenzIdentity) {
+ this.athenzIdentity = athenzIdentity;
+ return this;
+ }
public Environment build() {
return new Environment(configServerHosts, environment, region, parentHostHostname, inetAddressResolver,
pathResolver, logstashNodes, feedEndpoint,
- Optional.ofNullable(keyStoreOptions), Optional.ofNullable(trustStoreOptions));
+ Optional.ofNullable(keyStoreOptions), Optional.ofNullable(trustStoreOptions),
+ Optional.ofNullable(athenzIdentity));
}
}
}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java
index c6e4447a606..85d92dbee25 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java
@@ -57,7 +57,7 @@ public class NodeRepositoryImplTest {
public void startContainer() throws Exception {
final int port = findRandomOpenPort();
requestExecutor = ConfigServerHttpRequestExecutor.create(
- Collections.singleton(URI.create("http://127.0.0.1:" + port)), Optional.empty(), Optional.empty());
+ Collections.singleton(URI.create("http://127.0.0.1:" + port)), Optional.empty(), Optional.empty(), Optional.empty());
container = JDisc.fromServicesXml(ContainerConfig.servicesXmlV2(port), Networking.enable);
}