diff options
Diffstat (limited to 'vespa-athenz/src/main/java/com')
5 files changed, 143 insertions, 30 deletions
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; + } + } +} |