diff options
author | Ola Aunrønning <olaa@verizonmedia.com> | 2022-03-14 11:32:14 +0100 |
---|---|---|
committer | Ola Aunrønning <olaa@verizonmedia.com> | 2022-03-14 11:32:14 +0100 |
commit | 065053e8efaa6941521e1ec79b7948d34d73d18e (patch) | |
tree | c1bb2f31f341fc87d57836bb95561c6fa29d3434 | |
parent | fed4f6dddba35fe13b9d10dc79485fa7d4d97afb (diff) |
Infer managed access through assertion existence
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; |