summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClientMock.java14
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/AthenzFacade.java27
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/AthenzAccessControlRequests.java21
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/AthenzCredentials.java20
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java8
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java13
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java117
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OAuthCredentials.java52
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaAccessToken.java40
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaIdentityToken.java40
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java23
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClient.java14
12 files changed, 154 insertions, 235 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClientMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClientMock.java
index 63212c9c200..121abc8c9e3 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClientMock.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClientMock.java
@@ -9,9 +9,7 @@ import com.yahoo.vespa.athenz.api.AthenzPolicy;
import com.yahoo.vespa.athenz.api.AthenzResourceName;
import com.yahoo.vespa.athenz.api.AthenzRole;
import com.yahoo.vespa.athenz.api.AthenzService;
-import com.yahoo.vespa.athenz.api.AthenzUser;
-import com.yahoo.vespa.athenz.api.OktaAccessToken;
-import com.yahoo.vespa.athenz.api.OktaIdentityToken;
+import com.yahoo.vespa.athenz.api.OAuthCredentials;
import com.yahoo.vespa.athenz.client.zms.RoleAction;
import com.yahoo.vespa.athenz.client.zms.ZmsClient;
import com.yahoo.vespa.athenz.client.zms.ZmsClientException;
@@ -48,15 +46,13 @@ public class ZmsClientMock implements ZmsClient {
}
@Override
- public void createTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService,
- OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ public void createTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService, OAuthCredentials oAuthCredentials) {
log("createTenancy(tenantDomain='%s')", tenantDomain);
getDomainOrThrow(tenantDomain, false).isVespaTenant = true;
}
@Override
- public void deleteTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService,
- OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ public void deleteTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService, OAuthCredentials oAuthCredentials) {
log("deleteTenancy(tenantDomain='%s')", tenantDomain);
AthenzDbMock.Domain domain = getDomainOrThrow(tenantDomain, false);
domain.isVespaTenant = false;
@@ -66,7 +62,7 @@ public class ZmsClientMock implements ZmsClient {
@Override
public void createProviderResourceGroup(AthenzDomain tenantDomain, AthenzIdentity providerService, String resourceGroup,
- Set<RoleAction> roleActions, OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ Set<RoleAction> roleActions, OAuthCredentials oAuthCredentials) {
log("createProviderResourceGroup(tenantDomain='%s', resourceGroup='%s')", tenantDomain, resourceGroup);
AthenzDbMock.Domain domain = getDomainOrThrow(tenantDomain, true);
ApplicationId applicationId = new ApplicationId(resourceGroup);
@@ -77,7 +73,7 @@ public class ZmsClientMock implements ZmsClient {
@Override
public void deleteProviderResourceGroup(AthenzDomain tenantDomain, AthenzIdentity providerService, String resourceGroup,
- OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ OAuthCredentials oAuthCredentials) {
log("deleteProviderResourceGroup(tenantDomain='%s', resourceGroup='%s')", tenantDomain, resourceGroup);
getDomainOrThrow(tenantDomain, true).applications.remove(new ApplicationId(resourceGroup));
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/AthenzFacade.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/AthenzFacade.java
index a0b70eb88ab..eceb098d702 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/AthenzFacade.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/impl/AthenzFacade.java
@@ -16,8 +16,7 @@ import com.yahoo.vespa.athenz.api.AthenzResourceName;
import com.yahoo.vespa.athenz.api.AthenzRole;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.api.AthenzUser;
-import com.yahoo.vespa.athenz.api.OktaAccessToken;
-import com.yahoo.vespa.athenz.api.OktaIdentityToken;
+import com.yahoo.vespa.athenz.api.OAuthCredentials;
import com.yahoo.vespa.athenz.client.zms.RoleAction;
import com.yahoo.vespa.athenz.client.zms.ZmsClient;
import com.yahoo.vespa.athenz.client.zms.ZmsClientException;
@@ -109,7 +108,7 @@ public class AthenzFacade implements AccessControl {
}
else { // Create tenant resources in Athenz if domain is not already taken.
log("createTenancy(tenantDomain=%s, service=%s)", domain, service);
- zmsClient.createTenancy(domain, service, athenzCredentials.identityToken(), athenzCredentials.accessToken());
+ zmsClient.createTenancy(domain, service, athenzCredentials.oAuthCredentials());
}
return tenant;
@@ -150,14 +149,14 @@ public class AthenzFacade implements AccessControl {
}
else { // Delete and recreate tenant, and optionally application, resources in Athenz otherwise.
log("createTenancy(tenantDomain=%s, service=%s)", newDomain, service);
- zmsClient.createTenancy(newDomain, service, athenzCredentials.identityToken(), athenzCredentials.accessToken());
+ zmsClient.createTenancy(newDomain, service, athenzCredentials.oAuthCredentials());
for (Application application : applications)
- createApplication(newDomain, application.id().application(), athenzCredentials.identityToken(), athenzCredentials.accessToken());
+ createApplication(newDomain, application.id().application(), athenzCredentials.oAuthCredentials());
log("deleteTenancy(tenantDomain=%s, service=%s)", oldDomain, service);
for (Application application : applications)
- deleteApplication(oldDomain, application.id().application(), athenzCredentials.identityToken(), athenzCredentials.accessToken());
- zmsClient.deleteTenancy(oldDomain, service, athenzCredentials.identityToken(), athenzCredentials.accessToken());
+ deleteApplication(oldDomain, application.id().application(), athenzCredentials.oAuthCredentials());
+ zmsClient.deleteTenancy(oldDomain, service, athenzCredentials.oAuthCredentials());
}
return tenant;
@@ -169,7 +168,7 @@ public class AthenzFacade implements AccessControl {
AthenzDomain tenantDomain = athenzCredentials.domain();
log("deleteTenancy(tenantDomain=%s, service=%s)", tenantDomain, service);
try {
- zmsClient.deleteTenancy(tenantDomain, service, athenzCredentials.identityToken(), athenzCredentials.accessToken());
+ zmsClient.deleteTenancy(tenantDomain, service, athenzCredentials.oAuthCredentials());
} catch (ZmsClientException e) {
if (e.getErrorCode() == 404) {
log.log(Level.WARNING,
@@ -185,16 +184,16 @@ public class AthenzFacade implements AccessControl {
@Override
public void createApplication(TenantAndApplicationId id, Credentials credentials) {
AthenzCredentials athenzCredentials = (AthenzCredentials) credentials;
- createApplication(athenzCredentials.domain(), id.application(), athenzCredentials.identityToken(), athenzCredentials.accessToken());
+ createApplication(athenzCredentials.domain(), id.application(), athenzCredentials.oAuthCredentials());
}
- private void createApplication(AthenzDomain domain, ApplicationName application, OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ private void createApplication(AthenzDomain domain, ApplicationName application, OAuthCredentials oAuthCredentials) {
Set<RoleAction> tenantRoleActions = createTenantRoleActions();
log("createProviderResourceGroup(" +
"tenantDomain=%s, providerDomain=%s, service=%s, resourceGroup=%s, roleActions=%s)",
domain, service.getDomain().getName(), service.getName(), application, tenantRoleActions);
try {
- zmsClient.createProviderResourceGroup(domain, service, application.value(), tenantRoleActions, identityToken, accessToken);
+ zmsClient.createProviderResourceGroup(domain, service, application.value(), tenantRoleActions, oAuthCredentials);
}
catch (ZmsClientException e) {
if (e.getErrorCode() == com.yahoo.jdisc.Response.Status.FORBIDDEN)
@@ -211,7 +210,7 @@ public class AthenzFacade implements AccessControl {
athenzCredentials.domain(), service.getDomain().getName(), service.getName(), id.application());
try {
zmsClient.deleteProviderResourceGroup(athenzCredentials.domain(), service, id.application().value(),
- athenzCredentials.identityToken(), athenzCredentials.accessToken());
+ athenzCredentials.oAuthCredentials());
} catch (ZmsClientException e) {
if (e.getErrorCode() == 404) {
log.log(Level.WARNING,
@@ -243,10 +242,10 @@ public class AthenzFacade implements AccessControl {
zmsClient.addRoleMember(new AthenzRole(tenantDomain, "tenancy." + service.getFullName() + ".admin"), user, Optional.empty());
}
- private void deleteApplication(AthenzDomain domain, ApplicationName application, OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ private void deleteApplication(AthenzDomain domain, ApplicationName application, OAuthCredentials oAuthCredentials) {
log("deleteProviderResourceGroup(tenantDomain=%s, providerDomain=%s, service=%s, resourceGroup=%s)",
domain, service.getDomain().getName(), service.getName(), application);
- zmsClient.deleteProviderResourceGroup(domain, service, application.value(), identityToken, accessToken);
+ zmsClient.deleteProviderResourceGroup(domain, service, application.value(), oAuthCredentials);
}
public boolean hasApplicationAccess(
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/AthenzAccessControlRequests.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/AthenzAccessControlRequests.java
index 876882b7f19..f4f6df28ebc 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/AthenzAccessControlRequests.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/AthenzAccessControlRequests.java
@@ -8,8 +8,7 @@ import com.yahoo.slime.Inspector;
import com.yahoo.text.Text;
import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.athenz.api.AthenzPrincipal;
-import com.yahoo.vespa.athenz.api.OktaAccessToken;
-import com.yahoo.vespa.athenz.api.OktaIdentityToken;
+import com.yahoo.vespa.athenz.api.OAuthCredentials;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.TenantController;
import com.yahoo.vespa.hosted.controller.api.identifiers.Property;
@@ -19,7 +18,6 @@ import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant;
import java.security.Principal;
import java.util.Objects;
import java.util.Optional;
-import java.util.function.Function;
/**
* Extracts access control data for Athenz or user tenants from HTTP requests.
@@ -48,22 +46,7 @@ public class AthenzAccessControlRequests implements AccessControlRequests {
return new AthenzCredentials(requireAthenzPrincipal(request),
tenants.get(tenant).map(AthenzTenant.class::cast).map(AthenzTenant::domain)
.orElseGet(() -> new AthenzDomain(required("athensDomain", requestObject))),
- requireOktaIdentityToken(request),
- requireOktaAccessToken(request));
- }
-
- private static OktaIdentityToken requireOktaIdentityToken(HttpRequest request) {
- return requireToken(request, OktaIdentityToken::new, "okta.identity-token", "No Okta Identity Token provided");
- }
-
- private static OktaAccessToken requireOktaAccessToken(HttpRequest request) {
- return requireToken(request, OktaAccessToken::new, "okta.access-token", "No Okta Access Token provided");
- }
-
- private static <T> T requireToken(HttpRequest request, Function<String, T> tokenFactory, String attribute, String errorMessage) {
- return Optional.ofNullable(request.context().get(attribute))
- .map(value -> tokenFactory.apply((String) value))
- .orElseThrow(() -> new IllegalArgumentException(errorMessage));
+ OAuthCredentials.fromOktaRequestContext(request.context()));
}
private static String required(String fieldName, Inspector object) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/AthenzCredentials.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/AthenzCredentials.java
index 04b0d6adafd..fd74626a6cf 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/AthenzCredentials.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/AthenzCredentials.java
@@ -3,8 +3,7 @@ package com.yahoo.vespa.hosted.controller.security;
import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.athenz.api.AthenzPrincipal;
-import com.yahoo.vespa.athenz.api.OktaAccessToken;
-import com.yahoo.vespa.athenz.api.OktaIdentityToken;
+import com.yahoo.vespa.athenz.api.OAuthCredentials;
import static java.util.Objects.requireNonNull;
@@ -18,15 +17,12 @@ import static java.util.Objects.requireNonNull;
public class AthenzCredentials extends Credentials {
private final AthenzDomain domain;
- private final OktaIdentityToken identityToken;
- private final OktaAccessToken accessToken;
+ private final OAuthCredentials oAuthCredentials;
- public AthenzCredentials(AthenzPrincipal user, AthenzDomain domain,
- OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ public AthenzCredentials(AthenzPrincipal user, AthenzDomain domain, OAuthCredentials oAuthCredentials) {
super(user);
this.domain = requireNonNull(domain);
- this.accessToken = requireNonNull(accessToken);
- this.identityToken = requireNonNull(identityToken);
+ this.oAuthCredentials = requireNonNull(oAuthCredentials);
}
@Override
@@ -35,11 +31,7 @@ public class AthenzCredentials extends Credentials {
/** Returns the Athenz domain of the tenant on whose behalf this request is made. */
public AthenzDomain domain() { return domain; }
- /** Returns the Okta access token required for Athenz tenancy operation */
- public OktaAccessToken accessToken() { return accessToken; }
-
- /** Returns the Okta identity token required for Athenz tenancy operation */
- public OktaIdentityToken identityToken() { return identityToken; }
-
+ /** Returns the OAuth credentials required for Athenz tenancy operation */
+ public OAuthCredentials oAuthCredentials() { return oAuthCredentials; }
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
index 99c97b3bdd6..5cf55930274 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
@@ -16,8 +16,7 @@ import com.yahoo.text.Text;
import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.athenz.api.AthenzPrincipal;
import com.yahoo.vespa.athenz.api.AthenzUser;
-import com.yahoo.vespa.athenz.api.OktaAccessToken;
-import com.yahoo.vespa.athenz.api.OktaIdentityToken;
+import com.yahoo.vespa.athenz.api.OAuthCredentials;
import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.flags.PermanentFlags;
import com.yahoo.vespa.hosted.controller.api.identifiers.Property;
@@ -320,7 +319,7 @@ public final class ControllerTester {
new Property("Property" + propertyId),
Optional.ofNullable(propertyId).map(Object::toString).map(PropertyId::new));
AthenzCredentials credentials = new AthenzCredentials(
- new AthenzPrincipal(user), domain, new OktaIdentityToken("okta-identity-token"), new OktaAccessToken("okta-access-token"));
+ new AthenzPrincipal(user), domain, OAuthCredentials.createForTesting("okta-access-token", "okta-identity-token"));
controller().tenants().create(tenantSpec, credentials);
contact.ifPresent(value -> controller().tenants().lockOrThrow(name, LockedTenant.Athenz.class, tenant ->
controller().tenants().store(tenant.with(value))));
@@ -342,8 +341,7 @@ public final class ControllerTester {
case athenz:
return new AthenzCredentials(new AthenzPrincipal(new AthenzUser("user")),
((AthenzTenant) tenant).domain(),
- new OktaIdentityToken("okta-identity-token"),
- new OktaAccessToken("okta-access-token"));
+ OAuthCredentials.createForTesting("okta-access-token", "okta-identity-token"));
case cloud:
return new Credentials(new SimplePrincipal("dev"));
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
index 89394e8a30c..621a3272918 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
@@ -7,8 +7,7 @@ import com.yahoo.application.container.handler.Request;
import com.yahoo.config.provision.SystemName;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.athenz.api.AthenzUser;
-import com.yahoo.vespa.athenz.api.OktaAccessToken;
-import com.yahoo.vespa.athenz.api.OktaIdentityToken;
+import com.yahoo.vespa.athenz.api.OAuthCredentials;
import com.yahoo.vespa.hosted.controller.api.integration.athenz.AthenzClientFactoryMock;
import org.junit.After;
import org.junit.Before;
@@ -163,13 +162,9 @@ public class ControllerContainerTest {
return request;
}
- protected static Request addOktaIdentityToken(Request request, OktaIdentityToken token) {
- request.getHeaders().put(OKTA_IDENTITY_TOKEN_HEADER_NAME, token.token());
- return request;
- }
-
- protected static Request addOktaAccessToken(Request request, OktaAccessToken token) {
- request.getHeaders().put(OKTA_ACCESS_TOKEN_HEADER_NAME, token.token());
+ protected static Request addOAuthCredentials(Request request, OAuthCredentials oAuthCredentials) {
+ request.getHeaders().put(OKTA_IDENTITY_TOKEN_HEADER_NAME, oAuthCredentials.idToken());
+ request.getHeaders().put(OKTA_ACCESS_TOKEN_HEADER_NAME, oAuthCredentials.accessToken());
return request;
}
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 61e9ea02acc..32999d24a03 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
@@ -24,8 +24,7 @@ import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.athenz.api.AthenzPrincipal;
import com.yahoo.vespa.athenz.api.AthenzUser;
-import com.yahoo.vespa.athenz.api.OktaAccessToken;
-import com.yahoo.vespa.athenz.api.OktaIdentityToken;
+import com.yahoo.vespa.athenz.api.OAuthCredentials;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.ControllerTester;
import com.yahoo.vespa.hosted.controller.Instance;
@@ -150,8 +149,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
private static final UserId USER_ID = new UserId("myuser");
private static final UserId OTHER_USER_ID = new UserId("otheruser");
private static final UserId HOSTED_VESPA_OPERATOR = new UserId("johnoperator");
- private static final OktaIdentityToken OKTA_IT = new OktaIdentityToken("okta-it");
- private static final OktaAccessToken OKTA_AT = new OktaAccessToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.he0ErCNloe4J7Id0Ry2SEDg09lKkZkfsRiGsdX_vgEg");
+ private static final OAuthCredentials OKTA_CREDENTIALS = OAuthCredentials.createForTesting("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.he0ErCNloe4J7Id0Ry2SEDg09lKkZkfsRiGsdX_vgEg", "okta-it");
private ContainerTester tester;
@@ -175,12 +173,12 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1", POST)
.userIdentity(USER_ID)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("tenant-without-applications.json"));
// PUT (modify) a tenant
tester.assertResponse(request("/application/v4/tenant/tenant1", PUT)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT)
+ .oAuthCredentials(OKTA_CREDENTIALS)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"),
new File("tenant-without-applications.json"));
@@ -192,13 +190,13 @@ public class ApplicationApiTest extends ControllerContainerTest {
// POST (add) a tenant with property ID
tester.assertResponse(request("/application/v4/tenant/tenant2", POST)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT)
+ .oAuthCredentials(OKTA_CREDENTIALS)
.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)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT)
+ .oAuthCredentials(OKTA_CREDENTIALS)
.data("{\"athensDomain\":\"domain2\", \"property\":\"property2\", \"propertyId\":\"1234\"}"),
new File("tenant-without-applications-with-id.json"));
// GET a tenant with property ID and contact information
@@ -211,7 +209,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// POST (create) an application
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("instance-reference.json"));
// GET a tenant
tester.assertResponse(request("/application/v4/tenant/tenant1", GET).userIdentity(USER_ID),
@@ -322,7 +320,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// DELETE a user instance
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/myuser", DELETE)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"message\":\"Deleted instance tenant1.application1.myuser\"}");
addScrewdriverUserToDeployRole(SCREWDRIVER_ID,
@@ -349,7 +347,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// POST (create) another application
tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/instance/default", POST)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("instance-reference-2.json"));
ApplicationId id2 = ApplicationId.from("tenant2", "application2", "instance1");
@@ -436,13 +434,13 @@ public class ApplicationApiTest extends ControllerContainerTest {
// DELETE instance 1 of 2
tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/instance/default", DELETE)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"message\":\"Deleted instance tenant2.application2.default\"}");
// DELETE application with only one instance left
tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2", DELETE)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"message\":\"Deleted application tenant2.application2\"}");
// Set version 6.1 to broken to change compile version for.
@@ -707,7 +705,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// DELETE application with active deployments fails
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", DELETE)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("delete-with-active-deployments.json"), 400);
// DELETE (deactivate) a deployment - dev
@@ -874,17 +872,17 @@ public class ApplicationApiTest extends ControllerContainerTest {
// DELETE the application which no longer has any deployments
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"message\":\"Deleted application tenant1.application1\"}");
// DELETE an empty tenant
tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE).userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"message\":\"Deleted tenant tenant1\"}");
// The tenant is not found
tester.assertResponse(request("/application/v4/tenant/tenant1", GET).userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"error-code\":\"NOT_FOUND\",\"message\":\"Tenant 'tenant1' does not exist\"}", 404);
// ... unless we specify to show deleted tenants
@@ -895,14 +893,14 @@ public class ApplicationApiTest extends ControllerContainerTest {
// Tenant cannot be recreated
tester.assertResponse(request("/application/v4/tenant/tenant1", POST).userIdentity(USER_ID)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'tenant1' already exists\"}", 400);
// Forget a deleted tenant
tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE).properties(Map.of("forget", "true"))
.data("{\"athensDomain\":\"domain1\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT)
+ .oAuthCredentials(OKTA_CREDENTIALS)
.userIdentity(HOSTED_VESPA_OPERATOR),
"{\"message\":\"Deleted tenant tenant1\"}");
tester.assertResponse(request("/application/v4/tenant/tenant1", GET).properties(Map.of("includeDeleted", "true"))
@@ -1072,7 +1070,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/doesnotexist/application/doesnotexist/metering", GET)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("instance1-metering.json"));
}
@@ -1100,7 +1098,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deployment", DELETE)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"message\":\"All deployments removed\"}");
assertEquals(Set.of(ZoneId.from("dev.us-east-1")), app.instance().deployments().keySet());
@@ -1113,7 +1111,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// PUT (update) non-existing tenant returns 403 as tenant access cannot be determined when the tenant does not exist
tester.assertResponse(request("/application/v4/tenant/tenant1", PUT)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT)
+ .oAuthCredentials(OKTA_CREDENTIALS)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"),
accessDenied,
403);
@@ -1146,21 +1144,21 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1", POST)
.userIdentity(USER_ID)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
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\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"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)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT)
+ .oAuthCredentials(OKTA_CREDENTIALS)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"),
"{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'tenant1' already exists\"}",
400);
@@ -1169,7 +1167,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/my_tenant_2", POST)
.userIdentity(USER_ID)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"error-code\":\"BAD_REQUEST\",\"message\":\"New tenant or application names must start with a letter, may contain no more than 20 characters, and may only contain lowercase letters, digits or dashes, but no double-dashes.\"}",
400);
@@ -1177,19 +1175,19 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/hosted-vespa", POST)
.userIdentity(USER_ID)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'hosted-vespa' already exists\"}",
400);
// POST (create) an (empty) application
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("instance-reference.json"));
// Create the same application again
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT)
+ .oAuthCredentials(OKTA_CREDENTIALS)
.userIdentity(USER_ID),
"{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not create 'tenant1.application1.instance1': Instance already exists\"}",
400);
@@ -1226,18 +1224,18 @@ public class ApplicationApiTest extends ControllerContainerTest {
// DELETE tenant which has an application
tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"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/instance/instance1", DELETE)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"message\":\"Deleted instance tenant1.application1.instance1\"}");
// DELETE application again - should produce 404
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", DELETE)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT)
+ .oAuthCredentials(OKTA_CREDENTIALS)
.userIdentity(USER_ID),
"{\"error-code\":\"NOT_FOUND\",\"message\":\"Could not delete instance 'tenant1.application1.instance1': Instance not found\"}",
404);
@@ -1245,14 +1243,14 @@ public class ApplicationApiTest extends ControllerContainerTest {
// DELETE and forget an application as non-operator
tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE).properties(Map.of("forget", "true"))
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"error-code\":\"FORBIDDEN\",\"message\":\"Only operators can forget a tenant\"}",
403);
// DELETE tenant
tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"message\":\"Deleted tenant tenant1\"}");
// DELETE tenant again returns 403 as tenant access cannot be determined when the tenant does not exist
tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE)
@@ -1268,7 +1266,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/my-tenant", POST)
.userIdentity(USER_ID)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'my-tenant' already exists\"}",
400);
}
@@ -1296,7 +1294,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// 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\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT)
+ .oAuthCredentials(OKTA_CREDENTIALS)
.userIdentity(unauthorizedUser),
"{\"error-code\":\"FORBIDDEN\",\"message\":\"The user 'user.othertenant' is not admin in Athenz domain 'domain1'\"}",
403);
@@ -1305,21 +1303,21 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1", POST)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}")
.userIdentity(authorizedUser)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
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/instance/instance1", POST)
.userIdentity(unauthorizedUser)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
accessDenied,
403);
// (Create it with the right tenant id)
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
.userIdentity(authorizedUser)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("instance-reference.json"),
200);
@@ -1340,14 +1338,14 @@ public class ApplicationApiTest extends ControllerContainerTest {
// Create another instance under the application
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/default", POST)
.userIdentity(authorizedUser)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("instance-reference-default.json"),
200);
// (Deleting the application with the right tenant id)
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE)
.userIdentity(authorizedUser)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"message\":\"Deleted application tenant1.application1\"}",
200);
@@ -1363,7 +1361,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1", PUT)
.data("{\"athensDomain\":\"domain2\", \"property\":\"property1\"}")
.userIdentity(authorizedUser)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("tenant1.json"),
200);
@@ -1468,7 +1466,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
new Property("vespa"),
Optional.empty());
AthenzCredentials credentials = new AthenzCredentials(
- new AthenzPrincipal(new AthenzUser(developer.id())), sandboxDomain, OKTA_IT, OKTA_AT);
+ new AthenzPrincipal(new AthenzUser(developer.id())), sandboxDomain, OKTA_CREDENTIALS);
tester.controller().tenants().create(tenantSpec, credentials);
tester.controller().applications().createApplication(TenantAndApplicationId.from("sandbox", "myapp"), credentials);
@@ -1634,21 +1632,21 @@ public class ApplicationApiTest extends ControllerContainerTest {
// Not allowed to request apis not listed in feature flag allowed-service-view-apis. e.g /document/v1
tester.assertResponse(request(serviceApi + "/storagenode-awe3slno6mmq2fye191y324jl/document/v1/", GET)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"error-code\":\"FORBIDDEN\",\"message\":\"Access denied\"}",
403);
// Test path traversal
tester.assertResponse(request(serviceApi + "/storagenode-awe3slno6mmq2fye191y324jl/state/v1/../../document/v1/", GET)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"error-code\":\"FORBIDDEN\",\"message\":\"Access denied\"}",
403);
// Test urlencoded path traversal
tester.assertResponse(request(serviceApi + "/storagenode-awe3slno6mmq2fye191y324jl/state%2Fv1%2F..%2F..%2Fdocument%2Fv1%2F", GET)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
"{\"error-code\":\"FORBIDDEN\",\"message\":\"Access denied\"}",
403);
}
@@ -1662,7 +1660,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
// Create tenant
tester.assertResponse(request("/application/v4/tenant/tenant1", POST).userIdentity(USER_ID)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("tenant-without-applications.json"));
// Deploy application
@@ -1675,8 +1673,8 @@ public class ApplicationApiTest extends ControllerContainerTest {
// 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)
- .oktaIdentityToken(OKTA_IT)
- .oktaAccessToken(OKTA_AT)
+ .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}");
@@ -1772,11 +1770,11 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/tenant1", POST)
.userIdentity(USER_ID)
.data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}")
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("tenant-without-applications.json"));
tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST)
.userIdentity(USER_ID)
- .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT),
+ .oAuthCredentials(OKTA_CREDENTIALS),
new File("instance-reference.json"));
addScrewdriverUserToDeployRole(SCREWDRIVER_ID, ATHENZ_TENANT_DOMAIN, ApplicationName.from("application1"));
@@ -1874,8 +1872,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
private final Request.Method method;
private byte[] data = new byte[0];
private AthenzIdentity identity;
- private OktaIdentityToken oktaIdentityToken;
- private OktaAccessToken oktaAccessToken;
+ private OAuthCredentials oAuthCredentials;
private String contentType = "application/json";
private final Map<String, List<String>> headers = new HashMap<>();
private final Map<String, String> properties = new HashMap<>();
@@ -1893,8 +1890,7 @@ public class ApplicationApiTest extends ControllerContainerTest {
private RequestBuilder userIdentity(UserId userId) { this.identity = HostedAthenzIdentities.from(userId); return this; }
private RequestBuilder screwdriverIdentity(ScrewdriverId screwdriverId) { this.identity = HostedAthenzIdentities.from(screwdriverId); return this; }
- private RequestBuilder oktaIdentityToken(OktaIdentityToken oktaIdentityToken) { this.oktaIdentityToken = oktaIdentityToken; return this; }
- private RequestBuilder oktaAccessToken(OktaAccessToken oktaAccessToken) { this.oktaAccessToken = oktaAccessToken; return this; }
+ private RequestBuilder oAuthCredentials(OAuthCredentials oAuthCredentials) { this.oAuthCredentials = oAuthCredentials; return this; }
private RequestBuilder contentType(String contentType) { this.contentType = contentType; return this; }
private RequestBuilder recursive(String recursive) {return properties(Map.of("recursive", recursive)); }
private RequestBuilder properties(Map<String, String> properties) { this.properties.putAll(properties); return this; }
@@ -1914,15 +1910,8 @@ public class ApplicationApiTest extends ControllerContainerTest {
request.getHeaders().addAll(headers);
request.getHeaders().put("Content-Type", contentType);
// user and domain parameters are translated to a Principal by MockAuthorizer as we do not run HTTP filters
- if (identity != null) {
- addIdentityToRequest(request, identity);
- }
- if (oktaIdentityToken != null) {
- addOktaIdentityToken(request, oktaIdentityToken);
- }
- if (oktaAccessToken != null) {
- addOktaAccessToken(request, oktaAccessToken);
- }
+ if (identity != null) addIdentityToRequest(request, identity);
+ if (oAuthCredentials != null) addOAuthCredentials(request, oAuthCredentials);
return request;
}
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OAuthCredentials.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OAuthCredentials.java
new file mode 100644
index 00000000000..1798a679b27
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OAuthCredentials.java
@@ -0,0 +1,52 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.athenz.api;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * @author freva
+ */
+public class OAuthCredentials {
+
+ private final String accessTokenCookieName;
+ private final String accessToken;
+ private final String idTokenCookieName;
+ private final String idToken;
+
+ private OAuthCredentials(String accessTokenCookieName, String accessToken, String idTokenCookieName, String idToken) {
+ this.accessTokenCookieName = Objects.requireNonNull(accessTokenCookieName);
+ this.accessToken = Objects.requireNonNull(accessToken);
+ this.idTokenCookieName = Objects.requireNonNull(idTokenCookieName);
+ this.idToken = Objects.requireNonNull(idToken);
+ }
+
+ public String accessToken() { return accessToken; }
+ public String idToken() { return idToken; }
+
+ public String asCookie() {
+ return String.format("%s=%s; %s=%s", accessTokenCookieName, accessToken, idTokenCookieName, idToken);
+ }
+
+ public static OAuthCredentials fromOktaRequestContext(Map<String, Object> requestContext) {
+ return new OAuthCredentials("okta_at", requireToken(requestContext, "okta.access-token", "No Okta Access Token provided"),
+ "okta_it", requireToken(requestContext, "okta.identity-token", "No Okta Identity Token provided"));
+ }
+
+ public static OAuthCredentials fromAuth0RequestContext(Map<String, Object> requestContext) {
+ return new OAuthCredentials("access_token", requireToken(requestContext, "auth0.access-token", "No Auth0 Access Token provided"),
+ "id_token", requireToken(requestContext, "auth0.identity-token", "No Auth0 Identity Token provided"));
+ }
+
+ public static OAuthCredentials createForTesting(String accessToken, String idToken) {
+ return new OAuthCredentials("accessToken", accessToken, "idToken", idToken);
+ }
+
+ private static String requireToken(Map<String, Object> context, String attribute, String errorMessage) {
+ return Optional.ofNullable(context.get(attribute))
+ .map(String.class::cast)
+ .orElseThrow(() -> new IllegalArgumentException(errorMessage));
+ }
+
+}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaAccessToken.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaAccessToken.java
deleted file mode 100644
index 80f769f7fcd..00000000000
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaAccessToken.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.athenz.api;
-
-import java.util.Objects;
-
-/**
- * @author bjorncs
- */
-public class OktaAccessToken {
-
- private final String token;
-
- public OktaAccessToken(String token) {
- this.token = token;
- }
-
- public String token() {
- return token;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- OktaAccessToken that = (OktaAccessToken) o;
- return Objects.equals(token, that.token);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(token);
- }
-
- @Override
- public String toString() {
- return "OktaAccessToken{" +
- "token='" + token + '\'' +
- '}';
- }
-}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaIdentityToken.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaIdentityToken.java
deleted file mode 100644
index dfe69c7d9d4..00000000000
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/OktaIdentityToken.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.athenz.api;
-
-import java.util.Objects;
-
-/**
- * @author bjorncs
- */
-public class OktaIdentityToken {
-
- private final String token;
-
- public OktaIdentityToken(String token) {
- this.token = token;
- }
-
- public String token() {
- return token;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- OktaIdentityToken that = (OktaIdentityToken) o;
- return Objects.equals(token, that.token);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(token);
- }
-
- @Override
- public String toString() {
- return "OktaIdentityToken{" +
- "token='" + token + '\'' +
- '}';
- }
-}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java
index d83eab9e339..3c60d5bbcc3 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java
@@ -9,8 +9,7 @@ import com.yahoo.vespa.athenz.api.AthenzPolicy;
import com.yahoo.vespa.athenz.api.AthenzResourceName;
import com.yahoo.vespa.athenz.api.AthenzRole;
import com.yahoo.vespa.athenz.api.AthenzService;
-import com.yahoo.vespa.athenz.api.OktaAccessToken;
-import com.yahoo.vespa.athenz.api.OktaIdentityToken;
+import com.yahoo.vespa.athenz.api.OAuthCredentials;
import com.yahoo.vespa.athenz.client.ErrorHandler;
import com.yahoo.vespa.athenz.client.common.ClientBase;
import com.yahoo.vespa.athenz.client.zms.bindings.AccessResponseEntity;
@@ -74,33 +73,33 @@ public class DefaultZmsClient extends ClientBase implements ZmsClient {
}
@Override
- public void createTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService, OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ public void createTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService, OAuthCredentials oAuthCredentials) {
URI uri = zmsUrl.resolve(String.format("domain/%s/tenancy/%s", tenantDomain.getName(), providerService.getFullName()));
HttpUriRequest request = RequestBuilder.put()
.setUri(uri)
- .addHeader(createCookieHeaderWithOktaTokens(identityToken, accessToken))
+ .addHeader(createCookieHeader(oAuthCredentials))
.setEntity(toJsonStringEntity(new TenancyRequestEntity(tenantDomain, providerService, Collections.emptyList())))
.build();
execute(request, response -> readEntity(response, Void.class));
}
@Override
- public void deleteTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService, OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ public void deleteTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService, OAuthCredentials oAuthCredentials) {
URI uri = zmsUrl.resolve(String.format("domain/%s/tenancy/%s", tenantDomain.getName(), providerService.getFullName()));
HttpUriRequest request = RequestBuilder.delete()
.setUri(uri)
- .addHeader(createCookieHeaderWithOktaTokens(identityToken, accessToken))
+ .addHeader(createCookieHeader(oAuthCredentials))
.build();
execute(request, response -> readEntity(response, Void.class));
}
@Override
public void createProviderResourceGroup(AthenzDomain tenantDomain, AthenzIdentity providerService, String resourceGroup,
- Set<RoleAction> roleActions, OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ Set<RoleAction> roleActions, OAuthCredentials oAuthCredentials) {
URI uri = zmsUrl.resolve(String.format("domain/%s/provDomain/%s/provService/%s/resourceGroup/%s", tenantDomain.getName(), providerService.getDomainName(), providerService.getName(), resourceGroup));
HttpUriRequest request = RequestBuilder.put()
.setUri(uri)
- .addHeader(createCookieHeaderWithOktaTokens(identityToken, accessToken))
+ .addHeader(createCookieHeader(oAuthCredentials))
.setEntity(toJsonStringEntity(new ResourceGroupRolesEntity(providerService, tenantDomain, roleActions, resourceGroup)))
.build();
execute(request, response -> readEntity(response, Void.class)); // Note: The ZMS API will actually return a json object that is similar to ProviderResourceGroupRolesRequestEntity
@@ -108,11 +107,11 @@ public class DefaultZmsClient extends ClientBase implements ZmsClient {
@Override
public void deleteProviderResourceGroup(AthenzDomain tenantDomain, AthenzIdentity providerService, String resourceGroup,
- OktaIdentityToken identityToken, OktaAccessToken accessToken) {
+ OAuthCredentials oAuthCredentials) {
URI uri = zmsUrl.resolve(String.format("domain/%s/provDomain/%s/provService/%s/resourceGroup/%s", tenantDomain.getName(), providerService.getDomainName(), providerService.getName(), resourceGroup));
HttpUriRequest request = RequestBuilder.delete()
.setUri(uri)
- .addHeader(createCookieHeaderWithOktaTokens(identityToken, accessToken))
+ .addHeader(createCookieHeader(oAuthCredentials))
.build();
execute(request, response -> readEntity(response, Void.class));
}
@@ -404,8 +403,8 @@ public class DefaultZmsClient extends ClientBase implements ZmsClient {
execute(request, response -> readEntity(response, Void.class));
}
- private static Header createCookieHeaderWithOktaTokens(OktaIdentityToken identityToken, OktaAccessToken accessToken) {
- return new BasicHeader("Cookie", String.format("okta_at=%s; okta_it=%s", accessToken.token(), identityToken.token()));
+ private static Header createCookieHeader(OAuthCredentials oAuthCredentials) {
+ return new BasicHeader("Cookie", oAuthCredentials.asCookie());
}
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClient.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClient.java
index 38d11d33d74..bd73913ea64 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClient.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClient.java
@@ -8,9 +8,7 @@ import com.yahoo.vespa.athenz.api.AthenzPolicy;
import com.yahoo.vespa.athenz.api.AthenzResourceName;
import com.yahoo.vespa.athenz.api.AthenzRole;
import com.yahoo.vespa.athenz.api.AthenzService;
-import com.yahoo.vespa.athenz.api.AthenzUser;
-import com.yahoo.vespa.athenz.api.OktaAccessToken;
-import com.yahoo.vespa.athenz.api.OktaIdentityToken;
+import com.yahoo.vespa.athenz.api.OAuthCredentials;
import java.time.Instant;
import java.util.List;
@@ -23,17 +21,15 @@ import java.util.Set;
*/
public interface ZmsClient extends AutoCloseable {
- void createTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService,
- OktaIdentityToken identityToken, OktaAccessToken accessToken);
+ void createTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService, OAuthCredentials oAuthCredentials);
- void deleteTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService,
- OktaIdentityToken identityToken, OktaAccessToken accessToken);
+ void deleteTenancy(AthenzDomain tenantDomain, AthenzIdentity providerService, OAuthCredentials oAuthCredentials);
void createProviderResourceGroup(AthenzDomain tenantDomain, AthenzIdentity providerService, String resourceGroup,
- Set<RoleAction> roleActions, OktaIdentityToken identityToken, OktaAccessToken accessToken);
+ Set<RoleAction> roleActions, OAuthCredentials oAuthCredentials);
void deleteProviderResourceGroup(AthenzDomain tenantDomain, AthenzIdentity providerService, String resourceGroup,
- OktaIdentityToken identityToken, OktaAccessToken accessToken);
+ OAuthCredentials oAuthCredentials);
/** For manual tenancy provisioning - only creates roles/policies on provider domain */
void createTenantResourceGroup(AthenzDomain tenantDomain, AthenzIdentity provider, String resourceGroup,