summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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.java34
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzInstanceSynchronizer.java4
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzInstanceSynchronizerMock.java4
-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.java7
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java26
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzRoleInformation.java121
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/DefaultZmsClient.java17
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/ZmsClient.java7
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/RoleEntity.java68
11 files changed, 253 insertions, 56 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 b270c27092f..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,10 +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);
- boolean hasPreapprovedAccess(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 6b91f49af8e..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;
@@ -45,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;
@@ -64,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))
@@ -85,11 +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));
- athenzInstanceSynchronizer.synchronizeInstances();
+ 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;
}
@@ -110,15 +113,6 @@ public class AthenzAccessControlService implements AccessControlService {
return true;
}
- public boolean hasPreapprovedAccess(TenantName tenantName) {
- var role = sshRole(tenantName);
-
- if (!vespaZmsClient.listRoles(role.domain()).contains(role))
- return true; // true by default
-
- return !vespaZmsClient.isSelfServeRole(role);
- }
-
public void setPreapprovedAccess(TenantName tenantName, boolean preapprovedAccess) {
var role = sshRole(tenantName);
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
index fb2375d3ea2..3b9166d4363 100644
--- 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
@@ -1,6 +1,8 @@
// 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
*
@@ -8,6 +10,6 @@ package com.yahoo.vespa.hosted.controller.api.integration.athenz;
*/
public interface AthenzInstanceSynchronizer {
- void synchronizeInstances();
+ 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
index 484fb3d6dd2..1f0403a0b44 100644
--- 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
@@ -1,10 +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() {}
+ 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 505ee97bdf5..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,13 +45,8 @@ public class MockAccessControlService implements AccessControlService {
}
@Override
- public boolean hasPendingAccessRequests(TenantName tenantName) {
- return false;
- }
-
- @Override
- public boolean hasPreapprovedAccess(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
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 62a999bb7a6..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,8 +257,8 @@ public class ZmsClientMock implements ZmsClient {
public void createSubdomain(AthenzDomain parent, String name) {}
@Override
- public boolean isSelfServeRole(AthenzRole role) {
- return false;
+ public AthenzRoleInformation getFullRoleInformation(AthenzRole role) {
+ return new AthenzRoleInformation(role.domain(), role.roleName(), true, true, Optional.empty(), List.of());
}
@Override
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 3bcf62fde21..ef851311e63 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
@@ -417,11 +417,26 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
return ErrorResponse.badRequest("Can only see access requests for cloud tenants");
var accessControlService = controller.serviceRegistry().accessControlService();
- var pendingRequests = accessControlService.hasPendingAccessRequests(TenantName.from(tenantName));
- var preapprovedAccess = accessControlService.hasPreapprovedAccess(TenantName.from(tenantName));
+ var accessRoleInformation = accessControlService.getAccessRoleInformation(TenantName.from(tenantName));
+ var preapprovedAccess = !accessRoleInformation.isSelfServe() && !accessRoleInformation.isReviewEnabled();
var slime = new Slime();
- slime.setObject().setBool("hasPendingRequests", pendingRequests);
- slime.setObject().setBool("preapprovedAccess", preapprovedAccess);
+ var cursor = slime.setObject();
+ cursor.setBool("preapprovedAccess", preapprovedAccess);
+ accessRoleInformation.getPendingRequest()
+ .ifPresent(membershipRequest -> {
+ var requestCursor = cursor.setObject("pendingRequest");
+ requestCursor.setString("requestTime", membershipRequest.getCreationTime());
+ requestCursor.setString("reason", membershipRequest.getReason());
+ });
+ var auditLogCursor = cursor.setArray("auditLog");
+ accessRoleInformation.getAuditLog()
+ .forEach(auditLogEntry -> {
+ var entryCursor = auditLogCursor.addObject();
+ entryCursor.setString("created", auditLogEntry.getCreationTime());
+ entryCursor.setString("approver", auditLogEntry.getApprover());
+ entryCursor.setString("reason", auditLogEntry.getReason());
+ entryCursor.setString("status", auditLogEntry.getAction());
+ });
return new SlimeJsonResponse(slime);
}
@@ -448,8 +463,9 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
var expiry = inspector.field("expiry").valid() ?
Instant.ofEpochMilli(inspector.field("expiry").asLong()) :
Instant.now().plus(1, ChronoUnit.DAYS);
+ var approve = inspector.field("approve").asBool();
- controller.serviceRegistry().accessControlService().approveSshAccess(tenant, expiry, OAuthCredentials.fromAuth0RequestContext(request.getJDiscRequest().context()));
+ controller.serviceRegistry().accessControlService().decideSshAccess(tenant, expiry, OAuthCredentials.fromAuth0RequestContext(request.getJDiscRequest().context()), approve);
return new MessageResponse("OK");
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzRoleInformation.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzRoleInformation.java
new file mode 100644
index 00000000000..dcc3452a69a
--- /dev/null
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzRoleInformation.java
@@ -0,0 +1,121 @@
+// 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 com.yahoo.vespa.athenz.client.zms.bindings.RoleEntity;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * @author olaa
+ */
+public class AthenzRoleInformation extends AthenzRole {
+
+ private final boolean isSelfServe;
+ private final boolean reviewEnabled;
+ private final Optional<MembershipRequest> pendingRequest;
+ private final List<AuditLogEntry> auditLog;
+
+ public AthenzRoleInformation(AthenzDomain domain, String roleName, boolean isSelfServe, boolean reviewEnabled, Optional<MembershipRequest> pendingRequest, List<AuditLogEntry> auditLog) {
+ super(domain, roleName);
+ this.isSelfServe = isSelfServe;
+ this.reviewEnabled = reviewEnabled;
+ this.pendingRequest = pendingRequest;
+ this.auditLog = auditLog;
+ }
+
+ public boolean isSelfServe() {
+ return isSelfServe;
+ }
+
+ public boolean isReviewEnabled() {
+ return reviewEnabled;
+ }
+
+ public Optional<MembershipRequest> getPendingRequest() {
+ return pendingRequest;
+ }
+
+ public List<AuditLogEntry> getAuditLog() {
+ return auditLog;
+ }
+
+ public static AthenzRoleInformation fromRoleEntity(RoleEntity roleEntity) {
+ var role = fromResourceNameString(roleEntity.roleName());
+ var isSelfServe = roleEntity.selfServe() != null && roleEntity.selfServe();
+ var reviewEnabled = roleEntity.reviewEnabled() != null && roleEntity.reviewEnabled();
+ var pendingRequest = roleEntity.roleMembers()
+ .stream()
+ .filter(member -> member.pendingApproval())
+ .map(member -> new MembershipRequest(member.memberName(), member.auditRef(), member.requestTime(), member.active()))
+ .findFirst();
+ var auditLog = roleEntity.auditLog()
+ .stream()
+ .map(entry -> new AuditLogEntry(entry.getAdmin(), entry.getAction(), entry.getAuditRef(), entry.getCreated()))
+ .collect(Collectors.toList());
+ return new AthenzRoleInformation(role.domain(), role.roleName(), isSelfServe, reviewEnabled, pendingRequest, auditLog);
+ }
+
+
+ public static class MembershipRequest {
+ private final String memberName;
+ private final String reason;
+ private final String creationTime;
+ private final boolean active;
+
+ public MembershipRequest(String memberName, String reason, String creationTime, boolean active) {
+ this.memberName = memberName;
+ this.reason = reason;
+ this.creationTime = creationTime;
+ this.active = active;
+ }
+
+ public String getMemberName() {
+ return memberName;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public String getCreationTime() {
+ return creationTime;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+ }
+
+ public static class AuditLogEntry {
+ private final String approver;
+ private final String action;
+ private final String reason;
+ private final String creationTime;
+
+ public AuditLogEntry(String approver, String action, String reason, String creationTime) {
+ this.approver = approver;
+ this.action = action;
+ this.reason = reason;
+ this.creationTime = creationTime;
+ }
+
+ public String getApprover() {
+ return approver;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public String getCreationTime() {
+ return creationTime;
+ }
+ }
+
+}
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 23c530402b9..eef833c91a7 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
@@ -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.ErrorHandler;
@@ -301,10 +302,10 @@ public class DefaultZmsClient extends ClientBase 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) {
URI uri = zmsUrl.resolve(String.format("domain/%s/role/%s/member/%s/decision", athenzRole.domain().getName(), athenzRole.roleName(), athenzIdentity.getFullName()));
- MembershipEntity membership = new MembershipEntity.RoleMembershipEntity(athenzIdentity.getFullName(), true, athenzRole.roleName(), Long.toString(expiry.getEpochSecond()));
+ MembershipEntity membership = new MembershipEntity.RoleMembershipEntity(athenzIdentity.getFullName(), approve, athenzRole.roleName(), Long.toString(expiry.getEpochSecond()));
var requestBuilder = RequestBuilder.put()
.setUri(uri)
@@ -406,15 +407,11 @@ public class DefaultZmsClient extends ClientBase implements ZmsClient {
execute(request, response -> readEntity(response, Void.class));
}
- public boolean isSelfServeRole(AthenzRole role) {
- URI uri = zmsUrl.resolve(String.format("domain/%s/role/%s", role.domain().getName(), role.roleName()));
+ public AthenzRoleInformation getFullRoleInformation(AthenzRole role) {
+ var uri = zmsUrl.resolve(String.format("domain/%s/role/%s?pending=true&auditLog=true", role.domain().getName(), role.roleName()));
var request = RequestBuilder.get(uri).build();
var roleEntity = execute(request, response -> readEntity(response, RoleEntity.class));
-
- if (roleEntity.selfServe() == null || roleEntity.reviewEnabled() == null)
- return false;
-
- return roleEntity.selfServe() && roleEntity.reviewEnabled();
+ return AthenzRoleInformation.fromRoleEntity(roleEntity);
}
private static Header createCookieHeader(OAuthCredentials oAuthCredentials) {
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 611fe7aa451..3ff2ff843a0 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
@@ -7,6 +7,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;
@@ -59,8 +60,8 @@ public interface ZmsClient extends AutoCloseable {
Map<AthenzIdentity, String> listPendingRoleApprovals(AthenzRole athenzRole);
- void approvePendingRoleMembership(AthenzRole athenzRole, AthenzIdentity athenzIdentity, Instant expiry,
- Optional<String> reason, Optional<OAuthCredentials> oAuthCredentials);
+ void decidePendingRoleMembership(AthenzRole athenzRole, AthenzIdentity athenzIdentity, Instant expiry,
+ Optional<String> reason, Optional<OAuthCredentials> oAuthCredentials, boolean approve);
List<AthenzIdentity> listMembers(AthenzRole athenzRole);
@@ -80,7 +81,7 @@ public interface ZmsClient extends AutoCloseable {
void createSubdomain(AthenzDomain parent, String name);
- boolean isSelfServeRole(AthenzRole role);
+ AthenzRoleInformation getFullRoleInformation(AthenzRole role);
void close();
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/RoleEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/RoleEntity.java
index f0a498ed644..3ee0c717f19 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/RoleEntity.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/RoleEntity.java
@@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -17,16 +18,19 @@ public class RoleEntity {
private final List<Member> roleMembers;
private final Boolean selfServe;
private final Boolean reviewEnabled;
+ private final List<AuditLogEntry> auditLog;
@JsonCreator
public RoleEntity(@JsonProperty("roleName") String roleName,
@JsonProperty("roleMembers") List<Member> roleMembers,
@JsonProperty("selfServe") Boolean selfServe,
- @JsonProperty("reviewEnabled") Boolean reviewEnabled) {
+ @JsonProperty("reviewEnabled") Boolean reviewEnabled,
+ @JsonProperty("auditLog") List<AuditLogEntry> auditLog) {
this.roleName = roleName;
this.roleMembers = roleMembers;
this.selfServe = selfServe;
this.reviewEnabled = reviewEnabled;
+ this.auditLog = auditLog == null ? new ArrayList<>() : auditLog;
}
public String roleName() {
@@ -45,19 +49,29 @@ public class RoleEntity {
return reviewEnabled;
}
+ public List<AuditLogEntry> auditLog() {
+ return auditLog;
+ }
+
@JsonIgnoreProperties(ignoreUnknown = true)
public static final class Member {
private final String memberName;
private final boolean active;
private final boolean approved;
private final String auditRef;
+ private final String requestTime;
@JsonCreator
- public Member(@JsonProperty("memberName") String memberName, @JsonProperty("active") boolean active, @JsonProperty("approved") boolean approved, @JsonProperty("auditRef") String auditRef) {
+ public Member(@JsonProperty("memberName") String memberName,
+ @JsonProperty("active") boolean active,
+ @JsonProperty("approved") boolean approved,
+ @JsonProperty("auditRef") String auditRef,
+ @JsonProperty("requestTime") String requestTime) {
this.memberName = memberName;
this.active = active;
this.approved = approved;
this.auditRef = auditRef;
+ this.requestTime = requestTime;
}
public String memberName() {
@@ -71,5 +85,55 @@ public class RoleEntity {
public String auditRef() {
return auditRef;
}
+
+ public String requestTime() {
+ return requestTime;
+ }
+
+ public boolean active() {
+ return active;
+ }
+ }
+
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public static final class AuditLogEntry {
+ private final String member;
+ private final String admin;
+ private final String action;
+ private final String auditRef;
+ private final String created;
+
+ @JsonCreator
+ public AuditLogEntry(@JsonProperty("member") String member,
+ @JsonProperty("admin") String admin,
+ @JsonProperty("created") String created,
+ @JsonProperty("action") String action,
+ @JsonProperty("auditRef") String auditRef) {
+ this.member = member;
+ this.admin = admin;
+ this.created = created;
+ this.action = action;
+ this.auditRef = auditRef;
+ }
+
+ public String getMember() {
+ return member;
+ }
+
+ public String getAdmin() {
+ return admin;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public String getAuditRef() {
+ return auditRef;
+ }
+
+ public String getCreated() {
+ return created;
+ }
}
}