diff options
author | Morten Tokle <mortent@verizonmedia.com> | 2021-05-10 11:55:15 +0200 |
---|---|---|
committer | Morten Tokle <mortent@verizonmedia.com> | 2021-06-01 14:37:48 +0200 |
commit | d601a1cdb46ae3cce38feb431bcb8e44fe322cc8 (patch) | |
tree | 54b94f2bcff82853a3b2c7e2aacd61240240549e | |
parent | 2f67aed1f678d626ed9694a94041437c37e7d688 (diff) |
Api to let operators request approval
14 files changed, 300 insertions, 32 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java index 98591ba41e2..0b17428296c 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.controller.api.integration; import com.yahoo.vespa.hosted.controller.api.integration.archive.ArchiveService; +import com.yahoo.vespa.hosted.controller.api.integration.athenz.AccessControlService; import com.yahoo.vespa.hosted.controller.api.integration.aws.RoleService; import com.yahoo.vespa.hosted.controller.api.integration.aws.AwsEventFetcher; import com.yahoo.vespa.hosted.controller.api.integration.aws.ResourceTagger; @@ -93,4 +94,6 @@ public interface ServiceRegistry { ArchiveService archiveService(); ChangeRequestClient changeRequestClient(); + + AccessControlService accessControlService(); } 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 new file mode 100644 index 00000000000..765312b40a3 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AccessControlService.java @@ -0,0 +1,12 @@ +// Copyright Verizon Media. 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.vespa.athenz.api.AthenzUser; + +import java.util.Collection; + +public interface AccessControlService { + public boolean approveDataPlaneAccess(AthenzUser user); + public 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 new file mode 100644 index 00000000000..2882fb1483c --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzAccessControlService.java @@ -0,0 +1,40 @@ +// Copyright Verizon Media. 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.vespa.athenz.api.AthenzDomain; +import com.yahoo.vespa.athenz.api.AthenzRole; +import com.yahoo.vespa.athenz.api.AthenzUser; +import com.yahoo.vespa.athenz.client.zms.ZmsClient; + +import java.util.Collection; +import java.util.List; + +public class AthenzAccessControlService implements AccessControlService { + + private static final String DATAPLANE_ACCESS_ROLENAME = "operator-data-plane"; + private final ZmsClient zmsClient; + private final AthenzRole dataPlaneAccessRole; + + + public AthenzAccessControlService(ZmsClient zmsClient, AthenzDomain domain) { + this.zmsClient = zmsClient; + this.dataPlaneAccessRole = new AthenzRole(domain, DATAPLANE_ACCESS_ROLENAME); + } + + @Override + public boolean approveDataPlaneAccess(AthenzUser user) { + List<AthenzUser> users = zmsClient.listPendingRoleApprovals(dataPlaneAccessRole); + if (users.contains(user)) { + // TODO (mortent): Handle expiry + zmsClient.approvePendingRoleMembership(dataPlaneAccessRole, user, null); + return true; + } + return false; + } + + @Override + public Collection<AthenzUser> listMembers() { + return null; + } +} 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 new file mode 100644 index 00000000000..9a6027317c5 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/MockAccessControlService.java @@ -0,0 +1,33 @@ +// Copyright Verizon Media. 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.vespa.athenz.api.AthenzUser; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +public class MockAccessControlService implements AccessControlService { + + private final Set<AthenzUser> pendingMembers = new HashSet<>(); + private final Set<AthenzUser> members = new HashSet<>(); + + @Override + public boolean approveDataPlaneAccess(AthenzUser user) { + if (pendingMembers.remove(user)) { + return members.add(user); + } else { + return false; + } + } + + @Override + public Collection<AthenzUser> listMembers() { + return Set.copyOf(members); + } + + public void addPendingMember(AthenzUser user) { + pendingMembers.add(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 942f0f35f58..6509bd40ebf 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 @@ -5,6 +5,7 @@ import com.yahoo.vespa.athenz.api.AthenzDomain; import com.yahoo.vespa.athenz.api.AthenzIdentity; import com.yahoo.vespa.athenz.api.AthenzResourceName; import com.yahoo.vespa.athenz.api.AthenzRole; +import com.yahoo.vespa.athenz.api.AthenzUser; import com.yahoo.vespa.athenz.api.OktaAccessToken; import com.yahoo.vespa.athenz.api.OktaIdentityToken; import com.yahoo.vespa.athenz.client.zms.RoleAction; @@ -12,6 +13,7 @@ import com.yahoo.vespa.athenz.client.zms.ZmsClient; import com.yahoo.vespa.athenz.client.zms.ZmsClientException; import com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId; +import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -145,6 +147,15 @@ public class ZmsClientMock implements ZmsClient { return false; } + @Override + public List<AthenzUser> listPendingRoleApprovals(AthenzRole athenzRole) { + return List.of(); + } + + @Override + public void approvePendingRoleMembership(AthenzRole athenzRole, AthenzUser athenzUser, Instant expiry) { + } + @Override public void close() {} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/AccessRequestResponse.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/AccessRequestResponse.java new file mode 100644 index 00000000000..e17421764e5 --- /dev/null +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/AccessRequestResponse.java @@ -0,0 +1,28 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +package com.yahoo.vespa.hosted.controller.restapi.controller; + +import com.yahoo.restapi.SlimeJsonResponse; +import com.yahoo.slime.Cursor; +import com.yahoo.slime.Slime; +import com.yahoo.vespa.athenz.api.AthenzIdentity; +import com.yahoo.vespa.athenz.api.AthenzUser; + +import java.util.Collection; + +public class AccessRequestResponse extends SlimeJsonResponse { + + public AccessRequestResponse(Collection<AthenzUser> members) { + super(toSlime(members)); + } + + private static Slime toSlime(Collection<AthenzUser> members) { + Slime slime = new Slime(); + Cursor root = slime.setObject(); + Cursor array = root.setArray("members"); + members.stream() + .map(AthenzIdentity::getFullName) + .forEach(array::addString); + return slime; + } +} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiHandler.java index 98a9ade1b16..1a1118a127f 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiHandler.java @@ -11,6 +11,8 @@ import com.yahoo.restapi.Path; import com.yahoo.restapi.ResourceResponse; import com.yahoo.slime.Inspector; import com.yahoo.slime.SlimeUtils; +import com.yahoo.vespa.athenz.api.AthenzUser; +import com.yahoo.vespa.athenz.utils.AthenzIdentities; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.auditlog.AuditLoggingRequestHandler; import com.yahoo.vespa.hosted.controller.maintenance.ControllerMaintenance; @@ -77,9 +79,16 @@ public class ControllerApiHandler extends AuditLoggingRequestHandler { private HttpResponse post(HttpRequest request) { Path path = new Path(request.getUri()); if (path.matches("/controller/v1/jobs/upgrader/confidence/{version}")) return overrideConfidence(request, path.get("version")); + if (path.matches("/controller/v1/access/requests/{user}")) return approveMembership(request, path.get("user")); return notFound(path); } + private HttpResponse approveMembership(HttpRequest request, String user) { + AthenzUser athenzUser = AthenzUser.fromUserId(user); + boolean approved = controller.serviceRegistry().accessControlService().approveDataPlaneAccess(athenzUser); + return new AccessRequestResponse(controller.serviceRegistry().accessControlService().listMembers()); + } + private HttpResponse delete(HttpRequest request) { Path path = new Path(request.getUri()); if (path.matches("/controller/v1/jobs/upgrader/confidence/{version}")) return removeConfidenceOverride(path.get("version")); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java index 702ce83d116..4a068681a50 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java @@ -9,11 +9,12 @@ import com.yahoo.test.ManualClock; import com.yahoo.vespa.hosted.controller.api.integration.ServiceRegistry; import com.yahoo.vespa.hosted.controller.api.integration.archive.ArchiveService; import com.yahoo.vespa.hosted.controller.api.integration.archive.MockArchiveService; +import com.yahoo.vespa.hosted.controller.api.integration.athenz.AccessControlService; +import com.yahoo.vespa.hosted.controller.api.integration.athenz.MockAccessControlService; import com.yahoo.vespa.hosted.controller.api.integration.aws.MockRoleService; import com.yahoo.vespa.hosted.controller.api.integration.aws.RoleService; import com.yahoo.vespa.hosted.controller.api.integration.aws.MockAwsEventFetcher; import com.yahoo.vespa.hosted.controller.api.integration.aws.MockResourceTagger; -import com.yahoo.vespa.hosted.controller.api.integration.aws.NoopRoleService; import com.yahoo.vespa.hosted.controller.api.integration.aws.ResourceTagger; import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingController; import com.yahoo.vespa.hosted.controller.api.integration.billing.MockBillingController; @@ -35,7 +36,6 @@ import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMailer; import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMeteringClient; import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockRunDataStore; import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockTesterCloud; -import com.yahoo.vespa.hosted.controller.api.integration.vcmr.ChangeRequestClient; import com.yahoo.vespa.hosted.controller.api.integration.vcmr.MockChangeRequestClient; /** @@ -73,6 +73,7 @@ public class ServiceRegistryMock extends AbstractComponent implements ServiceReg private final NoopTenantSecretService tenantSecretService = new NoopTenantSecretService(); private final ArchiveService archiveService = new MockArchiveService(); private final MockChangeRequestClient changeRequestClient = new MockChangeRequestClient(); + private final AccessControlService accessControlService = new MockAccessControlService(); public ServiceRegistryMock(SystemName system) { this.zoneRegistryMock = new ZoneRegistryMock(system); @@ -229,6 +230,11 @@ public class ServiceRegistryMock extends AbstractComponent implements ServiceReg return changeRequestClient; } + @Override + public AccessControlService accessControlService() { + return accessControlService; + } + public ConfigServerMock configServerMock() { return configServerMock; } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java index 8f6988dbc27..74b609a495e 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java @@ -6,8 +6,10 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.test.ManualClock; +import com.yahoo.vespa.athenz.api.AthenzUser; import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.flags.PermanentFlags; +import com.yahoo.vespa.hosted.controller.api.integration.athenz.MockAccessControlService; import com.yahoo.vespa.hosted.controller.api.integration.configserver.Application; import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceSnapshot; import com.yahoo.vespa.hosted.controller.auditlog.AuditLogger; @@ -165,4 +167,15 @@ public class ControllerApiTest extends ControllerContainerTest { ); } + @Test + public void testApproveMembership() { + // TODO Migrate test to use MockZmsClient + MockAccessControlService accessControlService = (MockAccessControlService) tester.serviceRegistry().accessControlService(); + tester.assertResponse(operatorRequest("http://localhost:8080/controller/v1/access/requests/"+hostedOperator.getName(), "", Request.Method.POST), + "{\"members\":[]}"); + + accessControlService.addPendingMember(hostedOperator); + tester.assertResponse(operatorRequest("http://localhost:8080/controller/v1/access/requests/"+hostedOperator.getName(), "", Request.Method.POST), + "{\"members\":[\"user.alice\"]}"); + } } 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 f9fd1c5e7e9..7450950251c 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 @@ -5,6 +5,7 @@ import com.yahoo.vespa.athenz.api.AthenzDomain; import com.yahoo.vespa.athenz.api.AthenzIdentity; import com.yahoo.vespa.athenz.api.AthenzResourceName; import com.yahoo.vespa.athenz.api.AthenzRole; +import com.yahoo.vespa.athenz.api.AthenzUser; import com.yahoo.vespa.athenz.api.OktaAccessToken; import com.yahoo.vespa.athenz.api.OktaIdentityToken; import com.yahoo.vespa.athenz.client.ErrorHandler; @@ -12,23 +13,28 @@ import com.yahoo.vespa.athenz.client.common.ClientBase; import com.yahoo.vespa.athenz.client.zms.bindings.AccessResponseEntity; import com.yahoo.vespa.athenz.client.zms.bindings.AssertionEntity; import com.yahoo.vespa.athenz.client.zms.bindings.DomainListResponseEntity; -import com.yahoo.vespa.athenz.client.zms.bindings.MembershipResponseEntity; +import com.yahoo.vespa.athenz.client.zms.bindings.MembershipEntity; import com.yahoo.vespa.athenz.client.zms.bindings.PolicyEntity; import com.yahoo.vespa.athenz.client.zms.bindings.ProviderResourceGroupRolesRequestEntity; +import com.yahoo.vespa.athenz.client.zms.bindings.RoleEntity; import com.yahoo.vespa.athenz.client.zms.bindings.TenancyRequestEntity; import com.yahoo.vespa.athenz.identity.ServiceIdentityProvider; +import com.yahoo.vespa.athenz.utils.AthenzIdentities; import org.apache.http.Header; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicHeader; import javax.net.ssl.SSLContext; import java.net.URI; +import java.time.Instant; import java.util.Collections; import java.util.List; import java.util.OptionalInt; import java.util.Set; import java.util.function.Supplier; +import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; @@ -123,7 +129,7 @@ public class DefaultZmsClient extends ClientBase implements ZmsClient { .setUri(uri) .build(); return execute(request, response -> { - MembershipResponseEntity membership = readEntity(response, MembershipResponseEntity.class); + MembershipEntity membership = readEntity(response, MembershipEntity.class); return membership.isMember; }); } @@ -194,6 +200,34 @@ public class DefaultZmsClient extends ClientBase implements ZmsClient { return true; } + @Override + public List<AthenzUser> listPendingRoleApprovals(AthenzRole athenzRole) { + URI uri = zmsUrl.resolve(String.format("domain/%s/role/%s?pending=true", athenzRole.domain().getName(), athenzRole.roleName())); + HttpUriRequest request = RequestBuilder.get() + .setUri(uri) + .build(); + RoleEntity roleEntity = execute(request, response -> readEntity(response, RoleEntity.class)); + return roleEntity.roleMembers().stream() + .filter(RoleEntity.Member::pendingApproval) + .map(RoleEntity.Member::memberName) + .map(AthenzIdentities::from) + .filter(identity -> AthenzIdentities.USER_PRINCIPAL_DOMAIN.equals(identity.getDomain())) + .map(AthenzUser.class::cast) + .collect(Collectors.toList()); + } + + @Override + public void approvePendingRoleMembership(AthenzRole athenzRole, AthenzUser athenzUser, Instant expiry) { + URI uri = zmsUrl.resolve(String.format("domain/%s/role/%s/member/%s/decision", athenzRole.domain().getName(), athenzRole.roleName(), athenzUser.getFullName())); + // TODO provide the shortest expiry of what is provided and requested (or verify this is done by ZMS) + MembershipEntity membership = new MembershipEntity(athenzUser.getFullName(), true, athenzRole.roleName(), null); + HttpUriRequest request = RequestBuilder.put() + .setUri(uri) + .setEntity(toJsonStringEntity(membership)) + .build(); + execute(request, response -> readEntity(response, Void.class)); + } + private static Header createCookieHeaderWithOktaTokens(OktaIdentityToken identityToken, OktaAccessToken accessToken) { return new BasicHeader("Cookie", String.format("okta_at=%s; okta_it=%s", accessToken.token(), identityToken.token())); } 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 c7f865a58bb..8afa9000ed1 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 @@ -5,9 +5,11 @@ import com.yahoo.vespa.athenz.api.AthenzDomain; import com.yahoo.vespa.athenz.api.AthenzIdentity; import com.yahoo.vespa.athenz.api.AthenzResourceName; import com.yahoo.vespa.athenz.api.AthenzRole; +import com.yahoo.vespa.athenz.api.AthenzUser; import com.yahoo.vespa.athenz.api.OktaAccessToken; import com.yahoo.vespa.athenz.api.OktaIdentityToken; +import java.time.Instant; import java.util.List; import java.util.Set; @@ -42,5 +44,9 @@ public interface ZmsClient extends AutoCloseable { boolean deletePolicyRule(AthenzDomain athenzDomain, String athenzPolicy, String action, AthenzResourceName resourceName, AthenzRole athenzRole); + List<AthenzUser> listPendingRoleApprovals(AthenzRole athenzRole); + + void approvePendingRoleMembership(AthenzRole athenzRole, AthenzUser athenzUser, Instant expiry); + void close(); } diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/MembershipEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/MembershipEntity.java new file mode 100644 index 00000000000..b1e7df11638 --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/MembershipEntity.java @@ -0,0 +1,51 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.client.zms.bindings; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author bjorncs + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class MembershipEntity { + public final String memberName; + public final boolean isMember; + public final String roleName; + public final String expiration; + + @JsonCreator + public MembershipEntity(@JsonProperty("memberName") String memberName, + @JsonProperty("isMember") boolean isMember, + @JsonProperty("roleName") String roleName, + @JsonProperty("expiration") String expiration) { + this.memberName = memberName; + this.isMember = isMember; + this.roleName = roleName; + this.expiration = expiration; + } + + @JsonGetter("memberName") + public String memberName() { + return memberName; + } + + @JsonGetter("isMember") + public boolean isMember() { + return isMember; + } + + @JsonGetter("roleName") + public String roleName() { + return roleName; + } + + @JsonGetter("expiration") + public String expiration() { + return expiration; + } +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/MembershipResponseEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/MembershipResponseEntity.java deleted file mode 100644 index 499afb48f25..00000000000 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/MembershipResponseEntity.java +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.athenz.client.zms.bindings; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * @author bjorncs - */ -@JsonIgnoreProperties(ignoreUnknown = true) -public class MembershipResponseEntity { - public final String memberName; - public final boolean isMember; - public final String roleName; - public final String expiration; - - @JsonCreator - public MembershipResponseEntity(@JsonProperty("memberName") String memberName, - @JsonProperty("isMember") boolean isMember, - @JsonProperty("roleName") String roleName, - @JsonProperty("expiration") String expiration) { - this.memberName = memberName; - this.isMember = isMember; - this.roleName = roleName; - this.expiration = expiration; - } -} 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 new file mode 100644 index 00000000000..e5bcc4d977e --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/RoleEntity.java @@ -0,0 +1,50 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +package com.yahoo.vespa.athenz.client.zms.bindings; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class RoleEntity { + private final String roleName; + private final List<Member> roleMembers; + + @JsonCreator + public RoleEntity(@JsonProperty("roleName") String roleName, @JsonProperty("roleMembers") List<Member> roleMembers) { + this.roleName = roleName; + this.roleMembers = roleMembers; + } + + public String roleName() { + return roleName; + } + + public List<Member> roleMembers() { + return roleMembers; + } + + public static final class Member { + private final String memberName; + private final boolean active; + private final boolean approved; + + @JsonCreator + public Member(@JsonProperty("memberName") String memberName, @JsonProperty("active") boolean active, @JsonProperty("approved") boolean approved) { + this.memberName = memberName; + this.active = active; + this.approved = approved; + } + + public String memberName() { + return memberName; + } + + public boolean pendingApproval() { + return !approved; + } + } +} |