Skip to content

Commit

Permalink
Update conditional matcher ctors and include NotMatcher. (grpc#26256)
Browse files Browse the repository at this point in the history
  • Loading branch information
ashithasantosh authored May 18, 2021
1 parent 374e7b2 commit c20356c
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 327 deletions.
161 changes: 70 additions & 91 deletions src/core/lib/security/authorization/matchers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,134 +22,118 @@ namespace grpc_core {
std::unique_ptr<AuthorizationMatcher> AuthorizationMatcher::Create(
Rbac::Permission permission) {
switch (permission.type) {
case Rbac::Permission::RuleType::kAnd:
return absl::make_unique<AndAuthorizationMatcher>(
std::move(permission.permissions), permission.not_rule);
case Rbac::Permission::RuleType::kOr:
return absl::make_unique<OrAuthorizationMatcher>(
std::move(permission.permissions), permission.not_rule);
case Rbac::Permission::RuleType::kAnd: {
std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
for (const auto& rule : permission.permissions) {
matchers.push_back(AuthorizationMatcher::Create(std::move(*rule)));
}
return absl::make_unique<AndAuthorizationMatcher>(std::move(matchers));
}
case Rbac::Permission::RuleType::kOr: {
std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
for (const auto& rule : permission.permissions) {
matchers.push_back(AuthorizationMatcher::Create(std::move(*rule)));
}
return absl::make_unique<OrAuthorizationMatcher>(std::move(matchers));
}
case Rbac::Permission::RuleType::kNot:
return absl::make_unique<NotAuthorizationMatcher>(
AuthorizationMatcher::Create(std::move(*permission.permissions[0])));
case Rbac::Permission::RuleType::kAny:
return absl::make_unique<AlwaysAuthorizationMatcher>(permission.not_rule);
return absl::make_unique<AlwaysAuthorizationMatcher>();
case Rbac::Permission::RuleType::kHeader:
return absl::make_unique<HeaderAuthorizationMatcher>(
std::move(permission.header_matcher), permission.not_rule);
std::move(permission.header_matcher));
case Rbac::Permission::RuleType::kPath:
return absl::make_unique<PathAuthorizationMatcher>(
std::move(permission.string_matcher), permission.not_rule);
std::move(permission.string_matcher));
case Rbac::Permission::RuleType::kDestIp:
return absl::make_unique<IpAuthorizationMatcher>(
IpAuthorizationMatcher::Type::kDestIp, std::move(permission.ip),
permission.not_rule);
IpAuthorizationMatcher::Type::kDestIp, std::move(permission.ip));
case Rbac::Permission::RuleType::kDestPort:
return absl::make_unique<PortAuthorizationMatcher>(permission.port,
permission.not_rule);
return absl::make_unique<PortAuthorizationMatcher>(permission.port);
case Rbac::Permission::RuleType::kReqServerName:
return absl::make_unique<ReqServerNameAuthorizationMatcher>(
std::move(permission.string_matcher), permission.not_rule);
std::move(permission.string_matcher));
}
return nullptr;
}

std::unique_ptr<AuthorizationMatcher> AuthorizationMatcher::Create(
Rbac::Principal principal) {
switch (principal.type) {
case Rbac::Principal::RuleType::kAnd:
return absl::make_unique<AndAuthorizationMatcher>(
std::move(principal.principals), principal.not_rule);
case Rbac::Principal::RuleType::kOr:
return absl::make_unique<OrAuthorizationMatcher>(
std::move(principal.principals), principal.not_rule);
case Rbac::Principal::RuleType::kAnd: {
std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
for (const auto& id : principal.principals) {
matchers.push_back(AuthorizationMatcher::Create(std::move(*id)));
}
return absl::make_unique<AndAuthorizationMatcher>(std::move(matchers));
}
case Rbac::Principal::RuleType::kOr: {
std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
for (const auto& id : principal.principals) {
matchers.push_back(AuthorizationMatcher::Create(std::move(*id)));
}
return absl::make_unique<OrAuthorizationMatcher>(std::move(matchers));
}
case Rbac::Principal::RuleType::kNot:
return absl::make_unique<NotAuthorizationMatcher>(
AuthorizationMatcher::Create(std::move(*principal.principals[0])));
case Rbac::Principal::RuleType::kAny:
return absl::make_unique<AlwaysAuthorizationMatcher>(principal.not_rule);
return absl::make_unique<AlwaysAuthorizationMatcher>();
case Rbac::Principal::RuleType::kPrincipalName:
return absl::make_unique<AuthenticatedAuthorizationMatcher>(
std::move(principal.string_matcher), principal.not_rule);
std::move(principal.string_matcher));
case Rbac::Principal::RuleType::kSourceIp:
return absl::make_unique<IpAuthorizationMatcher>(
IpAuthorizationMatcher::Type::kSourceIp, std::move(principal.ip),
principal.not_rule);
IpAuthorizationMatcher::Type::kSourceIp, std::move(principal.ip));
case Rbac::Principal::RuleType::kDirectRemoteIp:
return absl::make_unique<IpAuthorizationMatcher>(
IpAuthorizationMatcher::Type::kDirectRemoteIp,
std::move(principal.ip), principal.not_rule);
std::move(principal.ip));
case Rbac::Principal::RuleType::kRemoteIp:
return absl::make_unique<IpAuthorizationMatcher>(
IpAuthorizationMatcher::Type::kRemoteIp, std::move(principal.ip),
principal.not_rule);
IpAuthorizationMatcher::Type::kRemoteIp, std::move(principal.ip));
case Rbac::Principal::RuleType::kHeader:
return absl::make_unique<HeaderAuthorizationMatcher>(
std::move(principal.header_matcher), principal.not_rule);
std::move(principal.header_matcher));
case Rbac::Principal::RuleType::kPath:
return absl::make_unique<PathAuthorizationMatcher>(
std::move(principal.string_matcher), principal.not_rule);
std::move(principal.string_matcher));
}
return nullptr;
}

AndAuthorizationMatcher::AndAuthorizationMatcher(
std::vector<std::unique_ptr<Rbac::Permission>> rules, bool not_rule)
: not_rule_(not_rule) {
for (auto& rule : rules) {
matchers_.push_back(AuthorizationMatcher::Create(std::move(*rule)));
}
}

AndAuthorizationMatcher::AndAuthorizationMatcher(
std::vector<std::unique_ptr<Rbac::Principal>> ids, bool not_rule)
: not_rule_(not_rule) {
for (const auto& id : ids) {
matchers_.push_back(AuthorizationMatcher::Create(std::move(*id)));
}
}

bool AndAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
bool matches = true;
for (const auto& matcher : matchers_) {
if (!matcher->Matches(args)) {
matches = false;
break;
return false;
}
}
return matches != not_rule_;
}

OrAuthorizationMatcher::OrAuthorizationMatcher(
std::vector<std::unique_ptr<Rbac::Permission>> rules, bool not_rule)
: not_rule_(not_rule) {
for (const auto& rule : rules) {
matchers_.push_back(AuthorizationMatcher::Create(std::move(*rule)));
}
}

OrAuthorizationMatcher::OrAuthorizationMatcher(
std::vector<std::unique_ptr<Rbac::Principal>> ids, bool not_rule)
: not_rule_(not_rule) {
for (const auto& id : ids) {
matchers_.push_back(AuthorizationMatcher::Create(std::move(*id)));
}
return true;
}

bool OrAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
bool matches = false;
for (const auto& matcher : matchers_) {
if (matcher->Matches(args)) {
matches = true;
break;
return true;
}
}
return matches != not_rule_;
return false;
}

bool NotAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
return !matcher_->Matches(args);
}

bool HeaderAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
std::string concatenated_value;
bool matches =
matcher_.Match(args.GetHeaderValue(matcher_.name(), &concatenated_value));
return matches != not_rule_;
return matcher_.Match(
args.GetHeaderValue(matcher_.name(), &concatenated_value));
}

IpAuthorizationMatcher::IpAuthorizationMatcher(Type type, Rbac::CidrRange range,
bool not_rule)
: type_(type), prefix_len_(range.prefix_len), not_rule_(not_rule) {
IpAuthorizationMatcher::IpAuthorizationMatcher(Type type, Rbac::CidrRange range)
: type_(type), prefix_len_(range.prefix_len) {
grpc_error_handle error =
grpc_string_to_sockaddr(&subnet_address_, range.address_prefix.c_str(),
/*port does not matter here*/ 0);
Expand All @@ -176,59 +160,54 @@ bool IpAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
}
default: {
// Currently we do not support matching rules containing "remote_ip".
return not_rule_;
return false;
}
}
bool matches =
grpc_sockaddr_match_subnet(&address, &subnet_address_, prefix_len_);
return matches != not_rule_;
return grpc_sockaddr_match_subnet(&address, &subnet_address_, prefix_len_);
}

bool PortAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
bool matches = (port_ == args.GetLocalPort());
return matches != not_rule_;
return port_ == args.GetLocalPort();
}

bool AuthenticatedAuthorizationMatcher::Matches(
const EvaluateArgs& args) const {
if (args.GetTransportSecurityType() != GRPC_SSL_TRANSPORT_SECURITY_TYPE) {
// Connection is not authenticated.
return not_rule_;
return false;
}
if (matcher_.string_matcher().empty()) {
// Allows any authenticated user.
return !not_rule_;
return true;
}
absl::string_view spiffe_id = args.GetSpiffeId();
if (!spiffe_id.empty()) {
return matcher_.Match(spiffe_id) != not_rule_;
return matcher_.Match(spiffe_id);
}
std::vector<absl::string_view> dns_sans = args.GetDnsSans();
if (!dns_sans.empty()) {
for (const auto& dns : dns_sans) {
if (matcher_.Match(dns)) {
return !not_rule_;
return true;
}
}
}
// TODO(ashithasantosh): Check Subject field from certificate.
return not_rule_;
return false;
}

bool ReqServerNameAuthorizationMatcher::Matches(const EvaluateArgs&) const {
// Currently we do not support matching rules containing
// "requested_server_name".
bool matches = false;
return matches != not_rule_;
return false;
}

bool PathAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
bool matches = false;
absl::string_view path = args.GetPath();
if (!path.empty()) {
matches = matcher_.Match(path);
return matcher_.Match(path);
}
return matches != not_rule_;
return false;
}

bool PolicyAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
Expand Down
Loading

0 comments on commit c20356c

Please sign in to comment.