summaryrefslogtreecommitdiffstats
path: root/vespa-athenz
diff options
context:
space:
mode:
authorMorten Tokle <morten.tokle@gmail.com>2018-06-12 11:17:36 +0200
committerGitHub <noreply@github.com>2018-06-12 11:17:36 +0200
commit06d3ba8c9e0edea16dafce70c13280330c4ab59f (patch)
tree1e52c89b325d180a51d74f071b7954c2427766d2 /vespa-athenz
parente6c99e57f297c4ca1861b436eecb51e406644627 (diff)
parent3430573724c0b9281c75298c4a6a3e976f6ed5cb (diff)
Merge pull request #5991 from vespa-engine/bjorncs/aws-ready-identity-provider
Bjorncs/aws ready identity provider
Diffstat (limited to 'vespa-athenz')
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java2
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java108
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java28
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentClient.java83
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceIdentity.java49
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceRefreshInformation.java23
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceRegisterInformation.java38
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/ZtsClient.java87
-rw-r--r--vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImplTest.java81
10 files changed, 101 insertions, 400 deletions
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java
index 270954c73b2..43378b6507a 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java
@@ -26,7 +26,7 @@ public interface ZtsClient extends AutoCloseable {
*/
InstanceIdentity registerInstance(AthenzService providerIdentity,
AthenzService instanceIdentity,
- String instanceId,
+ String instanceId, // TODO Remove this parameter (unused/unnecessary)
String attestationData,
boolean requestServiceToken,
Pkcs10Csr csr);
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java
index 60be42544c7..7c64d048944 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java
@@ -74,6 +74,7 @@ public class SignedIdentityDocument {
return providerUniqueId;
}
+ @Deprecated
public String dnsSuffix() {
return dnsSuffix;
}
@@ -82,6 +83,7 @@ public class SignedIdentityDocument {
return providerService;
}
+ @Deprecated
public URI ztsEndpoint() {
return ztsEndpoint;
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java
index e8ef2d9f97e..1136106ce19 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java
@@ -1,97 +1,105 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// 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.identityprovider.client;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.yahoo.container.core.identity.IdentityConfig;
import com.yahoo.vespa.athenz.api.AthenzService;
+import com.yahoo.vespa.athenz.client.zts.DefaultZtsClient;
+import com.yahoo.vespa.athenz.client.zts.InstanceIdentity;
+import com.yahoo.vespa.athenz.identity.ServiceIdentityProvider;
import com.yahoo.vespa.athenz.identityprovider.api.EntityBindingsMapper;
+import com.yahoo.vespa.athenz.identityprovider.api.IdentityDocumentClient;
import com.yahoo.vespa.athenz.identityprovider.api.SignedIdentityDocument;
-import com.yahoo.vespa.athenz.identityprovider.api.bindings.SignedIdentityDocumentEntity;
+import com.yahoo.vespa.athenz.tls.AthenzIdentityVerifier;
import com.yahoo.vespa.athenz.tls.KeyAlgorithm;
import com.yahoo.vespa.athenz.tls.KeyUtils;
import com.yahoo.vespa.athenz.tls.Pkcs10Csr;
-import com.yahoo.vespa.athenz.tls.Pkcs10CsrUtils;
import com.yahoo.vespa.athenz.tls.SslContextBuilder;
import javax.net.ssl.SSLContext;
import java.io.File;
-import java.io.IOException;
-import java.io.UncheckedIOException;
+import java.net.URI;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import static com.yahoo.vespa.athenz.tls.KeyStoreType.JKS;
+import static java.util.Collections.singleton;
/**
+ * A service that provides method for initially registering the instance and refreshing it.
+ *
* @author bjorncs
*/
class AthenzCredentialsService {
-
- private static final ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
-
private final IdentityConfig identityConfig;
- private final IdentityDocumentClient identityDocumentClient;
- private final ZtsClient ztsClient;
+ private final ServiceIdentityProvider nodeIdentityProvider;
private final File trustStoreJks;
+ private final String hostname;
+ private final InstanceCsrGenerator instanceCsrGenerator;
AthenzCredentialsService(IdentityConfig identityConfig,
- IdentityDocumentClient identityDocumentClient,
- ZtsClient ztsClient,
- File trustStoreJks) {
+ ServiceIdentityProvider nodeIdentityProvider,
+ File trustStoreJks,
+ String hostname) {
this.identityConfig = identityConfig;
- this.identityDocumentClient = identityDocumentClient;
- this.ztsClient = ztsClient;
+ this.nodeIdentityProvider = nodeIdentityProvider;
this.trustStoreJks = trustStoreJks;
+ this.hostname = hostname;
+ this.instanceCsrGenerator = new InstanceCsrGenerator(identityConfig.athenzDnsSuffix());
}
AthenzCredentials registerInstance() {
KeyPair keyPair = KeyUtils.generateKeypair(KeyAlgorithm.RSA);
- String rawDocument = identityDocumentClient.getSignedIdentityDocument();
- SignedIdentityDocument document = parseSignedIdentityDocument(rawDocument);
- InstanceCsrGenerator instanceCsrGenerator = new InstanceCsrGenerator(document.dnsSuffix());
+ IdentityDocumentClient identityDocumentClient = createIdentityDocumentClient(identityConfig, nodeIdentityProvider);
+ SignedIdentityDocument document = identityDocumentClient.getTenantIdentityDocument(hostname);
+ AthenzService tenantIdentity = new AthenzService(identityConfig.domain(), identityConfig.service());
Pkcs10Csr csr = instanceCsrGenerator.generateCsr(
- new AthenzService(identityConfig.domain(), identityConfig.service()),
+ tenantIdentity,
document.providerUniqueId(),
document.identityDocument().ipAddresses(),
keyPair);
- InstanceRegisterInformation instanceRegisterInformation =
- new InstanceRegisterInformation(document.providerService().getFullName(),
- identityConfig.domain(),
- identityConfig.service(),
- rawDocument,
- Pkcs10CsrUtils.toPem(csr));
- InstanceIdentity instanceIdentity = ztsClient.sendInstanceRegisterRequest(instanceRegisterInformation,
- document.ztsEndpoint());
- return toAthenzCredentials(instanceIdentity, keyPair, document);
+
+ try (com.yahoo.vespa.athenz.client.zts.ZtsClient ztsClient =
+ new DefaultZtsClient(URI.create(identityConfig.ztsUrl()), nodeIdentityProvider)) {
+ InstanceIdentity instanceIdentity =
+ ztsClient.registerInstance(
+ new AthenzService(identityConfig.configserverIdentityName()),
+ tenantIdentity,
+ null,
+ EntityBindingsMapper.toAttestationData(document),
+ true,
+ csr);
+ return toAthenzCredentials(instanceIdentity, keyPair, document);
+ }
}
AthenzCredentials updateCredentials(SignedIdentityDocument document, SSLContext sslContext) {
+ AthenzService tenantIdentity = new AthenzService(identityConfig.domain(), identityConfig.service());
KeyPair newKeyPair = KeyUtils.generateKeypair(KeyAlgorithm.RSA);
- InstanceCsrGenerator instanceCsrGenerator = new InstanceCsrGenerator(document.dnsSuffix());
Pkcs10Csr csr = instanceCsrGenerator.generateCsr(
- new AthenzService(identityConfig.domain(), identityConfig.service()),
+ tenantIdentity,
document.providerUniqueId(),
document.identityDocument().ipAddresses(),
newKeyPair);
- InstanceRefreshInformation refreshInfo = new InstanceRefreshInformation(Pkcs10CsrUtils.toPem(csr));
- InstanceIdentity instanceIdentity =
- ztsClient.sendInstanceRefreshRequest(document.providerService().getFullName(),
- identityConfig.domain(),
- identityConfig.service(),
- document.providerUniqueId().asDottedString(),
- refreshInfo,
- document.ztsEndpoint(),
- sslContext);
- return toAthenzCredentials(instanceIdentity, newKeyPair, document);
+
+ try (com.yahoo.vespa.athenz.client.zts.ZtsClient ztsClient =
+ new DefaultZtsClient(URI.create(identityConfig.ztsUrl()), tenantIdentity, sslContext)) {
+ InstanceIdentity instanceIdentity =
+ ztsClient.refreshInstance(
+ new AthenzService(identityConfig.configserverIdentityName()),
+ tenantIdentity,
+ document.providerUniqueId().asDottedString(),
+ true,
+ csr);
+ return toAthenzCredentials(instanceIdentity, newKeyPair, document);
+ }
}
private AthenzCredentials toAthenzCredentials(InstanceIdentity instanceIdentity,
KeyPair keyPair,
SignedIdentityDocument identityDocument) {
- X509Certificate certificate = instanceIdentity.getX509Certificate();
- String serviceToken = instanceIdentity.getServiceToken();
+ X509Certificate certificate = instanceIdentity.certificate();
+ String serviceToken = instanceIdentity.nToken().get().getRawToken();
SSLContext identitySslContext = createIdentitySslContext(keyPair.getPrivate(), certificate);
return new AthenzCredentials(serviceToken, certificate, keyPair, identityDocument, identitySslContext);
}
@@ -103,11 +111,11 @@ class AthenzCredentialsService {
.build();
}
- private static SignedIdentityDocument parseSignedIdentityDocument(String rawDocument) {
- try {
- return EntityBindingsMapper.toSignedIdentityDocument(mapper.readValue(rawDocument, SignedIdentityDocumentEntity.class));
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ private static DefaultIdentityDocumentClient createIdentityDocumentClient(IdentityConfig config,
+ ServiceIdentityProvider nodeIdentityProvider) {
+ return new DefaultIdentityDocumentClient(
+ URI.create(config.loadBalancerAddress()),
+ nodeIdentityProvider,
+ new AthenzIdentityVerifier(singleton(new AthenzService(config.configserverIdentityName()))));
}
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java
index 813941ac9b2..ce0743021ff 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImpl.java
@@ -16,12 +16,15 @@ import com.yahoo.vespa.athenz.api.AthenzRole;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.identity.ServiceIdentityProvider;
import com.yahoo.vespa.athenz.identity.ServiceIdentityProviderListenerHelper;
+import com.yahoo.vespa.athenz.identity.SiaIdentityProvider;
import com.yahoo.vespa.athenz.tls.KeyStoreType;
import com.yahoo.vespa.athenz.tls.SslContextBuilder;
+import com.yahoo.vespa.athenz.utils.SiaUtils;
import com.yahoo.vespa.defaults.Defaults;
import javax.net.ssl.SSLContext;
import java.io.File;
+import java.net.URI;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.time.Clock;
@@ -55,24 +58,26 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
private final Clock clock;
private final AthenzService identity;
private final ServiceIdentityProviderListenerHelper listenerHelper;
+ private final String dnsSuffix;
+ private final URI ztsEndpoint;
private final LoadingCache<AthenzRole, SSLContext> roleSslContextCache;
private final static Duration roleSslContextExpiry = Duration.ofHours(24);
- // TODO IdentityConfig should contain ZTS uri and dns suffix
@Inject
public AthenzIdentityProviderImpl(IdentityConfig config, Metric metric) {
this(config,
metric,
new AthenzCredentialsService(config,
- new IdentityDocumentClient(config.loadBalancerAddress()),
- new ZtsClient(),
- getDefaultTrustStoreLocation()),
+ createNodeIdentityProvider(config),
+ getDefaultTrustStoreLocation(),
+ Defaults.getDefaults().vespaHostname()),
new ScheduledThreadPoolExecutor(1),
Clock.systemUTC());
}
// Test only
+
AthenzIdentityProviderImpl(IdentityConfig config,
Metric metric,
AthenzCredentialsService athenzCredentialsService,
@@ -84,6 +89,8 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
this.clock = clock;
this.identity = new AthenzService(config.domain(), config.service());
this.listenerHelper = new ServiceIdentityProviderListenerHelper(this.identity);
+ this.dnsSuffix = config.athenzDnsSuffix();
+ this.ztsEndpoint = URI.create(config.ztsUrl());
registerInstance();
roleSslContextCache = CacheBuilder.newBuilder()
.refreshAfterWrite(roleSslContextExpiry.dividedBy(2).toMinutes(), TimeUnit.MINUTES)
@@ -150,8 +157,8 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
PrivateKey privateKey = credentials.getKeyPair().getPrivate();
X509Certificate roleCertificate = ztsClient.getRoleCertificate(
role,
- credentials.getIdentityDocument().dnsSuffix(),
- credentials.getIdentityDocument().ztsEndpoint(),
+ dnsSuffix,
+ ztsEndpoint,
identity,
privateKey,
credentials.getIdentitySslContext());
@@ -166,7 +173,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
return ztsClient
.getRoleToken(
new AthenzDomain(domain),
- credentials.getIdentityDocument().ztsEndpoint(),
+ ztsEndpoint,
credentials.getIdentitySslContext())
.getRawToken();
}
@@ -177,7 +184,7 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
.getRoleToken(
new AthenzDomain(domain),
role,
- credentials.getIdentityDocument().ztsEndpoint(),
+ ztsEndpoint,
credentials.getIdentitySslContext())
.getRawToken();
}
@@ -193,6 +200,11 @@ public final class AthenzIdentityProviderImpl extends AbstractComponent implemen
}
}
+ private static SiaIdentityProvider createNodeIdentityProvider(IdentityConfig config) {
+ return new SiaIdentityProvider(
+ new AthenzService(config.nodeIdentityName()), SiaUtils.DEFAULT_SIA_DIRECTORY, getDefaultTrustStoreLocation());
+ }
+
private static File getDefaultTrustStoreLocation() {
return new File(Defaults.getDefaults().underVespaHome("share/ssl/certs/yahoo_certificate_bundle.jks"));
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentClient.java
deleted file mode 100644
index dfc89431ce4..00000000000
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentClient.java
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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.identityprovider.client;
-
-import com.yahoo.vespa.defaults.Defaults;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.conn.ssl.NoopHostnameVerifier;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.http.ssl.SSLContextBuilder;
-import org.apache.http.util.EntityUtils;
-import org.eclipse.jetty.http.HttpStatus;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.GeneralSecurityException;
-
-/**
- * @author mortent
- * @author bjorncs
- */
-public class IdentityDocumentClient {
-
- private final URI identityDocumentApiUri;
-
- public IdentityDocumentClient(String loadBalancerName) {
- this.identityDocumentApiUri = createIdentityDocumentApiUri(loadBalancerName);
- }
-
- /**
- * Get signed identity document from config server
- */
- public String getSignedIdentityDocument() {
- try (CloseableHttpClient httpClient = createHttpClient()) {
- CloseableHttpResponse idDocResponse = httpClient.execute(new HttpGet(identityDocumentApiUri));
- String responseContent = EntityUtils.toString(idDocResponse.getEntity());
- if (HttpStatus.isSuccess(idDocResponse.getStatusLine().getStatusCode())) {
- return responseContent;
- } else {
- // TODO make sure we have retried a few times (AND logged) before giving up
- throw new RuntimeException(
- "Failed to initialize Athenz instance provider: " +
- idDocResponse.getStatusLine() + ": " + responseContent);
- }
- } catch (IOException e) {
- throw new RuntimeException("Failed getting signed identity document", e);
- }
- }
-
- // TODO Use client side auth to establish trusted secure channel
- // TODO Validate TLS certifcate of config server
- private static CloseableHttpClient createHttpClient() {
- try {
- SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
- sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
- SSLConnectionSocketFactory sslSocketFactory =
- new SSLConnectionSocketFactory(sslContextBuilder.build(),
- NoopHostnameVerifier.INSTANCE);
- return HttpClientBuilder.create().setSSLSocketFactory(sslSocketFactory).setUserAgent("identity-document-client").build();
- } catch (GeneralSecurityException e) {
- throw new RuntimeException(e);
- }
- }
-
- private static URI createIdentityDocumentApiUri(String loadBalancerName) {
- try {
- // TODO Figure out a proper way of determining the hostname matching what's registred in node-repository
- return new URIBuilder()
- .setScheme("https")
- .setHost(loadBalancerName)
- .setPort(4443)
- .setPath("/athenz/v1/provider/identity-document/tenant/" + Defaults.getDefaults().vespaHostname())
- .build();
- } catch (URISyntaxException e) {
- throw new RuntimeException(e);
- }
- }
-
-}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceIdentity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceIdentity.java
deleted file mode 100644
index 48200599149..00000000000
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceIdentity.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.athenz.identityprovider.client;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.yahoo.vespa.athenz.tls.X509CertificateUtils;
-
-import java.io.IOException;
-import java.security.cert.X509Certificate;
-
-/**
- * Used for deserializing response from ZTS
- *
- * @author mortent
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class InstanceIdentity {
- @JsonProperty("x509Certificate") private final X509Certificate x509Certificate;
- @JsonProperty("serviceToken") private final String serviceToken;
-
- public InstanceIdentity(@JsonProperty("x509Certificate") @JsonDeserialize(using = X509CertificateDeserializer.class)
- X509Certificate x509Certificate,
- @JsonProperty("serviceToken") String serviceToken) {
- this.x509Certificate = x509Certificate;
- this.serviceToken = serviceToken;
- }
-
- public X509Certificate getX509Certificate() {
- return x509Certificate;
- }
-
- public String getServiceToken() {
- return serviceToken;
- }
-
- public static class X509CertificateDeserializer extends JsonDeserializer<X509Certificate> {
- @Override
- public X509Certificate deserialize(JsonParser parser, DeserializationContext context) throws IOException {
- return X509CertificateUtils.fromPem(parser.getValueAsString());
- }
- }
-
-}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceRefreshInformation.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceRefreshInformation.java
deleted file mode 100644
index dd35cb7e401..00000000000
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceRefreshInformation.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.athenz.identityprovider.client;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * @author bjorncs
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class InstanceRefreshInformation {
-
- @JsonProperty("csr")
- private final String csr;
- @JsonProperty("token")
- private final boolean requestServiceToken = true;
-
- public InstanceRefreshInformation(String csr) {
- this.csr = csr;
- }
-}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceRegisterInformation.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceRegisterInformation.java
deleted file mode 100644
index cdf47ad8624..00000000000
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceRegisterInformation.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.athenz.identityprovider.client;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Used for serializing request to ZTS
- *
- * @author mortent
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class InstanceRegisterInformation {
- @JsonProperty("provider")
- private final String provider;
- @JsonProperty("domain")
- private final String domain;
- @JsonProperty("service")
- private final String service;
- @JsonProperty("attestationData")
- private final String attestationData;
- @JsonProperty("ssh")
- private final String ssh = null; // Not needed
- @JsonProperty("csr")
- private final String csr;
- @JsonProperty("token")
- private final boolean token = true;
-
- public InstanceRegisterInformation(String provider, String domain, String service, String attestationData, String csr) {
- this.provider = provider;
- this.domain = domain;
- this.service = service;
- this.attestationData = attestationData;
- this.csr = csr;
- }
-}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/ZtsClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/ZtsClient.java
index afdccac62cf..a3ec55eb815 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/ZtsClient.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/ZtsClient.java
@@ -1,8 +1,6 @@
// 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.identityprovider.client;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.yahoo.athenz.zts.RoleCertificateRequest;
import com.yahoo.athenz.zts.RoleToken;
import com.yahoo.athenz.zts.ZTSClient;
@@ -10,22 +8,10 @@ import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.athenz.api.AthenzRole;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.api.ZToken;
+import com.yahoo.vespa.athenz.client.zts.DefaultZtsClient;
import com.yahoo.vespa.athenz.tls.X509CertificateUtils;
-import org.apache.http.client.HttpRequestRetryHandler;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.methods.RequestBuilder;
-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.apache.http.util.EntityUtils;
-import org.eclipse.jetty.http.HttpStatus;
import javax.net.ssl.SSLContext;
-import java.io.IOException;
-import java.io.UncheckedIOException;
import java.net.URI;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
@@ -34,54 +20,11 @@ import java.time.Duration;
/**
* @author mortent
* @author bjorncs
+ * @deprecated Will be replaced by {@link DefaultZtsClient} once role token/certificate caching is ready.
*/
+@Deprecated
class ZtsClient {
- private static final String INSTANCE_API_PATH = "/zts/v1/instance";
-
- private final ObjectMapper objectMapper = new ObjectMapper();
- private final HttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(3, /*requestSentRetryEnabled*/true);
-
- /**
- * Send instance register request to ZTS, get InstanceIdentity
- */
- InstanceIdentity sendInstanceRegisterRequest(InstanceRegisterInformation instanceRegisterInformation,
- URI uri) {
- try(CloseableHttpClient client = HttpClientBuilder.create().setRetryHandler(retryHandler).build()) {
- HttpUriRequest postRequest = RequestBuilder.post()
- .setUri(uri.resolve(INSTANCE_API_PATH))
- .setEntity(toJsonStringEntity(instanceRegisterInformation))
- .build();
- return getInstanceIdentity(client, postRequest);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- InstanceIdentity sendInstanceRefreshRequest(String providerService,
- String instanceDomain,
- String instanceServiceName,
- String instanceId,
- InstanceRefreshInformation instanceRefreshInformation,
- URI ztsEndpoint,
- SSLContext sslContext) {
- try (CloseableHttpClient client = createHttpClientWithTlsAuth(sslContext, retryHandler)) {
- URI uri = ztsEndpoint
- .resolve(INSTANCE_API_PATH + '/')
- .resolve(providerService + '/')
- .resolve(instanceDomain + '/')
- .resolve(instanceServiceName + '/')
- .resolve(instanceId);
- HttpUriRequest postRequest = RequestBuilder.post()
- .setUri(uri)
- .setEntity(toJsonStringEntity(instanceRefreshInformation))
- .build();
- return getInstanceIdentity(client, postRequest);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
ZToken getRoleToken(AthenzDomain domain,
URI ztsEndpoint,
SSLContext sslContext) {
@@ -118,28 +61,4 @@ class ZtsClient {
return X509CertificateUtils.fromPem(pemCert.token);
}
- private InstanceIdentity getInstanceIdentity(CloseableHttpClient client, HttpUriRequest postRequest)
- throws IOException {
- try (CloseableHttpResponse response = client.execute(postRequest)) {
- if(HttpStatus.isSuccess(response.getStatusLine().getStatusCode())) {
- return objectMapper.readValue(response.getEntity().getContent(), InstanceIdentity.class);
- } else {
- String message = EntityUtils.toString(response.getEntity());
- throw new RuntimeException(String.format("Unable to get identity. http code/message: %d/%s",
- response.getStatusLine().getStatusCode(), message));
- }
- }
- }
-
- private StringEntity toJsonStringEntity(Object value) throws JsonProcessingException {
- return new StringEntity(objectMapper.writeValueAsString(value), ContentType.APPLICATION_JSON);
- }
-
- private static CloseableHttpClient createHttpClientWithTlsAuth(SSLContext sslContext,
- HttpRequestRetryHandler retryHandler) {
- return HttpClientBuilder.create()
- .setRetryHandler(retryHandler)
- .setSSLContext(sslContext)
- .build();
- }
}
diff --git a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImplTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImplTest.java
index 7ad465a7d80..48781aad651 100644
--- a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImplTest.java
+++ b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzIdentityProviderImplTest.java
@@ -1,42 +1,22 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.athenz.identityprovider.client;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.yahoo.container.core.identity.IdentityConfig;
import com.yahoo.container.jdisc.athenz.AthenzIdentityProviderException;
import com.yahoo.jdisc.Metric;
import com.yahoo.test.ManualClock;
-import com.yahoo.vespa.athenz.api.AthenzService;
-import com.yahoo.vespa.athenz.identityprovider.api.EntityBindingsMapper;
-import com.yahoo.vespa.athenz.identityprovider.api.IdentityDocument;
-import com.yahoo.vespa.athenz.identityprovider.api.IdentityType;
-import com.yahoo.vespa.athenz.identityprovider.api.SignedIdentityDocument;
-import com.yahoo.vespa.athenz.identityprovider.api.VespaUniqueInstanceId;
-import com.yahoo.vespa.athenz.tls.KeyStoreBuilder;
-import com.yahoo.vespa.athenz.tls.KeyStoreUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
-import java.util.Collections;
import java.util.Date;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Supplier;
-import static com.yahoo.vespa.athenz.tls.KeyStoreType.JKS;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -55,7 +35,13 @@ public class AthenzIdentityProviderImplTest {
private static final IdentityConfig IDENTITY_CONFIG =
new IdentityConfig(new IdentityConfig.Builder()
- .service("tenantService").domain("tenantDomain").loadBalancerAddress("cfg").ztsUrl("https:localhost:4443/zts/v1").athenzDnsSuffix("vespa.cloud"));
+ .service("tenantService")
+ .domain("tenantDomain")
+ .nodeIdentityName("vespa.tenant")
+ .configserverIdentityName("vespa.configserver")
+ .loadBalancerAddress("cfg")
+ .ztsUrl("https:localhost:4443/zts/v1")
+ .athenzDnsSuffix("dev-us-north-1.vespa.cloud"));
@Test(expected = AthenzIdentityProviderException.class)
public void component_creation_fails_when_credentials_not_found() {
@@ -67,30 +53,24 @@ public class AthenzIdentityProviderImplTest {
}
@Test
- public void metrics_updated_on_refresh() throws IOException {
- IdentityDocumentClient identityDocumentClient = mock(IdentityDocumentClient.class);
- ZtsClient ztsClient = mock(ZtsClient.class);
+ public void metrics_updated_on_refresh() {
ManualClock clock = new ManualClock(Instant.EPOCH);
Metric metric = mock(Metric.class);
- when(identityDocumentClient.getSignedIdentityDocument()).thenReturn(getIdentityDocument());
- when(ztsClient.sendInstanceRegisterRequest(any(), any())).then(new Answer<InstanceIdentity>() {
- @Override
- public InstanceIdentity answer(InvocationOnMock invocationOnMock) throws Throwable {
- return new InstanceIdentity(getCertificate(getExpirationSupplier(clock)), "TOKEN");
- }
- });
+ AthenzCredentialsService athenzCredentialsService = mock(AthenzCredentialsService.class);
- when(ztsClient.sendInstanceRefreshRequest(anyString(), anyString(), anyString(), anyString(), any(), any(), any()))
+ X509Certificate certificate = getCertificate(getExpirationSupplier(clock));
+
+ when(athenzCredentialsService.registerInstance())
+ .thenReturn(new AthenzCredentials(null, certificate, null, null, null));
+
+ when(athenzCredentialsService.updateCredentials(any(), any()))
.thenThrow(new RuntimeException("#1"))
.thenThrow(new RuntimeException("#2"))
- .thenReturn(new InstanceIdentity(getCertificate(getExpirationSupplier(clock)), "TOKEN"));
-
- AthenzCredentialsService credentialService =
- new AthenzCredentialsService(IDENTITY_CONFIG, identityDocumentClient, ztsClient, createDummyTrustStore());
+ .thenReturn(new AthenzCredentials(null, certificate, null, null, null));
AthenzIdentityProviderImpl identityProvider =
- new AthenzIdentityProviderImpl(IDENTITY_CONFIG, metric, credentialService, mock(ScheduledExecutorService.class), clock);
+ new AthenzIdentityProviderImpl(IDENTITY_CONFIG, metric, athenzCredentialsService, mock(ScheduledExecutorService.class), clock);
identityProvider.reportMetrics();
verify(metric).set(eq(AthenzIdentityProviderImpl.CERTIFICATE_EXPIRY_METRIC_NAME), eq(certificateValidity.getSeconds()), any());
@@ -125,31 +105,4 @@ public class AthenzIdentityProviderImplTest {
return x509Certificate;
}
- private File createDummyTrustStore() throws IOException {
- File file = tempDir.newFile();
- KeyStore keyStore = KeyStoreBuilder.withType(JKS).build();
- KeyStoreUtils.writeKeyStoreToFile(keyStore, file);
- return file;
- }
-
- private static String getIdentityDocument() throws JsonProcessingException {
- VespaUniqueInstanceId instanceId = new VespaUniqueInstanceId(0, "default", "default", "application", "tenant", "us-north-1", "dev", IdentityType.TENANT);
- SignedIdentityDocument signedIdentityDocument = new SignedIdentityDocument(
- new IdentityDocument(instanceId, "localhost", "x.y.com", Instant.EPOCH, Collections.emptySet()),
- "dummysignature",
- 0,
- instanceId,
- "dev-us-north-1.vespa.cloud",
- new AthenzService("vespa.vespa.provider_dev_us-north-1"),
- URI.create("https://zts:4443/zts/v1"),
- 1,
- "localhost",
- "x.y.com",
- Instant.EPOCH,
- Collections.emptySet(),
- IdentityType.TENANT);
-
- return new ObjectMapper().registerModule(new JavaTimeModule())
- .writeValueAsString(EntityBindingsMapper.toSignedIdentityDocumentEntity(signedIdentityDocument));
- }
}