summaryrefslogtreecommitdiffstats
path: root/vespa-athenz
diff options
context:
space:
mode:
authorOla Aunrønning <olaa@verizonmedia.com>2022-03-04 14:27:06 +0100
committerOla Aunrønning <olaa@verizonmedia.com>2022-03-04 14:27:06 +0100
commit810de0a30b9dc658769deb21c5579f88afdbd528 (patch)
treeffc2bbc9667718b9f2cf89a5f833e704be9daa6b /vespa-athenz
parentff570e8ff3f6e08f7851289efe292b4aa1acedfc (diff)
Fetch audit log and pending membership requests for athenz role
Athenz synchronizer accepts tenant name ZMSClient membership requests can be rejected
Diffstat (limited to 'vespa-athenz')
-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
4 files changed, 198 insertions, 15 deletions
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;
+ }
}
}