aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server/src
diff options
context:
space:
mode:
Diffstat (limited to 'controller-server/src')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java69
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/BasicServicesXml.java5
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificates.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/UnassignedCertificate.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CertificatePoolMaintainer.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java11
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/EndpointCertificateSerializer.java8
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/pkg/BasicServicesXmlTest.java4
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificatesTest.java19
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainerTest.java11
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java82
11 files changed, 160 insertions, 65 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java
index 90c4a506f10..b763af1af9d 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java
@@ -51,7 +51,6 @@ import com.yahoo.vespa.hosted.rotation.config.RotationsConfig;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -135,7 +134,7 @@ public class RoutingController {
}
// Add zone-scoped endpoints
- Map<EndpointId, GeneratedEndpointList> generatedForDeclaredEndpoints = new HashMap<>();
+ Map<EndpointId, List<GeneratedEndpoint>> generatedForDeclaredEndpoints = new HashMap<>();
Set<ClusterSpec.Id> clustersWithToken = new HashSet<>();
boolean generatedEndpointsEnabled = generatedEndpointsEnabled(deployment.applicationId());
RoutingPolicyList applicationPolicies = policies().read(TenantAndApplicationId.from(deployment.applicationId()));
@@ -149,9 +148,10 @@ public class RoutingController {
Optional<RoutingPolicy> clusterPolicy = deploymentPolicies.cluster(clusterId).first();
List<GeneratedEndpoint> generatedForCluster = clusterPolicy.map(policy -> policy.generatedEndpoints().cluster().asList())
.orElseGet(List::of);
- // Generate endpoints if cluster does not have any
- if (generatedForCluster.isEmpty()) {
- generatedForCluster = generateEndpoints(tokenSupported, certificate, Optional.empty());
+ // Generate endpoint for each auth method, if not present
+ generatedForCluster = generateEndpoints(AuthMethod.mtls, certificate, Optional.empty(), generatedForCluster);
+ if (tokenSupported) {
+ generatedForCluster = generateEndpoints(AuthMethod.token, certificate, Optional.empty(), generatedForCluster);
}
GeneratedEndpointList generatedEndpoints = generatedEndpointsEnabled ? GeneratedEndpointList.copyOf(generatedForCluster) : GeneratedEndpointList.EMPTY;
endpoints = endpoints.and(endpointsOf(deployment, clusterId, generatedEndpoints).scope(Scope.zone));
@@ -162,18 +162,34 @@ public class RoutingController {
ClusterSpec.Id clusterId = ClusterSpec.Id.from(container.id());
applicationPolicies.cluster(clusterId).asList().stream()
.flatMap(policy -> policy.generatedEndpoints().declared().asList().stream())
- .forEach(ge -> generatedForDeclaredEndpoints.computeIfAbsent(ge.endpoint().get(), (k) -> GeneratedEndpointList.of(ge)));
+ .forEach(ge -> {
+ List<GeneratedEndpoint> generated = generatedForDeclaredEndpoints.computeIfAbsent(ge.endpoint().get(), (k) -> new ArrayList<>());
+ if (!generated.contains(ge)) {
+ generated.add(ge);
+ }
+ });
}
// Generate endpoints if declared endpoint does not have any
Stream.concat(spec.endpoints().stream(), spec.instances().stream().flatMap(i -> i.endpoints().stream()))
.forEach(endpoint -> {
EndpointId endpointId = EndpointId.of(endpoint.endpointId());
- generatedForDeclaredEndpoints.computeIfAbsent(endpointId, (k) -> {
+ generatedForDeclaredEndpoints.compute(endpointId, (k, old) -> {
+ if (old == null) {
+ old = List.of();
+ }
+ List<GeneratedEndpoint> generatedEndpoints = generateEndpoints(AuthMethod.mtls, certificate, Optional.of(endpointId), old);
boolean tokenSupported = clustersWithToken.contains(ClusterSpec.Id.from(endpoint.containerId()));
- return generatedEndpointsEnabled ? GeneratedEndpointList.copyOf(generateEndpoints(tokenSupported, certificate, Optional.of(endpointId))) : null;
+ if (tokenSupported){
+ generatedEndpoints = generateEndpoints(AuthMethod.token, certificate, Optional.of(endpointId), generatedEndpoints);
+ }
+ return generatedEndpoints;
});
});
- Map<EndpointId, GeneratedEndpointList> generatedEndpoints = generatedEndpointsEnabled ? generatedForDeclaredEndpoints : Map.of();
+ Map<EndpointId, GeneratedEndpointList> generatedEndpoints = generatedEndpointsEnabled
+ ? generatedForDeclaredEndpoints.entrySet()
+ .stream()
+ .collect(Collectors.toMap(Map.Entry::getKey, kv -> GeneratedEndpointList.copyOf(kv.getValue())))
+ : Map.of();
endpoints = endpoints.and(declaredEndpointsOf(application.get().id(), spec, generatedEndpoints).targets(deployment));
PreparedEndpoints prepared = new PreparedEndpoints(deployment,
endpoints,
@@ -186,12 +202,6 @@ public class RoutingController {
return prepared;
}
- private List<GeneratedEndpoint> generateEndpoints(boolean tokenSupported, Optional<EndpointCertificate> certificate, Optional<EndpointId> endpoint) {
- return certificate.flatMap(EndpointCertificate::randomizedId)
- .map(id -> generateEndpoints(id, tokenSupported, endpoint))
- .orElseGet(List::of);
- }
-
// -------------- Implicit endpoints (scopes 'zone' and 'weighted') --------------
/** Returns the zone- and region-scoped endpoints of given deployment */
@@ -480,19 +490,22 @@ public class RoutingController {
}
}
- /** Generate endpoints for all authentication methods, using given application part */
- private List<GeneratedEndpoint> generateEndpoints(String applicationPart, boolean token, Optional<EndpointId> endpoint) {
- return Arrays.stream(AuthMethod.values())
- .filter(method -> switch (method) {
- case token -> token;
- case mtls -> true;
- case none -> false;
- })
- .map(method -> new GeneratedEndpoint(GeneratedEndpoint.createPart(controller.random(true)),
- applicationPart,
- method,
- endpoint))
- .toList();
+ /** Returns generated endpoints. A new endpoint is generated if no matching endpoint already exists */
+ private List<GeneratedEndpoint> generateEndpoints(AuthMethod authMethod, Optional<EndpointCertificate> certificate,
+ Optional<EndpointId> declaredEndpoint,
+ List<GeneratedEndpoint> current) {
+ if (current.stream().anyMatch(e -> e.authMethod() == authMethod && e.endpoint().equals(declaredEndpoint))) {
+ return current;
+ }
+ Optional<String> applicationPart = certificate.flatMap(EndpointCertificate::generatedId);
+ if (applicationPart.isPresent()) {
+ current = new ArrayList<>(current);
+ current.add(new GeneratedEndpoint(GeneratedEndpoint.createPart(controller.random(true)),
+ applicationPart.get(),
+ authMethod,
+ declaredEndpoint));
+ }
+ return current;
}
/** Generate the cluster part of a {@link GeneratedEndpoint} for use in a {@link Endpoint.Scope#weighted} endpoint */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/BasicServicesXml.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/BasicServicesXml.java
index 8f3a02528fe..6a634cb8f53 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/BasicServicesXml.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/BasicServicesXml.java
@@ -9,7 +9,6 @@ import org.w3c.dom.Element;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
-import java.util.TreeSet;
/**
* A partially parsed variant of services.xml, for use by the {@link com.yahoo.vespa.hosted.controller.Controller}.
@@ -40,7 +39,9 @@ public record BasicServicesXml(List<Container> containers) {
for (var childNode : XML.getChildren(root)) {
if (childNode.getTagName().equals(CONTAINER_TAG)) {
String id = childNode.getAttribute("id");
- if (id.isEmpty()) throw new IllegalArgumentException(CONTAINER_TAG + " tag requires 'id' attribute");
+ if (id.isEmpty()) {
+ id = CONTAINER_TAG; // ID defaults to tag name when unset. See ConfigModelBuilder::getIdString
+ }
List<Container.AuthMethod> methods = new ArrayList<>();
List<TokenId> tokens = new ArrayList<>();
parseAuthMethods(childNode, methods, tokens);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificates.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificates.java
index b5e012253c7..ec2ef4b7ff8 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificates.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificates.java
@@ -119,11 +119,11 @@ public class EndpointCertificates {
TenantAndApplicationId application = TenantAndApplicationId.from(instance.id());
Optional<AssignedCertificate> perInstanceAssignedCertificate = curator.readAssignedCertificate(application, Optional.of(instance.name()));
- if (perInstanceAssignedCertificate.isPresent() && perInstanceAssignedCertificate.get().certificate().randomizedId().isPresent()) {
+ if (perInstanceAssignedCertificate.isPresent() && perInstanceAssignedCertificate.get().certificate().generatedId().isPresent()) {
return updateLastRequested(perInstanceAssignedCertificate.get()).certificate();
} else if (! zone.environment().isManuallyDeployed()) {
Optional<AssignedCertificate> perApplicationAssignedCertificate = curator.readAssignedCertificate(application, Optional.empty());
- if (perApplicationAssignedCertificate.isPresent() && perApplicationAssignedCertificate.get().certificate().randomizedId().isPresent()) {
+ if (perApplicationAssignedCertificate.isPresent() && perApplicationAssignedCertificate.get().certificate().generatedId().isPresent()) {
return updateLastRequested(perApplicationAssignedCertificate.get()).certificate();
}
}
@@ -181,7 +181,7 @@ public class EndpointCertificates {
boolean legacyNames = assignLegacyNames.with(FetchVector.Dimension.INSTANCE_ID, instance.id().serializedForm())
.with(FetchVector.Dimension.APPLICATION_ID, instance.id().toSerializedFormWithoutInstance()).value();
- var requiredSansForZone = legacyNames || currentCertificate.get().randomizedId().isEmpty() ?
+ var requiredSansForZone = legacyNames || currentCertificate.get().generatedId().isEmpty() ?
controller.routing().certificateDnsNames(deployment, deploymentSpec) :
List.<String>of();
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/UnassignedCertificate.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/UnassignedCertificate.java
index 3a8580b7eb5..1566949664b 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/UnassignedCertificate.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/certificate/UnassignedCertificate.java
@@ -14,13 +14,13 @@ import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCe
public record UnassignedCertificate(EndpointCertificate certificate, UnassignedCertificate.State state) {
public UnassignedCertificate {
- if (certificate.randomizedId().isEmpty()) {
- throw new IllegalArgumentException("randomizedId must be set for a pooled certificate");
+ if (certificate.generatedId().isEmpty()) {
+ throw new IllegalArgumentException("generatedId must be set for a pooled certificate");
}
}
public String id() {
- return certificate.randomizedId().get();
+ return certificate.generatedId().get();
}
public UnassignedCertificate withState(State state) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CertificatePoolMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CertificatePoolMaintainer.java
index ed383175cc3..a07b6e14625 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CertificatePoolMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CertificatePoolMaintainer.java
@@ -106,7 +106,7 @@ public class CertificatePoolMaintainer extends ControllerMaintainer {
curator.readAssignedCertificates().stream()
.map(AssignedCertificate::certificate)
- .map(EndpointCertificate::randomizedId)
+ .map(EndpointCertificate::generatedId)
.forEach(id -> id.ifPresent(existingNames::add));
String id = generateRandomId();
@@ -122,7 +122,7 @@ public class CertificatePoolMaintainer extends ControllerMaintainer {
Optional.empty(),
endpointCertificateAlgo.value(),
useAlternateCertProvider.value())
- .withRandomizedId(id);
+ .withGeneratedId(id);
UnassignedCertificate certificate = new UnassignedCertificate(f, UnassignedCertificate.State.requested);
curator.writeUnassignedCertificate(certificate);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java
index 805bf3d7ada..f4936dcfa8b 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainer.java
@@ -11,7 +11,6 @@ import com.yahoo.container.jdisc.secretstore.SecretStore;
import com.yahoo.transaction.Mutex;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.vespa.flags.BooleanFlag;
-import com.yahoo.vespa.flags.FetchVector;
import com.yahoo.vespa.flags.Flags;
import com.yahoo.vespa.flags.IntFlag;
import com.yahoo.vespa.flags.PermanentFlags;
@@ -280,7 +279,7 @@ public class EndpointCertificateMaintainer extends ControllerMaintainer {
*/
assignedCertificates.stream()
.filter(c -> c.instance().isPresent())
- .filter(c -> c.certificate().randomizedId().isEmpty())
+ .filter(c -> c.certificate().generatedId().isEmpty())
.filter(c -> controller().applications().getApplication(c.application()).isPresent()) // In case application has been deleted, but certificate is pending deletion
.limit(assignRandomizedIdRate.value())
.forEach(c -> assignRandomizedId(c.application(), c.instance().get()));
@@ -300,7 +299,7 @@ public class EndpointCertificateMaintainer extends ControllerMaintainer {
log.log(Level.INFO, "Assigned certificate missing for " + tenantAndApplicationId.instance(instanceName).toFullString() + " when assigning randomized id");
}
// Verify that the assigned certificate still does not have randomized id assigned
- if (assignedCertificate.get().certificate().randomizedId().isPresent()) return;
+ if (assignedCertificate.get().certificate().generatedId().isPresent()) return;
controller().applications().lockApplicationOrThrow(tenantAndApplicationId, application -> {
DeploymentSpec deploymentSpec = application.get().deploymentSpec();
@@ -320,7 +319,7 @@ public class EndpointCertificateMaintainer extends ControllerMaintainer {
EndpointCertificate withRandomNames = requestRandomNames(
tenantAndApplicationId,
instanceLevelAssignedCertificate.instance(),
- applicationLevelAssignedCertificate.get().certificate().randomizedId()
+ applicationLevelAssignedCertificate.get().certificate().generatedId()
.orElseThrow(() -> new IllegalArgumentException("Application certificate already assigned to " + tenantAndApplicationId.toString() + ", but random id is missing")),
Optional.of(instanceLevelAssignedCertificate.certificate()));
AssignedCertificate assignedCertWithRandomNames = instanceLevelAssignedCertificate.with(withRandomNames);
@@ -365,12 +364,12 @@ public class EndpointCertificateMaintainer extends ControllerMaintainer {
previousRequest,
endpointCertificateAlgo.value(),
useAlternateCertProvider.value())
- .withRandomizedId(randomId);
+ .withGeneratedId(randomId);
}
private String generateRandomId() {
List<String> unassignedIds = curator.readUnassignedCertificates().stream().map(UnassignedCertificate::id).toList();
- List<String> assignedIds = curator.readAssignedCertificates().stream().map(AssignedCertificate::certificate).map(EndpointCertificate::randomizedId).filter(Optional::isPresent).map(Optional::get).toList();
+ List<String> assignedIds = curator.readAssignedCertificates().stream().map(AssignedCertificate::certificate).map(EndpointCertificate::generatedId).filter(Optional::isPresent).map(Optional::get).toList();
Set<String> allIds = Stream.concat(unassignedIds.stream(), assignedIds.stream()).collect(Collectors.toSet());
String randomId;
do {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/EndpointCertificateSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/EndpointCertificateSerializer.java
index fae9ea1e0e3..2ff4f1fb194 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/EndpointCertificateSerializer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/EndpointCertificateSerializer.java
@@ -35,7 +35,7 @@ public class EndpointCertificateSerializer {
private final static String issuerField = "issuer";
private final static String expiryField = "expiry";
private final static String lastRefreshedField = "lastRefreshed";
- private final static String randomizedIdField = "randomizedId";
+ private final static String generatedIdField = "randomizedId";
public static Slime toSlime(EndpointCertificate cert) {
Slime slime = new Slime();
@@ -56,7 +56,7 @@ public class EndpointCertificateSerializer {
object.setString(issuerField, cert.issuer());
cert.expiry().ifPresent(expiry -> object.setLong(expiryField, expiry));
cert.lastRefreshed().ifPresent(refreshTime -> object.setLong(lastRefreshedField, refreshTime));
- cert.randomizedId().ifPresent(randomizedId -> object.setString(randomizedIdField, randomizedId));
+ cert.generatedId().ifPresent(id -> object.setString(generatedIdField, id));
}
public static EndpointCertificate fromSlime(Inspector inspector) {
@@ -79,8 +79,8 @@ public class EndpointCertificateSerializer {
inspector.field(lastRefreshedField).valid() ?
Optional.of(inspector.field(lastRefreshedField).asLong()) :
Optional.empty(),
- inspector.field(randomizedIdField).valid() ?
- Optional.of(inspector.field(randomizedIdField).asString()) :
+ inspector.field(generatedIdField).valid() ?
+ Optional.of(inspector.field(generatedIdField).asString()) :
Optional.empty());
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/pkg/BasicServicesXmlTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/pkg/BasicServicesXmlTest.java
index c28185466b0..f7bd1e06e68 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/pkg/BasicServicesXmlTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/pkg/BasicServicesXmlTest.java
@@ -18,11 +18,13 @@ class BasicServicesXmlTest {
public void parse() {
assertServices(new BasicServicesXml(List.of()), "<services/>");
assertServices(new BasicServicesXml(List.of(new Container("foo", List.of(Container.AuthMethod.mtls), List.of()),
- new Container("bar", List.of(Container.AuthMethod.mtls), List.of()))),
+ new Container("bar", List.of(Container.AuthMethod.mtls), List.of()),
+ new Container("container", List.of(Container.AuthMethod.mtls), List.of()))),
"""
<services>
<container id="foo"/>
<container id="bar"/>
+ <container/>
</services>
""");
assertServices(new BasicServicesXml(List.of(
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificatesTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificatesTest.java
index a6d3b435dcb..2bc11adddf7 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificatesTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificatesTest.java
@@ -28,7 +28,6 @@ import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackage;
import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder;
import com.yahoo.vespa.hosted.controller.integration.SecretStoreMock;
import com.yahoo.vespa.hosted.controller.integration.ZoneApiMock;
-import com.yahoo.vespa.hosted.controller.maintenance.EndpointCertificateMaintainer;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -296,7 +295,7 @@ public class EndpointCertificatesTest {
// Initial certificate is requested directly from provider
Optional<EndpointCertificate> certFromProvider = endpointCertificates.get(instance, prodZone, DeploymentSpec.empty);
assertTrue(certFromProvider.isPresent());
- assertFalse(certFromProvider.get().randomizedId().isPresent());
+ assertFalse(certFromProvider.get().generatedId().isPresent());
// Pooled certificates become available
tester.flagSource().withBooleanFlag(Flags.RANDOMIZED_ENDPOINT_NAMES.id(), true);
@@ -315,8 +314,8 @@ public class EndpointCertificatesTest {
String certId = "pool-cert-1";
addCertificateToPool(certId, UnassignedCertificate.State.ready);
Optional<EndpointCertificate> cert = endpointCertificates.get(instance, prodZone, DeploymentSpec.empty);
- assertEquals(certId, cert.get().randomizedId().get());
- assertEquals(certId, tester.curator().readAssignedCertificate(TenantAndApplicationId.from(instance.id()), Optional.empty()).get().certificate().randomizedId().get(), "Certificate is assigned at application-level");
+ assertEquals(certId, cert.get().generatedId().get());
+ assertEquals(certId, tester.curator().readAssignedCertificate(TenantAndApplicationId.from(instance.id()), Optional.empty()).get().certificate().generatedId().get(), "Certificate is assigned at application-level");
assertTrue(tester.controller().curator().readUnassignedCertificate(certId).isEmpty(), "Certificate is removed from pool");
assertEquals(clock.instant().getEpochSecond(), cert.get().lastRequested());
}
@@ -326,8 +325,8 @@ public class EndpointCertificatesTest {
addCertificateToPool(certId, UnassignedCertificate.State.ready);
ZoneId devZone = tester.zoneRegistry().zones().all().routingMethod(RoutingMethod.exclusive).in(Environment.dev).zones().stream().findFirst().orElseThrow().getId();
Optional<EndpointCertificate> cert = endpointCertificates.get(instance, devZone, DeploymentSpec.empty);
- assertEquals(certId, cert.get().randomizedId().get());
- assertEquals(certId, tester.curator().readAssignedCertificate(instance.id()).get().certificate().randomizedId().get(), "Certificate is assigned at instance-level");
+ assertEquals(certId, cert.get().generatedId().get());
+ assertEquals(certId, tester.curator().readAssignedCertificate(instance.id()).get().certificate().generatedId().get(), "Certificate is assigned at instance-level");
assertTrue(tester.controller().curator().readUnassignedCertificate(certId).isEmpty(), "Certificate is removed from pool");
assertEquals(clock.instant().getEpochSecond(), cert.get().lastRequested());
}
@@ -338,7 +337,7 @@ public class EndpointCertificatesTest {
// Initial certificate is requested directly from provider
Optional<EndpointCertificate> certFromProvider = endpointCertificates.get(instance, prodZone, DeploymentSpec.empty);
assertTrue(certFromProvider.isPresent());
- assertFalse(certFromProvider.get().randomizedId().isPresent());
+ assertFalse(certFromProvider.get().generatedId().isPresent());
// Simulate endpoint certificate maintainer to assign random id
TenantAndApplicationId tenantAndApplicationId = TenantAndApplicationId.from(instance.id());
@@ -346,7 +345,7 @@ public class EndpointCertificatesTest {
Optional<AssignedCertificate> assignedCertificate = tester.controller().curator().readAssignedCertificate(tenantAndApplicationId, instanceName);
assertTrue(assignedCertificate.isPresent());
String assignedRandomId = "randomid";
- AssignedCertificate updated = assignedCertificate.get().with(assignedCertificate.get().certificate().withRandomizedId(assignedRandomId));
+ AssignedCertificate updated = assignedCertificate.get().with(assignedCertificate.get().certificate().withGeneratedId(assignedRandomId));
tester.controller().curator().writeAssignedCertificate(updated);
// Pooled certificates become available
@@ -358,12 +357,12 @@ public class EndpointCertificatesTest {
// Request cert for app
Optional<EndpointCertificate> cert = endpointCertificates.get(instance, prodZone, DeploymentSpec.empty);
- assertEquals(assignedRandomId, cert.get().randomizedId().get());
+ assertEquals(assignedRandomId, cert.get().generatedId().get());
// Pooled cert remains unassigned
List<String> unassignedCertificateIds = tester.curator().readUnassignedCertificates().stream()
.map(UnassignedCertificate::certificate)
- .map(EndpointCertificate::randomizedId)
+ .map(EndpointCertificate::generatedId)
.map(Optional::get)
.toList();
assertEquals(List.of(certId), unassignedCertificateIds);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainerTest.java
index 647c809231e..2f996bac897 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/EndpointCertificateMaintainerTest.java
@@ -41,7 +41,6 @@ import java.util.stream.Stream;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.devUsEast1;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.perfUsEast3;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.productionUsCentral1;
-import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.productionUsEast3;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.productionUsWest1;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.stagingTest;
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.systemTest;
@@ -138,7 +137,7 @@ public class EndpointCertificateMaintainerTest {
tester.clock().advance(Duration.ofDays(3));
secretStore.setSecret(assignedCertificate.certificate().keyName(), "foo", 1);
secretStore.setSecret(assignedCertificate.certificate().certName(), "bar", 1);
- tester.controller().serviceRegistry().endpointCertificateProvider().requestCaSignedCertificate("preprovisioned." + assignedCertificate.certificate().randomizedId().get(), assignedCertificate.certificate().requestedDnsSans(), Optional.of(assignedCertificate.certificate()), "rsa_2048", false);
+ tester.controller().serviceRegistry().endpointCertificateProvider().requestCaSignedCertificate("preprovisioned." + assignedCertificate.certificate().generatedId().get(), assignedCertificate.certificate().requestedDnsSans(), Optional.of(assignedCertificate.certificate()), "rsa_2048", false);
// We should now pick up the new key and cert version + uuid, but not force trigger deployment yet
assertEquals(0.0, maintainer.maintain(), 0.0000001);
@@ -206,7 +205,7 @@ public class EndpointCertificateMaintainerTest {
assertTrue(applicationCertificate.isPresent());
Optional<AssignedCertificate> instanceCertificate = tester.curator().readAssignedCertificate(TenantAndApplicationId.from(app), Optional.of(app.instance()));
assertTrue(instanceCertificate.isPresent());
- assertEquals(instanceCertificate.get().certificate().randomizedId(), applicationCertificate.get().certificate().randomizedId());
+ assertEquals(instanceCertificate.get().certificate().generatedId(), applicationCertificate.get().certificate().generatedId());
// Verify the 3 wildcard random names are same in all certs
List<String> appWildcardSans = applicationCertificate.get().certificate().requestedDnsSans();
@@ -226,13 +225,13 @@ public class EndpointCertificateMaintainerTest {
assertEquals(1, tester.curator().readAssignedCertificates().size());
maintainer.maintain();
- String randomId = tester.curator().readAssignedCertificate(instance1).get().certificate().randomizedId().get();
+ String randomId = tester.curator().readAssignedCertificate(instance1).get().certificate().generatedId().get();
deployToAssignCert(deploymentTester, instance2, List.of(productionUsWest1), Optional.of("instance1,instance2"));
maintainer.maintain();
assertEquals(3, tester.curator().readAssignedCertificates().size());
- assertEquals(randomId, tester.curator().readAssignedCertificate(instance1).get().certificate().randomizedId().get());
+ assertEquals(randomId, tester.curator().readAssignedCertificate(instance1).get().certificate().generatedId().get());
}
@Test
@@ -247,7 +246,7 @@ public class EndpointCertificateMaintainerTest {
// Verify certificate is assigned random id and 3 new names
Optional<AssignedCertificate> assignedCertificate = tester.curator().readAssignedCertificate(devApp);
- assertTrue(assignedCertificate.get().certificate().randomizedId().isPresent());
+ assertTrue(assignedCertificate.get().certificate().generatedId().isPresent());
List<String> newRequestedSans = assignedCertificate.get().certificate().requestedDnsSans();
List<String> randomizedNames = newRequestedSans.stream().filter(san -> !originalRequestedSans.contains(san)).toList();
assertEquals(3, randomizedNames.size());
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java
index 22523103208..3405009714d 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java
@@ -1206,6 +1206,70 @@ public class RoutingPoliciesTest {
}
@Test
+ public void generated_endpoints_enable_token() {
+ var tester = new RoutingPoliciesTester(SystemName.Public);
+ var context = tester.newDeploymentContext("tenant1", "app1", "default");
+ tester.controllerTester().flagSource().withBooleanFlag(Flags.RANDOMIZED_ENDPOINT_NAMES.id(), true);
+ tester.controllerTester().flagSource().withBooleanFlag(Flags.LEGACY_ENDPOINTS.id(), false);
+ addCertificateToPool("cafed00d", UnassignedCertificate.State.ready, tester);
+
+ // Deploy application without token
+ var zone1 = ZoneId.from("prod", "aws-us-east-1c");
+ ApplicationPackage applicationPackage = applicationPackageBuilder().region(zone1.region())
+ .container("c0", AuthMethod.mtls)
+ .endpoint("foo", "c0")
+ .build();
+ tester.provisionLoadBalancers(1, context.instanceId(), ZoneId.from("test", "aws-us-east-2c"));
+ tester.provisionLoadBalancers(1, context.instanceId(), ZoneId.from("staging", "aws-us-east-3c"));
+ tester.provisionLoadBalancers(1, context.instanceId(), zone1);
+ context.submit(applicationPackage).deferLoadBalancerProvisioningIn(Environment.test, Environment.staging, Environment.prod).deploy();
+ assertEquals(List.of("a9c8c045.cafed00d.g.vespa-app.cloud",
+ "ebd395b6.cafed00d.z.vespa-app.cloud",
+ "fcf1bd63.cafed00d.aws-us-east-1.w.vespa-app.cloud"),
+ tester.recordNames());
+
+ // Re-deploy with token enabled
+ applicationPackage = applicationPackageBuilder().region(zone1.region())
+ .container("c0", AuthMethod.mtls, AuthMethod.token)
+ .endpoint("foo", "c0")
+ .build();
+ tester.provisionLoadBalancers(1, context.instanceId(), ZoneId.from("test", "aws-us-east-2c"));
+ tester.provisionLoadBalancers(1, context.instanceId(), ZoneId.from("staging", "aws-us-east-3c"));
+ context.submit(applicationPackage).deferLoadBalancerProvisioningIn(Environment.test, Environment.staging, Environment.prod).deploy();
+ // Additional zone- and global-scoped endpoints are added (token)
+ assertEquals(List.of("a9c8c045.cafed00d.g.vespa-app.cloud",
+ "b7e79800.cafed00d.z.vespa-app.cloud",
+ "c60d3149.cafed00d.g.vespa-app.cloud",
+ "ebd395b6.cafed00d.z.vespa-app.cloud",
+ "fcf1bd63.cafed00d.aws-us-east-1.w.vespa-app.cloud"),
+ tester.recordNames());
+
+ // Add new endpoint is generated for an additional global endpoint
+ applicationPackage = applicationPackageBuilder().region(zone1.region())
+ .container("c0", AuthMethod.mtls, AuthMethod.token)
+ .endpoint("foo", "c0")
+ .endpoint("bar", "c0")
+ .build();
+ tester.provisionLoadBalancers(1, context.instanceId(), ZoneId.from("test", "aws-us-east-2c"));
+ tester.provisionLoadBalancers(1, context.instanceId(), ZoneId.from("staging", "aws-us-east-3c"));
+ context.submit(applicationPackage).deferLoadBalancerProvisioningIn(Environment.test, Environment.staging, Environment.prod).deploy();
+ List<String> expectedRecords = List.of("a9c8c045.cafed00d.g.vespa-app.cloud",
+ "aa7591aa.cafed00d.g.vespa-app.cloud",
+ "b7e79800.cafed00d.z.vespa-app.cloud",
+ "c60d3149.cafed00d.g.vespa-app.cloud",
+ "d467800f.cafed00d.g.vespa-app.cloud",
+ "ebd395b6.cafed00d.z.vespa-app.cloud",
+ "fcf1bd63.cafed00d.aws-us-east-1.w.vespa-app.cloud");
+ assertEquals(expectedRecords, tester.recordNames());
+
+ // No change on redeployment
+ tester.provisionLoadBalancers(1, context.instanceId(), ZoneId.from("test", "aws-us-east-2c"));
+ tester.provisionLoadBalancers(1, context.instanceId(), ZoneId.from("staging", "aws-us-east-3c"));
+ context.submit(applicationPackage).deferLoadBalancerProvisioningIn(Environment.test, Environment.staging, Environment.prod).deploy();
+ assertEquals(expectedRecords, tester.recordNames());
+ }
+
+ @Test
public void generated_endpoints_only() {
var tester = new RoutingPoliciesTester(SystemName.Public);
var context = tester.newDeploymentContext("tenant1", "app1", "default");
@@ -1216,6 +1280,7 @@ public class RoutingPoliciesTest {
// Deploy application
var zone1 = ZoneId.from("prod", "aws-us-east-1c");
+ var zone2 = ZoneId.from("prod", "aws-eu-west-1a");
ApplicationPackage applicationPackage = applicationPackageBuilder().region(zone1.region())
.container("c0", AuthMethod.mtls)
.endpoint("foo", "c0")
@@ -1232,6 +1297,23 @@ public class RoutingPoliciesTest {
"ebd395b6.cafed00d.z.vespa-app.cloud",
"fcf1bd63.cafed00d.aws-us-east-1.w.vespa-app.cloud"),
tester.recordNames());
+
+ // Another zone is added to global endpoint
+ applicationPackage = applicationPackageBuilder().region(zone1.region())
+ .region(zone2.region())
+ .container("c0", AuthMethod.mtls)
+ .endpoint("foo", "c0")
+ .build();
+ tester.provisionLoadBalancers(1, context.instanceId(), ZoneId.from("test", "aws-us-east-2c"));
+ tester.provisionLoadBalancers(1, context.instanceId(), ZoneId.from("staging", "aws-us-east-3c"));
+ tester.provisionLoadBalancers(1, context.instanceId(), zone2);
+ context.submit(applicationPackage).deferLoadBalancerProvisioningIn(Environment.test, Environment.staging, Environment.prod).deploy();
+ assertEquals(List.of("a6414896.cafed00d.aws-eu-west-1.w.vespa-app.cloud",
+ "a9c8c045.cafed00d.g.vespa-app.cloud",
+ "cbff1506.cafed00d.z.vespa-app.cloud",
+ "ebd395b6.cafed00d.z.vespa-app.cloud",
+ "fcf1bd63.cafed00d.aws-us-east-1.w.vespa-app.cloud"),
+ tester.recordNames());
}
@Test