aboutsummaryrefslogtreecommitdiffstats
path: root/controller-api
diff options
context:
space:
mode:
authorOla Aunrønning <olaa@verizonmedia.com>2022-03-07 09:25:20 +0100
committerGitHub <noreply@github.com>2022-03-07 09:25:20 +0100
commit5ead84bb17aa1ebb39d934d9b74d2d6ef758d566 (patch)
treea07192f1d6dc8d9ca8102fef5ec79c93f7a560e1 /controller-api
parent2e05df2de19c2d5b87befa2ee6c4fd182dcb5630 (diff)
parent810de0a30b9dc658769deb21c5579f88afdbd528 (diff)
Merge pull request #21480 from vespa-engine/olaa/athenz-synchronization
Synchronize athenz instances on request approval
Diffstat (limited to 'controller-api')
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java6
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java38
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzInstanceSynchronizer.java15
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzInstanceSynchronizerMock.java12
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java15
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClientMock.java8
6 files changed, 77 insertions, 17 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 a08319055ff..1dd6eb543ef 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
@@ -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.AthenzRoleInformation;
import com.yahoo.vespa.athenz.api.AthenzUser;
import com.yahoo.vespa.athenz.api.OAuthCredentials;
@@ -16,8 +17,9 @@ import java.util.Collection;
*/
public interface AccessControlService {
boolean approveDataPlaneAccess(AthenzUser user, Instant expiry);
- boolean approveSshAccess(TenantName tenantName, Instant expiry, OAuthCredentials oAuthCredentials);
+ boolean decideSshAccess(TenantName tenantName, Instant expiry, OAuthCredentials oAuthCredentials, boolean approve);
boolean requestSshAccess(TenantName tenantName);
- boolean hasPendingAccessRequests(TenantName tenantName);
+ AthenzRoleInformation getAccessRoleInformation(TenantName tenantName);
+ void setPreapprovedAccess(TenantName tenantName, boolean preapproved);
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 0568678219e..415a087d990 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
@@ -7,6 +7,7 @@ import com.yahoo.vespa.athenz.api.AthenzDomain;
import com.yahoo.vespa.athenz.api.AthenzGroup;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.athenz.api.AthenzRole;
+import com.yahoo.vespa.athenz.api.AthenzRoleInformation;
import com.yahoo.vespa.athenz.api.AthenzUser;
import com.yahoo.vespa.athenz.api.OAuthCredentials;
import com.yahoo.vespa.athenz.client.zms.ZmsClient;
@@ -26,11 +27,13 @@ public class AthenzAccessControlService implements AccessControlService {
private final AthenzRole dataPlaneAccessRole;
private final AthenzGroup vespaTeam;
private final ZmsClient vespaZmsClient; //TODO: Merge ZMS clients
+ private final AthenzInstanceSynchronizer athenzInstanceSynchronizer;
- public AthenzAccessControlService(ZmsClient zmsClient, AthenzDomain domain, ZmsClient vespaZmsClient) {
+ public AthenzAccessControlService(ZmsClient zmsClient, AthenzDomain domain, ZmsClient vespaZmsClient, AthenzInstanceSynchronizer athenzInstanceSynchronizer) {
this.zmsClient = zmsClient;
this.vespaZmsClient = vespaZmsClient;
+ this.athenzInstanceSynchronizer = athenzInstanceSynchronizer;
this.dataPlaneAccessRole = new AthenzRole(domain, DATAPLANE_ACCESS_ROLENAME);
this.vespaTeam = new AthenzGroup(domain, ALLOWED_OPERATOR_GROUPNAME);
}
@@ -43,7 +46,7 @@ public class AthenzAccessControlService implements AccessControlService {
}
Map<AthenzIdentity, String> users = zmsClient.listPendingRoleApprovals(dataPlaneAccessRole);
if (users.containsKey(user)) {
- zmsClient.approvePendingRoleMembership(dataPlaneAccessRole, user, expiry, Optional.empty(), Optional.empty());
+ zmsClient.decidePendingRoleMembership(dataPlaneAccessRole, user, expiry, Optional.empty(), Optional.empty(), true);
return true;
}
return false;
@@ -62,19 +65,19 @@ public class AthenzAccessControlService implements AccessControlService {
* @return Whether the ssh access role has any pending role membership requests
*/
@Override
- public boolean hasPendingAccessRequests(TenantName tenantName) {
+ public AthenzRoleInformation getAccessRoleInformation(TenantName tenantName) {
var role = sshRole(tenantName);
if (!vespaZmsClient.listRoles(role.domain()).contains(role))
- return false;
- var pendingApprovals = vespaZmsClient.listPendingRoleApprovals(role);
- return pendingApprovals.containsKey(vespaTeam);
+ vespaZmsClient.createRole(role, Map.of());
+
+ return vespaZmsClient.getFullRoleInformation(role);
}
/**
* @return true if access has been granted - false if already member
*/
@Override
- public boolean approveSshAccess(TenantName tenantName, Instant expiry, OAuthCredentials oAuthCredentials) {
+ public boolean decideSshAccess(TenantName tenantName, Instant expiry, OAuthCredentials oAuthCredentials, boolean approve) {
var role = sshRole(tenantName);
if (!vespaZmsClient.listRoles(role.domain()).contains(role))
@@ -83,10 +86,13 @@ public class AthenzAccessControlService implements AccessControlService {
if (vespaZmsClient.getMembership(role, vespaTeam))
return false;
- if (!hasPendingAccessRequests(tenantName)) {
- vespaZmsClient.addRoleMember(role, vespaTeam, Optional.empty());
- }
- vespaZmsClient.approvePendingRoleMembership(role, vespaTeam, expiry, Optional.empty(), Optional.of(oAuthCredentials));
+ 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;
}
@@ -107,6 +113,16 @@ public class AthenzAccessControlService implements AccessControlService {
return true;
}
+ 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);
+ }
+
private AthenzRole sshRole(TenantName tenantName) {
return new AthenzRole(getOrCreateTenantDomain(tenantName), "ssh_access");
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzInstanceSynchronizer.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzInstanceSynchronizer.java
new file mode 100644
index 00000000000..3b9166d4363
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzInstanceSynchronizer.java
@@ -0,0 +1,15 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.api.integration.athenz;
+
+import com.yahoo.config.provision.TenantName;
+
+/**
+ * @author olaa
+ *
+ * Responsible for synchronizing misc roles and their pending memberships between separate Athenz instances
+ */
+public interface AthenzInstanceSynchronizer {
+
+ void synchronizeInstances(TenantName tenant);
+
+}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzInstanceSynchronizerMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzInstanceSynchronizerMock.java
new file mode 100644
index 00000000000..1f0403a0b44
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzInstanceSynchronizerMock.java
@@ -0,0 +1,12 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.api.integration.athenz;
+
+import com.yahoo.config.provision.TenantName;
+
+/**
+ * @author olaa
+ */
+public class AthenzInstanceSynchronizerMock implements AthenzInstanceSynchronizer {
+ @Override
+ public void synchronizeInstances(TenantName tenant) {}
+}
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 b8106450705..c14ca2bdc80 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
@@ -3,12 +3,16 @@
package com.yahoo.vespa.hosted.controller.api.integration.athenz;
import com.yahoo.config.provision.TenantName;
+import com.yahoo.vespa.athenz.api.AthenzDomain;
+import com.yahoo.vespa.athenz.api.AthenzRoleInformation;
import com.yahoo.vespa.athenz.api.AthenzUser;
import com.yahoo.vespa.athenz.api.OAuthCredentials;
import java.time.Instant;
import java.util.Collection;
import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
import java.util.Set;
public class MockAccessControlService implements AccessControlService {
@@ -31,7 +35,7 @@ public class MockAccessControlService implements AccessControlService {
}
@Override
- public boolean approveSshAccess(TenantName tenantName, Instant expiry, OAuthCredentials oAuthCredentials) {
+ public boolean decideSshAccess(TenantName tenantName, Instant expiry, OAuthCredentials oAuthCredentials, boolean approve) {
return false;
}
@@ -41,8 +45,13 @@ public class MockAccessControlService implements AccessControlService {
}
@Override
- public boolean hasPendingAccessRequests(TenantName tenantName) {
- return false;
+ public AthenzRoleInformation getAccessRoleInformation(TenantName tenantName) {
+ return new AthenzRoleInformation(new AthenzDomain("test-domain"), "tenant-role", false, false, Optional.empty(), List.of());
+ }
+
+ @Override
+ public void setPreapprovedAccess(TenantName tenantName, boolean preapproved) {
+
}
public void addPendingMember(AthenzUser user) {
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 38b2a36a348..5f567e8b84a 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
@@ -8,6 +8,7 @@ import com.yahoo.vespa.athenz.api.AthenzIdentity;
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.AthenzRoleInformation;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.api.OAuthCredentials;
import com.yahoo.vespa.athenz.client.zms.RoleAction;
@@ -201,7 +202,7 @@ public class ZmsClientMock implements ZmsClient {
}
@Override
- public void approvePendingRoleMembership(AthenzRole athenzRole, AthenzIdentity athenzIdentity, Instant expiry, Optional<String> reason, Optional<OAuthCredentials> oAuthCredentials) {
+ public void decidePendingRoleMembership(AthenzRole athenzRole, AthenzIdentity athenzIdentity, Instant expiry, Optional<String> reason, Optional<OAuthCredentials> oAuthCredentials, boolean approve) {
}
@Override
@@ -256,6 +257,11 @@ public class ZmsClientMock implements ZmsClient {
public void createSubdomain(AthenzDomain parent, String name) {}
@Override
+ public AthenzRoleInformation getFullRoleInformation(AthenzRole role) {
+ return new AthenzRoleInformation(role.domain(), role.roleName(), true, true, Optional.empty(), List.of());
+ }
+
+ @Override
public void close() {}
private static AthenzDomain getTenantDomain(AthenzResourceName resource) {