xds: implement equals hashcode in rbac matcher tree (#8546)

This commit is contained in:
yifeizhuang 2021-09-21 16:29:07 -07:00 committed by GitHub
parent a6abb1b8d9
commit f33daf0d9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 225 additions and 159 deletions

View File

@ -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()));
}

View File

@ -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<PolicyMatcher> policies;
private final Action action;
@AutoValue
public abstract static class AuthConfig {
public abstract ImmutableList<PolicyMatcher> policies();
public AuthConfig(List<PolicyMatcher> policies, Action action) {
this.policies = Collections.unmodifiableList(new ArrayList<>(policies));
this.action = action;
public abstract Action action();
public static AuthConfig create(List<PolicyMatcher> policies, Action action) {
return new AutoValue_GrpcAuthorizationEngine_AuthConfig(
ImmutableList.copyOf(policies), action);
}
}
@ -121,33 +124,36 @@ public final class GrpcAuthorizationEngine {
* <p>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<? extends Matcher> anyMatch;
@AutoValue
public abstract static class OrMatcher implements Matcher {
public abstract ImmutableList<? extends Matcher> anyMatch();
/** Matches when any of the matcher matches. */
public OrMatcher(List<? extends Matcher> matchers) {
public static OrMatcher create(List<? extends Matcher> 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<? extends Matcher> allMatch;
@AutoValue
public abstract static class AndMatcher implements Matcher {
public abstract ImmutableList<? extends Matcher> allMatch();
/** Matches when all of the matchers match. */
public AndMatcher(List<? extends Matcher> matchers) {
public static AndMatcher create(List<? extends Matcher> 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);
}
}
}

View File

@ -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);

View File

@ -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.<List<?>>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<Void, Void> method() {
return MethodDescriptor.<Void,Void>newBuilder()
.setType(MethodType.BIDI_STREAMING)