diff --git a/xds/src/main/java/io/grpc/xds/RbacFilter.java b/xds/src/main/java/io/grpc/xds/RbacFilter.java index 39f91b475a..be49df31b1 100644 --- a/xds/src/main/java/io/grpc/xds/RbacFilter.java +++ b/xds/src/main/java/io/grpc/xds/RbacFilter.java @@ -126,14 +126,15 @@ final class RbacFilter implements Filter, ServerInterceptorBuilder { return ConfigOrError.fromError( "Policy.condition and Policy.checked_condition must not set: " + entry.getKey()); } - policyMatchers.add(new PolicyMatcher(entry.getKey(), + policyMatchers.add(PolicyMatcher.create(entry.getKey(), parsePermissionList(policy.getPermissionsList()), parsePrincipalList(policy.getPrincipalsList()))); } catch (Exception e) { return ConfigOrError.fromError("Encountered error parsing policy: " + e); } } - return ConfigOrError.fromConfig(RbacConfig.create(new AuthConfig(policyMatchers, authAction))); + return ConfigOrError.fromConfig(RbacConfig.create( + AuthConfig.create(policyMatchers, authAction))); } @Override @@ -195,7 +196,7 @@ final class RbacFilter implements Filter, ServerInterceptorBuilder { for (Permission permission : permissions) { anyMatch.add(parsePermission(permission)); } - return new OrMatcher(anyMatch); + return OrMatcher.create(anyMatch); } private static Matcher parsePermission(Permission permission) { @@ -205,7 +206,7 @@ final class RbacFilter implements Filter, ServerInterceptorBuilder { for (Permission p : permission.getAndRules().getRulesList()) { andMatch.add(parsePermission(p)); } - return new AndMatcher(andMatch); + return AndMatcher.create(andMatch); case OR_RULES: return parsePermissionList(permission.getOrRules().getRulesList()); case ANY: @@ -221,9 +222,9 @@ final class RbacFilter implements Filter, ServerInterceptorBuilder { case DESTINATION_PORT_RANGE: return parseDestinationPortRangeMatcher(permission.getDestinationPortRange()); case NOT_RULE: - return new InvertMatcher(parsePermission(permission.getNotRule())); + return InvertMatcher.create(parsePermission(permission.getNotRule())); case METADATA: // hard coded, never match. - return new InvertMatcher(AlwaysTrueMatcher.INSTANCE); + return InvertMatcher.create(AlwaysTrueMatcher.INSTANCE); case REQUESTED_SERVER_NAME: return parseRequestedServerNameMatcher(permission.getRequestedServerName()); case RULE_NOT_SET: @@ -238,7 +239,7 @@ final class RbacFilter implements Filter, ServerInterceptorBuilder { for (Principal principal: principals) { anyMatch.add(parsePrincipal(principal)); } - return new OrMatcher(anyMatch); + return OrMatcher.create(anyMatch); } private static Matcher parsePrincipal(Principal principal) { @@ -250,7 +251,7 @@ final class RbacFilter implements Filter, ServerInterceptorBuilder { for (Principal next : principal.getAndIds().getIdsList()) { nextMatchers.add(parsePrincipal(next)); } - return new AndMatcher(nextMatchers); + return AndMatcher.create(nextMatchers); case ANY: return AlwaysTrueMatcher.INSTANCE; case AUTHENTICATED: @@ -264,11 +265,11 @@ final class RbacFilter implements Filter, ServerInterceptorBuilder { case HEADER: return parseHeaderMatcher(principal.getHeader()); case NOT_ID: - return new InvertMatcher(parsePrincipal(principal.getNotId())); + return InvertMatcher.create(parsePrincipal(principal.getNotId())); case URL_PATH: return parsePathMatcher(principal.getUrlPath()); case METADATA: // hard coded, never match. - return new InvertMatcher(AlwaysTrueMatcher.INSTANCE); + return InvertMatcher.create(AlwaysTrueMatcher.INSTANCE); case IDENTIFIER_NOT_SET: default: throw new IllegalArgumentException( @@ -280,7 +281,7 @@ final class RbacFilter implements Filter, ServerInterceptorBuilder { io.envoyproxy.envoy.type.matcher.v3.PathMatcher proto) { switch (proto.getRuleCase()) { case PATH: - return new PathMatcher(MatcherParser.parseStringMatcher(proto.getPath())); + return PathMatcher.create(MatcherParser.parseStringMatcher(proto.getPath())); case RULE_NOT_SET: default: throw new IllegalArgumentException( @@ -290,7 +291,7 @@ final class RbacFilter implements Filter, ServerInterceptorBuilder { private static RequestedServerNameMatcher parseRequestedServerNameMatcher( io.envoyproxy.envoy.type.matcher.v3.StringMatcher proto) { - return new RequestedServerNameMatcher(MatcherParser.parseStringMatcher(proto)); + return RequestedServerNameMatcher.create(MatcherParser.parseStringMatcher(proto)); } private static AuthHeaderMatcher parseHeaderMatcher( @@ -303,30 +304,30 @@ final class RbacFilter implements Filter, ServerInterceptorBuilder { throw new IllegalArgumentException("Invalid header matcher config: header name [:scheme] " + "is not allowed."); } - return new AuthHeaderMatcher(MatcherParser.parseHeaderMatcher(proto)); + return AuthHeaderMatcher.create(MatcherParser.parseHeaderMatcher(proto)); } private static AuthenticatedMatcher parseAuthenticatedMatcher( Principal.Authenticated proto) { Matchers.StringMatcher matcher = MatcherParser.parseStringMatcher(proto.getPrincipalName()); - return new AuthenticatedMatcher(matcher); + return AuthenticatedMatcher.create(matcher); } private static DestinationPortMatcher createDestinationPortMatcher(int port) { - return new DestinationPortMatcher(port); + return DestinationPortMatcher.create(port); } private static DestinationPortRangeMatcher parseDestinationPortRangeMatcher(Int32Range range) { - return new DestinationPortRangeMatcher(range.getStart(), range.getEnd()); + return DestinationPortRangeMatcher.create(range.getStart(), range.getEnd()); } private static DestinationIpMatcher createDestinationIpMatcher(CidrRange cidrRange) { - return new DestinationIpMatcher(Matchers.CidrMatcher.create( + return DestinationIpMatcher.create(Matchers.CidrMatcher.create( resolve(cidrRange), cidrRange.getPrefixLen().getValue())); } private static SourceIpMatcher createSourceIpMatcher(CidrRange cidrRange) { - return new SourceIpMatcher(Matchers.CidrMatcher.create( + return SourceIpMatcher.create(Matchers.CidrMatcher.create( resolve(cidrRange), cidrRange.getPrefixLen().getValue())); } diff --git a/xds/src/main/java/io/grpc/xds/internal/rbac/engine/GrpcAuthorizationEngine.java b/xds/src/main/java/io/grpc/xds/internal/rbac/engine/GrpcAuthorizationEngine.java index bb911461a2..385a055dae 100644 --- a/xds/src/main/java/io/grpc/xds/internal/rbac/engine/GrpcAuthorizationEngine.java +++ b/xds/src/main/java/io/grpc/xds/internal/rbac/engine/GrpcAuthorizationEngine.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; import com.google.common.io.BaseEncoding; import io.grpc.Grpc; import io.grpc.Metadata; @@ -67,14 +68,14 @@ public final class GrpcAuthorizationEngine { checkNotNull(serverCall, "serverCall"); String firstMatch = null; EvaluateArgs args = new EvaluateArgs(metadata, serverCall); - for (PolicyMatcher policyMatcher : authConfig.policies) { + for (PolicyMatcher policyMatcher : authConfig.policies()) { if (policyMatcher.matches(args)) { - firstMatch = policyMatcher.name; + firstMatch = policyMatcher.name(); break; } } Action decisionType = Action.DENY; - if (Action.DENY.equals(authConfig.action) == (firstMatch == null)) { + if (Action.DENY.equals(authConfig.action()) == (firstMatch == null)) { decisionType = Action.ALLOW; } log.log(Level.FINER, "RBAC decision: {0}, policy match: {1}.", @@ -103,13 +104,15 @@ public final class GrpcAuthorizationEngine { } /** Represents authorization config policy that the engine will evaluate against. */ - public static final class AuthConfig { - private final List policies; - private final Action action; + @AutoValue + public abstract static class AuthConfig { + public abstract ImmutableList policies(); - public AuthConfig(List policies, Action action) { - this.policies = Collections.unmodifiableList(new ArrayList<>(policies)); - this.action = action; + public abstract Action action(); + + public static AuthConfig create(List policies, Action action) { + return new AutoValue_GrpcAuthorizationEngine_AuthConfig( + ImmutableList.copyOf(policies), action); } } @@ -121,33 +124,36 @@ public final class GrpcAuthorizationEngine { *

Currently we only support matching some of the request fields. Those unsupported fields are * considered not match until we stop ignoring them. */ - public static final class PolicyMatcher implements Matcher { - private final OrMatcher permissions; - private final OrMatcher principals; - private final String name; + @AutoValue + public abstract static class PolicyMatcher implements Matcher { + public abstract String name(); + + public abstract OrMatcher permissions(); + + public abstract OrMatcher principals(); /** Constructs a matcher for one RBAC policy. */ - public PolicyMatcher(String name, OrMatcher permissions, OrMatcher principals) { - this.name = name; - this.permissions = permissions; - this.principals = principals; + public static PolicyMatcher create(String name, OrMatcher permissions, OrMatcher principals) { + return new AutoValue_GrpcAuthorizationEngine_PolicyMatcher(name, permissions, principals); } @Override public boolean matches(EvaluateArgs args) { - return permissions.matches(args) && principals.matches(args); + return permissions().matches(args) && principals().matches(args); } } - public static final class AuthenticatedMatcher implements Matcher { - private final Matchers.StringMatcher delegate; + @AutoValue + public abstract static class AuthenticatedMatcher implements Matcher { + @Nullable + public abstract Matchers.StringMatcher delegate(); /** * Passing in null will match all authenticated user, i.e. SSL session is present. * https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/rbac/v3/rbac.proto#L240 * */ - public AuthenticatedMatcher(@Nullable Matchers.StringMatcher delegate) { - this.delegate = delegate; + public static AuthenticatedMatcher create(@Nullable Matchers.StringMatcher delegate) { + return new AutoValue_GrpcAuthorizationEngine_AuthenticatedMatcher(delegate); } @Override @@ -159,11 +165,11 @@ public final class GrpcAuthorizationEngine { return false; } // Connection is authenticated, so returns match when delegated string matcher is not present. - if (delegate == null) { + if (delegate() == null) { return true; } for (String name : principalNames) { - if (delegate.matches(name)) { + if (delegate().matches(name)) { return true; } } @@ -171,98 +177,105 @@ public final class GrpcAuthorizationEngine { } } - public static final class DestinationIpMatcher implements Matcher { - private final Matchers.CidrMatcher delegate; + @AutoValue + public abstract static class DestinationIpMatcher implements Matcher { + public abstract Matchers.CidrMatcher delegate(); - public DestinationIpMatcher(Matchers.CidrMatcher delegate) { - this.delegate = checkNotNull(delegate, "delegate"); + public static DestinationIpMatcher create(Matchers.CidrMatcher delegate) { + return new AutoValue_GrpcAuthorizationEngine_DestinationIpMatcher(delegate); } @Override public boolean matches(EvaluateArgs args) { - return delegate.matches(args.getDestinationIp()); + return delegate().matches(args.getDestinationIp()); } } - public static final class SourceIpMatcher implements Matcher { - private final Matchers.CidrMatcher delegate; + @AutoValue + public abstract static class SourceIpMatcher implements Matcher { + public abstract Matchers.CidrMatcher delegate(); - public SourceIpMatcher(Matchers.CidrMatcher delegate) { - this.delegate = checkNotNull(delegate, "delegate"); + public static SourceIpMatcher create(Matchers.CidrMatcher delegate) { + return new AutoValue_GrpcAuthorizationEngine_SourceIpMatcher(delegate); } @Override public boolean matches(EvaluateArgs args) { - return delegate.matches(args.getSourceIp()); + return delegate().matches(args.getSourceIp()); } } - public static final class PathMatcher implements Matcher { - private final Matchers.StringMatcher delegate; + @AutoValue + public abstract static class PathMatcher implements Matcher { + public abstract Matchers.StringMatcher delegate(); - public PathMatcher(Matchers.StringMatcher delegate) { - this.delegate = checkNotNull(delegate, "delegate"); + public static PathMatcher create(Matchers.StringMatcher delegate) { + return new AutoValue_GrpcAuthorizationEngine_PathMatcher(delegate); } @Override public boolean matches(EvaluateArgs args) { - return delegate.matches(args.getPath()); + return delegate().matches(args.getPath()); } } - public static final class AuthHeaderMatcher implements Matcher { - private final Matchers.HeaderMatcher delegate; + @AutoValue + public abstract static class AuthHeaderMatcher implements Matcher { + public abstract Matchers.HeaderMatcher delegate(); - public AuthHeaderMatcher(Matchers.HeaderMatcher delegate) { - this.delegate = checkNotNull(delegate, "delegate"); + public static AuthHeaderMatcher create(Matchers.HeaderMatcher delegate) { + return new AutoValue_GrpcAuthorizationEngine_AuthHeaderMatcher(delegate); } @Override public boolean matches(EvaluateArgs args) { - return delegate.matches(args.getHeader(delegate.name())); + return delegate().matches(args.getHeader(delegate().name())); } } - public static final class DestinationPortMatcher implements Matcher { - private final int port; + @AutoValue + public abstract static class DestinationPortMatcher implements Matcher { + public abstract int port(); - public DestinationPortMatcher(int port) { - this.port = port; + public static DestinationPortMatcher create(int port) { + return new AutoValue_GrpcAuthorizationEngine_DestinationPortMatcher(port); } @Override public boolean matches(EvaluateArgs args) { - return port == args.getDestinationPort(); + return port() == args.getDestinationPort(); } } - public static final class DestinationPortRangeMatcher implements Matcher { - private final int start; - private final int end; + @AutoValue + public abstract static class DestinationPortRangeMatcher implements Matcher { + public abstract int start(); + + public abstract int end(); /** Start of the range is inclusive. End of the range is exclusive.*/ - public DestinationPortRangeMatcher(int start, int end) { - this.start = start; - this.end = end; + public static DestinationPortRangeMatcher create(int start, int end) { + return new AutoValue_GrpcAuthorizationEngine_DestinationPortRangeMatcher(start, end); } @Override public boolean matches(EvaluateArgs args) { int port = args.getDestinationPort(); - return port >= start && port < end; + return port >= start() && port < end(); } } - public static final class RequestedServerNameMatcher implements Matcher { - private final Matchers.StringMatcher delegate; + @AutoValue + public abstract static class RequestedServerNameMatcher implements Matcher { + public abstract Matchers.StringMatcher delegate(); - public RequestedServerNameMatcher(Matchers.StringMatcher delegate) { - this.delegate = checkNotNull(delegate, "delegate"); + public static RequestedServerNameMatcher create(Matchers.StringMatcher delegate) { + return new AutoValue_GrpcAuthorizationEngine_RequestedServerNameMatcher(delegate); } @Override public boolean matches(EvaluateArgs args) { - return delegate.matches(args.getRequestedServerName()); + return delegate().matches(args.getRequestedServerName()); } } @@ -407,25 +420,26 @@ public final class GrpcAuthorizationEngine { boolean matches(EvaluateArgs args); } - public static final class OrMatcher implements Matcher { - private final List anyMatch; + @AutoValue + public abstract static class OrMatcher implements Matcher { + public abstract ImmutableList anyMatch(); /** Matches when any of the matcher matches. */ - public OrMatcher(List matchers) { + public static OrMatcher create(List matchers) { checkNotNull(matchers, "matchers"); for (Matcher matcher : matchers) { checkNotNull(matcher, "matcher"); } - this.anyMatch = Collections.unmodifiableList(new ArrayList<>(matchers)); + return new AutoValue_GrpcAuthorizationEngine_OrMatcher(ImmutableList.copyOf(matchers)); } public static OrMatcher create(Matcher...matchers) { - return new OrMatcher(Arrays.asList(matchers)); + return OrMatcher.create(Arrays.asList(matchers)); } @Override public boolean matches(EvaluateArgs args) { - for (Matcher m : anyMatch) { + for (Matcher m : anyMatch()) { if (m.matches(args)) { return true; } @@ -434,25 +448,26 @@ public final class GrpcAuthorizationEngine { } } - public static final class AndMatcher implements Matcher { - private final List allMatch; + @AutoValue + public abstract static class AndMatcher implements Matcher { + public abstract ImmutableList allMatch(); /** Matches when all of the matchers match. */ - public AndMatcher(List matchers) { + public static AndMatcher create(List matchers) { checkNotNull(matchers, "matchers"); for (Matcher matcher : matchers) { checkNotNull(matcher, "matcher"); } - this.allMatch = Collections.unmodifiableList(new ArrayList<>(matchers)); + return new AutoValue_GrpcAuthorizationEngine_AndMatcher(ImmutableList.copyOf(matchers)); } public static AndMatcher create(Matcher...matchers) { - return new AndMatcher(Arrays.asList(matchers)); + return AndMatcher.create(Arrays.asList(matchers)); } @Override public boolean matches(EvaluateArgs args) { - for (Matcher m : allMatch) { + for (Matcher m : allMatch()) { if (!m.matches(args)) { return false; } @@ -462,8 +477,10 @@ public final class GrpcAuthorizationEngine { } /** Always true matcher.*/ - public static final class AlwaysTrueMatcher implements Matcher { - public static AlwaysTrueMatcher INSTANCE = new AlwaysTrueMatcher(); + @AutoValue + public abstract static class AlwaysTrueMatcher implements Matcher { + public static AlwaysTrueMatcher INSTANCE = + new AutoValue_GrpcAuthorizationEngine_AlwaysTrueMatcher(); @Override public boolean matches(EvaluateArgs args) { @@ -472,16 +489,17 @@ public final class GrpcAuthorizationEngine { } /** Negate matcher.*/ - public static final class InvertMatcher implements Matcher { - private final Matcher toInvertMatcher; + @AutoValue + public abstract static class InvertMatcher implements Matcher { + public abstract Matcher toInvertMatcher(); - public InvertMatcher(Matcher matcher) { - this.toInvertMatcher = checkNotNull(matcher, "matcher"); + public static InvertMatcher create(Matcher matcher) { + return new AutoValue_GrpcAuthorizationEngine_InvertMatcher(matcher); } @Override public boolean matches(EvaluateArgs args) { - return !toInvertMatcher.matches(args); + return !toInvertMatcher().matches(args); } } } diff --git a/xds/src/test/java/io/grpc/xds/RbacFilterTest.java b/xds/src/test/java/io/grpc/xds/RbacFilterTest.java index 082c49ef66..c97ca5c52d 100644 --- a/xds/src/test/java/io/grpc/xds/RbacFilterTest.java +++ b/xds/src/test/java/io/grpc/xds/RbacFilterTest.java @@ -246,10 +246,10 @@ public class RbacFilterTest { .set(Grpc.TRANSPORT_ATTR_LOCAL_ADDR, new InetSocketAddress("1::", 20)) .build(); when(mockServerCall.getAttributes()).thenReturn(attr); - PolicyMatcher policyMatcher = new PolicyMatcher("policy-matcher", - OrMatcher.create(new DestinationPortMatcher(99999)), + PolicyMatcher policyMatcher = PolicyMatcher.create("policy-matcher", + OrMatcher.create(DestinationPortMatcher.create(99999)), OrMatcher.create(AlwaysTrueMatcher.INSTANCE)); - AuthConfig authconfig = new AuthConfig(Collections.singletonList(policyMatcher), + AuthConfig authconfig = AuthConfig.create(Collections.singletonList(policyMatcher), GrpcAuthorizationEngine.Action.ALLOW); new RbacFilter().buildServerInterceptor(RbacConfig.create(authconfig), null) .interceptCall(mockServerCall, new Metadata(), mockHandler); @@ -260,7 +260,7 @@ public class RbacFilterTest { verify(mockServerCall).getAttributes(); verifyNoMoreInteractions(mockServerCall); - authconfig = new AuthConfig(Collections.singletonList(policyMatcher), + authconfig = AuthConfig.create(Collections.singletonList(policyMatcher), GrpcAuthorizationEngine.Action.DENY); new RbacFilter().buildServerInterceptor(RbacConfig.create(authconfig), null) .interceptCall(mockServerCall, new Metadata(), mockHandler); @@ -302,10 +302,10 @@ public class RbacFilterTest { .build(); when(mockServerCall.getAttributes()).thenReturn(attr); - PolicyMatcher policyMatcher = new PolicyMatcher("policy-matcher", - OrMatcher.create(new DestinationPortMatcher(99999)), + PolicyMatcher policyMatcher = PolicyMatcher.create("policy-matcher", + OrMatcher.create(DestinationPortMatcher.create(99999)), OrMatcher.create(AlwaysTrueMatcher.INSTANCE)); - AuthConfig authconfig = new AuthConfig(Collections.singletonList(policyMatcher), + AuthConfig authconfig = AuthConfig.create(Collections.singletonList(policyMatcher), GrpcAuthorizationEngine.Action.ALLOW); RbacConfig original = RbacConfig.create(authconfig); @@ -316,10 +316,10 @@ public class RbacFilterTest { ServerInterceptor interceptor = new RbacFilter().buildServerInterceptor(original, override); assertThat(interceptor).isNull(); - policyMatcher = new PolicyMatcher("policy-matcher-override", - OrMatcher.create(new DestinationPortMatcher(20)), + policyMatcher = PolicyMatcher.create("policy-matcher-override", + OrMatcher.create(DestinationPortMatcher.create(20)), OrMatcher.create(AlwaysTrueMatcher.INSTANCE)); - authconfig = new AuthConfig(Collections.singletonList(policyMatcher), + authconfig = AuthConfig.create(Collections.singletonList(policyMatcher), GrpcAuthorizationEngine.Action.ALLOW); override = RbacConfig.create(authconfig); diff --git a/xds/src/test/java/io/grpc/xds/internal/rbac/engine/GrpcAuthorizationEngineTest.java b/xds/src/test/java/io/grpc/xds/internal/rbac/engine/GrpcAuthorizationEngineTest.java index 626a4cfc27..410ffb1b46 100644 --- a/xds/src/test/java/io/grpc/xds/internal/rbac/engine/GrpcAuthorizationEngineTest.java +++ b/xds/src/test/java/io/grpc/xds/internal/rbac/engine/GrpcAuthorizationEngineTest.java @@ -104,16 +104,16 @@ public class GrpcAuthorizationEngineTest { @Test public void ipMatcher() throws Exception { CidrMatcher ip1 = CidrMatcher.create(InetAddress.getByName(IP_ADDR1), 24); - DestinationIpMatcher destIpMatcher = new DestinationIpMatcher(ip1); + DestinationIpMatcher destIpMatcher = DestinationIpMatcher.create(ip1); CidrMatcher ip2 = CidrMatcher.create(InetAddress.getByName(IP_ADDR2), 24); - SourceIpMatcher sourceIpMatcher = new SourceIpMatcher(ip2); - DestinationPortMatcher portMatcher = new DestinationPortMatcher(PORT); + SourceIpMatcher sourceIpMatcher = SourceIpMatcher.create(ip2); + DestinationPortMatcher portMatcher = DestinationPortMatcher.create(PORT); OrMatcher permission = OrMatcher.create(AndMatcher.create(portMatcher, destIpMatcher)); OrMatcher principal = OrMatcher.create(sourceIpMatcher); - PolicyMatcher policyMatcher = new PolicyMatcher(POLICY_NAME, permission, principal); + PolicyMatcher policyMatcher = PolicyMatcher.create(POLICY_NAME, permission, principal); GrpcAuthorizationEngine engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.ALLOW)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.ALLOW)); AuthDecision decision = engine.evaluate(HEADER, serverCall); assertThat(decision.decision()).isEqualTo(Action.ALLOW); assertThat(decision.matchingPolicyName()).isEqualTo(POLICY_NAME); @@ -137,7 +137,7 @@ public class GrpcAuthorizationEngineTest { assertThat(decision.matchingPolicyName()).isEqualTo(null); engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.DENY)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.DENY)); decision = engine.evaluate(HEADER, serverCall); assertThat(decision.decision()).isEqualTo(Action.ALLOW); assertThat(decision.matchingPolicyName()).isEqualTo(null); @@ -145,51 +145,51 @@ public class GrpcAuthorizationEngineTest { @Test public void headerMatcher() { - AuthHeaderMatcher headerMatcher = new AuthHeaderMatcher(Matchers.HeaderMatcher + AuthHeaderMatcher headerMatcher = AuthHeaderMatcher.create(Matchers.HeaderMatcher .forExactValue(HEADER_KEY, HEADER_VALUE, false)); OrMatcher principal = OrMatcher.create(headerMatcher); OrMatcher permission = OrMatcher.create( - new InvertMatcher(new DestinationPortMatcher(PORT + 1))); - PolicyMatcher policyMatcher = new PolicyMatcher(POLICY_NAME, permission, principal); + InvertMatcher.create(DestinationPortMatcher.create(PORT + 1))); + PolicyMatcher policyMatcher = PolicyMatcher.create(POLICY_NAME, permission, principal); GrpcAuthorizationEngine engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.ALLOW)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.ALLOW)); AuthDecision decision = engine.evaluate(HEADER, serverCall); assertThat(decision.decision()).isEqualTo(Action.ALLOW); assertThat(decision.matchingPolicyName()).isEqualTo(POLICY_NAME); HEADER.put(Metadata.Key.of(HEADER_KEY, Metadata.ASCII_STRING_MARSHALLER), HEADER_VALUE); - headerMatcher = new AuthHeaderMatcher(Matchers.HeaderMatcher + headerMatcher = AuthHeaderMatcher.create(Matchers.HeaderMatcher .forExactValue(HEADER_KEY, HEADER_VALUE + "," + HEADER_VALUE, false)); principal = OrMatcher.create(headerMatcher); - policyMatcher = new PolicyMatcher(POLICY_NAME, + policyMatcher = PolicyMatcher.create(POLICY_NAME, OrMatcher.create(AlwaysTrueMatcher.INSTANCE), principal); engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.ALLOW)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.ALLOW)); decision = engine.evaluate(HEADER, serverCall); assertThat(decision.decision()).isEqualTo(Action.ALLOW); - headerMatcher = new AuthHeaderMatcher(Matchers.HeaderMatcher + headerMatcher = AuthHeaderMatcher.create(Matchers.HeaderMatcher .forExactValue(HEADER_KEY + Metadata.BINARY_HEADER_SUFFIX, HEADER_VALUE, false)); principal = OrMatcher.create(headerMatcher); - policyMatcher = new PolicyMatcher(POLICY_NAME, + policyMatcher = PolicyMatcher.create(POLICY_NAME, OrMatcher.create(AlwaysTrueMatcher.INSTANCE), principal); engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.ALLOW)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.ALLOW)); decision = engine.evaluate(HEADER, serverCall); assertThat(decision.decision()).isEqualTo(Action.DENY); } @Test public void headerMatcher_binaryHeader() { - AuthHeaderMatcher headerMatcher = new AuthHeaderMatcher(Matchers.HeaderMatcher + AuthHeaderMatcher headerMatcher = AuthHeaderMatcher.create(Matchers.HeaderMatcher .forExactValue(HEADER_KEY + Metadata.BINARY_HEADER_SUFFIX, BaseEncoding.base64().omitPadding().encode(HEADER_VALUE.getBytes(US_ASCII)), false)); OrMatcher principal = OrMatcher.create(headerMatcher); OrMatcher permission = OrMatcher.create( - new InvertMatcher(new DestinationPortMatcher(PORT + 1))); - PolicyMatcher policyMatcher = new PolicyMatcher(POLICY_NAME, permission, principal); + InvertMatcher.create(DestinationPortMatcher.create(PORT + 1))); + PolicyMatcher policyMatcher = PolicyMatcher.create(POLICY_NAME, permission, principal); GrpcAuthorizationEngine engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.ALLOW)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.ALLOW)); Metadata metadata = new Metadata(); metadata.put(Metadata.Key.of(HEADER_KEY + Metadata.BINARY_HEADER_SUFFIX, Metadata.BINARY_BYTE_MARSHALLER), HEADER_VALUE.getBytes(US_ASCII)); @@ -200,14 +200,14 @@ public class GrpcAuthorizationEngineTest { @Test public void headerMatcher_hardcodePostMethod() { - AuthHeaderMatcher headerMatcher = new AuthHeaderMatcher(Matchers.HeaderMatcher + AuthHeaderMatcher headerMatcher = AuthHeaderMatcher.create(Matchers.HeaderMatcher .forExactValue(":method", "POST", false)); OrMatcher principal = OrMatcher.create(headerMatcher); OrMatcher permission = OrMatcher.create( - new InvertMatcher(new DestinationPortMatcher(PORT + 1))); - PolicyMatcher policyMatcher = new PolicyMatcher(POLICY_NAME, permission, principal); + InvertMatcher.create(DestinationPortMatcher.create(PORT + 1))); + PolicyMatcher policyMatcher = PolicyMatcher.create(POLICY_NAME, permission, principal); GrpcAuthorizationEngine engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.ALLOW)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.ALLOW)); AuthDecision decision = engine.evaluate(new Metadata(), serverCall); assertThat(decision.decision()).isEqualTo(Action.ALLOW); assertThat(decision.matchingPolicyName()).isEqualTo(POLICY_NAME); @@ -215,14 +215,14 @@ public class GrpcAuthorizationEngineTest { @Test public void headerMatcher_pathHeader() { - AuthHeaderMatcher headerMatcher = new AuthHeaderMatcher(Matchers.HeaderMatcher + AuthHeaderMatcher headerMatcher = AuthHeaderMatcher.create(Matchers.HeaderMatcher .forExactValue(":path", "/" + PATH, false)); OrMatcher principal = OrMatcher.create(headerMatcher); OrMatcher permission = OrMatcher.create( - new InvertMatcher(new DestinationPortMatcher(PORT + 1))); - PolicyMatcher policyMatcher = new PolicyMatcher(POLICY_NAME, permission, principal); + InvertMatcher.create(DestinationPortMatcher.create(PORT + 1))); + PolicyMatcher policyMatcher = PolicyMatcher.create(POLICY_NAME, permission, principal); GrpcAuthorizationEngine engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.ALLOW)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.ALLOW)); AuthDecision decision = engine.evaluate(HEADER, serverCall); assertThat(decision.decision()).isEqualTo(Action.ALLOW); assertThat(decision.matchingPolicyName()).isEqualTo(POLICY_NAME); @@ -230,14 +230,14 @@ public class GrpcAuthorizationEngineTest { @Test public void headerMatcher_aliasAuthorityAndHost() { - AuthHeaderMatcher headerMatcher = new AuthHeaderMatcher(Matchers.HeaderMatcher + AuthHeaderMatcher headerMatcher = AuthHeaderMatcher.create(Matchers.HeaderMatcher .forExactValue("Host", "google.com", false)); OrMatcher principal = OrMatcher.create(headerMatcher); OrMatcher permission = OrMatcher.create( - new InvertMatcher(new DestinationPortMatcher(PORT + 1))); - PolicyMatcher policyMatcher = new PolicyMatcher(POLICY_NAME, permission, principal); + InvertMatcher.create(DestinationPortMatcher.create(PORT + 1))); + PolicyMatcher policyMatcher = PolicyMatcher.create(POLICY_NAME, permission, principal); GrpcAuthorizationEngine engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.ALLOW)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.ALLOW)); when(serverCall.getAuthority()).thenReturn("google.com"); AuthDecision decision = engine.evaluate(new Metadata(), serverCall); assertThat(decision.decision()).isEqualTo(Action.ALLOW); @@ -246,12 +246,12 @@ public class GrpcAuthorizationEngineTest { @Test public void pathMatcher() { - PathMatcher pathMatcher = new PathMatcher(STRING_MATCHER); + PathMatcher pathMatcher = PathMatcher.create(STRING_MATCHER); OrMatcher permission = OrMatcher.create(AlwaysTrueMatcher.INSTANCE); OrMatcher principal = OrMatcher.create(pathMatcher); - PolicyMatcher policyMatcher = new PolicyMatcher(POLICY_NAME, permission, principal); + PolicyMatcher policyMatcher = PolicyMatcher.create(POLICY_NAME, permission, principal); GrpcAuthorizationEngine engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.DENY)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.DENY)); AuthDecision decision = engine.evaluate(HEADER, serverCall); assertThat(decision.decision()).isEqualTo(Action.DENY); assertThat(decision.matchingPolicyName()).isEqualTo(POLICY_NAME); @@ -259,14 +259,14 @@ public class GrpcAuthorizationEngineTest { @Test public void authenticatedMatcher() throws Exception { - AuthenticatedMatcher authMatcher = new AuthenticatedMatcher( + AuthenticatedMatcher authMatcher = AuthenticatedMatcher.create( StringMatcher.forExact("*.test.google.fr", false)); - PathMatcher pathMatcher = new PathMatcher(STRING_MATCHER); + PathMatcher pathMatcher = PathMatcher.create(STRING_MATCHER); OrMatcher permission = OrMatcher.create(authMatcher); OrMatcher principal = OrMatcher.create(pathMatcher); - PolicyMatcher policyMatcher = new PolicyMatcher(POLICY_NAME, permission, principal); + PolicyMatcher policyMatcher = PolicyMatcher.create(POLICY_NAME, permission, principal); GrpcAuthorizationEngine engine = new GrpcAuthorizationEngine( - new AuthConfig(Collections.singletonList(policyMatcher), Action.ALLOW)); + AuthConfig.create(Collections.singletonList(policyMatcher), Action.ALLOW)); AuthDecision decision = engine.evaluate(HEADER, serverCall); assertThat(decision.decision()).isEqualTo(Action.ALLOW); assertThat(decision.matchingPolicyName()).isEqualTo(POLICY_NAME); @@ -306,11 +306,11 @@ public class GrpcAuthorizationEngineTest { assertThat(engine.evaluate(HEADER, serverCall).decision()).isEqualTo(Action.ALLOW); // match any authenticated connection if StringMatcher not set in AuthenticatedMatcher - permission = OrMatcher.create(new AuthenticatedMatcher(null)); - policyMatcher = new PolicyMatcher(POLICY_NAME, permission, principal); + permission = OrMatcher.create(AuthenticatedMatcher.create(null)); + policyMatcher = PolicyMatcher.create(POLICY_NAME, permission, principal); when(mockCert.getSubjectAlternativeNames()).thenReturn( Arrays.>asList(Arrays.asList(6, "random"))); - engine = new GrpcAuthorizationEngine(new AuthConfig(Collections.singletonList(policyMatcher), + engine = new GrpcAuthorizationEngine(AuthConfig.create(Collections.singletonList(policyMatcher), Action.ALLOW)); assertThat(engine.evaluate(HEADER, serverCall).decision()).isEqualTo(Action.ALLOW); @@ -330,31 +330,78 @@ public class GrpcAuthorizationEngineTest { @Test public void multiplePolicies() throws Exception { - AuthenticatedMatcher authMatcher = new AuthenticatedMatcher( + AuthenticatedMatcher authMatcher = AuthenticatedMatcher.create( StringMatcher.forSuffix("TEST.google.fr", true)); - PathMatcher pathMatcher = new PathMatcher(STRING_MATCHER); + PathMatcher pathMatcher = PathMatcher.create(STRING_MATCHER); OrMatcher principal = OrMatcher.create(AndMatcher.create(authMatcher, pathMatcher)); OrMatcher permission = OrMatcher.create(AndMatcher.create(pathMatcher, - new InvertMatcher(new DestinationPortMatcher(PORT + 1)))); - PolicyMatcher policyMatcher1 = new PolicyMatcher(POLICY_NAME, permission, principal); + InvertMatcher.create(DestinationPortMatcher.create(PORT + 1)))); + PolicyMatcher policyMatcher1 = PolicyMatcher.create(POLICY_NAME, permission, principal); - AuthHeaderMatcher headerMatcher = new AuthHeaderMatcher(Matchers.HeaderMatcher + AuthHeaderMatcher headerMatcher = AuthHeaderMatcher.create(Matchers.HeaderMatcher .forExactValue(HEADER_KEY, HEADER_VALUE + 1, false)); - authMatcher = new AuthenticatedMatcher( + authMatcher = AuthenticatedMatcher.create( StringMatcher.forContains("TEST.google.fr")); principal = OrMatcher.create(headerMatcher, authMatcher); CidrMatcher ip1 = CidrMatcher.create(InetAddress.getByName(IP_ADDR1), 24); - DestinationIpMatcher destIpMatcher = new DestinationIpMatcher(ip1); + DestinationIpMatcher destIpMatcher = DestinationIpMatcher.create(ip1); permission = OrMatcher.create(destIpMatcher, pathMatcher); - PolicyMatcher policyMatcher2 = new PolicyMatcher(POLICY_NAME + "-2", permission, principal); + PolicyMatcher policyMatcher2 = PolicyMatcher.create(POLICY_NAME + "-2", permission, principal); GrpcAuthorizationEngine engine = new GrpcAuthorizationEngine( - new AuthConfig(ImmutableList.of(policyMatcher1, policyMatcher2), Action.DENY)); + AuthConfig.create(ImmutableList.of(policyMatcher1, policyMatcher2), Action.DENY)); AuthDecision decision = engine.evaluate(HEADER, serverCall); assertThat(decision.decision()).isEqualTo(Action.DENY); assertThat(decision.matchingPolicyName()).isEqualTo(POLICY_NAME); } + @Test + public void matchersEqualHashcode() throws Exception { + PathMatcher pathMatcher = PathMatcher.create(STRING_MATCHER); + AuthHeaderMatcher headerMatcher = AuthHeaderMatcher.create( + Matchers.HeaderMatcher.forExactValue("foo", "bar", true)); + DestinationIpMatcher destinationIpMatcher = DestinationIpMatcher.create( + CidrMatcher.create(InetAddress.getByName(IP_ADDR1), 24)); + DestinationPortMatcher destinationPortMatcher = DestinationPortMatcher.create(PORT); + GrpcAuthorizationEngine.DestinationPortRangeMatcher portRangeMatcher = + GrpcAuthorizationEngine.DestinationPortRangeMatcher.create(PORT, PORT + 1); + InvertMatcher invertMatcher = InvertMatcher.create(portRangeMatcher); + GrpcAuthorizationEngine.RequestedServerNameMatcher requestedServerNameMatcher = + GrpcAuthorizationEngine.RequestedServerNameMatcher.create(STRING_MATCHER); + OrMatcher permission = OrMatcher.create(pathMatcher, headerMatcher, destinationIpMatcher, + destinationPortMatcher, invertMatcher, requestedServerNameMatcher); + AuthenticatedMatcher authenticatedMatcher = AuthenticatedMatcher.create(STRING_MATCHER); + SourceIpMatcher sourceIpMatcher1 = SourceIpMatcher.create( + CidrMatcher.create(InetAddress.getByName(IP_ADDR1), 24)); + OrMatcher principal = OrMatcher.create(authenticatedMatcher, + AndMatcher.create(sourceIpMatcher1, AlwaysTrueMatcher.INSTANCE)); + PolicyMatcher policyMatcher1 = PolicyMatcher.create("match", permission, principal); + AuthConfig config1 = AuthConfig.create(Collections.singletonList(policyMatcher1), Action.ALLOW); + + PathMatcher pathMatcher2 = PathMatcher.create(STRING_MATCHER); + AuthHeaderMatcher headerMatcher2 = AuthHeaderMatcher.create( + Matchers.HeaderMatcher.forExactValue("foo", "bar", true)); + DestinationIpMatcher destinationIpMatcher2 = DestinationIpMatcher.create( + CidrMatcher.create(InetAddress.getByName(IP_ADDR1), 24)); + DestinationPortMatcher destinationPortMatcher2 = DestinationPortMatcher.create(PORT); + GrpcAuthorizationEngine.DestinationPortRangeMatcher portRangeMatcher2 = + GrpcAuthorizationEngine.DestinationPortRangeMatcher.create(PORT, PORT + 1); + InvertMatcher invertMatcher2 = InvertMatcher.create(portRangeMatcher2); + GrpcAuthorizationEngine.RequestedServerNameMatcher requestedServerNameMatcher2 = + GrpcAuthorizationEngine.RequestedServerNameMatcher.create(STRING_MATCHER); + OrMatcher permission2 = OrMatcher.create(pathMatcher2, headerMatcher2, destinationIpMatcher2, + destinationPortMatcher2, invertMatcher2, requestedServerNameMatcher2); + AuthenticatedMatcher authenticatedMatcher2 = AuthenticatedMatcher.create(STRING_MATCHER); + SourceIpMatcher sourceIpMatcher2 = SourceIpMatcher.create( + CidrMatcher.create(InetAddress.getByName(IP_ADDR1), 24)); + OrMatcher principal2 = OrMatcher.create(authenticatedMatcher2, + AndMatcher.create(sourceIpMatcher2, AlwaysTrueMatcher.INSTANCE)); + PolicyMatcher policyMatcher2 = PolicyMatcher.create("match", permission2, principal2); + AuthConfig config2 = AuthConfig.create(Collections.singletonList(policyMatcher2), Action.ALLOW); + assertThat(config1).isEqualTo(config2); + assertThat(config1.hashCode()).isEqualTo(config2.hashCode()); + } + private MethodDescriptor.Builder method() { return MethodDescriptor.newBuilder() .setType(MethodType.BIDI_STREAMING)