summaryrefslogtreecommitdiffstats
path: root/vespa-athenz
diff options
context:
space:
mode:
authorMorten Tokle <morten.tokle@gmail.com>2018-10-25 08:59:00 +0200
committerGitHub <noreply@github.com>2018-10-25 08:59:00 +0200
commitd39518cec5b3b0202efbcc8a9a22527136f83a3c (patch)
tree9f5442d90fa63fbd0a4249f11b4f0086a21a48b3 /vespa-athenz
parent9a91a16f12a00eae938b349b44fce589451ed3b2 (diff)
parentd3d43177c8bc9a5a3a376f5eaf2384edcfc7e285 (diff)
Merge pull request #7436 from vespa-engine/bjorncs/athenz-okta-tenancy
Bjorncs/athenz okta tenancy
Diffstat (limited to 'vespa-athenz')
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzResourceGroup.java40
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaAccessToken.java42
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/ClientBase.java95
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/bindings/ErrorResponseEntity.java (renamed from vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/ErrorResponseEntity.java)2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/Pkcs10CsrSerializer.java (renamed from vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/Pkcs10CsrSerializer.java)2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/X509CertificateDeserializer.java (renamed from vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/X509CertificateDeserializer.java)2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/X509CertificateListDeserializer.java (renamed from vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/X509CertificateListDeserializer.java)2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/common/serializers/package-info.java (renamed from vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/serializers/package-info.java)2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java141
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/RoleAction.java49
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClient.java35
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClientException.java32
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/AccessResponseEntity.java19
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/DomainListResponseEntity.java21
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/MembershipResponseEntity.java28
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/ProviderResourceGroupRolesRequestEntity.java56
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/TenancyRequestEntity.java31
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java79
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/IdentityRefreshRequestEntity.java2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/IdentityResponseEntity.java4
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceIdentityCredentials.java2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRefreshInformation.java2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/RoleCertificateRequestEntity.java2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/RoleCertificateResponseEntity.java2
24 files changed, 608 insertions, 84 deletions
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzResourceGroup.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzResourceGroup.java
new file mode 100644
index 00000000000..2825cf57c7b
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzResourceGroup.java
@@ -0,0 +1,40 @@
+// 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.api;
+
+import java.util.Objects;
+
+/**
+ * @author bjorncs
+ */
+public class AthenzResourceGroup {
+ private final String name;
+
+ public AthenzResourceGroup(String name) {
+ this.name = name;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return "AthenzResourceGroup{" +
+ "name='" + name + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ AthenzResourceGroup that = (AthenzResourceGroup) o;
+ return Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+
+}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaAccessToken.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaAccessToken.java
new file mode 100644
index 00000000000..8b19f7abdd5
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaAccessToken.java
@@ -0,0 +1,42 @@
+// 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.api;
+
+import java.util.Objects;
+
+/**
+ * @author bjorncs
+ */
+public class OktaAccessToken {
+
+ public static final String HTTP_HEADER_NAME = "Okta-Access-Token";
+
+ private final String token;
+
+ public OktaAccessToken(String token) {
+ this.token = token;
+ }
+
+ public String token() {
+ return token;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ OktaAccessToken that = (OktaAccessToken) o;
+ return Objects.equals(token, that.token);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(token);
+ }
+
+ @Override
+ public String toString() {
+ return "OktaAccessToken{" +
+ "token='" + token + '\'' +
+ '}';
+ }
+}
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/zms/DefaultZmsClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java
new file mode 100644
index 00000000000..ed9c1da56c2
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java
@@ -0,0 +1,141 @@
+// 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.zms;
+
+import com.yahoo.vespa.athenz.api.AthenzDomain;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.api.AthenzResourceName;
+import com.yahoo.vespa.athenz.api.AthenzRole;
+import com.yahoo.vespa.athenz.api.AthenzService;
+import com.yahoo.vespa.athenz.api.OktaAccessToken;
+import com.yahoo.vespa.athenz.client.common.ClientBase;
+import com.yahoo.vespa.athenz.client.zms.bindings.AccessResponseEntity;
+import com.yahoo.vespa.athenz.client.zms.bindings.DomainListResponseEntity;
+import com.yahoo.vespa.athenz.client.zms.bindings.MembershipResponseEntity;
+import com.yahoo.vespa.athenz.client.zms.bindings.ProviderResourceGroupRolesRequestEntity;
+import com.yahoo.vespa.athenz.client.zms.bindings.TenancyRequestEntity;
+import com.yahoo.vespa.athenz.identity.ServiceIdentityProvider;
+import org.apache.http.Header;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.methods.RequestBuilder;
+import org.apache.http.message.BasicHeader;
+
+import javax.net.ssl.SSLContext;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * @author bjorncs
+ */
+public class DefaultZmsClient extends ClientBase implements ZmsClient {
+
+ private final URI zmsUrl;
+ private final AthenzIdentity identity;
+
+ public DefaultZmsClient(URI zmsUrl, AthenzIdentity identity, SSLContext sslContext) {
+ this(zmsUrl, identity, () -> sslContext);
+ }
+
+ public DefaultZmsClient(URI zmsUrl, ServiceIdentityProvider identityProvider) {
+ this(zmsUrl, identityProvider.identity(), identityProvider::getIdentitySslContext);
+ }
+
+ private DefaultZmsClient(URI zmsUrl, AthenzIdentity identity, Supplier<SSLContext> sslContextSupplier) {
+ super("vespa-zms-client", sslContextSupplier, ZmsClientException::new);
+ this.zmsUrl = addTrailingSlash(zmsUrl);
+ this.identity = identity;
+ }
+
+ private static URI addTrailingSlash(URI zmsUrl) {
+ return zmsUrl.getPath().endsWith("/") ? zmsUrl : URI.create(zmsUrl.toString() + '/');
+ }
+
+ @Override
+ public void createTenancy(AthenzDomain tenantDomain, AthenzService providerService, OktaAccessToken token) {
+ URI uri = zmsUrl.resolve(String.format("domain/%s/tenancy/%s", tenantDomain.getName(), providerService.getFullName()));
+ HttpUriRequest request = RequestBuilder.put()
+ .setUri(uri)
+ .addHeader(creatOktaAccessTokenHeader(token))
+ .setEntity(toJsonStringEntity(new TenancyRequestEntity(tenantDomain, providerService, Collections.emptyList())))
+ .build();
+ execute(request, response -> {
+ readEntity(response, String.class);
+ return response.getStatusLine().getStatusCode();
+ });
+ }
+
+ @Override
+ public void deleteTenancy(AthenzDomain tenantDomain, AthenzService providerService, OktaAccessToken token) {
+ URI uri = zmsUrl.resolve(String.format("domain/%s/tenancy/%s", tenantDomain.getName(), providerService.getFullName()));
+ HttpUriRequest request = RequestBuilder.delete()
+ .setUri(uri)
+ .addHeader(creatOktaAccessTokenHeader(token))
+ .build();
+ execute(request, response -> readEntity(response, String.class));
+ }
+
+ @Override
+ public void createProviderResourceGroup(AthenzDomain tenantDomain, AthenzService providerService, String resourceGroup, Set<RoleAction> roleActions, OktaAccessToken token) {
+ URI uri = zmsUrl.resolve(String.format("domain/%s/provDomain/%s/provService/%s/resourceGroup/%s", tenantDomain.getName(), providerService.getDomainName(), providerService.getName(), resourceGroup));
+ HttpUriRequest request = RequestBuilder.put()
+ .setUri(uri)
+ .addHeader(creatOktaAccessTokenHeader(token))
+ .setEntity(toJsonStringEntity(new ProviderResourceGroupRolesRequestEntity(providerService, tenantDomain, roleActions, resourceGroup)))
+ .build();
+ execute(request, response -> readEntity(response, String.class)); // The ZMS API will return a json object that is similar to ProviderResourceGroupRolesRequestEntity
+ }
+
+ @Override
+ public void deleteProviderResourceGroup(AthenzDomain tenantDomain, AthenzService providerService, String resourceGroup, OktaAccessToken token) {
+ URI uri = zmsUrl.resolve(String.format("domain/%s/provDomain/%s/provService/%s/resourceGroup/%s", tenantDomain.getName(), providerService.getDomainName(), providerService.getName(), resourceGroup));
+ HttpUriRequest request = RequestBuilder.delete()
+ .setUri(uri)
+ .addHeader(creatOktaAccessTokenHeader(token))
+ .build();
+ execute(request, response -> readEntity(response, String.class));
+ }
+
+ @Override
+ public boolean getMembership(AthenzRole role, AthenzIdentity identity) {
+ URI uri = zmsUrl.resolve(String.format("domain/%s/role/%s/member/%s", role.domain().getName(), role.roleName(), identity.getFullName()));
+ HttpUriRequest request = RequestBuilder.get()
+ .setUri(uri)
+ .build();
+ return execute(request, response -> {
+ MembershipResponseEntity membership = readEntity(response, MembershipResponseEntity.class);
+ return membership.isMember;
+ });
+ }
+
+ @Override
+ public List<AthenzDomain> getDomainList(String prefix) {
+ HttpUriRequest request = RequestBuilder.get()
+ .setUri(zmsUrl.resolve("domain"))
+ .addParameter("prefix", prefix)
+ .build();
+ return execute(request, response -> {
+ DomainListResponseEntity result = readEntity(response, DomainListResponseEntity.class);
+ return result.domains.stream().map(AthenzDomain::new).collect(toList());
+ });
+ }
+
+ @Override
+ public boolean hasAccess(AthenzResourceName resource, String action, AthenzIdentity identity) {
+ URI uri = zmsUrl.resolve(String.format("access/%s/%s", action, resource.toResourceNameString()));
+ HttpUriRequest request = RequestBuilder.get()
+ .setUri(uri)
+ .build();
+ return execute(request, response -> {
+ AccessResponseEntity result = readEntity(response, AccessResponseEntity.class);
+ return result.granted;
+ });
+ }
+
+ private static Header creatOktaAccessTokenHeader(OktaAccessToken token) {
+ return new BasicHeader("Cookie", String.format("okta_at=%s", token.token()));
+ }
+}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/RoleAction.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/RoleAction.java
new file mode 100644
index 00000000000..405dd1aa56a
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/RoleAction.java
@@ -0,0 +1,49 @@
+// 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.zms;
+
+import com.yahoo.vespa.athenz.api.AthenzRole;
+
+import java.util.Objects;
+
+/**
+ * @author bjorncs
+ */
+public class RoleAction {
+ private final String roleName;
+ private final String action;
+
+ public RoleAction(String roleName, String action) {
+ this.roleName = roleName;
+ this.action = action;
+ }
+
+ public String getRoleName() {
+ return roleName;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ @Override
+ public String toString() {
+ return "RoleAction{" +
+ "roleName=" + roleName +
+ ", action='" + action + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ RoleAction that = (RoleAction) o;
+ return Objects.equals(roleName, that.roleName) &&
+ Objects.equals(action, that.action);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(roleName, action);
+ }
+}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClient.java
new file mode 100644
index 00000000000..cf044edeac0
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClient.java
@@ -0,0 +1,35 @@
+// 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.zms;
+
+import com.yahoo.vespa.athenz.api.AthenzDomain;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.api.AthenzResourceName;
+import com.yahoo.vespa.athenz.api.AthenzRole;
+import com.yahoo.vespa.athenz.api.AthenzService;
+import com.yahoo.vespa.athenz.api.OktaAccessToken;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author bjorncs
+ */
+public interface ZmsClient extends AutoCloseable {
+
+ void createTenancy(AthenzDomain tenantDomain, AthenzService providerService, OktaAccessToken token);
+
+ void deleteTenancy(AthenzDomain tenantDomain, AthenzService providerService, OktaAccessToken token);
+
+ void createProviderResourceGroup(AthenzDomain tenantDomain, AthenzService providerService, String resourceGroup, Set<RoleAction> roleActions, OktaAccessToken token);
+
+ void deleteProviderResourceGroup(AthenzDomain tenantDomain, AthenzService providerService, String resourceGroup, OktaAccessToken token);
+
+ boolean getMembership(AthenzRole role, AthenzIdentity identity);
+
+ List<AthenzDomain> getDomainList(String prefix);
+
+ boolean hasAccess(AthenzResourceName resource, String action, AthenzIdentity identity);
+
+ void close();
+}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClientException.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClientException.java
new file mode 100644
index 00000000000..f1b3ab8e7da
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClientException.java
@@ -0,0 +1,32 @@
+// 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.zms;
+
+/**
+ * An exception that can be thrown by {@link ZmsClient} implementations.
+ *
+ * @author bjorncs
+ */
+public class ZmsClientException extends RuntimeException {
+
+ private final int errorCode;
+ private final String description;
+
+ public ZmsClientException(int errorCode, String description) {
+ super(createMessage(errorCode, description));
+ this.errorCode = errorCode;
+ this.description = description;
+ }
+
+ public int getErrorCode() {
+ return errorCode;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ private static String createMessage(int code, String description) {
+ return String.format("Received error from ZMS: code=%d, message=\"%s\"", code, description);
+ }
+
+}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/AccessResponseEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/AccessResponseEntity.java
new file mode 100644
index 00000000000..dcc17bc807a
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/AccessResponseEntity.java
@@ -0,0 +1,19 @@
+// 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.zms.bindings;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * @author bjorncs
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class AccessResponseEntity {
+ public final boolean granted;
+
+ @JsonCreator
+ public AccessResponseEntity(@JsonProperty("granted") boolean granted) {
+ this.granted = granted;
+ }
+}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/DomainListResponseEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/DomainListResponseEntity.java
new file mode 100644
index 00000000000..938d85dd74f
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/DomainListResponseEntity.java
@@ -0,0 +1,21 @@
+// 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.zms.bindings;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+/**
+ * @author bjorncs
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class DomainListResponseEntity {
+ public final List<String> domains;
+
+ @JsonCreator
+ public DomainListResponseEntity(@JsonProperty("names") List<String> domains) {
+ this.domains = domains;
+ }
+}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/MembershipResponseEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/MembershipResponseEntity.java
new file mode 100644
index 00000000000..499afb48f25
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/MembershipResponseEntity.java
@@ -0,0 +1,28 @@
+// 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.zms.bindings;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * @author bjorncs
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class MembershipResponseEntity {
+ public final String memberName;
+ public final boolean isMember;
+ public final String roleName;
+ public final String expiration;
+
+ @JsonCreator
+ public MembershipResponseEntity(@JsonProperty("memberName") String memberName,
+ @JsonProperty("isMember") boolean isMember,
+ @JsonProperty("roleName") String roleName,
+ @JsonProperty("expiration") String expiration) {
+ this.memberName = memberName;
+ this.isMember = isMember;
+ this.roleName = roleName;
+ this.expiration = expiration;
+ }
+}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/ProviderResourceGroupRolesRequestEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/ProviderResourceGroupRolesRequestEntity.java
new file mode 100644
index 00000000000..dccd18fed61
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/ProviderResourceGroupRolesRequestEntity.java
@@ -0,0 +1,56 @@
+// 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.zms.bindings;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.yahoo.vespa.athenz.api.AthenzDomain;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.api.AthenzService;
+import com.yahoo.vespa.athenz.client.zms.RoleAction;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * @author bjorncs
+ */
+public class ProviderResourceGroupRolesRequestEntity {
+
+ @JsonProperty("domain")
+ private final String domain;
+
+ @JsonProperty("service")
+ private final String service;
+
+ @JsonProperty("tenant")
+ private final String tenant;
+
+ @JsonProperty("roles")
+ private final List<TenantRoleAction> roles;
+
+ @JsonProperty("resourceGroup")
+ private final String resourceGroup;
+
+ public ProviderResourceGroupRolesRequestEntity(AthenzService providerService, AthenzDomain tenantDomain, Set<RoleAction> rolesActions, String resourceGroup) {
+ this.domain = providerService.getDomainName();
+ this.service = providerService.getName();
+ this.tenant = tenantDomain.getName();
+ this.roles = rolesActions.stream().map(roleAction -> new TenantRoleAction(roleAction.getRoleName(), roleAction.getAction())).collect(toList());
+ this.resourceGroup = resourceGroup;
+ }
+
+ public static class TenantRoleAction {
+ @JsonProperty("role")
+ private final String role;
+
+ @JsonProperty("action")
+ private final String action;
+
+ public TenantRoleAction(String role, String action) {
+ this.role = role;
+ this.action = action;
+ }
+ }
+}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/TenancyRequestEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/TenancyRequestEntity.java
new file mode 100644
index 00000000000..7883a505c71
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/TenancyRequestEntity.java
@@ -0,0 +1,31 @@
+// 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.zms.bindings;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.yahoo.vespa.athenz.api.AthenzDomain;
+import com.yahoo.vespa.athenz.api.AthenzService;
+
+import java.util.List;
+
+/**
+ * @author bjorncs
+ */
+public class TenancyRequestEntity {
+
+ @JsonProperty("domain")
+ private final String tenantDomain;
+
+ @JsonProperty("service")
+ private final String providerService;
+
+ @JsonProperty("resourceGroups")
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ private final List<String> resourceGroups;
+
+ public TenancyRequestEntity(AthenzDomain tenantDomain, AthenzService providerService, List<String> resourceGroups) {
+ this.tenantDomain = tenantDomain.getName();
+ this.providerService = providerService.getFullName();
+ this.resourceGroups = resourceGroups;
+ }
+}
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;