blob: 36b38621d1885020c78458ef95aea0f42632e224 [file] [log] [blame]
// Copyright 2021 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <grpc/support/port_platform.h>
#include <list>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "src/core/lib/security/authorization/evaluate_args.h"
#include "src/core/lib/security/authorization/matchers.h"
#include "test/core/util/evaluate_args_test_util.h"
namespace grpc_core {
class AuthorizationMatchersTest : public ::testing::Test {
protected:
EvaluateArgsTestUtil args_;
};
TEST_F(AuthorizationMatchersTest, AlwaysAuthorizationMatcher) {
EvaluateArgs args = args_.MakeEvaluateArgs();
AlwaysAuthorizationMatcher matcher;
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, NotAlwaysAuthorizationMatcher) {
EvaluateArgs args = args_.MakeEvaluateArgs();
AlwaysAuthorizationMatcher matcher(/*not_rule=*/true);
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, AndAuthorizationMatcherSuccessfulMatch) {
args_.AddPairToMetadata("foo", "bar");
args_.SetLocalEndpoint("ipv4:255.255.255.255:123");
EvaluateArgs args = args_.MakeEvaluateArgs();
std::vector<std::unique_ptr<Rbac::Permission>> rules;
rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kHeader,
HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact,
/*matcher=*/"bar")
.value()));
rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kDestPort, /*port=*/123));
AndAuthorizationMatcher matcher(std::move(rules));
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, AndAuthorizationMatcherFailedMatch) {
args_.AddPairToMetadata("foo", "not_bar");
args_.SetLocalEndpoint("ipv4:255.255.255.255:123");
EvaluateArgs args = args_.MakeEvaluateArgs();
std::vector<std::unique_ptr<Rbac::Permission>> rules;
rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kHeader,
HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact,
/*matcher=*/"bar")
.value()));
rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kDestPort, /*port=*/123));
AndAuthorizationMatcher matcher(std::move(rules));
// Header rule fails. Expected value "bar", got "not_bar" for key "foo".
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, NotAndAuthorizationMatcher) {
args_.AddPairToMetadata(":path", "/expected/foo");
EvaluateArgs args = args_.MakeEvaluateArgs();
StringMatcher string_matcher =
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"/expected/foo",
/*case_sensitive=*/false)
.value();
std::vector<std::unique_ptr<Rbac::Permission>> ids;
ids.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kPath, std::move(string_matcher)));
AndAuthorizationMatcher matcher(std::move(ids), /*not_rule=*/true);
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, OrAuthorizationMatcherSuccessfulMatch) {
args_.AddPairToMetadata("foo", "bar");
args_.SetLocalEndpoint("ipv4:255.255.255.255:123");
EvaluateArgs args = args_.MakeEvaluateArgs();
HeaderMatcher header_matcher =
HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact,
/*matcher=*/"bar")
.value();
std::vector<std::unique_ptr<Rbac::Permission>> rules;
rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kHeader, header_matcher));
rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kDestPort, /*port=*/456));
OrAuthorizationMatcher matcher(std::move(rules));
// Matches as header rule matches even though port rule fails.
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, OrAuthorizationMatcherFailedMatch) {
args_.AddPairToMetadata("foo", "not_bar");
EvaluateArgs args = args_.MakeEvaluateArgs();
std::vector<std::unique_ptr<Rbac::Permission>> rules;
rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kHeader,
HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact,
/*matcher=*/"bar")
.value()));
OrAuthorizationMatcher matcher(std::move(rules));
// Header rule fails. Expected value "bar", got "not_bar" for key "foo".
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, NotOrAuthorizationMatcher) {
args_.AddPairToMetadata("foo", "not_bar");
EvaluateArgs args = args_.MakeEvaluateArgs();
std::vector<std::unique_ptr<Rbac::Permission>> rules;
rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kHeader,
HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact,
/*matcher=*/"bar")
.value()));
OrAuthorizationMatcher matcher(std::move(rules), /*not_rule=*/true);
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, HybridAuthorizationMatcherSuccessfulMatch) {
args_.AddPairToMetadata("foo", "bar");
args_.SetLocalEndpoint("ipv4:255.255.255.255:123");
EvaluateArgs args = args_.MakeEvaluateArgs();
std::vector<std::unique_ptr<Rbac::Permission>> sub_and_rules;
sub_and_rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kHeader,
HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact,
/*matcher=*/"bar")
.value()));
std::vector<std::unique_ptr<Rbac::Permission>> sub_or_rules;
sub_or_rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kDestPort, /*port=*/123));
std::vector<std::unique_ptr<Rbac::Permission>> and_rules;
and_rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kAnd, std::move(sub_and_rules)));
and_rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kOr, std::move(std::move(sub_or_rules))));
AndAuthorizationMatcher matcher(std::move(and_rules));
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, HybridAuthorizationMatcherFailedMatch) {
args_.AddPairToMetadata("foo", "bar");
args_.SetLocalEndpoint("ipv4:255.255.255.255:123");
EvaluateArgs args = args_.MakeEvaluateArgs();
std::vector<std::unique_ptr<Rbac::Permission>> sub_and_rules;
sub_and_rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kHeader,
HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact,
/*matcher=*/"bar")
.value()));
sub_and_rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kHeader,
HeaderMatcher::Create(/*name=*/"absent_key", HeaderMatcher::Type::kExact,
/*matcher=*/"some_value")
.value()));
std::vector<std::unique_ptr<Rbac::Permission>> sub_or_rules;
sub_or_rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kDestPort, /*port=*/123));
std::vector<std::unique_ptr<Rbac::Permission>> and_rules;
and_rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kAnd, std::move(sub_and_rules)));
and_rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kOr, std::move(std::move(sub_or_rules))));
AndAuthorizationMatcher matcher(std::move(and_rules));
// Fails as "absent_key" header was not present.
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, PathAuthorizationMatcherSuccessfulMatch) {
args_.AddPairToMetadata(":path", "expected/path");
EvaluateArgs args = args_.MakeEvaluateArgs();
PathAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"expected/path",
/*case_sensitive=*/false)
.value());
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, PathAuthorizationMatcherFailedMatch) {
args_.AddPairToMetadata(":path", "different/path");
EvaluateArgs args = args_.MakeEvaluateArgs();
PathAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"expected/path",
/*case_sensitive=*/false)
.value());
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, NotPathAuthorizationMatcher) {
args_.AddPairToMetadata(":path", "expected/path");
EvaluateArgs args = args_.MakeEvaluateArgs();
PathAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact, "expected/path", false)
.value(),
/*not_rule=*/true);
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest,
PathAuthorizationMatcherFailedMatchMissingPath) {
EvaluateArgs args = args_.MakeEvaluateArgs();
PathAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"expected/path",
/*case_sensitive=*/false)
.value());
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, HeaderAuthorizationMatcherSuccessfulMatch) {
args_.AddPairToMetadata("key123", "foo_xxx");
EvaluateArgs args = args_.MakeEvaluateArgs();
HeaderAuthorizationMatcher matcher(
HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kPrefix,
/*matcher=*/"foo")
.value());
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, HeaderAuthorizationMatcherFailedMatch) {
args_.AddPairToMetadata("key123", "foo");
EvaluateArgs args = args_.MakeEvaluateArgs();
HeaderAuthorizationMatcher matcher(
HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kExact,
/*matcher=*/"bar")
.value());
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest,
HeaderAuthorizationMatcherFailedMatchMultivaluedHeader) {
args_.AddPairToMetadata("key123", "foo");
args_.AddPairToMetadata("key123", "bar");
EvaluateArgs args = args_.MakeEvaluateArgs();
HeaderAuthorizationMatcher matcher(
HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kExact,
/*matcher=*/"foo")
.value());
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest,
HeaderAuthorizationMatcherFailedMatchMissingHeader) {
EvaluateArgs args = args_.MakeEvaluateArgs();
HeaderAuthorizationMatcher matcher(
HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kSuffix,
/*matcher=*/"foo")
.value());
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, NotHeaderAuthorizationMatcher) {
args_.AddPairToMetadata("key123", "foo");
EvaluateArgs args = args_.MakeEvaluateArgs();
HeaderAuthorizationMatcher matcher(
HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kExact,
/*matcher=*/"bar")
.value(),
/*not_rule=*/true);
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, PortAuthorizationMatcherSuccessfulMatch) {
args_.SetLocalEndpoint("ipv4:255.255.255.255:123");
EvaluateArgs args = args_.MakeEvaluateArgs();
PortAuthorizationMatcher matcher(/*port=*/123);
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, PortAuthorizationMatcherFailedMatch) {
args_.SetLocalEndpoint("ipv4:255.255.255.255:123");
EvaluateArgs args = args_.MakeEvaluateArgs();
PortAuthorizationMatcher matcher(/*port=*/456);
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, NotPortAuthorizationMatcher) {
args_.SetLocalEndpoint("ipv4:255.255.255.255:123");
EvaluateArgs args = args_.MakeEvaluateArgs();
PortAuthorizationMatcher matcher(/*port=*/123, /*not_rule=*/true);
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest,
AuthenticatedMatcherUnAuthenticatedConnection) {
EvaluateArgs args = args_.MakeEvaluateArgs();
AuthenticatedAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"foo.com",
/*case_sensitive=*/false)
.value());
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest,
AuthenticatedMatcherAuthenticatedConnectionMatcherUnset) {
args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE);
EvaluateArgs args = args_.MakeEvaluateArgs();
AuthenticatedAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"",
/*case_sensitive=*/false)
.value());
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest,
AuthenticatedMatcherSuccessfulSpiffeIdMatches) {
args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE);
args_.AddPropertyToAuthContext(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME,
"spiffe://foo.abc");
EvaluateArgs args = args_.MakeEvaluateArgs();
AuthenticatedAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"spiffe://foo.abc",
/*case_sensitive=*/false)
.value());
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, AuthenticatedMatcherFailedSpiffeIdMatches) {
args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE);
args_.AddPropertyToAuthContext(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME,
"spiffe://bar.abc");
EvaluateArgs args = args_.MakeEvaluateArgs();
AuthenticatedAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"spiffe://foo.abc",
/*case_sensitive=*/false)
.value());
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, AuthenticatedMatcherFailedNothingMatches) {
args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE);
EvaluateArgs args = args_.MakeEvaluateArgs();
AuthenticatedAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"foo",
/*case_sensitive=*/false)
.value());
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, NotAuthenticatedMatcher) {
args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE);
EvaluateArgs args = args_.MakeEvaluateArgs();
AuthenticatedAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact, /*matcher=*/"foo",
/*case_sensitive=*/false)
.value(),
/*not_rule=*/true);
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, PolicyAuthorizationMatcherSuccessfulMatch) {
args_.AddPairToMetadata("key123", "foo");
EvaluateArgs args = args_.MakeEvaluateArgs();
std::vector<std::unique_ptr<Rbac::Permission>> rules;
rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kHeader,
HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kExact,
/*matcher=*/"foo")
.value()));
PolicyAuthorizationMatcher matcher(Rbac::Policy(
Rbac::Permission(Rbac::Permission::RuleType::kOr, std::move(rules)),
Rbac::Principal(Rbac::Principal::RuleType::kAny)));
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, PolicyAuthorizationMatcherFailedMatch) {
args_.AddPairToMetadata("key123", "foo");
EvaluateArgs args = args_.MakeEvaluateArgs();
std::vector<std::unique_ptr<Rbac::Permission>> rules;
rules.push_back(absl::make_unique<Rbac::Permission>(
Rbac::Permission::RuleType::kHeader,
HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kExact,
/*matcher=*/"bar")
.value()));
PolicyAuthorizationMatcher matcher(Rbac::Policy(
Rbac::Permission(Rbac::Permission::RuleType::kOr, std::move(rules)),
Rbac::Principal(Rbac::Principal::RuleType::kAny)));
EXPECT_FALSE(matcher.Matches(args));
}
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc_init();
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}