diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-10-01 15:35:24 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-10-01 15:35:24 +0200 |
commit | 9ce8e3121ba0c5fe36792e930c438f081dd0445d (patch) | |
tree | 5b4bf3d66cf636ee3f432aa9422339374e7d670b | |
parent | 2f74bf462fa321d9612fb6bdd144c0f77a0b09f8 (diff) |
Add ZmsClient.getPolicy()
7 files changed, 178 insertions, 8 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java index a9b20040f20..0f50ff4e198 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java @@ -150,7 +150,12 @@ public class AthenzDbMock { this.resource = resource; } - public Assertion(String role, String action, String resource) { this("grant", role, action, resource); } + public Assertion(String role, String action, String resource) { this("allow", role, action, resource); } + + public String effect() { return effect; } + public String role() { return role; } + public String action() { return action; } + public String resource() { return resource; } public boolean matches(AthenzIdentity principal, String action, String resource) { return Pattern.compile(this.role).matcher(principal.getFullName()).matches() 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 b362a0c7a47..7960e5e8df7 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 @@ -1,9 +1,11 @@ // Copyright 2017 Yahoo Holdings. 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.AthenzAssertion; 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.AthenzPolicy; import com.yahoo.vespa.athenz.api.AthenzResourceName; import com.yahoo.vespa.athenz.api.AthenzRole; import com.yahoo.vespa.athenz.api.AthenzService; @@ -184,6 +186,20 @@ public class ZmsClientMock implements ZmsClient { } @Override + public Optional<AthenzPolicy> getPolicy(AthenzDomain domain, String name) { + AthenzDbMock.Policy policy = athenz.getOrCreateDomain(domain).policies.get(name); + if (policy == null) return Optional.empty(); + List<AthenzAssertion> assertions = policy.assertions.stream() + .map(a -> AthenzAssertion.newBuilder( + new AthenzRole(domain, a.role()), + AthenzResourceName.fromString(a.resource()), + a.action()) + .build()) + .collect(Collectors.toList()); + return Optional.of(new AthenzPolicy(policy.name(), assertions)); + } + + @Override public Map<AthenzUser,String> listPendingRoleApprovals(AthenzRole athenzRole) { return Map.of(); } diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzAssertion.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzAssertion.java new file mode 100644 index 00000000000..23d1b4dfc7e --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzAssertion.java @@ -0,0 +1,80 @@ +// 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 java.util.Objects; +import java.util.Optional; +import java.util.OptionalLong; + +/** + * @author bjorncs + */ +public class AthenzAssertion { + + public enum Effect { ALLOW, DENY } + + private final Long id; + private final Effect effect; + private final AthenzRole role; + private final AthenzResourceName resource; + private final String action; + + private AthenzAssertion(Builder builder) { + this.id = builder.id; + this.effect = builder.effect; + this.role = builder.role; + this.resource = builder.resource; + this.action = builder.action; + } + + public OptionalLong id() { return id == null ? OptionalLong.empty() : OptionalLong.of(id); } + public Optional<Effect> effect() { return Optional.ofNullable(effect); } + public AthenzRole role() { return role; } + public AthenzResourceName resource() { return resource; } + public String action() { return action; } + + public static Builder newBuilder(AthenzRole role, AthenzResourceName resource, String action) { + return new Builder(role, resource, action); + } + + public static class Builder { + private Long id; + private Effect effect; + private AthenzRole role; + private AthenzResourceName resource; + private String action; + + private Builder(AthenzRole role, AthenzResourceName resource, String action) { + this.role = role; + this.resource = resource; + this.action = action; + } + + public Builder id(long id) { this.id = id; return this; } + public Builder effect(Effect effect) { this.effect = effect; return this; } + public AthenzAssertion build() { return new AthenzAssertion(this); } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AthenzAssertion that = (AthenzAssertion) o; + return Objects.equals(id, that.id) && effect == that.effect && Objects.equals(role, that.role) && Objects.equals(resource, that.resource) && Objects.equals(action, that.action); + } + + @Override + public int hashCode() { + return Objects.hash(id, effect, role, resource, action); + } + + @Override + public String toString() { + return "AthenzAssertion{" + + "id=" + id + + ", effect=" + effect + + ", role=" + role + + ", resource=" + resource + + ", action='" + action + '\'' + + '}'; + } +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzPolicy.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzPolicy.java new file mode 100644 index 00000000000..40436432c47 --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/api/AthenzPolicy.java @@ -0,0 +1,42 @@ +// 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 java.util.List; +import java.util.Objects; + +/** + * @author bjorncs + */ +public class AthenzPolicy { + private final String name; + private final List<AthenzAssertion> assertions; + + public AthenzPolicy(String name, List<AthenzAssertion> assertions) { + this.assertions = List.copyOf(assertions); + this.name = name; + } + + public String name() { return name; } + public List<AthenzAssertion> assertions() { return assertions; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AthenzPolicy that = (AthenzPolicy) o; + return Objects.equals(name, that.name) && Objects.equals(assertions, that.assertions); + } + + @Override + public int hashCode() { + return Objects.hash(name, assertions); + } + + @Override + public String toString() { + return "AthenzPolicy{" + + "name='" + name + '\'' + + ", assertions=" + assertions + + '}'; + } +} 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 769a2a54c95..09d02715fa0 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 @@ -1,9 +1,11 @@ // 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; +import com.yahoo.vespa.athenz.api.AthenzAssertion; 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.AthenzPolicy; import com.yahoo.vespa.athenz.api.AthenzResourceName; import com.yahoo.vespa.athenz.api.AthenzRole; import com.yahoo.vespa.athenz.api.AthenzService; @@ -39,7 +41,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.OptionalInt; +import java.util.OptionalLong; import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -242,18 +244,18 @@ public class DefaultZmsClient extends ClientBase implements ZmsClient { .build(); PolicyEntity policyEntity = execute(request, response -> readEntity(response, PolicyEntity.class)); - OptionalInt assertionId = policyEntity.getAssertions().stream() + OptionalLong assertionId = policyEntity.getAssertions().stream() .filter(assertionEntity -> assertionEntity.getAction().equals(action) && assertionEntity.getResource().equals(resourceName.toResourceNameString()) && assertionEntity.getRole().equals(athenzRole.toResourceNameString())) - .mapToInt(AssertionEntity::getId).findFirst(); + .mapToLong(AssertionEntity::getId).findFirst(); if (assertionId.isEmpty()) { return false; } uri = zmsUrl.resolve(String.format("domain/%s/policy/%s/assertion/%d", - athenzDomain.getName(), athenzPolicy, assertionId.getAsInt())); + athenzDomain.getName(), athenzPolicy, assertionId.getAsLong())); request = RequestBuilder.delete() .setUri(uri) @@ -264,6 +266,28 @@ public class DefaultZmsClient extends ClientBase implements ZmsClient { } @Override + public Optional<AthenzPolicy> getPolicy(AthenzDomain domain, String name) { + var uri = zmsUrl.resolve(String.format("domain/%s/policy/%s", domain.getName(), name)); + HttpUriRequest request = RequestBuilder.get().setUri(uri).build(); + PolicyEntity entity; + try { + entity = execute(request, response -> readEntity(response, PolicyEntity.class)); + } catch (ZmsClientException e) { + if (e.getErrorCode() == 404) return Optional.empty(); + throw e; + } + List<AthenzAssertion> assertions = entity.getAssertions().stream() + .map(a -> AthenzAssertion.newBuilder( + AthenzRole.fromResourceNameString(a.getRole()), + AthenzResourceName.fromString(a.getResource()), + a.getAction()) + .id(a.getId()) + .build()) + .collect(toList()); + return Optional.of(new AthenzPolicy(entity.getName(), assertions)); + } + + @Override public Map<AthenzUser, String> listPendingRoleApprovals(AthenzRole athenzRole) { URI uri = zmsUrl.resolve(String.format("domain/%s/role/%s?pending=true", athenzRole.domain().getName(), athenzRole.roleName())); HttpUriRequest request = RequestBuilder.get() 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 b1c26923113..34f1f4d891f 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 @@ -4,6 +4,7 @@ package com.yahoo.vespa.athenz.client.zms; 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.AthenzPolicy; import com.yahoo.vespa.athenz.api.AthenzResourceName; import com.yahoo.vespa.athenz.api.AthenzRole; import com.yahoo.vespa.athenz.api.AthenzService; @@ -58,6 +59,8 @@ public interface ZmsClient extends AutoCloseable { boolean deletePolicyRule(AthenzDomain athenzDomain, String athenzPolicy, String action, AthenzResourceName resourceName, AthenzRole athenzRole); + Optional<AthenzPolicy> getPolicy(AthenzDomain domain, String name); + Map<AthenzUser, String> listPendingRoleApprovals(AthenzRole athenzRole); void approvePendingRoleMembership(AthenzRole athenzRole, AthenzUser athenzUser, Instant expiry, Optional<String> reason); diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/AssertionEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/AssertionEntity.java index 824aa3b4606..77f9af957aa 100644 --- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/AssertionEntity.java +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/client/zms/bindings/AssertionEntity.java @@ -16,7 +16,7 @@ public class AssertionEntity { private final String role; private final String resource; private final String action; - private final Integer id; + private final Long id; public AssertionEntity(String role, String resource, String action) { @@ -26,7 +26,7 @@ public class AssertionEntity { public AssertionEntity(@JsonProperty("role") String role, @JsonProperty("resource") String resource, @JsonProperty("action") String action, - @JsonProperty("id") Integer id) { + @JsonProperty("id") Long id) { this.role = role; this.resource = resource; this.action = action; @@ -46,7 +46,7 @@ public class AssertionEntity { } @JsonIgnore - public int getId() { + public long getId() { return id; } } |