aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOla Aunrønning <olaa@verizonmedia.com>2022-03-14 11:32:14 +0100
committerOla Aunrønning <olaa@verizonmedia.com>2022-03-14 11:32:14 +0100
commit065053e8efaa6941521e1ec79b7948d34d73d18e (patch)
treec1bb2f31f341fc87d57836bb95561c6fa29d3434
parentfed4f6dddba35fe13b9d10dc79485fa7d4d97afb (diff)
Infer managed access through assertion existence
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java1
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java27
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java5
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java7
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzAssertion.java6
5 files changed, 37 insertions, 9 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java
index 1dd6eb543ef..f7876f9cddd 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java
@@ -21,5 +21,6 @@ public interface AccessControlService {
boolean requestSshAccess(TenantName tenantName);
AthenzRoleInformation getAccessRoleInformation(TenantName tenantName);
void setPreapprovedAccess(TenantName tenantName, boolean preapproved);
+ boolean getPreapprovedAccess(TenantName tenantName);
Collection<AthenzUser> listMembers();
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java
index 11cace3b10e..3a42c0c6535 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java
@@ -3,6 +3,7 @@
package com.yahoo.vespa.hosted.controller.api.integration.athenz;
import com.yahoo.config.provision.TenantName;
+import com.yahoo.vespa.athenz.api.AthenzAssertion;
import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.athenz.api.AthenzGroup;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
@@ -23,6 +24,7 @@ public class AthenzAccessControlService implements AccessControlService {
private static final String ALLOWED_OPERATOR_GROUPNAME = "vespa-team";
private static final String DATAPLANE_ACCESS_ROLENAME = "operator-data-plane";
private final String TENANT_DOMAIN_PREFIX = "vespa.tenant";
+ private final String ACCESS_APPROVAL_POLICY = "vespa-access-requester";
private final ZmsClient zmsClient;
private final AthenzRole dataPlaneAccessRole;
private final AthenzGroup vespaTeam;
@@ -129,18 +131,26 @@ public class AthenzAccessControlService implements AccessControlService {
vespaZmsClient.ifPresentOrElse(
zms -> {
var role = sshRole(tenantName);
-
- var policyName = "vespa-access-requester";
- var action = "update_members";
- var approverRole = new AthenzRole(role.domain(), "vespa-access-approver");
+ var assertion = getApprovalAssertion(role);
if (preapprovedAccess) {
- zms.addPolicyRule(role.domain(), policyName, action, role.toResourceName(), approverRole);
+ zms.addPolicyRule(role.domain(), ACCESS_APPROVAL_POLICY, assertion.action(), assertion.resource(), assertion.role());
} else {
- zms.deletePolicyRule(role.domain(), policyName, action, role.toResourceName(), approverRole);
+ zms.deletePolicyRule(role.domain(), ACCESS_APPROVAL_POLICY, assertion.action(), assertion.resource(), assertion.role());
}
},() -> { throw new UnsupportedOperationException("Only allowed in systems running Vespa Athenz instance"); });
}
+ public boolean getPreapprovedAccess(TenantName tenantName) {
+ return vespaZmsClient.map(
+ zms -> {
+ var role = sshRole(tenantName);
+ var approvalAssertion = getApprovalAssertion(role);
+ return zms.getPolicy(role.domain(), ACCESS_APPROVAL_POLICY)
+ .map(policy -> policy.assertions().stream().anyMatch(assertion -> assertion.satisfies(approvalAssertion)))
+ .orElse(false);
+ }).orElseThrow(() -> new UnsupportedOperationException("Only allowed in systems running Vespa Athenz instance") );
+ }
+
private AthenzRole sshRole(TenantName tenantName) {
return new AthenzRole(getTenantDomain(tenantName), "ssh_access");
}
@@ -152,4 +162,9 @@ public class AthenzAccessControlService implements AccessControlService {
public boolean isVespaTeamMember(AthenzUser user) {
return zmsClient.getGroupMembership(vespaTeam, user);
}
+
+ private AthenzAssertion getApprovalAssertion(AthenzRole accessRole) {
+ var approverRole = new AthenzRole(accessRole.domain(), "vespa-access-approver");
+ return AthenzAssertion.newBuilder(approverRole, accessRole.toResourceName(), "update_members").build();
+ }
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java
index c14ca2bdc80..95ebe3380d4 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java
@@ -54,6 +54,11 @@ public class MockAccessControlService implements AccessControlService {
}
+ @Override
+ public boolean getPreapprovedAccess(TenantName tenant) {
+ return false;
+ }
+
public void addPendingMember(AthenzUser user) {
pendingMembers.add(user);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index de8f1ec7ddc..c8e16634464 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -413,12 +413,13 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
}
private HttpResponse accessRequests(String tenantName, HttpRequest request) {
- if (controller.tenants().require(TenantName.from(tenantName)).type() != Tenant.Type.cloud)
+ var tenant = TenantName.from(tenantName);
+ if (controller.tenants().require(tenant).type() != Tenant.Type.cloud)
return ErrorResponse.badRequest("Can only see access requests for cloud tenants");
var accessControlService = controller.serviceRegistry().accessControlService();
- var accessRoleInformation = accessControlService.getAccessRoleInformation(TenantName.from(tenantName));
- var preapprovedAccess = !accessRoleInformation.isSelfServe() && !accessRoleInformation.isReviewEnabled();
+ var accessRoleInformation = accessControlService.getAccessRoleInformation(tenant);
+ var preapprovedAccess = accessControlService.getPreapprovedAccess(tenant);
var slime = new Slime();
var cursor = slime.setObject();
cursor.setBool("preapprovedAccess", preapprovedAccess);
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzAssertion.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzAssertion.java
index 23d1b4dfc7e..cf6f40155fc 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzAssertion.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzAssertion.java
@@ -36,6 +36,12 @@ public class AthenzAssertion {
return new Builder(role, resource, action);
}
+ public boolean satisfies(AthenzAssertion other) {
+ return role.equals(other.role()) &&
+ action.equals(other.action()) &&
+ resource.equals(other.resource());
+ }
+
public static class Builder {
private Long id;
private Effect effect;