blob: a081c5141474eb8474879602488c6f15601f483a [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 "src/core/lib/security/authorization/rbac_policy.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
namespace grpc_core {
//
// Rbac
//
Rbac::Rbac(Rbac::Action action, std::map<std::string, Policy> policies)
: action(action), policies(std::move(policies)) {}
Rbac::Rbac(Rbac&& other) noexcept
: action(other.action), policies(std::move(other.policies)) {}
Rbac& Rbac::operator=(Rbac&& other) noexcept {
action = other.action;
policies = std::move(other.policies);
return *this;
}
std::string Rbac::ToString() const {
std::vector<std::string> contents;
contents.push_back(absl::StrFormat(
"Rbac action=%s{", action == Rbac::Action::kAllow ? "Allow" : "Deny"));
for (const auto& p : policies) {
contents.push_back(absl::StrFormat("{\n policy_name=%s\n%s\n}", p.first,
p.second.ToString()));
}
contents.push_back("}");
return absl::StrJoin(contents, "\n");
}
//
// CidrRange
//
Rbac::CidrRange::CidrRange(std::string address_prefix, uint32_t prefix_len)
: address_prefix(std::move(address_prefix)), prefix_len(prefix_len) {}
Rbac::CidrRange::CidrRange(Rbac::CidrRange&& other) noexcept
: address_prefix(std::move(other.address_prefix)),
prefix_len(other.prefix_len) {}
Rbac::CidrRange& Rbac::CidrRange::operator=(Rbac::CidrRange&& other) noexcept {
address_prefix = std::move(other.address_prefix);
prefix_len = other.prefix_len;
return *this;
}
std::string Rbac::CidrRange::ToString() const {
return absl::StrFormat("CidrRange{address_prefix=%s,prefix_len=%d}",
address_prefix, prefix_len);
}
//
// Permission
//
Rbac::Permission::Permission(
Permission::RuleType type,
std::vector<std::unique_ptr<Permission>> permissions, bool not_rule)
: type(type), permissions(std::move(permissions)), not_rule(not_rule) {}
Rbac::Permission::Permission(Permission::RuleType type, bool not_rule)
: type(type), not_rule(not_rule) {}
Rbac::Permission::Permission(Permission::RuleType type,
HeaderMatcher header_matcher, bool not_rule)
: type(type),
header_matcher(std::move(header_matcher)),
not_rule(not_rule) {}
Rbac::Permission::Permission(Permission::RuleType type,
StringMatcher string_matcher, bool not_rule)
: type(type),
string_matcher(std::move(string_matcher)),
not_rule(not_rule) {}
Rbac::Permission::Permission(Permission::RuleType type, CidrRange ip,
bool not_rule)
: type(type), ip(std::move(ip)), not_rule(not_rule) {}
Rbac::Permission::Permission(Permission::RuleType type, int port, bool not_rule)
: type(type), port(port), not_rule(not_rule) {}
Rbac::Permission::Permission(Rbac::Permission&& other) noexcept
: type(other.type), not_rule(other.not_rule) {
switch (type) {
case RuleType::kAnd:
case RuleType::kOr:
permissions = std::move(other.permissions);
break;
case RuleType::kAny:
break;
case RuleType::kHeader:
header_matcher = std::move(other.header_matcher);
break;
case RuleType::kPath:
case RuleType::kReqServerName:
string_matcher = std::move(other.string_matcher);
break;
case RuleType::kDestIp:
ip = std::move(other.ip);
break;
default:
port = other.port;
}
}
Rbac::Permission& Rbac::Permission::operator=(
Rbac::Permission&& other) noexcept {
type = other.type;
not_rule = other.not_rule;
switch (type) {
case RuleType::kAnd:
case RuleType::kOr:
permissions = std::move(other.permissions);
break;
case RuleType::kAny:
break;
case RuleType::kHeader:
header_matcher = std::move(other.header_matcher);
break;
case RuleType::kPath:
case RuleType::kReqServerName:
string_matcher = std::move(other.string_matcher);
break;
case RuleType::kDestIp:
ip = std::move(other.ip);
break;
default:
port = other.port;
}
return *this;
}
std::string Rbac::Permission::ToString() const {
switch (type) {
case RuleType::kAnd: {
std::vector<std::string> contents;
contents.reserve(permissions.size());
for (const auto& permission : permissions) {
contents.push_back(permission->ToString());
}
return absl::StrFormat("%sand=[%s]", not_rule ? "not " : "",
absl::StrJoin(contents, ","));
}
case RuleType::kOr: {
std::vector<std::string> contents;
contents.reserve(permissions.size());
for (const auto& permission : permissions) {
contents.push_back(permission->ToString());
}
return absl::StrFormat("%sor=[%s]", not_rule ? "not " : "",
absl::StrJoin(contents, ","));
}
case RuleType::kAny:
return absl::StrFormat("%sany", not_rule ? "not " : "");
case RuleType::kHeader:
return absl::StrFormat("%sheader=%s", not_rule ? "not " : "",
header_matcher.ToString());
case RuleType::kPath:
return absl::StrFormat("%spath=%s", not_rule ? "not " : "",
string_matcher.ToString());
case RuleType::kDestIp:
return absl::StrFormat("%sdest_ip=%s", not_rule ? "not " : "",
ip.ToString());
case RuleType::kDestPort:
return absl::StrFormat("%sdest_port=%d", not_rule ? "not " : "", port);
case RuleType::kReqServerName:
return absl::StrFormat("%srequested_server_name=%s",
not_rule ? "not " : "", string_matcher.ToString());
default:
return "";
}
}
//
// Principal
//
Rbac::Principal::Principal(Principal::RuleType type,
std::vector<std::unique_ptr<Principal>> principals,
bool not_rule)
: type(type), principals(std::move(principals)), not_rule(not_rule) {}
Rbac::Principal::Principal(Principal::RuleType type, bool not_rule)
: type(type), not_rule(not_rule) {}
Rbac::Principal::Principal(Principal::RuleType type,
StringMatcher string_matcher, bool not_rule)
: type(type),
string_matcher(std::move(string_matcher)),
not_rule(not_rule) {}
Rbac::Principal::Principal(Principal::RuleType type, CidrRange ip,
bool not_rule)
: type(type), ip(std::move(ip)), not_rule(not_rule) {}
Rbac::Principal::Principal(Principal::RuleType type,
HeaderMatcher header_matcher, bool not_rule)
: type(type),
header_matcher(std::move(header_matcher)),
not_rule(not_rule) {}
Rbac::Principal::Principal(Rbac::Principal&& other) noexcept
: type(other.type), not_rule(other.not_rule) {
switch (type) {
case RuleType::kAnd:
case RuleType::kOr:
principals = std::move(other.principals);
break;
case RuleType::kAny:
break;
case RuleType::kHeader:
header_matcher = std::move(other.header_matcher);
break;
case RuleType::kPrincipalName:
case RuleType::kPath:
string_matcher = std::move(other.string_matcher);
break;
default:
ip = std::move(other.ip);
}
}
Rbac::Principal& Rbac::Principal::operator=(Rbac::Principal&& other) noexcept {
type = other.type;
not_rule = other.not_rule;
switch (type) {
case RuleType::kAnd:
case RuleType::kOr:
principals = std::move(other.principals);
break;
case RuleType::kAny:
break;
case RuleType::kHeader:
header_matcher = std::move(other.header_matcher);
break;
case RuleType::kPrincipalName:
case RuleType::kPath:
string_matcher = std::move(other.string_matcher);
break;
default:
ip = std::move(other.ip);
}
return *this;
}
std::string Rbac::Principal::ToString() const {
switch (type) {
case RuleType::kAnd: {
std::vector<std::string> contents;
contents.reserve(principals.size());
for (const auto& principal : principals) {
contents.push_back(principal->ToString());
}
return absl::StrFormat("%sand=[%s]", not_rule ? "not " : "",
absl::StrJoin(contents, ","));
}
case RuleType::kOr: {
std::vector<std::string> contents;
contents.reserve(principals.size());
for (const auto& principal : principals) {
contents.push_back(principal->ToString());
}
return absl::StrFormat("%sor=[%s]", not_rule ? "not " : "",
absl::StrJoin(contents, ","));
}
case RuleType::kAny:
return absl::StrFormat("%sany", not_rule ? "not " : "");
case RuleType::kPrincipalName:
return absl::StrFormat("%sprincipal_name=%s", not_rule ? "not " : "",
string_matcher.ToString());
case RuleType::kSourceIp:
return absl::StrFormat("%ssource_ip=%s", not_rule ? "not " : "",
ip.ToString());
case RuleType::kDirectRemoteIp:
return absl::StrFormat("%sdirect_remote_ip=%s", not_rule ? "not " : "",
ip.ToString());
case RuleType::kRemoteIp:
return absl::StrFormat("%sremote_ip=%s", not_rule ? "not " : "",
ip.ToString());
case RuleType::kHeader:
return absl::StrFormat("%sheader=%s", not_rule ? "not " : "",
header_matcher.ToString());
case RuleType::kPath:
return absl::StrFormat("%spath=%s", not_rule ? "not " : "",
string_matcher.ToString());
default:
return "";
}
}
//
// Policy
//
Rbac::Policy::Policy(Permission permissions, Principal principals)
: permissions(std::move(permissions)), principals(std::move(principals)) {}
Rbac::Policy::Policy(Rbac::Policy&& other) noexcept
: permissions(std::move(other.permissions)),
principals(std::move(other.principals)) {}
Rbac::Policy& Rbac::Policy::operator=(Rbac::Policy&& other) noexcept {
permissions = std::move(other.permissions);
principals = std::move(other.principals);
return *this;
}
std::string Rbac::Policy::ToString() const {
return absl::StrFormat(
" Policy {\n Permissions{%s}\n Principals{%s}\n }",
permissions.ToString(), principals.ToString());
}
} // namespace grpc_core