aboutsummaryrefslogtreecommitdiffstats
path: root/controller-api
diff options
context:
space:
mode:
authorOla Aunrønning <olaa@verizonmedia.com>2022-03-11 15:24:48 +0100
committerGitHub <noreply@github.com>2022-03-11 15:24:48 +0100
commitc251906a217e6b465965b4dcccc410e21d4789dd (patch)
treef768cf2f50392798d322fe88b97c069574632a96 /controller-api
parent07e5c4bcfdf2f3b074266e83e2dcff603fedd341 (diff)
parentfc85f3c49561ad7c51164d35363587730c85de62 (diff)
Merge pull request #21636 from vespa-engine/olaa/vespa-athenz-maintenance
Managed access decided by athenz policy
Diffstat (limited to 'controller-api')
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java102
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java26
2 files changed, 83 insertions, 45 deletions
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 415a087d990..11cace3b10e 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
@@ -26,11 +26,11 @@ public class AthenzAccessControlService implements AccessControlService {
private final ZmsClient zmsClient;
private final AthenzRole dataPlaneAccessRole;
private final AthenzGroup vespaTeam;
- private final ZmsClient vespaZmsClient; //TODO: Merge ZMS clients
+ private final Optional<ZmsClient> vespaZmsClient;
private final AthenzInstanceSynchronizer athenzInstanceSynchronizer;
- public AthenzAccessControlService(ZmsClient zmsClient, AthenzDomain domain, ZmsClient vespaZmsClient, AthenzInstanceSynchronizer athenzInstanceSynchronizer) {
+ public AthenzAccessControlService(ZmsClient zmsClient, AthenzDomain domain, Optional<ZmsClient> vespaZmsClient, AthenzInstanceSynchronizer athenzInstanceSynchronizer) {
this.zmsClient = zmsClient;
this.vespaZmsClient = vespaZmsClient;
this.athenzInstanceSynchronizer = athenzInstanceSynchronizer;
@@ -66,11 +66,16 @@ public class AthenzAccessControlService implements AccessControlService {
*/
@Override
public AthenzRoleInformation getAccessRoleInformation(TenantName tenantName) {
- var role = sshRole(tenantName);
- if (!vespaZmsClient.listRoles(role.domain()).contains(role))
- vespaZmsClient.createRole(role, Map.of());
+ return vespaZmsClient.map(
+ zms -> {
+ var role = sshRole(tenantName);
+ if (!zms.listRoles(role.domain()).contains(role))
+ zms.createRole(role, Map.of());
+
+ return zms.getFullRoleInformation(role);
+ }
+ ).orElseThrow(() -> new UnsupportedOperationException("Only allowed in systems running Vespa Athenz instance"));
- return vespaZmsClient.getFullRoleInformation(role);
}
/**
@@ -78,22 +83,25 @@ public class AthenzAccessControlService implements AccessControlService {
*/
@Override
public boolean decideSshAccess(TenantName tenantName, Instant expiry, OAuthCredentials oAuthCredentials, boolean approve) {
- var role = sshRole(tenantName);
-
- if (!vespaZmsClient.listRoles(role.domain()).contains(role))
- vespaZmsClient.createRole(role, Map.of());
-
- if (vespaZmsClient.getMembership(role, vespaTeam))
- return false;
-
- var roleInformation = vespaZmsClient.getFullRoleInformation(role);
- if (roleInformation.getPendingRequest().isEmpty())
- return false;
- var reason = roleInformation.getPendingRequest().get().getReason();
-
- vespaZmsClient.decidePendingRoleMembership(role, vespaTeam, expiry, Optional.of(reason), Optional.of(oAuthCredentials), approve);
- athenzInstanceSynchronizer.synchronizeInstances(tenantName);
- return true;
+ return vespaZmsClient.map(
+ zms -> {
+ var role = sshRole(tenantName);
+ if (!zms.listRoles(role.domain()).contains(role))
+ zms.createRole(role, Map.of());
+
+ if (zms.getMembership(role, vespaTeam))
+ return false;
+
+ var roleInformation = zms.getFullRoleInformation(role);
+ if (roleInformation.getPendingRequest().isEmpty())
+ return false;
+ var reason = roleInformation.getPendingRequest().get().getReason();
+
+ zms.decidePendingRoleMembership(role, vespaTeam, expiry, Optional.of(reason), Optional.of(oAuthCredentials), approve);
+ athenzInstanceSynchronizer.synchronizeInstances(tenantName);
+ return true;
+ }
+ ).orElseThrow(() -> new UnsupportedOperationException("Only allowed in systems running Vespa Athenz instance"));
}
/**
@@ -101,40 +109,44 @@ public class AthenzAccessControlService implements AccessControlService {
*/
@Override
public boolean requestSshAccess(TenantName tenantName) {
- var role = sshRole(tenantName);
+ return vespaZmsClient.map(
+ zms -> {
+ var role = sshRole(tenantName);
- if (!vespaZmsClient.listRoles(role.domain()).contains(role))
- vespaZmsClient.createRole(role, Map.of());
+ if (!zms.listRoles(role.domain()).contains(role))
+ zms.createRole(role, Map.of());
- if (vespaZmsClient.getMembership(role, vespaTeam))
- return false;
+ if (zms.getMembership(role, vespaTeam))
+ return false;
- vespaZmsClient.addRoleMember(role, vespaTeam, Optional.empty());
- return true;
+ zms.addRoleMember(role, vespaTeam, Optional.empty());
+ return true;
+ }
+ ).orElseThrow(() -> new UnsupportedOperationException("Only allowed in systems running Vespa Athenz instance"));
}
public void setPreapprovedAccess(TenantName tenantName, boolean preapprovedAccess) {
- var role = sshRole(tenantName);
-
- var attributes = Map.<String, Object>of(
- "selfServe", !preapprovedAccess,
- "reviewEnabled", !preapprovedAccess
- );
- vespaZmsClient.createRole(role, attributes);
+ 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");
+ if (preapprovedAccess) {
+ zms.addPolicyRule(role.domain(), policyName, action, role.toResourceName(), approverRole);
+ } else {
+ zms.deletePolicyRule(role.domain(), policyName, action, role.toResourceName(), approverRole);
+ }
+ },() -> { throw new UnsupportedOperationException("Only allowed in systems running Vespa Athenz instance"); });
}
private AthenzRole sshRole(TenantName tenantName) {
- return new AthenzRole(getOrCreateTenantDomain(tenantName), "ssh_access");
+ return new AthenzRole(getTenantDomain(tenantName), "ssh_access");
}
- private AthenzDomain getOrCreateTenantDomain(TenantName tenantName) {
- var domain = new AthenzDomain(TENANT_DOMAIN_PREFIX + "." + tenantName.value());
-
- if (vespaZmsClient.getDomainList(domain.getName()).isEmpty()) {
- vespaZmsClient.createSubdomain(new AthenzDomain(TENANT_DOMAIN_PREFIX), tenantName.value());
- }
-
- return domain;
+ private AthenzDomain getTenantDomain(TenantName tenantName) {
+ return new AthenzDomain(TENANT_DOMAIN_PREFIX + "." + tenantName.value());
}
public boolean isVespaTeamMember(AthenzUser user) {
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java
index 44271846d7d..63dfff95c03 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java
@@ -135,6 +135,19 @@ public class AthenzDbMock {
public boolean matches(AthenzIdentity principal, String action, String resource) {
return assertions.stream().anyMatch(a -> a.matches(principal, action, resource));
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Policy policy = (Policy) o;
+ return Objects.equals(name, policy.name) && Objects.equals(assertions, policy.assertions);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, assertions);
+ }
}
public static class Assertion {
@@ -192,5 +205,18 @@ public class AthenzDbMock {
public String name() {
return name;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Role role = (Role) o;
+ return Objects.equals(name, role.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
}
}