summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Musum <musum@oath.com>2018-03-17 18:06:17 +0100
committerGitHub <noreply@github.com>2018-03-17 18:06:17 +0100
commita7beed17a937f80e05a326356b38935728815682 (patch)
tree57ce70f3fcd9a55cd31aff0cbcdedb67e1defd8a
parent5c69befea0798e854c247362a149641bca432f3b (diff)
parent6102c4480d8769ebcc36e6c4a338ee18294ede34 (diff)
Merge pull request #5369 from vespa-engine/revert-5361-bjorncs/athenz-client-factory
Revert "Bjorncs/athenz client factory"
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsClient.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/AthenzClientFactoryImpl.java26
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/ZtsClientImpl.java57
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/mock/ZtsClientMock.java50
4 files changed, 132 insertions, 7 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsClient.java
index eefd11bdeec..381896c11cf 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsClient.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsClient.java
@@ -3,6 +3,8 @@ package com.yahoo.vespa.hosted.controller.api.integration.athenz;
import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.api.AthenzIdentityCertificate;
+import com.yahoo.vespa.athenz.api.AthenzRoleCertificate;
import java.util.List;
@@ -13,4 +15,8 @@ public interface ZtsClient {
List<AthenzDomain> getTenantDomainsForUser(AthenzIdentity principal);
+ AthenzIdentityCertificate getIdentityCertificate();
+
+ AthenzRoleCertificate getRoleCertificate(AthenzDomain roleDomain, String roleName);
+
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/AthenzClientFactoryImpl.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/AthenzClientFactoryImpl.java
index 893dafa5885..c3471a40234 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/AthenzClientFactoryImpl.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/AthenzClientFactoryImpl.java
@@ -5,12 +5,12 @@ import com.google.inject.Inject;
import com.yahoo.athenz.auth.Principal;
import com.yahoo.athenz.auth.impl.PrincipalAuthority;
import com.yahoo.athenz.auth.impl.SimplePrincipal;
+import com.yahoo.athenz.auth.impl.SimpleServiceIdentityProvider;
import com.yahoo.athenz.auth.token.PrincipalToken;
import com.yahoo.athenz.auth.util.Crypto;
import com.yahoo.athenz.zms.ZMSClient;
import com.yahoo.athenz.zts.ZTSClient;
import com.yahoo.container.jdisc.Ckms;
-import com.yahoo.container.jdisc.athenz.AthenzIdentityProvider;
import com.yahoo.vespa.athenz.api.NToken;
import com.yahoo.vespa.athenz.utils.AthenzIdentities;
import com.yahoo.vespa.hosted.controller.api.integration.athenz.AthenzClientFactory;
@@ -19,21 +19,21 @@ import com.yahoo.vespa.hosted.controller.api.integration.athenz.ZtsClient;
import com.yahoo.vespa.hosted.controller.athenz.config.AthenzConfig;
import java.security.PrivateKey;
+import java.time.Duration;
/**
* @author bjorncs
*/
+// TODO Use SiaIdentityProvider
public class AthenzClientFactoryImpl implements AthenzClientFactory {
private final Ckms ckms;
private final AthenzConfig config;
private final AthenzPrincipalAuthority athenzPrincipalAuthority;
- private final AthenzIdentityProvider identityProvider;
@Inject
- public AthenzClientFactoryImpl(Ckms ckms, AthenzIdentityProvider identityProvider, AthenzConfig config) {
+ public AthenzClientFactoryImpl(Ckms ckms, AthenzConfig config) {
this.ckms = ckms;
- this.identityProvider = identityProvider;
this.config = config;
this.athenzPrincipalAuthority = new AthenzPrincipalAuthority(config.principalHeaderName());
}
@@ -43,7 +43,7 @@ public class AthenzClientFactoryImpl implements AthenzClientFactory {
*/
@Override
public ZmsClient createZmsClientWithServicePrincipal() {
- return new ZmsClientImpl(new ZMSClient(config.zmsUrl(), identityProvider.getIdentitySslContext()), config);
+ return new ZmsClientImpl(new ZMSClient(config.zmsUrl(), createServicePrincipal()), config);
}
/**
@@ -51,7 +51,7 @@ public class AthenzClientFactoryImpl implements AthenzClientFactory {
*/
@Override
public ZtsClient createZtsClientWithServicePrincipal() {
- return new ZtsClientImpl(new ZTSClient(config.ztsUrl(), identityProvider.getIdentitySslContext()), config);
+ return new ZtsClientImpl(new ZTSClient(config.ztsUrl(), createServicePrincipal()), getServicePrivateKey(), config);
}
/**
@@ -70,6 +70,20 @@ public class AthenzClientFactoryImpl implements AthenzClientFactory {
}
+ private Principal createServicePrincipal() {
+ AthenzConfig.Service service = config.service();
+ // TODO bjorncs: Cache principal token
+ SimpleServiceIdentityProvider identityProvider =
+ new SimpleServiceIdentityProvider(
+ athenzPrincipalAuthority,
+ config.domain(),
+ service.name(),
+ getServicePrivateKey(),
+ service.publicKeyId(),
+ Duration.ofMinutes(service.credentialsExpiryMinutes()).getSeconds());
+ return identityProvider.getIdentity(config.domain(), service.name());
+ }
+
private PrivateKey getServicePrivateKey() {
AthenzConfig.Service service = config.service();
String privateKey = ckms.getSecret(service.privateKeySecretName(), service.privateKeyVersion()).trim();
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/ZtsClientImpl.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/ZtsClientImpl.java
index c3ed8f0a99f..0166c02db2e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/ZtsClientImpl.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/ZtsClientImpl.java
@@ -1,17 +1,25 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.athenz.impl;
+import com.yahoo.athenz.auth.util.Crypto;
+import com.yahoo.athenz.zts.InstanceRefreshRequest;
+import com.yahoo.athenz.zts.RoleCertificateRequest;
import com.yahoo.athenz.zts.TenantDomains;
import com.yahoo.athenz.zts.ZTSClient;
import com.yahoo.athenz.zts.ZTSClientException;
import com.yahoo.log.LogLevel;
import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.api.AthenzIdentityCertificate;
+import com.yahoo.vespa.athenz.api.AthenzRoleCertificate;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.hosted.controller.api.integration.athenz.ZtsClient;
import com.yahoo.vespa.hosted.controller.api.integration.athenz.ZtsException;
import com.yahoo.vespa.hosted.controller.athenz.config.AthenzConfig;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.time.Duration;
import java.util.List;
import java.util.function.Supplier;
import java.util.logging.Logger;
@@ -27,10 +35,16 @@ public class ZtsClientImpl implements ZtsClient {
private final ZTSClient ztsClient;
private final AthenzService service;
+ private final PrivateKey privateKey;
+ private final String certificateDnsDomain;
+ private final Duration certExpiry;
- public ZtsClientImpl(ZTSClient ztsClient, AthenzConfig config) {
+ public ZtsClientImpl(ZTSClient ztsClient, PrivateKey privateKey, AthenzConfig config) {
this.ztsClient = ztsClient;
this.service = new AthenzService(config.domain(), config.service().name());
+ this.privateKey = privateKey;
+ this.certificateDnsDomain = config.certDnsDomain();
+ this.certExpiry = Duration.ofMinutes(config.service().credentialsExpiryMinutes());
}
@Override
@@ -47,6 +61,47 @@ public class ZtsClientImpl implements ZtsClient {
});
}
+ @Override
+ public AthenzIdentityCertificate getIdentityCertificate() {
+ return getOrThrow(() -> {
+ log.log(LogLevel.DEBUG,
+ String.format("postInstanceRefreshRequest(service=%s)", service.getFullName()));
+ InstanceRefreshRequest req =
+ ZTSClient.generateInstanceRefreshRequest(
+ service.getDomain().getName(),
+ service.getName(),
+ privateKey,
+ certificateDnsDomain,
+ (int) certExpiry.getSeconds());
+ X509Certificate certificate = Crypto.loadX509Certificate(
+ ztsClient.postInstanceRefreshRequest(service.getDomain().getName(), service.getName(), req)
+ .getCertificate());
+ return new AthenzIdentityCertificate(certificate, privateKey);
+ });
+ }
+
+ @Override
+ public AthenzRoleCertificate getRoleCertificate(AthenzDomain roleDomain, String roleName) {
+ return getOrThrow(() -> {
+ log.log(LogLevel.DEBUG,
+ String.format("postRoleCertificateRequest(service=%s, roleDomain=%s, roleName=%s)",
+ service.getFullName(), roleDomain.getName(), roleName));
+ RoleCertificateRequest req =
+ ZTSClient.generateRoleCertificateRequest(
+ service.getDomain().getName(),
+ service.getName(),
+ roleDomain.getName(),
+ roleName,
+ privateKey,
+ certificateDnsDomain,
+ (int)certExpiry.getSeconds());
+ X509Certificate roleCertificate = Crypto.loadX509Certificate(
+ ztsClient.postRoleCertificateRequest(roleDomain.getName(), roleName, req)
+ .getToken());
+ return new AthenzRoleCertificate(roleCertificate, privateKey);
+ });
+ }
+
private static <T> T getOrThrow(Supplier<T> wrappedCode) {
try {
return wrappedCode.get();
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/mock/ZtsClientMock.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/mock/ZtsClientMock.java
index 4aa1c2b93a5..7aea79a93c6 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/mock/ZtsClientMock.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/mock/ZtsClientMock.java
@@ -1,10 +1,21 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.athenz.mock;
+import com.yahoo.athenz.auth.util.Crypto;
import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.api.AthenzIdentityCertificate;
+import com.yahoo.vespa.athenz.api.AthenzRoleCertificate;
import com.yahoo.vespa.hosted.controller.api.integration.athenz.ZtsClient;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import java.io.IOException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -32,4 +43,43 @@ public class ZtsClientMock implements ZtsClient {
.collect(toList());
}
+ @Override
+ public AthenzIdentityCertificate getIdentityCertificate() {
+ log.log(Level.INFO, "getIdentityCertificate()");
+ try {
+ KeyPair keyPair = createKeyPair();
+ String subject = "CN=controller";
+ return new AthenzIdentityCertificate(createCertificate(keyPair, subject), keyPair.getPrivate());
+ } catch (NoSuchAlgorithmException | OperatorCreationException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public AthenzRoleCertificate getRoleCertificate(AthenzDomain roleDomain, String roleName) {
+ log.log(Level.INFO,
+ String.format("getRoleCertificate(roleDomain=%s, roleName=%s)", roleDomain.getName(), roleDomain));
+ try {
+ KeyPair keyPair = createKeyPair();
+ String subject = String.format("CN=%s:role.%s", roleDomain.getName(), roleName);
+ return new AthenzRoleCertificate(createCertificate(keyPair, subject), keyPair.getPrivate());
+ } catch (NoSuchAlgorithmException | OperatorCreationException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static X509Certificate createCertificate(KeyPair keyPair, String subject) throws
+ OperatorCreationException, IOException {
+ PKCS10CertificationRequest csr =
+ Crypto.getPKCS10CertRequest(
+ Crypto.generateX509CSR(keyPair.getPrivate(), subject, null));
+ return Crypto.generateX509Certificate(csr, keyPair.getPrivate(), new X500Name(subject), 3600, false);
+ }
+
+ private static KeyPair createKeyPair() throws NoSuchAlgorithmException {
+ KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+ keyGen.initialize(512);
+ return keyGen.genKeyPair();
+ }
+
}