diff options
5 files changed, 38 insertions, 11 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/ApplicationCertificate.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/ApplicationCertificate.java index e079458ba78..41f5b65d263 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/ApplicationCertificate.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/ApplicationCertificate.java @@ -34,4 +34,10 @@ public class ApplicationCertificate { public int hashCode() { return Objects.hash(secretsKeyNamePrefix); } + + @Override + public String toString() { + return "application certificate '" + secretsKeyNamePrefix + "'"; + } + } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/ApplicationCertificateProvider.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/ApplicationCertificateProvider.java index fa489a6b754..b3fdee1415c 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/ApplicationCertificateProvider.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/ApplicationCertificateProvider.java @@ -8,5 +8,7 @@ import com.yahoo.config.provision.ApplicationId; * @author andreer */ public interface ApplicationCertificateProvider { + ApplicationCertificate requestCaSignedCertificate(ApplicationId applicationId); + } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java index 54518cad511..8f0aa6f4453 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java @@ -367,9 +367,8 @@ public class ApplicationController { app.rotations().stream().map(RotationId::asString).forEach(legacyRotations::add); } - // Get application certificate (provisions a new certificate if missing) - applicationCertificate = getApplicationCertificate(applicationId); + applicationCertificate = getApplicationCertificate(application.get()); // Update application with information from application package if ( ! preferOldestVersion @@ -537,13 +536,18 @@ public class ApplicationController { }); } - private Optional<ApplicationCertificate> getApplicationCertificate(ApplicationId application) { + private Optional<ApplicationCertificate> getApplicationCertificate(Application application) { + // Re-use certificate if already provisioned + if (application.applicationCertificate().isPresent()) { + return application.applicationCertificate(); + } // TODO(tokle): Verify that the application is deploying to a zone where certificate provisioning is enabled - boolean provisionCertificate = provisionApplicationCertificate.with(FetchVector.Dimension.APPLICATION_ID, application.serializedForm()).value(); + boolean provisionCertificate = provisionApplicationCertificate.with(FetchVector.Dimension.APPLICATION_ID, + application.id().serializedForm()).value(); if (!provisionCertificate) { return Optional.empty(); } - return Optional.of(applicationCertificateProvider.requestCaSignedCertificate(application)); + return Optional.of(applicationCertificateProvider.requestCaSignedCertificate(application.id())); } private ActivateResult unexpectedDeployment(ApplicationId application, ZoneId zone) { diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java index 7fe099ff276..aea32ab49f3 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java @@ -18,6 +18,7 @@ import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.hosted.controller.api.application.v4.model.DeployOptions; import com.yahoo.vespa.hosted.controller.api.application.v4.model.EndpointStatus; import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; +import com.yahoo.vespa.hosted.controller.api.integration.certificates.ApplicationCertificate; import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion; import com.yahoo.vespa.hosted.controller.api.integration.deployment.SourceRevision; import com.yahoo.vespa.hosted.controller.api.integration.dns.Record; @@ -698,25 +699,31 @@ public class ControllerTest { @Test public void testDeployProvisionsCertificate() { ((InMemoryFlagSource) tester.controller().flagSource()).withBooleanFlag(Flags.PROVISION_APPLICATION_CERTIFICATE.id(), true); + Function<Application, Optional<ApplicationCertificate>> certificate = (application) -> tester.application(application.id()).applicationCertificate(); // Create app1 - Application app1 = tester.createApplication("app1", "tenant1", 1, 2L); - ApplicationPackage applicationPackage = new ApplicationPackageBuilder().environment(Environment.prod) + var app1 = tester.createApplication("app1", "tenant1", 1, 2L); + var applicationPackage = new ApplicationPackageBuilder().environment(Environment.prod) .region("us-west-1") .build(); // Deploy app1 in production tester.deployCompletely(app1, applicationPackage); - assertTrue("Provisions certificate in " + Environment.prod, tester.application(app1.id()).applicationCertificate().isPresent()); + var cert = certificate.apply(app1); + assertTrue("Provisions certificate in " + Environment.prod, cert.isPresent()); + + // Next deployment reuses certificate + tester.deployCompletely(app1, applicationPackage, BuildJob.defaultBuildNumber + 1); + assertEquals(cert, certificate.apply(app1)); // Create app2 - Application app2 = tester.createApplication("app2", "tenant2", 3, 4L); + var app2 = tester.createApplication("app2", "tenant2", 3, 4L); ZoneId zone = ZoneId.from("dev", "us-east-1"); // Deploy app2 in dev tester.controller().applications().deploy(app2.id(), zone, Optional.of(applicationPackage), DeployOptions.none()); assertTrue("Application deployed and activated", tester.controllerTester().configServer().application(app2.id()).get().activated()); - assertTrue("Provisions certificate in " + Environment.dev, tester.application(app2.id()).applicationCertificate().isPresent()); + assertTrue("Provisions certificate in " + Environment.dev, certificate.apply(app2).isPresent()); } private void runUpgrade(DeploymentTester tester, ApplicationId application, ApplicationVersion version) { diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationCertificateMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationCertificateMock.java index 3246a260217..f3bee70db4c 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationCertificateMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationCertificateMock.java @@ -5,10 +5,18 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.vespa.hosted.controller.api.integration.certificates.ApplicationCertificate; import com.yahoo.vespa.hosted.controller.api.integration.certificates.ApplicationCertificateProvider; +import java.util.UUID; + +/** + * @author tokle + */ public class ApplicationCertificateMock implements ApplicationCertificateProvider { @Override public ApplicationCertificate requestCaSignedCertificate(ApplicationId applicationId) { - return new ApplicationCertificate(String.format("vespa.tls.%s.%s", applicationId.tenant(),applicationId.application())); + return new ApplicationCertificate(String.format("vespa.tls.%s.%s@%s", applicationId.tenant(), + applicationId.application(), + UUID.randomUUID().toString())); } + } |