From 468793cf14d2804e1680c280c827167bd37e8b96 Mon Sep 17 00:00:00 2001 From: Øyvind Grønnesby Date: Thu, 22 Sep 2022 10:30:34 +0200 Subject: Applications must be created in console in hosted --- .../restapi/application/ApplicationApiHandler.java | 20 ++++++++++-- .../restapi/application/ApplicationApiTest.java | 36 ++++++++++++++++++++-- 2 files changed, 50 insertions(+), 6 deletions(-) (limited to 'controller-server') diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java index 341cba60519..e12cd169499 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java @@ -3043,9 +3043,23 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler { private void ensureApplicationExists(TenantAndApplicationId id, HttpRequest request) { if (controller.applications().getApplication(id).isEmpty()) { - log.fine("Application does not exist in public, creating: " + id); - var credentials = accessControlRequests.credentials(id.tenant(), null /* not used on public */ , request.getJDiscRequest()); - controller.applications().createApplication(id, credentials); + if (controller.system().isPublic() || hasOktaContext(request)) { + log.fine("Application does not exist in public, creating: " + id); + var credentials = accessControlRequests.credentials(id.tenant(), null /* not used on public */ , request.getJDiscRequest()); + controller.applications().createApplication(id, credentials); + } else { + log.fine("Application does not exist in hosted, failing: " + id); + throw new IllegalArgumentException("Application does not exist. Create application in Console first."); + } + } + } + + private boolean hasOktaContext(HttpRequest request) { + try { + OAuthCredentials.fromOktaRequestContext(request.getJDiscRequest().context()); + return true; + } catch (IllegalArgumentException e) { + return false; } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java index ed4f0597fad..0f03333146f 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java @@ -102,6 +102,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.stream.Collectors.joining; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -1647,7 +1648,7 @@ public class ApplicationApiTest extends ControllerContainerTest { } @Test - void create_application_on_deploy() { + void create_application_on_deploy_with_okta() { // Setup createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR)); @@ -1669,13 +1670,42 @@ public class ApplicationApiTest extends ControllerContainerTest { tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploy/dev-us-east-1/", POST) .data(entity) .oAuthCredentials(OKTA_CREDENTIALS) - .userIdentity(USER_ID), - "{\"message\":\"Deployment started in run 1 of dev-us-east-1 for tenant1.application1.instance1. This may take about 15 minutes the first time.\",\"run\":1}"); + """ + {"message":"Deployment started in run 1 of dev-us-east-1 for tenant1.application1.instance1. This may take about 15 minutes the first time.","run":1}"""); assertTrue(tester.controller().applications().getApplication(appId).isPresent()); } + @Test + void create_application_on_deploy_with_athenz() { + // Setup + createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); + addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR)); + + // Create tenant + tester.assertResponse(request("/application/v4/tenant/tenant1", POST).userIdentity(USER_ID) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") + .oAuthCredentials(OKTA_CREDENTIALS), + new File("tenant-without-applications.json")); + + // Deploy application + var id = ApplicationId.from("tenant1", "application1", "instance1"); + var appId = TenantAndApplicationId.from(id); + var entity = createApplicationDeployData(applicationPackageInstance1); + + assertTrue(tester.controller().applications().getApplication(appId).isEmpty()); + + // POST (deploy) an application to start a manual deployment to dev + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploy/dev-us-east-1/", POST) + .data(entity) + .userIdentity(USER_ID), + """ + {"error-code":"BAD_REQUEST","message":"Application does not exist. Create application in Console first."}""", 400); + + assertFalse(tester.controller().applications().getApplication(appId).isPresent()); + } + private static String serializeInstant(Instant i) { return DateTimeFormatter.ISO_INSTANT.format(i.truncatedTo(ChronoUnit.SECONDS)); } -- cgit v1.2.3