aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@yahooinc.com>2023-02-03 12:22:44 +0100
committerBjørn Christian Seime <bjorncs@yahooinc.com>2023-02-03 12:23:24 +0100
commit90892ba4d2a302b1a262fdd1198fac8c6724e44f (patch)
tree0eaa5c41368af736cd3bdb0a36f4b74f4370b886
parente09b191faf77bb95b923bb709b2181a0a3ee2c81 (diff)
Add SAN URI with cluster type in instance certificates
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/IdentityDocumentGenerator.java2
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/InstanceValidator.java4
-rw-r--r--athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/InstanceSerializer.java3
-rw-r--r--athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/InstanceValidatorTest.java30
-rw-r--r--athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/ca/restapi/InstanceSerializerTest.java3
-rw-r--r--vespa-athenz/pom.xml6
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java6
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java3
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/CsrGenerator.java9
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSigner.java7
-rw-r--r--vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java3
-rw-r--r--vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/InstanceCsrGeneratorTest.java17
12 files changed, 69 insertions, 24 deletions
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/IdentityDocumentGenerator.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/IdentityDocumentGenerator.java
index 5042c8cf617..258cd3fc091 100644
--- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/IdentityDocumentGenerator.java
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/IdentityDocumentGenerator.java
@@ -65,7 +65,7 @@ public class IdentityDocumentGenerator {
String configServerHostname = HostName.getLocalhost();
Instant createdAt = Instant.now();
- var clusterType = allocation.membership().cluster().type().name();
+ var clusterType = allocation.membership().cluster().type();
String signature = signer.generateSignature(
providerUniqueId, providerService, configServerHostname,
node.hostname(), createdAt, ips, identityType, clusterType, privateKey);
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/InstanceValidator.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/InstanceValidator.java
index 82f486f1bc0..b316d9fb0b4 100644
--- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/InstanceValidator.java
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/InstanceValidator.java
@@ -176,9 +176,9 @@ public class InstanceValidator {
log.log(Level.WARNING, "Invalid SAN URIs: " + urisCommaSeparated);
return false;
}
- var clusterType = node.allocation().map(a -> a.membership().cluster().type().name()).orElse(null);
+ var clusterType = node.allocation().map(a -> a.membership().cluster().type()).orElse(null);
Set<URI> allowedUris = clusterType != null
- ? Set.of(URI.create("vespa://cluster-type/%s".formatted(clusterType))) : Set.of();
+ ? Set.of(URI.create("vespa://cluster-type/%s".formatted(clusterType.name()))) : Set.of();
if (!allowedUris.containsAll(requestedUris)) {
log.log(Level.WARNING, "Illegal SAN URIs: expected '%s' found '%s'".formatted(allowedUris, requestedUris));
return false;
diff --git a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/InstanceSerializer.java b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/InstanceSerializer.java
index 2e143bc53cc..800636943d9 100644
--- a/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/InstanceSerializer.java
+++ b/athenz-identity-provider-service/src/main/java/com/yahoo/vespa/hosted/ca/restapi/InstanceSerializer.java
@@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.ca.restapi;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.security.Pkcs10CsrUtils;
import com.yahoo.security.X509CertificateUtils;
import com.yahoo.slime.ArrayTraverser;
@@ -98,7 +99,7 @@ public class InstanceSerializer {
requireField(IDD_IPADDRESSES_FIELD, root).traverse((ArrayTraverser) (__, entry) -> ips.add(entry.asString()));
IdentityType identityType = IdentityType.fromId(requireField(IDD_IDENTITY_TYPE_FIELD, root).asString());
var clusterTypeField = root.field(IDD_CLUSTER_TYPE_FIELD);
- var clusterType = root.valid() ? clusterTypeField.asString() : null;
+ var clusterType = clusterTypeField.valid() ? ClusterSpec.Type.from(clusterTypeField.asString()) : null;
return new SignedIdentityDocument(signature, (int)signingKeyVersion, providerUniqueId, athenzService, (int)documentVersion,
diff --git a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/InstanceValidatorTest.java b/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/InstanceValidatorTest.java
index 2014b74a3e6..fbaa57d9694 100644
--- a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/InstanceValidatorTest.java
+++ b/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/athenz/instanceproviderservice/InstanceValidatorTest.java
@@ -10,6 +10,7 @@ import com.yahoo.config.model.api.SuperModel;
import com.yahoo.config.model.api.SuperModelProvider;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterMembership;
+import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
import com.yahoo.vespa.athenz.api.AthenzService;
@@ -59,6 +60,7 @@ public class InstanceValidatorTest {
private final String service = "service";
private final AthenzService vespaTenantDomain = new AthenzService("vespa.vespa.tenant");
+ private final AutoGeneratedKeyProvider keyProvider = new AutoGeneratedKeyProvider();
@Test
void application_does_not_exist() {
@@ -133,6 +135,17 @@ public class InstanceValidatorTest {
}
@Test
+ void rejects_invalid_cluster_type_in_csr() {
+ var props = Map.of(SERVICE_PROPERTIES_DOMAIN_KEY, domain, SERVICE_PROPERTIES_SERVICE_KEY, service);
+ var info = new ServiceInfo("serviceName", "type", List.of(), props, "confId", "hostName");
+ var provider = mockSuperModelProvider(mockApplicationInfo(applicationId, 5, List.of(info)));
+ var instanceValidator = new InstanceValidator(keyProvider, provider, mockNodeRepo(), new IdentityDocumentSigner(), vespaTenantDomain);
+ var instanceConfirmation = createRegisterInstanceConfirmation(applicationId, domain, service);
+ instanceConfirmation.set("sanURI", "vespa://cluster-type/content");
+ assertFalse(instanceValidator.isValidInstance(instanceConfirmation));
+ }
+
+ @Test
void accepts_valid_refresh_requests() {
NodeRepository nodeRepository = mock(NodeRepository.class);
Nodes nodes = mock(Nodes.class);
@@ -188,8 +201,6 @@ public class InstanceValidatorTest {
NodeRepository nodeRepository = mock(NodeRepository.class);
Nodes nodes = mock(Nodes.class);
when(nodeRepository.nodes()).thenReturn(nodes);
- InstanceValidator instanceValidator = new InstanceValidator(null, null, nodeRepository, new IdentityDocumentSigner(), vespaTenantDomain);
-
List<Node> nodeList = createNodes(10);
Node node = nodeList.get(0);
nodeList = allocateNode(nodeList, node, applicationId);
@@ -197,11 +208,19 @@ public class InstanceValidatorTest {
return nodeRepository;
}
- private InstanceConfirmation createRegisterInstanceConfirmation(ApplicationId applicationId, String domain, String service) {
+ private InstanceConfirmation createRegisterInstanceConfirmation(
+ ApplicationId applicationId, String domain, String service) {
VespaUniqueInstanceId vespaUniqueInstanceId = new VespaUniqueInstanceId(0, "default", applicationId.instance().value(), applicationId.application().value(), applicationId.tenant().value(), "us-north-1", "dev", IdentityType.NODE);
+ var domainService = new AthenzService(domain, service);
+ var clock = Instant.now();
+ var clusterType = ClusterSpec.Type.container;
+ var signature = new IdentityDocumentSigner()
+ .generateSignature(
+ vespaUniqueInstanceId, domainService, "localhost", "localhost", clock, Set.of(),
+ IdentityType.NODE, clusterType, keyProvider.getPrivateKey(0));
SignedIdentityDocument signedIdentityDocument = new SignedIdentityDocument(
- null, 0, vespaUniqueInstanceId, new AthenzService(domain, service), 0, "localhost", "localhost",
- Instant.now(), Collections.emptySet(), IdentityType.NODE, "container");
+ signature, 0, vespaUniqueInstanceId, domainService, 0, "localhost", "localhost",
+ clock, Collections.emptySet(), IdentityType.NODE, clusterType);
return createInstanceConfirmation(vespaUniqueInstanceId, domain, service, signedIdentityDocument);
}
@@ -221,6 +240,7 @@ public class InstanceValidatorTest {
.map(EntityBindingsMapper::toSignedIdentityDocumentEntity)
.orElse(null));
instanceConfirmation.set("sanDNS", vespaUniqueInstanceId.asDottedString() + ".instanceid.athenz.dev-us-north-1.vespa.yahoo.cloud");
+ instanceConfirmation.set("sanURI", "vespa://cluster-type/container");
return instanceConfirmation;
}
diff --git a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/ca/restapi/InstanceSerializerTest.java b/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/ca/restapi/InstanceSerializerTest.java
index 4e977324298..fbd98a70b74 100644
--- a/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/ca/restapi/InstanceSerializerTest.java
+++ b/athenz-identity-provider-service/src/test/java/com/yahoo/vespa/hosted/ca/restapi/InstanceSerializerTest.java
@@ -1,6 +1,7 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.ca.restapi;
+import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.security.Pkcs10CsrUtils;
import com.yahoo.security.X509CertificateUtils;
import com.yahoo.slime.Slime;
@@ -47,7 +48,7 @@ public class InstanceSerializerTest {
Instant.now().truncatedTo(ChronoUnit.MICROS), // Truncate to the precision given from EntityBindingsMapper.toAttestationData()
Collections.emptySet(),
IdentityType.NODE,
- "container");
+ ClusterSpec.Type.container);
var json = String.format("{\n" +
" \"provider\": \"provider_prod_us-north-1\",\n" +
diff --git a/vespa-athenz/pom.xml b/vespa-athenz/pom.xml
index 29a4058e180..d7a9b55d05f 100644
--- a/vespa-athenz/pom.xml
+++ b/vespa-athenz/pom.xml
@@ -92,6 +92,12 @@
<artifactId>guava</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>config-provisioning</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
<!-- test -->
<dependency>
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java
index 0949192b884..ddec80cda9d 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.athenz.identityprovider.api;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.identityprovider.api.bindings.SignedIdentityDocumentEntity;
@@ -14,6 +15,7 @@ import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
+import java.util.Optional;
import static com.yahoo.vespa.athenz.identityprovider.api.VespaUniqueInstanceId.fromDottedString;
@@ -48,7 +50,7 @@ public class EntityBindingsMapper {
entity.createdAt(),
entity.ipAddresses(),
IdentityType.fromId(entity.identityType()),
- entity.clusterType());
+ ClusterSpec.Type.from(entity.clusterType()));
}
public static SignedIdentityDocumentEntity toSignedIdentityDocumentEntity(SignedIdentityDocument model) {
@@ -63,7 +65,7 @@ public class EntityBindingsMapper {
model.createdAt(),
model.ipAddresses(),
model.identityType().id(),
- model.clusterType());
+ Optional.ofNullable(model.clusterType()).map(ClusterSpec.Type::name).orElse(null));
}
public static SignedIdentityDocument readSignedIdentityDocumentFromFile(Path file) {
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 c2d8ece84a5..0fe09f47d80 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
@@ -1,6 +1,7 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.athenz.identityprovider.api;
+import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.vespa.athenz.api.AthenzService;
import java.time.Instant;
@@ -14,7 +15,7 @@ import java.util.Set;
public record SignedIdentityDocument(String signature, int signingKeyVersion, VespaUniqueInstanceId providerUniqueId,
AthenzService providerService, int documentVersion, String configServerHostname,
String instanceHostname, Instant createdAt, Set<String> ipAddresses,
- IdentityType identityType, String clusterType) {
+ IdentityType identityType, ClusterSpec.Type clusterType) {
public static final int DEFAULT_DOCUMENT_VERSION = 2;
}
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 bafeab805bd..8deecb9d549 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
@@ -1,6 +1,7 @@
// Copyright Yahoo. 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.config.provision.ClusterSpec;
import com.yahoo.security.Pkcs10Csr;
import com.yahoo.security.Pkcs10CsrBuilder;
import com.yahoo.security.SubjectAlternativeName;
@@ -36,7 +37,7 @@ public class CsrGenerator {
public Pkcs10Csr generateInstanceCsr(AthenzIdentity instanceIdentity,
VespaUniqueInstanceId instanceId,
Set<String> ipAddresses,
- String clusterType,
+ ClusterSpec.Type clusterType,
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>
@@ -50,7 +51,7 @@ public class CsrGenerator {
instanceIdentity.getDomainName().replace(".", "-"),
dnsSuffix))
.addSubjectAlternativeName(DNS, getIdentitySAN(instanceId));
- if (clusterType != null) pkcs10CsrBuilder.addSubjectAlternativeName(URI, "vespa://cluster-type/%s".formatted(clusterType));
+ if (clusterType != null) pkcs10CsrBuilder.addSubjectAlternativeName(URI, "vespa://cluster-type/%s".formatted(clusterType.name()));
ipAddresses.forEach(ip -> pkcs10CsrBuilder.addSubjectAlternativeName(new SubjectAlternativeName(IP, ip)));
return pkcs10CsrBuilder.build();
}
@@ -58,13 +59,13 @@ public class CsrGenerator {
public Pkcs10Csr generateRoleCsr(AthenzIdentity identity,
AthenzRole role,
VespaUniqueInstanceId instanceId,
- String clusterType,
+ ClusterSpec.Type clusterType,
KeyPair keyPair) {
X500Principal principal = new X500Principal(String.format("OU=%s, cn=%s:role.%s", providerService, role.domain().getName(), role.roleName()));
var b = Pkcs10CsrBuilder.fromKeypair(principal, keyPair, SHA256_WITH_RSA)
.addSubjectAlternativeName(DNS, getIdentitySAN(instanceId))
.addSubjectAlternativeName(EMAIL, String.format("%s.%s@%s", identity.getDomainName(), identity.getName(), dnsSuffix));
- if (clusterType != null) b.addSubjectAlternativeName(URI, "vespa://cluster-type/%s".formatted(clusterType));
+ if (clusterType != null) b.addSubjectAlternativeName(URI, "vespa://cluster-type/%s".formatted(clusterType.name()));
return b.build();
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSigner.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSigner.java
index 13bea80dfed..6aa22263a7e 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSigner.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSigner.java
@@ -1,6 +1,7 @@
// Copyright Yahoo. 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.config.provision.ClusterSpec;
import com.yahoo.security.SignatureUtils;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.identityprovider.api.IdentityType;
@@ -34,7 +35,7 @@ public class IdentityDocumentSigner {
Instant createdAt,
Set<String> ipAddresses,
IdentityType identityType,
- String clusterType,
+ ClusterSpec.Type clusterType,
PrivateKey privateKey) {
try {
Signature signer = SignatureUtils.createSigner(privateKey);
@@ -70,7 +71,7 @@ public class IdentityDocumentSigner {
Instant createdAt,
Set<String> ipAddresses,
IdentityType identityType,
- String clusterType) throws SignatureException {
+ ClusterSpec.Type clusterType) throws SignatureException {
signer.update(providerUniqueId.asDottedString().getBytes(UTF_8));
signer.update(providerService.getFullName().getBytes(UTF_8));
signer.update(configServerHostname.getBytes(UTF_8));
@@ -82,6 +83,6 @@ public class IdentityDocumentSigner {
signer.update(ipAddress.getBytes(UTF_8));
}
signer.update(identityType.id().getBytes(UTF_8));
- if (clusterType != null) signer.update(clusterType.getBytes(UTF_8));
+ if (clusterType != null) signer.update(clusterType.name().getBytes(UTF_8));
}
}
diff --git a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java
index ede006539a1..55d134fd7cb 100644
--- a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java
+++ b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java
@@ -1,6 +1,7 @@
// Copyright Yahoo. 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.config.provision.ClusterSpec;
import com.yahoo.security.KeyAlgorithm;
import com.yahoo.security.KeyUtils;
import com.yahoo.vespa.athenz.api.AthenzService;
@@ -36,7 +37,7 @@ public class IdentityDocumentSignerTest {
String instanceHostname = "instancehostname";
Instant createdAt = Instant.EPOCH;
HashSet<String> ipAddresses = new HashSet<>(Arrays.asList("1.2.3.4", "::1"));
- String clusterType = "container";
+ var clusterType = ClusterSpec.Type.container;
String signature =
signer.generateSignature(id, providerService, configserverHostname, instanceHostname, createdAt,
ipAddresses, identityType, clusterType, keyPair.getPrivate());
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 aa4c3e68094..09fefdff0bd 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
@@ -1,17 +1,22 @@
// Copyright Yahoo. 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.config.provision.ClusterSpec;
import com.yahoo.security.KeyAlgorithm;
import com.yahoo.security.KeyUtils;
+import com.yahoo.security.Pkcs10Csr;
+import com.yahoo.security.SubjectAlternativeName;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.identityprovider.api.VespaUniqueInstanceId;
-import com.yahoo.security.Pkcs10Csr;
import org.junit.jupiter.api.Test;
import javax.security.auth.x500.X500Principal;
import java.security.KeyPair;
import java.util.Collections;
+import java.util.Set;
+import static com.yahoo.security.SubjectAlternativeName.Type.DNS;
+import static com.yahoo.security.SubjectAlternativeName.Type.URI;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -24,14 +29,20 @@ public class InstanceCsrGeneratorTest {
private static final String ATHENZ_SERVICE = "foo.bar";
@Test
- void it_generates_csr_with_correct_subject() {
+ void generates_correct_subject_and_alternative_names() {
CsrGenerator csrGenerator = new CsrGenerator(DNS_SUFFIX, PROVIDER_SERVICE);
AthenzService service = new AthenzService(ATHENZ_SERVICE);
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(), "container", keyPair);
+ Pkcs10Csr csr = csrGenerator.generateInstanceCsr(service, vespaUniqueInstanceId, Collections.emptySet(), ClusterSpec.Type.container, keyPair);
assertEquals(new X500Principal(String.format("OU=%s, CN=%s", PROVIDER_SERVICE, ATHENZ_SERVICE)), csr.getSubject());
+ var actualSans = Set.copyOf(csr.getSubjectAlternativeNames());
+ var expectedSans = Set.of(
+ new SubjectAlternativeName(DNS, "bar.foo.prod-us-north-1.vespa.yahoo.cloud"),
+ new SubjectAlternativeName(DNS, "0.default.default.foo-app.vespa.us-north-1.prod.node.instanceid.athenz.prod-us-north-1.vespa.yahoo.cloud"),
+ new SubjectAlternativeName(URI, "vespa://cluster-type/container"));
+ assertEquals(expectedSans, actualSans);
}
}