diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-09-30 09:40:52 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-09-30 15:46:33 +0200 |
commit | 58b3b16509b139470633460349dec26753a6160e (patch) | |
tree | 33994b4a33bd0729d0b1ffbab375e1c061b07e75 | |
parent | 43ea2db071aac1434e2c05c81b9b5f76939eac00 (diff) |
Model policies with multiple assertions in AthenzDbMock
2 files changed, 68 insertions, 22 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 899e3174df9..e3c0f47625f 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 @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; @@ -43,7 +44,7 @@ public class AthenzDbMock { public final Map<ApplicationId, Application> applications = new HashMap<>(); public final Map<String, Service> services = new HashMap<>(); public final List<Role> roles = new ArrayList<>(); - public final List<Policy> policies = new ArrayList<>(); + public final Map<String, Policy> policies = new HashMap<>(); public boolean isVespaTenant = false; public Domain(AthenzDomain name) { @@ -52,7 +53,7 @@ public class AthenzDbMock { public Domain admin(AthenzIdentity identity) { admins.add(identity); - policies.add(new Policy("admin", identity.getFullName(), ".*", ".*")); + policies.put("admin", new Policy("admin", identity.getFullName(), ".*", ".*")); return this; } @@ -67,7 +68,7 @@ public class AthenzDbMock { } public Domain withPolicy(String principalRegex, String operation, String resource) { - policies.add(new Policy("admin", principalRegex, operation, resource)); + policies.put("admin", new Policy("admin", principalRegex, operation, resource)); return this; } @@ -107,31 +108,77 @@ public class AthenzDbMock { public static class Policy { private final String name; - private final Pattern principal; - private final Pattern action; - private final Pattern resource; + final List<Assertion> assertions = new ArrayList<>(); public Policy(String name, String principal, String action, String resource) { - this.name = name; - this.principal = Pattern.compile(principal); - this.action = Pattern.compile(action); - this.resource = Pattern.compile(resource); + this(name); + this.assertions.add(new Assertion("grant", principal, action, resource)); } + public Policy(String name) { this.name = name; } + public String name() { return name; } public boolean principalMatches(AthenzIdentity athenzIdentity) { - return this.principal.matcher(athenzIdentity.getFullName()).matches(); + return assertions.get(0).principalMatches(athenzIdentity); } public boolean actionMatches(String operation) { - return this.action.matcher(operation).matches(); + return assertions.get(0).actionMatches(operation); } public boolean resourceMatches(String resource) { - return this.resource.matcher(resource).matches(); + return assertions.get(0).resourceMatches(resource); + } + + public boolean hasAssertionMatching(String assertion) { + return assertions.stream().anyMatch(a -> a.asString().equals(assertion)); + } + } + + public static class Assertion { + private final String effect; + private final String role; + private final String action; + private final String resource; + + public Assertion(String effect, String role, String action, String resource) { + this.effect = effect; + this.role = role; + this.action = action; + this.resource = resource; + } + + public Assertion(String role, String action, String resource) { this("grant", role, action, resource); } + + public boolean principalMatches(AthenzIdentity athenzIdentity) { + return Pattern.compile(role).matcher(athenzIdentity.getFullName()).matches(); + } + + public boolean actionMatches(String operation) { + return Pattern.compile(action).matcher(operation).matches(); + } + + public boolean resourceMatches(String resource) { + return Pattern.compile(resource).matcher(resource).matches(); + } + + public String asString() { return String.format("%s %s to %s on %s", effect, action, role, resource).toLowerCase(); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Assertion assertion = (Assertion) o; + return Objects.equals(effect, assertion.effect) && Objects.equals(role, assertion.role) + && Objects.equals(action, assertion.action) && Objects.equals(resource, assertion.resource); + } + + @Override + public int hashCode() { + return Objects.hash(effect, role, action, resource); } } 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 42a5e2b42be..dd49f3a1e7c 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 @@ -158,7 +158,7 @@ public class ZmsClientMock implements ZmsClient { return false; } else { AthenzDbMock.Domain domain = getDomainOrThrow(resource.getDomain(), false); - return domain.policies.stream() + return domain.policies.values().stream() .anyMatch(policy -> policy.principalMatches(identity) && policy.actionMatches(action) && @@ -168,17 +168,18 @@ public class ZmsClientMock implements ZmsClient { @Override public void createPolicy(AthenzDomain athenzDomain, String athenzPolicy) { - List<AthenzDbMock.Policy> policies = athenz.getOrCreateDomain(athenzDomain).policies; - if (policies.stream().anyMatch(p -> p.name().equals(athenzPolicy))) { + Map<String, AthenzDbMock.Policy> policies = athenz.getOrCreateDomain(athenzDomain).policies; + if (policies.containsKey(athenzPolicy)) { throw new IllegalArgumentException("Policy already exists"); } - - // Policy will be created in the mock when an assertion is added + policies.put(athenzPolicy, new AthenzDbMock.Policy(athenzPolicy)); } @Override public void addPolicyRule(AthenzDomain athenzDomain, String athenzPolicy, String action, AthenzResourceName resourceName, AthenzRole athenzRole) { - athenz.getOrCreateDomain(athenzDomain).policies.add(new AthenzDbMock.Policy(athenzPolicy, athenzRole.roleName(), action, resourceName.toResourceNameString())); + AthenzDbMock.Policy policy = athenz.getOrCreateDomain(athenzDomain).policies.get(athenzPolicy); + if (policy == null) throw new IllegalArgumentException("No policy with name " + athenzPolicy); + policy.assertions.add(new AthenzDbMock.Assertion(athenzRole.roleName(), action, resourceName.toResourceNameString())); } @Override @@ -235,9 +236,7 @@ public class ZmsClientMock implements ZmsClient { @Override public Set<String> listPolicies(AthenzDomain domain) { - return athenz.getOrCreateDomain(domain).policies.stream() - .map(AthenzDbMock.Policy::name) - .collect(Collectors.toSet()); + return athenz.getOrCreateDomain(domain).policies.keySet(); } @Override |