diff options
Diffstat (limited to 'controller-server/src/test')
7 files changed, 162 insertions, 128 deletions
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/TestIdentities.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/TestIdentities.java index 355b63335c0..9dbebecdb25 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/TestIdentities.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/TestIdentities.java @@ -9,7 +9,7 @@ import com.yahoo.vespa.hosted.controller.api.identifiers.RegionId; import com.yahoo.vespa.hosted.controller.api.identifiers.TenantId; import com.yahoo.vespa.hosted.controller.api.identifiers.UserGroup; import com.yahoo.vespa.hosted.controller.api.identifiers.UserId; -import com.yahoo.vespa.hosted.controller.athenz.AthenzUtils; +import com.yahoo.vespa.hosted.controller.athenz.AthenzUser; import com.yahoo.vespa.hosted.controller.athenz.NToken; import com.yahoo.vespa.hosted.controller.athenz.filter.AthenzTestUtils; @@ -35,7 +35,7 @@ public class TestIdentities { public static Tenant tenant = Tenant.createOpsDbTenant(tenantId, userGroup1, property); public static NToken userNToken = new NToken.Builder( - "U1", AthenzUtils.createPrincipal(userId), AthenzTestUtils.generateRsaKeypair().getPrivate(), "0") + "U1", AthenzUser.fromUserId(userId), AthenzTestUtils.generateRsaKeypair().getPrivate(), "0") .build(); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/athenz/filter/AthenzPrincipalFilterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/athenz/filter/AthenzPrincipalFilterTest.java index 20db038485d..5a3f048101a 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/athenz/filter/AthenzPrincipalFilterTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/athenz/filter/AthenzPrincipalFilterTest.java @@ -8,7 +8,7 @@ import com.yahoo.jdisc.handler.ResponseHandler; import com.yahoo.jdisc.http.filter.DiscFilterRequest; import com.yahoo.vespa.hosted.controller.api.identifiers.UserId; import com.yahoo.vespa.hosted.controller.athenz.AthenzPrincipal; -import com.yahoo.vespa.hosted.controller.athenz.AthenzUtils; +import com.yahoo.vespa.hosted.controller.athenz.AthenzUser; import com.yahoo.vespa.hosted.controller.athenz.InvalidTokenException; import com.yahoo.vespa.hosted.controller.athenz.NToken; import org.junit.Before; @@ -44,7 +44,7 @@ public class AthenzPrincipalFilterTest { @Before public void before() { validator = mock(NTokenValidator.class); - principal = AthenzUtils.createPrincipal(new UserId("bob")); + principal = new AthenzPrincipal(AthenzUser.fromUserId(new UserId("bob"))); } @Test @@ -94,7 +94,7 @@ public class AthenzPrincipalFilterTest { private static NToken createDummyToken() { return new NToken.Builder( - "U1", AthenzUtils.createPrincipal(new UserId("bob")), AthenzTestUtils.generateRsaKeypair().getPrivate(), "0") + "U1", AthenzUser.fromUserId(new UserId("bob")), AthenzTestUtils.generateRsaKeypair().getPrivate(), "0") .build(); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/athenz/filter/NTokenValidatorTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/athenz/filter/NTokenValidatorTest.java index 70ba504df03..927910a89a1 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/athenz/filter/NTokenValidatorTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/athenz/filter/NTokenValidatorTest.java @@ -2,7 +2,9 @@ package com.yahoo.vespa.hosted.controller.athenz.filter; import com.yahoo.vespa.hosted.controller.api.identifiers.UserId; +import com.yahoo.vespa.hosted.controller.athenz.AthenzIdentity; import com.yahoo.vespa.hosted.controller.athenz.AthenzPrincipal; +import com.yahoo.vespa.hosted.controller.athenz.AthenzUser; import com.yahoo.vespa.hosted.controller.athenz.InvalidTokenException; import com.yahoo.vespa.hosted.controller.athenz.NToken; import com.yahoo.vespa.hosted.controller.athenz.ZmsKeystore; @@ -15,7 +17,6 @@ import java.security.NoSuchAlgorithmException; import java.util.Optional; import static com.yahoo.vespa.hosted.controller.athenz.AthenzUtils.ZMS_ATHENZ_SERVICE; -import static com.yahoo.vespa.hosted.controller.athenz.AthenzUtils.createPrincipal; import static org.junit.Assert.assertEquals; /** @@ -25,7 +26,7 @@ public class NTokenValidatorTest { private static final KeyPair TRUSTED_KEY = AthenzTestUtils.generateRsaKeypair(); private static final KeyPair UNKNOWN_KEY = AthenzTestUtils.generateRsaKeypair(); - private static final AthenzPrincipal PRINCIPAL = createPrincipal(new UserId("myuser")); + private static final AthenzIdentity IDENTITY = AthenzUser.fromUserId(new UserId("myuser")); @Rule public ExpectedException exceptionRule = ExpectedException.none(); @@ -33,15 +34,15 @@ public class NTokenValidatorTest { @Test public void valid_token_is_accepted() throws NoSuchAlgorithmException, InvalidTokenException { NTokenValidator validator = new NTokenValidator(createKeystore()); - NToken token = createNToken(PRINCIPAL, System.currentTimeMillis(), TRUSTED_KEY, "0"); + NToken token = createNToken(IDENTITY, System.currentTimeMillis(), TRUSTED_KEY, "0"); AthenzPrincipal principal = validator.validate(token); - assertEquals("user.myuser", principal.toYRN()); + assertEquals("user.myuser", principal.getIdentity().getFullName()); } @Test public void invalid_signature_is_not_accepted() throws InvalidTokenException { NTokenValidator validator = new NTokenValidator(createKeystore()); - NToken token = createNToken(PRINCIPAL, System.currentTimeMillis(), UNKNOWN_KEY, "0"); + NToken token = createNToken(IDENTITY, System.currentTimeMillis(), UNKNOWN_KEY, "0"); exceptionRule.expect(InvalidTokenException.class); exceptionRule.expectMessage("NToken is expired or has invalid signature"); validator.validate(token); @@ -50,7 +51,7 @@ public class NTokenValidatorTest { @Test public void expired_token_is_not_accepted() throws InvalidTokenException { NTokenValidator validator = new NTokenValidator(createKeystore()); - NToken token = createNToken(PRINCIPAL, 1234 /*long time ago*/, TRUSTED_KEY, "0"); + NToken token = createNToken(IDENTITY, 1234 /*long time ago*/, TRUSTED_KEY, "0"); exceptionRule.expect(InvalidTokenException.class); exceptionRule.expectMessage("NToken is expired or has invalid signature"); validator.validate(token); @@ -59,7 +60,7 @@ public class NTokenValidatorTest { @Test public void unknown_keyId_is_not_accepted() throws InvalidTokenException { NTokenValidator validator = new NTokenValidator(createKeystore()); - NToken token = createNToken(PRINCIPAL, System.currentTimeMillis(), TRUSTED_KEY, "unknown-key-id"); + NToken token = createNToken(IDENTITY, System.currentTimeMillis(), TRUSTED_KEY, "unknown-key-id"); exceptionRule.expect(InvalidTokenException.class); exceptionRule.expectMessage("NToken has an unknown keyId"); validator.validate(token); @@ -69,7 +70,7 @@ public class NTokenValidatorTest { public void failing_to_find_key_should_throw_exception() throws InvalidTokenException { ZmsKeystore keystore = (athensService, keyId) -> { throw new RuntimeException(); }; NTokenValidator validator = new NTokenValidator(keystore); - NToken token = createNToken(PRINCIPAL, System.currentTimeMillis(), TRUSTED_KEY, "0"); + NToken token = createNToken(IDENTITY, System.currentTimeMillis(), TRUSTED_KEY, "0"); exceptionRule.expect(InvalidTokenException.class); exceptionRule.expectMessage("Failed to retrieve public key"); validator.validate(token); @@ -82,8 +83,8 @@ public class NTokenValidatorTest { : Optional.empty(); } - private static NToken createNToken(AthenzPrincipal principal, long issueTime, KeyPair keyPair, String keyId) { - return new NToken.Builder("U1", principal, keyPair.getPrivate(), keyId) + private static NToken createNToken(AthenzIdentity identity, long issueTime, KeyPair keyPair, String keyId) { + return new NToken.Builder("U1", identity, keyPair.getPrivate(), keyId) .salt("1234") .hostname("host") .ip("1.2.3.4") diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerControllerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerControllerTester.java index 71ad6560126..fb0adcd3152 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerControllerTester.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerControllerTester.java @@ -20,11 +20,10 @@ import com.yahoo.vespa.hosted.controller.api.identifiers.Property; import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId; import com.yahoo.vespa.hosted.controller.api.identifiers.ScrewdriverId; import com.yahoo.vespa.hosted.controller.api.identifiers.TenantId; -import com.yahoo.vespa.hosted.controller.api.identifiers.UserId; import com.yahoo.vespa.hosted.controller.application.ApplicationPackage; import com.yahoo.vespa.hosted.controller.application.DeploymentJobs; import com.yahoo.vespa.hosted.controller.athenz.ApplicationAction; -import com.yahoo.vespa.hosted.controller.athenz.AthenzPrincipal; +import com.yahoo.vespa.hosted.controller.athenz.AthenzService; import com.yahoo.vespa.hosted.controller.athenz.AthenzUtils; import com.yahoo.vespa.hosted.controller.athenz.mock.AthenzClientFactoryMock; import com.yahoo.vespa.hosted.controller.athenz.mock.AthenzDbMock; @@ -108,7 +107,7 @@ public class ContainerControllerTester { AthenzDomain athensDomain = new AthenzDomain(domainName); AthenzDbMock.Domain domain = new AthenzDbMock.Domain(athensDomain); domain.markAsVespaTenant(); - domain.admin(new AthenzPrincipal(new AthenzDomain("domain"), new UserId(userName))); + domain.admin(AthenzUtils.createAthenzIdentity(new AthenzDomain("domain"), userName)); mock.getSetup().addDomain(domain); return athensDomain; } @@ -133,6 +132,6 @@ public class ContainerControllerTester { mock.getSetup() .domains.get(tenantDomain) .applications.get(new com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId(application.id().application().value())) - .addRoleMember(action, AthenzUtils.createPrincipal(screwdriverId)); + .addRoleMember(action, AthenzService.fromScrewdriverId(screwdriverId)); } } 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 540550e871d..7b05f0ce438 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 @@ -3,7 +3,6 @@ package com.yahoo.vespa.hosted.controller.restapi.application; import com.yahoo.application.container.handler.Request; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.AthenzService; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Environment; import com.yahoo.vespa.hosted.controller.Application; @@ -24,8 +23,9 @@ import com.yahoo.vespa.hosted.controller.application.Deployment; import com.yahoo.vespa.hosted.controller.application.DeploymentJobs; import com.yahoo.vespa.hosted.controller.application.DeploymentMetrics; import com.yahoo.vespa.hosted.controller.athenz.ApplicationAction; -import com.yahoo.vespa.hosted.controller.athenz.AthenzPrincipal; -import com.yahoo.vespa.hosted.controller.athenz.AthenzUtils; +import com.yahoo.vespa.hosted.controller.athenz.AthenzIdentity; +import com.yahoo.vespa.hosted.controller.athenz.AthenzService; +import com.yahoo.vespa.hosted.controller.athenz.AthenzUser; import com.yahoo.vespa.hosted.controller.athenz.mock.AthenzClientFactoryMock; import com.yahoo.vespa.hosted.controller.athenz.mock.AthenzDbMock; import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder; @@ -60,6 +60,7 @@ import static com.yahoo.application.container.handler.Request.Method.PUT; /** * @author bratseth * @author mpolden + * @author bjorncs */ public class ApplicationApiTest extends ControllerContainerTest { @@ -73,9 +74,9 @@ public class ApplicationApiTest extends ControllerContainerTest { .region("us-west-1") .build(); - private static final String athenzUserDomain = "domain1"; - - private static final String athenzScrewdriverDomain = AthenzUtils.SCREWDRIVER_DOMAIN.id(); + private static final AthenzDomain ATHENZ_TENANT_DOMAIN = new AthenzDomain("domain1"); + private static final ScrewdriverId SCREWDRIVER_ID = new ScrewdriverId("12345"); + private static final UserId USER_ID = new UserId("myuser"); @Test public void testApplicationApi() throws Exception { @@ -83,7 +84,7 @@ public class ApplicationApiTest extends ControllerContainerTest { ContainerTester tester = controllerTester.containerTester(); tester.updateSystemVersion(); - addTenantAthenzDomain(athenzUserDomain, "mytenant"); // (Necessary but not provided in this API) + createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); // (Necessary but not provided in this API) // GET API root tester.assertResponse(request("/application/v4/", GET), @@ -99,14 +100,16 @@ public class ApplicationApiTest extends ControllerContainerTest { new File("cookiefreshness.json")); // POST (add) a tenant without property ID tester.assertResponse(request("/application/v4/tenant/tenant1", POST) + .userIdentity(USER_ID) .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), new File("tenant-without-applications.json")); // PUT (modify) a tenant tester.assertResponse(request("/application/v4/tenant/tenant1", PUT) + .userIdentity(USER_ID) .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), new File("tenant-without-applications.json")); // GET the authenticated user (with associated tenants) - tester.assertResponse(request("/application/v4/user", GET), + tester.assertResponse(request("/application/v4/user", GET).userIdentity(USER_ID), new File("user.json")); // GET all tenants tester.assertResponse(request("/application/v4/tenant/", GET), @@ -114,15 +117,17 @@ public class ApplicationApiTest extends ControllerContainerTest { // Add another Athens domain, so we can try to create more tenants - addTenantAthenzDomain("domain2", "mytenant"); // New domain to test tenant w/property ID + createAthenzDomainWithAdmin(new AthenzDomain("domain2"), USER_ID); // New domain to test tenant w/property ID // Add property info for that property id, as well, in the mock organization. addPropertyData((MockOrganization) controllerTester.controller().organization(), "1234"); // POST (add) a tenant with property ID tester.assertResponse(request("/application/v4/tenant/tenant2", POST) + .userIdentity(USER_ID) .data("{\"athensDomain\":\"domain2\", \"property\":\"property2\", \"propertyId\":\"1234\"}"), new File("tenant-without-applications-with-id.json")); // PUT (modify) a tenant with property ID tester.assertResponse(request("/application/v4/tenant/tenant2", PUT) + .userIdentity(USER_ID) .data("{\"athensDomain\":\"domain2\", \"property\":\"property2\", \"propertyId\":\"1234\"}"), new File("tenant-without-applications-with-id.json")); // GET a tenant with property ID @@ -132,15 +137,18 @@ public class ApplicationApiTest extends ControllerContainerTest { // Test legacy OpsDB tenants // POST (add) an OpsDB tenant with property ID tester.assertResponse(request("/application/v4/tenant/tenant3", POST) + .userIdentity(USER_ID) .data("{\"userGroup\":\"group1\",\"property\":\"property1\",\"propertyId\":\"1234\"}"), new File("opsdb-tenant-with-id-without-applications.json")); // PUT (modify) the OpsDB tenant to set another property tester.assertResponse(request("/application/v4/tenant/tenant3", PUT) + .userIdentity(USER_ID) .data("{\"userGroup\":\"group1\",\"property\":\"property2\",\"propertyId\":\"4321\"}"), new File("opsdb-tenant-with-new-id-without-applications.json")); // POST (create) an application - tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST), + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST) + .userIdentity(USER_ID), new File("application-reference.json")); // GET a tenant tester.assertResponse(request("/application/v4/tenant/tenant1", GET), @@ -151,11 +159,13 @@ public class ApplicationApiTest extends ControllerContainerTest { new File("application-list.json")); // POST triggering of a full deployment to an application (if version is omitted, current system version is used) tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deploying", POST) + .userIdentity(USER_ID) .data("6.1.0"), new File("application-deployment.json")); // DELETE (cancel) ongoing change - tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deploying", DELETE), + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deploying", DELETE) + .userIdentity(USER_ID), new File("application-deployment-cancelled.json")); // DELETE (cancel) again is a no-op @@ -166,14 +176,16 @@ public class ApplicationApiTest extends ControllerContainerTest { HttpEntity entity = createApplicationDeployData(applicationPackage, Optional.empty()); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-west-1/instance/default/deploy", POST) .data(entity) - .domain(athenzUserDomain).user("mytenant"), + .userIdentity(USER_ID), new File("deploy-result.json")); // POST (deploy) an application to a zone. This simulates calls done by our tenant pipeline. ApplicationId id = ApplicationId.from("tenant1", "application1", "default"); long screwdriverProjectId = 123; - addScrewdriverUserToDomain("screwdriveruser1", "domain1"); // (Necessary but not provided in this API) + addScrewdriverUserToDeployRole(SCREWDRIVER_ID, + ATHENZ_TENANT_DOMAIN, + new com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId(id.application().value())); // (Necessary but not provided in this API) // Trigger deployment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deploying", POST) @@ -183,7 +195,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // ... systemtest tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/test/region/us-east-1/instance/default/", POST) .data(createApplicationDeployData(applicationPackage, Optional.of(screwdriverProjectId))) - .domain(athenzScrewdriverDomain).user("screwdriveruser1"), + .screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json")); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/test/region/us-east-1/instance/default", DELETE), "Deactivated tenant/tenant1/application/application1/environment/test/region/us-east-1/instance/default"); @@ -192,7 +204,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // ... staging tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/staging/region/us-east-3/instance/default/", POST) .data(createApplicationDeployData(applicationPackage, Optional.of(screwdriverProjectId))) - .domain(athenzScrewdriverDomain).user("screwdriveruser1"), + .screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json")); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/staging/region/us-east-3/instance/default", DELETE), "Deactivated tenant/tenant1/application/application1/environment/staging/region/us-east-3/instance/default"); @@ -201,7 +213,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // ... prod zone tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/", POST) .data(createApplicationDeployData(applicationPackage, Optional.of(screwdriverProjectId))) - .domain(athenzScrewdriverDomain).user("screwdriveruser1"), + .screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json")); controllerTester.notifyJobCompletion(id, screwdriverProjectId, false, DeploymentJobs.JobType.productionCorpUsEast1); @@ -219,22 +231,22 @@ public class ApplicationApiTest extends ControllerContainerTest { addIssues(controllerTester, ApplicationId.from("tenant1", "application1", "default")); // GET at root, with "&recursive=deployment", returns info about all tenants, their applications and their deployments tester.assertResponse(request("/application/v4/", GET) - .domain("domain1").user("mytenant") + .userIdentity(USER_ID) .recursive("deployment"), new File("recursive-root.json")); // GET at root, with "&recursive=tenant", returns info about all tenants, with limmited info about their applications. tester.assertResponse(request("/application/v4/", GET) - .domain("domain1").user("mytenant") + .userIdentity(USER_ID) .recursive("tenant"), new File("recursive-until-tenant-root.json")); // GET at a tenant, with "&recursive=true", returns full info about their applications and their deployments tester.assertResponse(request("/application/v4/tenant/tenant1/", GET) - .domain("domain1").user("mytenant") + .userIdentity(USER_ID) .recursive("true"), new File("tenant1-recursive.json")); // GET at an application, with "&recursive=true", returns full info about its deployments tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/", GET) - .domain("domain1").user("mytenant") + .userIdentity(USER_ID) .recursive("true"), new File("application1-recursive.json")); @@ -272,7 +284,7 @@ public class ApplicationApiTest extends ControllerContainerTest { byte[] data = new byte[0]; tester.assertResponse(request("/application/v4/user?user=newuser&domain=by", PUT) .data(data) - .domain(athenzUserDomain).user("newuser"), + .userIdentity(new UserId("newuser")), new File("create-user-response.json")); // OPTIONS return 200 OK tester.assertResponse(request("/application/v4/", Request.Method.OPTIONS), @@ -288,11 +300,13 @@ public class ApplicationApiTest extends ControllerContainerTest { // SET global rotation override status tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/environment/prod/region/us-west-1/instance/default/global-rotation/override", PUT) + .userIdentity(USER_ID) .data("{\"reason\":\"because i can\"}"), new File("global-rotation-put.json")); // DELETE global rotation override status tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/environment/prod/region/us-west-1/instance/default/global-rotation/override", DELETE) + .userIdentity(USER_ID) .data("{\"reason\":\"because i can\"}"), new File("global-rotation-delete.json")); @@ -302,10 +316,10 @@ public class ApplicationApiTest extends ControllerContainerTest { "{\"message\":\"Successfully copied environment hosted-instance_tenant1_application1_placeholder_component_default to hosted-instance_tenant1_application1_us-west-1_prod_default\"}"); // DELETE an application - tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE), + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE).userIdentity(USER_ID), ""); // DELETE a tenant - tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE), + tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE).userIdentity(USER_ID), new File("tenant-without-applications.json")); controllerTester.controller().deconstruct(); @@ -324,23 +338,28 @@ public class ApplicationApiTest extends ControllerContainerTest { ContainerControllerTester controllerTester = new ContainerControllerTester(container, responseFiles); ContainerTester tester = controllerTester.containerTester(); tester.updateSystemVersion(); - addTenantAthenzDomain(athenzUserDomain, "mytenant"); - addScrewdriverUserToDomain("screwdriveruser1", "domain1"); + createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); // Create tenant - tester.assertResponse(request("/application/v4/tenant/tenant1", POST) + tester.assertResponse(request("/application/v4/tenant/tenant1", POST).userIdentity(USER_ID) .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), new File("tenant-without-applications.json")); // Create application - tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST), + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST) + .userIdentity(USER_ID), new File("application-reference.json")); + // Grant deploy access + addScrewdriverUserToDeployRole(SCREWDRIVER_ID, + ATHENZ_TENANT_DOMAIN, + new com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId("application1")); + // POST (deploy) an application to a prod zone - allowed when project ID is not specified HttpEntity entity = createApplicationDeployData(applicationPackage, Optional.empty()); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/deploy", POST) .data(entity) - .domain(athenzScrewdriverDomain).user("screwdriveruser1"), + .screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json")); } @@ -350,18 +369,22 @@ public class ApplicationApiTest extends ControllerContainerTest { ContainerControllerTester controllerTester = new ContainerControllerTester(container, responseFiles); ContainerTester tester = controllerTester.containerTester(); tester.updateSystemVersion(); - addTenantAthenzDomain(athenzUserDomain, "mytenant"); - addScrewdriverUserToDomain("screwdriveruser1", "domain1"); + createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); // Create tenant tester.assertResponse(request("/application/v4/tenant/tenant1", POST) + .userIdentity(USER_ID) .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), new File("tenant-without-applications.json")); // Create application - tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST), + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST) + .userIdentity(USER_ID), new File("application-reference.json")); + // Give Screwdriver project deploy access + addScrewdriverUserToDeployRole(SCREWDRIVER_ID, ATHENZ_TENANT_DOMAIN, new com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId("application1")); + // Deploy ApplicationPackage applicationPackage = new ApplicationPackageBuilder() .region("us-east-3") @@ -375,7 +398,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // us-east-3 tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-east-3/instance/default/deploy", POST) .data(deployData) - .domain(athenzScrewdriverDomain).user("screwdriveruser1"), + .screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json")); controllerTester.notifyJobCompletion(id, projectId, true, DeploymentJobs.JobType.productionUsEast3); @@ -392,13 +415,13 @@ public class ApplicationApiTest extends ControllerContainerTest { // us-west-1 tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/default/deploy", POST) .data(deployData) - .domain(athenzScrewdriverDomain).user("screwdriveruser1"), + .screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json")); controllerTester.notifyJobCompletion(id, projectId, true, DeploymentJobs.JobType.productionUsWest1); // us-east-3 tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-east-3/instance/default/deploy", POST) - .data(deployData).domain(athenzScrewdriverDomain).user("screwdriveruser1"), + .data(deployData).screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json")); controllerTester.notifyJobCompletion(id, projectId, true, DeploymentJobs.JobType.productionUsEast3); @@ -411,7 +434,7 @@ public class ApplicationApiTest extends ControllerContainerTest { public void testErrorResponses() throws Exception { ContainerTester tester = new ContainerTester(container, responseFiles); tester.updateSystemVersion(); - addTenantAthenzDomain("domain1", "mytenant"); + createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); // PUT (update) non-existing tenant tester.assertResponse(request("/application/v4/tenant/tenant1", PUT) @@ -436,27 +459,32 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST (add) a tenant tester.assertResponse(request("/application/v4/tenant/tenant1", POST) + .userIdentity(USER_ID) .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), new File("tenant-without-applications.json")); // POST (add) another tenant under the same domain tester.assertResponse(request("/application/v4/tenant/tenant2", POST) + .userIdentity(USER_ID) .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not create tenant 'tenant2': The Athens domain 'domain1' is already connected to tenant 'tenant1'\"}", 400); // Add the same tenant again tester.assertResponse(request("/application/v4/tenant/tenant1", POST) + .userIdentity(USER_ID) .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'tenant1' already exists\"}", 400); // POST (create) an (empty) application - tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST), + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST) + .userIdentity(USER_ID), new File("application-reference.json")); // Create the same application again - tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST), + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST) + .userIdentity(USER_ID), "{\"error-code\":\"BAD_REQUEST\",\"message\":\"An application with id 'tenant1.application1' already exists\"}", 400); @@ -467,44 +495,48 @@ public class ApplicationApiTest extends ControllerContainerTest { HttpEntity entity = createApplicationDeployData(applicationPackage, Optional.empty()); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-west-1/instance/default/deploy", POST) .data(entity) - .domain(athenzUserDomain).user("mytenant"), + .userIdentity(USER_ID), new File("deploy-failure.json"), 400); // POST (deploy) an application without available capacity configServer.throwOnNextPrepare(new ConfigServerException(new URI("server-url"), "Failed to prepare application", ConfigServerException.ErrorCode.OUT_OF_CAPACITY, null)); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-west-1/instance/default/deploy", POST) .data(entity) - .domain(athenzUserDomain).user("mytenant"), + .userIdentity(USER_ID), new File("deploy-out-of-capacity.json"), 400); // POST (deploy) an application where activation fails configServer.throwOnNextPrepare(new ConfigServerException(new URI("server-url"), "Failed to activate application", ConfigServerException.ErrorCode.ACTIVATION_CONFLICT, null)); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-west-1/instance/default/deploy", POST) .data(entity) - .domain(athenzUserDomain).user("mytenant"), + .userIdentity(USER_ID), new File("deploy-activation-conflict.json"), 409); // POST (deploy) an application where we get an internal server error configServer.throwOnNextPrepare(new ConfigServerException(new URI("server-url"), "Internal server error", ConfigServerException.ErrorCode.INTERNAL_SERVER_ERROR, null)); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-west-1/instance/default/deploy", POST) .data(entity) - .domain(athenzUserDomain).user("mytenant"), + .userIdentity(USER_ID), new File("deploy-internal-server-error.json"), 500); // DELETE tenant which has an application - tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE), + tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE) + .userIdentity(USER_ID), "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not delete tenant 'tenant1': This tenant has active applications\"}", 400); // DELETE application - tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE), + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE) + .userIdentity(USER_ID), ""); // DELETE application again - should produce 404 - tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE), + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE) + .userIdentity(USER_ID), "{\"error-code\":\"NOT_FOUND\",\"message\":\"Could not delete application 'tenant1.application1': Application not found\"}", 404); // DELETE tenant - tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE), + tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE) + .userIdentity(USER_ID), new File("tenant-without-applications.json")); // DELETE tenant again - should produce 404 tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE), @@ -520,48 +552,46 @@ public class ApplicationApiTest extends ControllerContainerTest { @Test public void testAuthorization() throws Exception { ContainerTester tester = new ContainerTester(container, responseFiles); - String authorizedUser = "mytenant"; - String unauthorizedUser = "othertenant"; + UserId authorizedUser = USER_ID; + UserId unauthorizedUser = new UserId("othertenant"); // Mutation without an authorized user is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1", POST) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .domain("domain1").user(null), + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), "{\"error-code\":\"FORBIDDEN\",\"message\":\"User is not authenticated\"}", 403); // ... but read methods are allowed tester.assertResponse(request("/application/v4/tenant/", GET) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .domain("domain1").user(null), + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), "[]", 200); - addTenantAthenzDomain("domain1", "mytenant"); + createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); // Creating a tenant for an Athens domain the user is not admin for is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1", POST) .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .domain("domain1").user(unauthorizedUser), - "{\"error-code\":\"FORBIDDEN\",\"message\":\"The user 'othertenant' is not admin in Athenz domain 'domain1'\"}", + .userIdentity(unauthorizedUser), + "{\"error-code\":\"FORBIDDEN\",\"message\":\"The user 'user.othertenant' is not admin in Athenz domain 'domain1'\"}", 403); // (Create it with the right tenant id) tester.assertResponse(request("/application/v4/tenant/tenant1", POST) .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .domain("domain1").user(authorizedUser), + .userIdentity(authorizedUser), new File("tenant-without-applications.json"), 200); // Creating an application for an Athens domain the user is not admin for is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST) - .domain("domain1").user(unauthorizedUser), - "{\"error-code\":\"FORBIDDEN\",\"message\":\"User othertenant does not have write access to tenant tenant1\"}", + .userIdentity(unauthorizedUser), + "{\"error-code\":\"FORBIDDEN\",\"message\":\"User user.othertenant does not have write access to tenant tenant1\"}", 403); // (Create it with the right tenant id) tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST) - .domain("domain1").user(authorizedUser), + .userIdentity(authorizedUser), new File("application-reference.json"), 200); @@ -569,41 +599,41 @@ public class ApplicationApiTest extends ControllerContainerTest { HttpEntity entity = createApplicationDeployData(applicationPackage, Optional.empty()); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/default/deploy", POST) .data(entity) - .domain(athenzUserDomain).user("mytenant"), - "{\"error-code\":\"FORBIDDEN\",\"message\":\"Principal 'mytenant' is not a Screwdriver principal. Excepted principal with Athenz domain 'cd.screwdriver.project', got 'domain1'.\"}", + .userIdentity(USER_ID), + "{\"error-code\":\"FORBIDDEN\",\"message\":\"Principal 'user.myuser' is not a Screwdriver principal. Excepted principal with Athenz domain 'cd.screwdriver.project', got 'user'.\"}", 403); // Deleting an application for an Athens domain the user is not admin for is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE) - .domain("domain1").user(unauthorizedUser), - "{\"error-code\":\"FORBIDDEN\",\"message\":\"User othertenant does not have write access to tenant tenant1\"}", + .userIdentity(unauthorizedUser), + "{\"error-code\":\"FORBIDDEN\",\"message\":\"User user.othertenant does not have write access to tenant tenant1\"}", 403); // (Deleting it with the right tenant id) tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE) - .domain("domain1").user(authorizedUser), + .userIdentity(authorizedUser), "", 200); // Updating a tenant for an Athens domain the user is not admin for is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1", PUT) .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .domain("domain1").user(unauthorizedUser), - "{\"error-code\":\"FORBIDDEN\",\"message\":\"User othertenant does not have write access to tenant tenant1\"}", + .userIdentity(unauthorizedUser), + "{\"error-code\":\"FORBIDDEN\",\"message\":\"User user.othertenant does not have write access to tenant tenant1\"}", 403); // Change Athens domain - addTenantAthenzDomain("domain2", "mytenant"); + createAthenzDomainWithAdmin(new AthenzDomain("domain2"), USER_ID); tester.assertResponse(request("/application/v4/tenant/tenant1", PUT) .data("{\"athensDomain\":\"domain2\", \"property\":\"property1\"}") - .domain("domain1").user(authorizedUser), + .userIdentity(authorizedUser), "{\"tenant\":\"tenant1\",\"type\":\"ATHENS\",\"athensDomain\":\"domain2\",\"property\":\"property1\",\"applications\":[]}", 200); // Deleting a tenant for an Athens domain the user is not admin for is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE) - .domain("domain1").user(unauthorizedUser), - "{\"error-code\":\"FORBIDDEN\",\"message\":\"User othertenant does not have write access to tenant tenant1\"}", + .userIdentity(unauthorizedUser), + "{\"error-code\":\"FORBIDDEN\",\"message\":\"User user.othertenant does not have write access to tenant tenant1\"}", 403); } @@ -613,19 +643,20 @@ public class ApplicationApiTest extends ControllerContainerTest { ContainerTester tester = controllerTester.containerTester(); ApplicationPackage applicationPackage = new ApplicationPackageBuilder() .upgradePolicy("default") - .athenzIdentity(com.yahoo.config.provision.AthenzDomain.from("invalid.domain"), AthenzService.from("service")) + .athenzIdentity(com.yahoo.config.provision.AthenzDomain.from("invalid.domain"), com.yahoo.config.provision.AthenzService.from("service")) .environment(Environment.prod) .region("us-west-1") .build(); long screwdriverProjectId = 123; - AthenzDomain domain = addTenantAthenzDomain(athenzUserDomain, "mytenant"); + createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); - Application application = controllerTester.createApplication(athenzUserDomain, "tenant1", "application1"); - controllerTester.authorize(domain, new ScrewdriverId(Long.toString(screwdriverProjectId)), ApplicationAction.deploy, application); + Application application = controllerTester.createApplication(ATHENZ_TENANT_DOMAIN.id(), "tenant1", "application1"); + ScrewdriverId screwdriverId = new ScrewdriverId(Long.toString(screwdriverProjectId)); + controllerTester.authorize(ATHENZ_TENANT_DOMAIN, screwdriverId, ApplicationAction.deploy, application); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/test/region/us-east-1/instance/default/", POST) .data(createApplicationDeployData(applicationPackage, Optional.of(screwdriverProjectId))) - .domain(athenzScrewdriverDomain).user("sd" + screwdriverProjectId), + .screwdriverIdentity(screwdriverId), "{\"error-code\":\"FORBIDDEN\",\"message\":\"Athenz domain in deployment.xml: [invalid.domain] must match tenant domain: [domain1]\"}", 403); @@ -637,21 +668,23 @@ public class ApplicationApiTest extends ControllerContainerTest { ContainerTester tester = controllerTester.containerTester(); ApplicationPackage applicationPackage = new ApplicationPackageBuilder() .upgradePolicy("default") - .athenzIdentity(com.yahoo.config.provision.AthenzDomain.from("domain1"), AthenzService.from("service")) + .athenzIdentity(com.yahoo.config.provision.AthenzDomain.from("domain1"), com.yahoo.config.provision.AthenzService.from("service")) .environment(Environment.prod) .region("us-west-1") .build(); long screwdriverProjectId = 123; - AthenzDomain domain = addTenantAthenzDomain(athenzUserDomain, "mytenant"); + ScrewdriverId screwdriverId = new ScrewdriverId(Long.toString(screwdriverProjectId)); - Application application = controllerTester.createApplication(athenzUserDomain, "tenant1", "application1"); - controllerTester.authorize(domain, new ScrewdriverId(Long.toString(screwdriverProjectId)), ApplicationAction.deploy, application); + createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); + + Application application = controllerTester.createApplication(ATHENZ_TENANT_DOMAIN.id(), "tenant1", "application1"); + controllerTester.authorize(ATHENZ_TENANT_DOMAIN, screwdriverId, ApplicationAction.deploy, application); // Allow systemtest to succeed by notifying completion of system test controllerTester.notifyJobCompletion(application.id(), screwdriverProjectId, true, DeploymentJobs.JobType.component); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/test/region/us-east-1/instance/default/", POST) .data(createApplicationDeployData(applicationPackage, Optional.of(screwdriverProjectId))) - .domain(athenzScrewdriverDomain).user("sd" + screwdriverProjectId), + .screwdriverIdentity(screwdriverId), new File("deploy-result.json")); } @@ -692,8 +725,7 @@ public class ApplicationApiTest extends ControllerContainerTest { private final String path; private final Request.Method method; private byte[] data = new byte[0]; - private String domain = "domain1"; - private String user = "mytenant"; + private AthenzIdentity identity; private String contentType = "application/json"; private String recursive; @@ -713,8 +745,8 @@ public class ApplicationApiTest extends ControllerContainerTest { } return data(out.toByteArray()).contentType(data.getContentType().getValue()); } - private RequestBuilder domain(String domain) { this.domain = domain; return this; } - private RequestBuilder user(String user) { this.user = user; return this; } + private RequestBuilder userIdentity(UserId userId) { this.identity = AthenzUser.fromUserId(userId); return this; } + private RequestBuilder screwdriverIdentity(ScrewdriverId screwdriverId) { this.identity = AthenzService.fromScrewdriverId(screwdriverId); return this; } private RequestBuilder contentType(String contentType) { this.contentType = contentType; return this; } private RequestBuilder recursive(String recursive) { this.recursive = recursive; return this; } @@ -722,10 +754,13 @@ public class ApplicationApiTest extends ControllerContainerTest { public Request get() { Request request = new Request("http://localhost:8080" + path + // user and domain parameters are translated to a Principal by MockAuthorizer as we do not run HTTP filters - "?domain=" + domain + (user == null ? "" : "&user=" + user) + - (recursive == null ? "" : "&recursive=" + recursive), + (recursive == null ? "" : "?recursive=" + recursive), data, method); request.getHeaders().put("Content-Type", contentType); + if (identity != null) { + request.getHeaders().put("Athenz-Identity-Domain", identity.getDomain().id()); + request.getHeaders().put("Athenz-Identity-Name", identity.getName()); + } return request; } } @@ -739,26 +774,27 @@ public class ApplicationApiTest extends ControllerContainerTest { * In production this happens outside hosted Vespa, so there is no API for it and we need to reach down into the * mock setup to replicate the action. */ - private AthenzDomain addTenantAthenzDomain(String domainName, String userName) { + private void createAthenzDomainWithAdmin(AthenzDomain domain, UserId userId) { AthenzClientFactoryMock mock = (AthenzClientFactoryMock) container.components() .getComponent(AthenzClientFactoryMock.class.getName()); - AthenzDomain athensDomain = new AthenzDomain(domainName); - AthenzDbMock.Domain domain = new AthenzDbMock.Domain(athensDomain); - domain.markAsVespaTenant(); - domain.admin(AthenzUtils.createPrincipal(new UserId(userName))); - mock.getSetup().addDomain(domain); - return athensDomain; + AthenzDbMock.Domain domainMock = new AthenzDbMock.Domain(domain); + domainMock.markAsVespaTenant(); + domainMock.admin(AthenzUser.fromUserId(userId)); + mock.getSetup().addDomain(domainMock); } /** * In production this happens outside hosted Vespa, so there is no API for it and we need to reach down into the * mock setup to replicate the action. */ - private void addScrewdriverUserToDomain(String screwdriverUserId, String domainName) { + private void addScrewdriverUserToDeployRole(ScrewdriverId screwdriverId, + AthenzDomain domain, + com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId applicationId) { AthenzClientFactoryMock mock = (AthenzClientFactoryMock) container.components() .getComponent(AthenzClientFactoryMock.class.getName()); - AthenzDbMock.Domain domain = mock.getSetup().domains.get(new AthenzDomain(domainName)); - domain.admin(new AthenzPrincipal(new AthenzDomain(athenzScrewdriverDomain), new UserId(screwdriverUserId))); + AthenzIdentity screwdriverIdentity = AthenzService.fromScrewdriverId(screwdriverId); + AthenzDbMock.Application athenzApplication = mock.getSetup().domains.get(domain).applications.get(applicationId); + athenzApplication.addRoleMember(ApplicationAction.deploy, screwdriverIdentity); } private void startAndTestChange(ContainerControllerTester controllerTester, ApplicationId application, long projectId, @@ -773,7 +809,7 @@ public class ApplicationApiTest extends ControllerContainerTest { application.tenant().value(), application.application().value()); tester.assertResponse(request(testPath, POST) .data(deployData) - .domain(athenzScrewdriverDomain).user("screwdriveruser1"), + .screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json")); tester.assertResponse(request(testPath, DELETE), "Deactivated " + testPath.replaceFirst("/application/v4/", "")); @@ -784,7 +820,7 @@ public class ApplicationApiTest extends ControllerContainerTest { application.tenant().value(), application.application().value()); tester.assertResponse(request(stagingPath, POST) .data(deployData) - .domain(athenzScrewdriverDomain).user("screwdriveruser1"), + .screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json")); tester.assertResponse(request(stagingPath, DELETE), "Deactivated " + stagingPath.replaceFirst("/application/v4/", "")); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/MockAuthorizer.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/MockAuthorizer.java index e5898b7a593..5899c767beb 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/MockAuthorizer.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/MockAuthorizer.java @@ -5,10 +5,10 @@ import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.TestIdentities; import com.yahoo.vespa.hosted.controller.api.identifiers.AthenzDomain; -import com.yahoo.vespa.hosted.controller.api.identifiers.UserId; import com.yahoo.vespa.hosted.controller.api.integration.entity.EntityService; import com.yahoo.vespa.hosted.controller.athenz.AthenzClientFactory; import com.yahoo.vespa.hosted.controller.athenz.AthenzPrincipal; +import com.yahoo.vespa.hosted.controller.athenz.AthenzUtils; import com.yahoo.vespa.hosted.controller.athenz.NToken; import javax.ws.rs.core.SecurityContext; @@ -20,6 +20,7 @@ import java.util.Optional; * This is necessary because filters are not currently executed when executing requests with Application. * * @author bratseth + * @author bjorncs */ @SuppressWarnings("unused") // injected public class MockAuthorizer extends Authorizer { @@ -30,10 +31,13 @@ public class MockAuthorizer extends Authorizer { /** Returns a principal given by the request parameters 'domain' and 'user' */ @Override - public Optional<Principal> getPrincipalIfAny(HttpRequest request) { - if (request.getProperty("user") == null) return Optional.empty(); - return Optional.of(new AthenzPrincipal(new AthenzDomain(request.getProperty("domain")), - new UserId(request.getProperty("user")))); + public Optional<AthenzPrincipal> getPrincipalIfAny(HttpRequest request) { + String domain = request.getHeader("Athenz-Identity-Domain"); + String name = request.getHeader("Athenz-Identity-Name"); + if (domain == null || name == null) return Optional.empty(); + return Optional.of( + new AthenzPrincipal( + AthenzUtils.createAthenzIdentity(new AthenzDomain(domain), name))); } /** Returns the hardcoded NToken of {@link TestIdentities#userId} */ @@ -42,12 +46,6 @@ public class MockAuthorizer extends Authorizer { return Optional.of(TestIdentities.userNToken); } - private static class MockPrincipal implements Principal { - - @Override - public String getName() { return TestIdentities.userId.id(); } - - } @Override protected Optional<SecurityContext> securityContextOf(HttpRequest request) { diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/user.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/user.json index d3927cbcfcf..79b9a785801 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/user.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/user.json @@ -1,5 +1,5 @@ { - "user": "mytenant", + "user": "myuser", "tenants": @include(tenant-list.json), "tenantExists": false }
\ No newline at end of file |