summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2019-08-28 13:29:55 +0200
committerGitHub <noreply@github.com>2019-08-28 13:29:55 +0200
commit0fffe157136a0dc033a0fd63abd61ddf1eaf5eaa (patch)
treeedbbebb10f020508ab8afb571e22dfa05e9e82f9
parent82a57087a6f9b9d13c708ae930ffa16a01514334 (diff)
parentc3f734b9fdce30ada768c52427004bde763354b4 (diff)
Merge pull request #10412 from vespa-engine/bjorncs/hostname
Bjorncs/hostname
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceConfirmation.java7
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceValidator.java29
-rw-r--r--athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceValidatorTest.java46
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/mock/ZtsClientMock.java7
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/identity/AthenzCredentialsMaintainer.java23
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/DefaultZtsClient.java9
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/ZtsClient.java6
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRefreshInformation.java9
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRegisterInformation.java15
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/AthenzCredentialsService.java7
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/CsrGenerator.java5
-rw-r--r--vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceCsrGeneratorTest.java2
12 files changed, 121 insertions, 44 deletions
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceConfirmation.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceConfirmation.java
index e6dd40faaca..24998a49faf 100644
--- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceConfirmation.java
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceConfirmation.java
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
/**
* InstanceConfirmation object as per Athenz InstanceConfirmation API.
@@ -28,6 +29,8 @@ import java.util.Objects;
*/
public class InstanceConfirmation {
+ static final String HOSTNAME_ATTRIBUTE = "hostname";
+
@JsonProperty("provider") public final String provider;
@JsonProperty("domain") public final String domain;
@JsonProperty("service") public final String service;
@@ -53,6 +56,10 @@ public class InstanceConfirmation {
attributes.put(name, value);
}
+ public Optional<String> getInstanceHostname() {
+ return Optional.ofNullable(attributes.get(HOSTNAME_ATTRIBUTE));
+ }
+
@Override
public String toString() {
return "InstanceConfirmation{" +
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceValidator.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceValidator.java
index f1a93e58526..54611172b57 100644
--- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceValidator.java
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceValidator.java
@@ -10,6 +10,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.log.LogLevel;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.identityprovider.api.EntityBindingsMapper;
+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.identityprovider.client.IdentityDocumentSigner;
@@ -158,6 +159,34 @@ public class InstanceValidator {
log.log(LogLevel.WARNING, "Invalid InstanceConfirmation, wrong ip in : " + vespaUniqueInstanceId);
return false;
}
+
+ // Validate hostname
+ boolean hasValidHostname =
+ confirmation.getInstanceHostname()
+ .map(requestHostname -> validateHostname(vespaUniqueInstanceId, node, requestHostname))
+ .orElse(true);
+ if (!hasValidHostname) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static boolean validateHostname(VespaUniqueInstanceId vespaUniqueInstanceId, Node node, String requestedHostname) {
+ String nodeHostname = node.hostname();
+ if (vespaUniqueInstanceId.type() == IdentityType.TENANT) {
+ log.log(LogLevel.WARNING, "Instance hostname not allowed in tenant certificates");
+ return false;
+ }
+ if (!nodeHostname.equals(requestedHostname)) {
+ log.log(LogLevel.WARNING,
+ String.format(
+ "Invalid instance confirmation: request instance hostname is '%s', but node repository has '%s'",
+ requestedHostname,
+ nodeHostname));
+
+ return false;
+ }
return true;
}
diff --git a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceValidatorTest.java b/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceValidatorTest.java
index d5787516254..957b71a64bf 100644
--- a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceValidatorTest.java
+++ b/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/instanceconfirmation/InstanceValidatorTest.java
@@ -1,7 +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.hosted.athenz.instanceproviderservice.instanceconfirmation;
-import com.google.common.collect.ImmutableList;
import com.yahoo.component.Version;
import com.yahoo.config.model.api.ApplicationInfo;
import com.yahoo.config.model.api.HostInfo;
@@ -123,7 +122,7 @@ public class InstanceValidatorTest {
nodeList = allocateNode(nodeList, node, applicationId);
when(nodeRepository.getNodes()).thenReturn(nodeList);
String nodeIp = node.ipAddresses().stream().findAny().orElseThrow(() -> new RuntimeException("No ipaddress for mocked node"));
- InstanceConfirmation instanceConfirmation = createRefreshInstanceConfirmation(applicationId, domain, service, ImmutableList.of(nodeIp));
+ InstanceConfirmation instanceConfirmation = createRefreshInstanceConfirmation(applicationId, domain, service, IdentityType.NODE, node.hostname(), List.of(nodeIp));
assertTrue(instanceValidator.isValidRefresh(instanceConfirmation));
}
@@ -140,7 +139,41 @@ public class InstanceValidatorTest {
String nodeIp = node.ipAddresses().stream().findAny().orElseThrow(() -> new RuntimeException("No ipaddress for mocked node"));
// Add invalid ip to list of ip addresses
- InstanceConfirmation instanceConfirmation = createRefreshInstanceConfirmation(applicationId, domain, service, ImmutableList.of(nodeIp, "::ff"));
+ InstanceConfirmation instanceConfirmation = createRefreshInstanceConfirmation(applicationId, domain, service, IdentityType.NODE, node.hostname(), List.of(nodeIp, "::ff"));
+
+ assertFalse(instanceValidator.isValidRefresh(instanceConfirmation));
+ }
+
+ @Test
+ public void rejects_invalid_hostname() {
+ NodeRepository nodeRepository = mock(NodeRepository.class);
+ InstanceValidator instanceValidator = new InstanceValidator(null, null, nodeRepository);
+
+ List<Node> nodeList = createNodes(10);
+ Node node = nodeList.get(0);
+ nodeList = allocateNode(nodeList, node, applicationId);
+ when(nodeRepository.getNodes()).thenReturn(nodeList);
+ String nodeIp = node.ipAddresses().stream().findAny().orElseThrow(() -> new RuntimeException("No ipaddress for mocked node"));
+
+ // Add invalid hostname to request
+ InstanceConfirmation instanceConfirmation = createRefreshInstanceConfirmation(applicationId, domain, service, IdentityType.NODE, "invalidhostname", List.of(nodeIp));
+
+ assertFalse(instanceValidator.isValidRefresh(instanceConfirmation));
+ }
+
+ @Test
+ public void rejects_hostname_for_tenant_certificates() {
+ NodeRepository nodeRepository = mock(NodeRepository.class);
+ InstanceValidator instanceValidator = new InstanceValidator(null, null, nodeRepository);
+
+ List<Node> nodeList = createNodes(10);
+ Node node = nodeList.get(0);
+ nodeList = allocateNode(nodeList, node, applicationId);
+ when(nodeRepository.getNodes()).thenReturn(nodeList);
+ String nodeIp = node.ipAddresses().stream().findAny().orElseThrow(() -> new RuntimeException("No ipaddress for mocked node"));
+
+ // Request tenant certificate with valid hostname
+ InstanceConfirmation instanceConfirmation = createRefreshInstanceConfirmation(applicationId, domain, service, IdentityType.TENANT, node.hostname(), List.of(nodeIp));
assertFalse(instanceValidator.isValidRefresh(instanceConfirmation));
}
@@ -152,7 +185,7 @@ public class InstanceValidatorTest {
List<Node> nodeList = createNodes(10);
when(nodeRepository.getNodes()).thenReturn(nodeList);
- InstanceConfirmation instanceConfirmation = createRefreshInstanceConfirmation(applicationId, domain, service, ImmutableList.of("::11"));
+ InstanceConfirmation instanceConfirmation = createRefreshInstanceConfirmation(applicationId, domain, service, IdentityType.NODE, nodeList.get(0).hostname(), List.of("::11"));
assertFalse(instanceValidator.isValidRefresh(instanceConfirmation));
@@ -173,10 +206,11 @@ public class InstanceValidatorTest {
return createInstanceConfirmation(vespaUniqueInstanceId, domain, service, signedIdentityDocument);
}
- private InstanceConfirmation createRefreshInstanceConfirmation(ApplicationId applicationId, String domain, String service, List<String> ips) {
- VespaUniqueInstanceId vespaUniqueInstanceId = new VespaUniqueInstanceId(0, "default", applicationId.instance().value(), applicationId.application().value(), applicationId.tenant().value(), "us-north-1", "dev", IdentityType.NODE);
+ private InstanceConfirmation createRefreshInstanceConfirmation(ApplicationId applicationId, String domain, String service, IdentityType identityType, String hostname, List<String> ips) {
+ VespaUniqueInstanceId vespaUniqueInstanceId = new VespaUniqueInstanceId(0, "default", applicationId.instance().value(), applicationId.application().value(), applicationId.tenant().value(), "us-north-1", "dev", identityType);
InstanceConfirmation instanceConfirmation = createInstanceConfirmation(vespaUniqueInstanceId, domain, service, null);
instanceConfirmation.set("sanIP", String.join(",", ips));
+ instanceConfirmation.set(InstanceConfirmation.HOSTNAME_ATTRIBUTE, hostname);
return instanceConfirmation;
}
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 5c0407d35a9..752c003cf75 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,17 +1,16 @@
// 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.security.Pkcs10Csr;
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.AwsRole;
import com.yahoo.vespa.athenz.api.AwsTemporaryCredentials;
import com.yahoo.vespa.athenz.api.ZToken;
import com.yahoo.vespa.athenz.client.zts.Identity;
import com.yahoo.vespa.athenz.client.zts.InstanceIdentity;
import com.yahoo.vespa.athenz.client.zts.ZtsClient;
-import com.yahoo.security.Pkcs10Csr;
import java.security.KeyPair;
import java.security.cert.X509Certificate;
@@ -45,12 +44,12 @@ public class ZtsClientMock implements ZtsClient {
}
@Override
- public InstanceIdentity registerInstance(AthenzIdentity providerIdentity, AthenzIdentity instanceIdentity, String instanceId, String attestationData, boolean requestServiceToken, Pkcs10Csr csr) {
+ public InstanceIdentity registerInstance(AthenzIdentity providerIdentity, AthenzIdentity instanceIdentity, String hostname, String attestationData, Pkcs10Csr csr) {
throw new UnsupportedOperationException();
}
@Override
- public InstanceIdentity refreshInstance(AthenzIdentity providerIdentity, AthenzIdentity instanceIdentity, String instanceId, boolean requestServiceToken, Pkcs10Csr csr) {
+ public InstanceIdentity refreshInstance(AthenzIdentity providerIdentity, AthenzIdentity instanceIdentity, String instanceId, String hostname, Pkcs10Csr csr) {
throw new UnsupportedOperationException();
}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/identity/AthenzCredentialsMaintainer.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/identity/AthenzCredentialsMaintainer.java
index ce7a99fd841..f994530bef4 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/identity/AthenzCredentialsMaintainer.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/maintenance/identity/AthenzCredentialsMaintainer.java
@@ -155,16 +155,20 @@ public class AthenzCredentialsMaintainer implements CredentialsMaintainer {
private void registerIdentity(NodeAgentContext context, Path privateKeyFile, Path certificateFile, Path identityDocumentFile) {
KeyPair keyPair = KeyUtils.generateKeypair(KeyAlgorithm.RSA);
SignedIdentityDocument signedIdentityDocument = identityDocumentClient.getNodeIdentityDocument(context.hostname().value());
- Pkcs10Csr csr = csrGenerator.generateInstanceCsr(
- context.identity(), signedIdentityDocument.providerUniqueId(), signedIdentityDocument.ipAddresses(), keyPair);
+ Pkcs10Csr csr =
+ csrGenerator.generateInstanceCsr(
+ context.identity(),
+ signedIdentityDocument.providerUniqueId(),
+ signedIdentityDocument.instanceHostname(),
+ signedIdentityDocument.ipAddresses(),
+ keyPair);
try (ZtsClient ztsClient = new DefaultZtsClient(ztsEndpoint, hostIdentityProvider)) {
InstanceIdentity instanceIdentity =
ztsClient.registerInstance(
configserverIdentity,
context.identity(),
- signedIdentityDocument.providerUniqueId().asDottedString(),
+ signedIdentityDocument.instanceHostname(),
EntityBindingsMapper.toAttestationData(signedIdentityDocument),
- false,
csr);
EntityBindingsMapper.writeSignedIdentityDocumentToFile(identityDocumentFile, signedIdentityDocument);
writePrivateKeyAndCertificate(context.vespaUserOnHost(), privateKeyFile, keyPair.getPrivate(),
@@ -176,8 +180,13 @@ public class AthenzCredentialsMaintainer implements CredentialsMaintainer {
private void refreshIdentity(NodeAgentContext context, Path privateKeyFile, Path certificateFile, Path identityDocumentFile) {
SignedIdentityDocument identityDocument = EntityBindingsMapper.readSignedIdentityDocumentFromFile(identityDocumentFile);
KeyPair keyPair = KeyUtils.generateKeypair(KeyAlgorithm.RSA);
- Pkcs10Csr csr = csrGenerator.generateInstanceCsr(
- context.identity(), identityDocument.providerUniqueId(), identityDocument.ipAddresses(), keyPair);
+ Pkcs10Csr csr = csrGenerator
+ .generateInstanceCsr(
+ context.identity(),
+ identityDocument.providerUniqueId(),
+ identityDocument.instanceHostname(),
+ identityDocument.ipAddresses(),
+ keyPair);
SSLContext containerIdentitySslContext =
new SslContextBuilder()
.withKeyStore(privateKeyFile, certificateFile)
@@ -190,7 +199,7 @@ public class AthenzCredentialsMaintainer implements CredentialsMaintainer {
configserverIdentity,
context.identity(),
identityDocument.providerUniqueId().asDottedString(),
- false,
+ identityDocument.instanceHostname(),
csr);
writePrivateKeyAndCertificate(context.vespaUserOnHost(), privateKeyFile, keyPair.getPrivate(),
certificateFile, instanceIdentity.certificate());
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 ddba229d8d1..13150158dad 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
@@ -66,12 +66,11 @@ public class DefaultZtsClient extends ClientBase implements ZtsClient {
@Override
public InstanceIdentity registerInstance(AthenzIdentity providerIdentity,
AthenzIdentity instanceIdentity,
- String instanceId,
String attestationData,
- boolean requestServiceToken,
+ String hostname,
Pkcs10Csr csr) {
InstanceRegisterInformation payload =
- new InstanceRegisterInformation(providerIdentity, instanceIdentity, attestationData, csr, requestServiceToken);
+ new InstanceRegisterInformation(providerIdentity, instanceIdentity, attestationData, hostname, csr);
HttpUriRequest request = RequestBuilder.post()
.setUri(ztsUrl.resolve("instance/"))
.setEntity(toJsonStringEntity(payload))
@@ -83,9 +82,9 @@ public class DefaultZtsClient extends ClientBase implements ZtsClient {
public InstanceIdentity refreshInstance(AthenzIdentity providerIdentity,
AthenzIdentity instanceIdentity,
String instanceId,
- boolean requestServiceToken,
+ String hostname,
Pkcs10Csr csr) {
- InstanceRefreshInformation payload = new InstanceRefreshInformation(csr, requestServiceToken);
+ InstanceRefreshInformation payload = new InstanceRefreshInformation(csr, hostname);
URI uri = ztsUrl.resolve(
String.format("instance/%s/%s/%s/%s",
providerIdentity.getFullName(),
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 efe244d500f..4f44dba4864 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
@@ -5,7 +5,6 @@ import com.yahoo.security.Pkcs10Csr;
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.AwsRole;
import com.yahoo.vespa.athenz.api.AwsTemporaryCredentials;
import com.yahoo.vespa.athenz.api.ZToken;
@@ -30,9 +29,8 @@ public interface ZtsClient extends AutoCloseable {
*/
InstanceIdentity registerInstance(AthenzIdentity providerIdentity,
AthenzIdentity instanceIdentity,
- String instanceId, // TODO Remove this parameter (unused/unnecessary)
+ String hostname,
String attestationData,
- boolean requestServiceToken,
Pkcs10Csr csr);
/**
@@ -43,7 +41,7 @@ public interface ZtsClient extends AutoCloseable {
InstanceIdentity refreshInstance(AthenzIdentity providerIdentity,
AthenzIdentity instanceIdentity,
String instanceId,
- boolean requestServiceToken,
+ String hostname,
Pkcs10Csr csr);
/**
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 fee91dbc15b..5d101ed31e6 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
@@ -18,12 +18,11 @@ public class InstanceRefreshInformation {
@JsonProperty("csr")
@JsonSerialize(using = Pkcs10CsrSerializer.class)
private final Pkcs10Csr csr;
- @JsonProperty("token")
- private final boolean requestServiceToken;
+ @JsonProperty("hostname")
+ private final String hostname;
- public InstanceRefreshInformation(Pkcs10Csr csr,
- boolean requestServiceToken) {
+ public InstanceRefreshInformation(Pkcs10Csr csr, String hostname) {
this.csr = csr;
- this.requestServiceToken = requestServiceToken;
+ this.hostname = hostname;
}
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRegisterInformation.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRegisterInformation.java
index 67a49059776..c5175f19b44 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRegisterInformation.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zts/bindings/InstanceRegisterInformation.java
@@ -4,10 +4,9 @@ package com.yahoo.vespa.athenz.client.zts.bindings;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.yahoo.vespa.athenz.api.AthenzIdentity;
-import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.security.Pkcs10Csr;
import com.yahoo.security.Pkcs10CsrUtils;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
/**
* Used for serializing request to ZTS
@@ -26,23 +25,21 @@ public class InstanceRegisterInformation {
private final String service;
@JsonProperty("attestationData")
private final String attestationData;
- @JsonProperty("ssh")
- private final String ssh = null; // Not needed
+ @JsonProperty("hostname")
+ private final String hostname;
@JsonProperty("csr")
private final String csr;
- @JsonProperty("token")
- private final boolean token;
public InstanceRegisterInformation(AthenzIdentity providerIdentity,
AthenzIdentity instanceIdentity,
String attestationData,
- Pkcs10Csr csr,
- boolean requestServiceToken) {
+ String hostname,
+ Pkcs10Csr csr) {
this.provider = providerIdentity.getFullName();
this.domain = instanceIdentity.getDomain().getName();
this.service = instanceIdentity.getName();
this.attestationData = attestationData;
this.csr = Pkcs10CsrUtils.toPem(csr);
- this.token = requestServiceToken;
+ this.hostname = hostname;
}
}
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 9e2d8bc548c..8e0bdb9b19c 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
@@ -75,6 +75,7 @@ class AthenzCredentialsService {
Pkcs10Csr csr = csrGenerator.generateInstanceCsr(
tenantIdentity,
document.providerUniqueId(),
+ /*hostname*/null, // no hostname in tenant certificates
document.ipAddresses(),
keyPair);
@@ -83,9 +84,8 @@ class AthenzCredentialsService {
ztsClient.registerInstance(
configserverIdentity,
tenantIdentity,
- null,
+ /*hostname*/null,
EntityBindingsMapper.toAttestationData(document),
- false,
csr);
X509Certificate certificate = instanceIdentity.certificate();
writeCredentialsToDisk(keyPair.getPrivate(), certificate, document);
@@ -98,6 +98,7 @@ class AthenzCredentialsService {
Pkcs10Csr csr = csrGenerator.generateInstanceCsr(
tenantIdentity,
document.providerUniqueId(),
+ /*hostname*/null, // no hostname in tenant certificates
document.ipAddresses(),
newKeyPair);
@@ -106,8 +107,8 @@ class AthenzCredentialsService {
ztsClient.refreshInstance(
configserverIdentity,
tenantIdentity,
+ /*hostname*/null,
document.providerUniqueId().asDottedString(),
- false,
csr);
X509Certificate certificate = instanceIdentity.certificate();
writeCredentialsToDisk(newKeyPair.getPrivate(), certificate, document);
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/CsrGenerator.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/CsrGenerator.java
index f73a52b373b..dff753b9126 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/CsrGenerator.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/CsrGenerator.java
@@ -34,11 +34,13 @@ public class CsrGenerator {
public Pkcs10Csr generateInstanceCsr(AthenzIdentity instanceIdentity,
VespaUniqueInstanceId instanceId,
+ String hostname,
Set<String> ipAddresses,
KeyPair keyPair) {
X500Principal subject = new X500Principal(String.format("OU=%s, CN=%s", providerService, instanceIdentity.getFullName()));
// Add SAN dnsname <service>.<domain-with-dashes>.<provider-dnsname-suffix>
// and SAN dnsname <provider-unique-instance-id>.instanceid.athenz.<provider-dnsname-suffix>
+ // and SAN dnsname <hostname> (note: ZTS will verify that there is a DNS A record with hostname having the remote ip)
Pkcs10CsrBuilder pkcs10CsrBuilder = Pkcs10CsrBuilder.fromKeypair(subject, keyPair, SHA256_WITH_RSA)
.addSubjectAlternativeName(
DNS_NAME,
@@ -48,6 +50,9 @@ public class CsrGenerator {
instanceIdentity.getDomainName().replace(".", "-"),
dnsSuffix))
.addSubjectAlternativeName(DNS_NAME, getIdentitySAN(instanceId));
+ if (hostname != null) {
+ pkcs10CsrBuilder.addSubjectAlternativeName(DNS_NAME, hostname);
+ }
ipAddresses.forEach(ip -> pkcs10CsrBuilder.addSubjectAlternativeName(new SubjectAlternativeName(IP_ADDRESS, ip)));
return pkcs10CsrBuilder.build();
}
diff --git a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceCsrGeneratorTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceCsrGeneratorTest.java
index 8b6d2f06777..3b2129821a3 100644
--- a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceCsrGeneratorTest.java
+++ b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceCsrGeneratorTest.java
@@ -31,7 +31,7 @@ public class InstanceCsrGeneratorTest {
VespaUniqueInstanceId vespaUniqueInstanceId = VespaUniqueInstanceId.fromDottedString("0.default.default.foo-app.vespa.us-north-1.prod.node");
KeyPair keyPair = KeyUtils.generateKeypair(KeyAlgorithm.RSA);
- Pkcs10Csr csr = csrGenerator.generateInstanceCsr(service, vespaUniqueInstanceId, Collections.emptySet(), keyPair);
+ Pkcs10Csr csr = csrGenerator.generateInstanceCsr(service, vespaUniqueInstanceId, "myhostname", Collections.emptySet(), keyPair);
assertEquals(new X500Principal(String.format("OU=%s, CN=%s", PROVIDER_SERVICE, ATHENZ_SERVICE)), csr.getSubject());
}
}