diff options
author | Bjørn Christian Seime <bjorncs@oath.com> | 2018-10-19 11:04:23 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@oath.com> | 2018-10-24 13:32:38 +0200 |
commit | 6553a6949824fdfd61913732824d77d47904dbad (patch) | |
tree | aa4230b83b408a460df8d2adf738d2c58f3a0ead /vespa-athenz | |
parent | 74cc0cc3bf2489bba14929cd056759042d340fd7 (diff) |
Create ClientBase containing common Athenz client logic
Diffstat (limited to 'vespa-athenz')
13 files changed, 114 insertions, 84 deletions
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/ClientBase.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/ClientBase.java new file mode 100644 index 00000000000..02952d7c26b --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/ClientBase.java @@ -0,0 +1,95 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.client.common; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.yahoo.vespa.athenz.client.common.bindings.ErrorResponseEntity; +import com.yahoo.vespa.athenz.identity.ServiceIdentitySslSocketFactory; +import org.apache.http.HttpResponse; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; +import org.apache.http.impl.client.HttpClientBuilder; +import org.eclipse.jetty.http.HttpStatus; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.time.Duration; +import java.util.function.Supplier; + +/** + * @author bjorncs + */ +public abstract class ClientBase implements AutoCloseable { + + private static final ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule()); + + private final CloseableHttpClient client; + private final ClientExceptionFactory exceptionFactory; + + protected ClientBase(String userAgent, + Supplier<SSLContext> sslContextSupplier, + ClientExceptionFactory exceptionFactory) { + this.exceptionFactory = exceptionFactory; + this.client = createHttpClient(userAgent, sslContextSupplier); + } + + protected <T> T execute(HttpUriRequest request, ResponseHandler<T> responseHandler) { + try { + return client.execute(request, responseHandler); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + protected StringEntity toJsonStringEntity(Object entity) { + try { + return new StringEntity(objectMapper.writeValueAsString(entity), ContentType.APPLICATION_JSON); + } catch (JsonProcessingException e) { + throw new UncheckedIOException(e); + } + } + + protected <T> T readEntity(HttpResponse response, Class<T> entityType) throws IOException { + if (HttpStatus.isSuccess(response.getStatusLine().getStatusCode())) { + return objectMapper.readValue(response.getEntity().getContent(), entityType); + } else { + ErrorResponseEntity errorEntity = objectMapper.readValue(response.getEntity().getContent(), ErrorResponseEntity.class); + throw exceptionFactory.createException(errorEntity.code, errorEntity.description); + } + } + + private static CloseableHttpClient createHttpClient(String userAgent, Supplier<SSLContext> sslContextSupplier) { + return HttpClientBuilder.create() + .setRetryHandler(new DefaultHttpRequestRetryHandler(3, /*requestSentRetryEnabled*/true)) + .setUserAgent(userAgent) + .setSSLSocketFactory(new SSLConnectionSocketFactory(new ServiceIdentitySslSocketFactory(sslContextSupplier), (HostnameVerifier)null)) + .setDefaultRequestConfig(RequestConfig.custom() + .setConnectTimeout((int) Duration.ofSeconds(10).toMillis()) + .setConnectionRequestTimeout((int)Duration.ofSeconds(10).toMillis()) + .setSocketTimeout((int)Duration.ofSeconds(20).toMillis()) + .build()) + .build(); + } + + @Override + public void close() { + try { + this.client.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + protected interface ClientExceptionFactory { + RuntimeException createException(int errorCode, String description); + } +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/ErrorResponseEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/bindings/ErrorResponseEntity.java index 431af084f9f..acbb831194e 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/ErrorResponseEntity.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/bindings/ErrorResponseEntity.java @@ -1,5 +1,5 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.athenz.client.zts.bindings; +package com.yahoo.vespa.athenz.client.common.bindings; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/Pkcs10CsrSerializer.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/Pkcs10CsrSerializer.java index ca33962c7c8..9b26f5f2517 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/Pkcs10CsrSerializer.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/Pkcs10CsrSerializer.java @@ -1,5 +1,5 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.athenz.client.zts.bindings.serializers; +package com.yahoo.vespa.athenz.client.common.serializers; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/X509CertificateDeserializer.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/X509CertificateDeserializer.java index 59f10a78a58..f948115d4f2 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/X509CertificateDeserializer.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/X509CertificateDeserializer.java @@ -1,5 +1,5 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.athenz.client.zts.bindings.serializers; +package com.yahoo.vespa.athenz.client.common.serializers; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/X509CertificateListDeserializer.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/X509CertificateListDeserializer.java index 64b23af9295..baa56512a62 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/X509CertificateListDeserializer.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/X509CertificateListDeserializer.java @@ -1,5 +1,5 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.athenz.client.zts.bindings.serializers; +package com.yahoo.vespa.athenz.client.common.serializers; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/package-info.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/package-info.java index 4c442617494..f1fe2a75b1b 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/package-info.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/package-info.java @@ -3,6 +3,6 @@ * @author bjorncs */ @ExportPackage -package com.yahoo.vespa.athenz.client.zts.bindings.serializers; +package com.yahoo.vespa.athenz.client.common.serializers; import com.yahoo.osgi.annotation.ExportPackage;
\ No newline at end of file diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java index e9aba31cf56..9eef2ff9903 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java @@ -1,16 +1,13 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.athenz.client.zts; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.yahoo.vespa.athenz.api.AthenzDomain; import com.yahoo.vespa.athenz.api.AthenzIdentity; import com.yahoo.vespa.athenz.api.AthenzRole; import com.yahoo.vespa.athenz.api.AthenzService; import com.yahoo.vespa.athenz.api.NToken; import com.yahoo.vespa.athenz.api.ZToken; -import com.yahoo.vespa.athenz.client.zts.bindings.ErrorResponseEntity; +import com.yahoo.vespa.athenz.client.common.ClientBase; import com.yahoo.vespa.athenz.client.zts.bindings.IdentityRefreshRequestEntity; import com.yahoo.vespa.athenz.client.zts.bindings.IdentityResponseEntity; import com.yahoo.vespa.athenz.client.zts.bindings.InstanceIdentityCredentials; @@ -22,25 +19,13 @@ import com.yahoo.vespa.athenz.client.zts.bindings.RoleTokenResponseEntity; import com.yahoo.vespa.athenz.client.zts.bindings.TenantDomainsResponseEntity; import com.yahoo.vespa.athenz.client.zts.utils.IdentityCsrGenerator; import com.yahoo.vespa.athenz.identity.ServiceIdentityProvider; -import com.yahoo.vespa.athenz.identity.ServiceIdentitySslSocketFactory; import com.yahoo.security.Pkcs10Csr; import org.apache.http.HttpResponse; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; -import org.apache.http.impl.client.HttpClientBuilder; -import org.eclipse.jetty.http.HttpStatus; - -import javax.net.ssl.HostnameVerifier; + import javax.net.ssl.SSLContext; import java.io.IOException; -import java.io.UncheckedIOException; import java.net.URI; import java.security.KeyPair; import java.security.cert.X509Certificate; @@ -56,12 +41,9 @@ import static java.util.stream.Collectors.toList; * @author bjorncs * @author mortent */ -public class DefaultZtsClient implements ZtsClient { - - private static final ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule()); +public class DefaultZtsClient extends ClientBase implements ZtsClient { private final URI ztsUrl; - private final CloseableHttpClient client; private final AthenzIdentity identity; public DefaultZtsClient(URI ztsUrl, AthenzIdentity identity, SSLContext sslContext) { @@ -73,9 +55,9 @@ public class DefaultZtsClient implements ZtsClient { } private DefaultZtsClient(URI ztsUrl, AthenzIdentity identity, Supplier<SSLContext> sslContextSupplier) { + super("vespa-zts-client", sslContextSupplier, ZtsClientException::new); this.ztsUrl = addTrailingSlash(ztsUrl); this.identity = identity; - this.client = createHttpClient(sslContextSupplier); } @Override @@ -91,7 +73,7 @@ public class DefaultZtsClient implements ZtsClient { .setUri(ztsUrl.resolve("instance/")) .setEntity(toJsonStringEntity(payload)) .build(); - return execute(request, DefaultZtsClient::getInstanceIdentity); + return execute(request, this::getInstanceIdentity); } @Override @@ -111,7 +93,7 @@ public class DefaultZtsClient implements ZtsClient { .setUri(uri) .setEntity(toJsonStringEntity(payload)) .build(); - return execute(request, DefaultZtsClient::getInstanceIdentity); + return execute(request, this::getInstanceIdentity); } @Override @@ -189,30 +171,13 @@ public class DefaultZtsClient implements ZtsClient { }); } - private <T> T execute(HttpUriRequest request, ResponseHandler<T> responseHandler) { - try { - return client.execute(request, responseHandler); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private static InstanceIdentity getInstanceIdentity(HttpResponse response) throws IOException { + private InstanceIdentity getInstanceIdentity(HttpResponse response) throws IOException { InstanceIdentityCredentials entity = readEntity(response, InstanceIdentityCredentials.class); return entity.getServiceToken() != null ? new InstanceIdentity(entity.getX509Certificate(), new NToken(entity.getServiceToken())) : new InstanceIdentity(entity.getX509Certificate()); } - private static <T> T readEntity(HttpResponse response, Class<T> entityType) throws IOException { - if (HttpStatus.isSuccess(response.getStatusLine().getStatusCode())) { - return objectMapper.readValue(response.getEntity().getContent(), entityType); - } else { - ErrorResponseEntity errorEntity = objectMapper.readValue(response.getEntity().getContent(), ErrorResponseEntity.class); - throw new ZtsClientException(errorEntity.code, errorEntity.description); - } - } - private static URI addTrailingSlash(URI ztsUrl) { if (ztsUrl.getPath().endsWith("/")) return ztsUrl; @@ -220,34 +185,4 @@ public class DefaultZtsClient implements ZtsClient { return URI.create(ztsUrl.toString() + '/'); } - private static StringEntity toJsonStringEntity(Object entity) { - try { - return new StringEntity(objectMapper.writeValueAsString(entity), ContentType.APPLICATION_JSON); - } catch (JsonProcessingException e) { - throw new UncheckedIOException(e); - } - } - - private static CloseableHttpClient createHttpClient(Supplier<SSLContext> sslContextSupplier) { - return HttpClientBuilder.create() - .setRetryHandler(new DefaultHttpRequestRetryHandler(3, /*requestSentRetryEnabled*/true)) - .setUserAgent("vespa-zts-client") - .setSSLSocketFactory(new SSLConnectionSocketFactory(new ServiceIdentitySslSocketFactory(sslContextSupplier), (HostnameVerifier)null)) - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectTimeout((int)Duration.ofSeconds(10).toMillis()) - .setConnectionRequestTimeout((int)Duration.ofSeconds(10).toMillis()) - .setSocketTimeout((int)Duration.ofSeconds(20).toMillis()) - .build()) - .build(); - } - - @Override - public void close() { - try { - this.client.close(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - } diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/IdentityRefreshRequestEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/IdentityRefreshRequestEntity.java index 808c1162ef1..0704fef2ae3 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/IdentityRefreshRequestEntity.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/IdentityRefreshRequestEntity.java @@ -3,7 +3,7 @@ package com.yahoo.vespa.athenz.client.zts.bindings; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.yahoo.vespa.athenz.client.zts.bindings.serializers.Pkcs10CsrSerializer; +import com.yahoo.vespa.athenz.client.common.serializers.Pkcs10CsrSerializer; import com.yahoo.security.Pkcs10Csr; /** diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/IdentityResponseEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/IdentityResponseEntity.java index 7bd04362599..f36858ef7b8 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/IdentityResponseEntity.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/IdentityResponseEntity.java @@ -5,8 +5,8 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.yahoo.vespa.athenz.client.zts.bindings.serializers.X509CertificateDeserializer; -import com.yahoo.vespa.athenz.client.zts.bindings.serializers.X509CertificateListDeserializer; +import com.yahoo.vespa.athenz.client.common.serializers.X509CertificateDeserializer; +import com.yahoo.vespa.athenz.client.common.serializers.X509CertificateListDeserializer; import java.security.cert.X509Certificate; import java.util.List; diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceIdentityCredentials.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceIdentityCredentials.java index 0ab697a1c4c..b9baba85ea1 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceIdentityCredentials.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceIdentityCredentials.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.yahoo.vespa.athenz.client.zts.bindings.serializers.X509CertificateDeserializer; +import com.yahoo.vespa.athenz.client.common.serializers.X509CertificateDeserializer; import java.security.cert.X509Certificate; diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRefreshInformation.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRefreshInformation.java index 0e7e94e96ac..fee91dbc15b 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRefreshInformation.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRefreshInformation.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.yahoo.vespa.athenz.client.zts.bindings.serializers.Pkcs10CsrSerializer; +import com.yahoo.vespa.athenz.client.common.serializers.Pkcs10CsrSerializer; import com.yahoo.security.Pkcs10Csr; /** diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/RoleCertificateRequestEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/RoleCertificateRequestEntity.java index 1b974bcc6fc..89bfce91154 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/RoleCertificateRequestEntity.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/RoleCertificateRequestEntity.java @@ -8,7 +8,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.yahoo.vespa.athenz.client.zts.bindings.serializers.Pkcs10CsrSerializer; +import com.yahoo.vespa.athenz.client.common.serializers.Pkcs10CsrSerializer; import com.yahoo.security.Pkcs10Csr; import java.io.IOException; diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/RoleCertificateResponseEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/RoleCertificateResponseEntity.java index e80f5626843..857bfad9143 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/RoleCertificateResponseEntity.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/RoleCertificateResponseEntity.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.yahoo.vespa.athenz.client.zts.bindings.serializers.X509CertificateDeserializer; +import com.yahoo.vespa.athenz.client.common.serializers.X509CertificateDeserializer; import java.security.cert.X509Certificate; import java.time.Instant; |