1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <grpc/support/port_platform.h>
16
17 #include "src/core/lib/security/authorization/matchers.h"
18
19 #include <string.h>
20
21 #include <algorithm>
22 #include <string>
23
24 #include "absl/status/status.h"
25 #include "absl/status/statusor.h"
26 #include "absl/strings/string_view.h"
27
28 #include <grpc/grpc_security_constants.h>
29 #include <grpc/support/log.h>
30
31 #include "src/core/lib/address_utils/parse_address.h"
32 #include "src/core/lib/address_utils/sockaddr_utils.h"
33
34 namespace grpc_core {
35
Create(Rbac::Permission permission)36 std::unique_ptr<AuthorizationMatcher> AuthorizationMatcher::Create(
37 Rbac::Permission permission) {
38 switch (permission.type) {
39 case Rbac::Permission::RuleType::kAnd: {
40 std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
41 matchers.reserve(permission.permissions.size());
42 for (const auto& rule : permission.permissions) {
43 matchers.push_back(AuthorizationMatcher::Create(std::move(*rule)));
44 }
45 return std::make_unique<AndAuthorizationMatcher>(std::move(matchers));
46 }
47 case Rbac::Permission::RuleType::kOr: {
48 std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
49 matchers.reserve(permission.permissions.size());
50 for (const auto& rule : permission.permissions) {
51 matchers.push_back(AuthorizationMatcher::Create(std::move(*rule)));
52 }
53 return std::make_unique<OrAuthorizationMatcher>(std::move(matchers));
54 }
55 case Rbac::Permission::RuleType::kNot:
56 return std::make_unique<NotAuthorizationMatcher>(
57 AuthorizationMatcher::Create(std::move(*permission.permissions[0])));
58 case Rbac::Permission::RuleType::kAny:
59 return std::make_unique<AlwaysAuthorizationMatcher>();
60 case Rbac::Permission::RuleType::kHeader:
61 return std::make_unique<HeaderAuthorizationMatcher>(
62 std::move(permission.header_matcher));
63 case Rbac::Permission::RuleType::kPath:
64 return std::make_unique<PathAuthorizationMatcher>(
65 std::move(permission.string_matcher));
66 case Rbac::Permission::RuleType::kDestIp:
67 return std::make_unique<IpAuthorizationMatcher>(
68 IpAuthorizationMatcher::Type::kDestIp, std::move(permission.ip));
69 case Rbac::Permission::RuleType::kDestPort:
70 return std::make_unique<PortAuthorizationMatcher>(permission.port);
71 case Rbac::Permission::RuleType::kMetadata:
72 return std::make_unique<MetadataAuthorizationMatcher>(permission.invert);
73 case Rbac::Permission::RuleType::kReqServerName:
74 return std::make_unique<ReqServerNameAuthorizationMatcher>(
75 std::move(permission.string_matcher));
76 }
77 return nullptr;
78 }
79
Create(Rbac::Principal principal)80 std::unique_ptr<AuthorizationMatcher> AuthorizationMatcher::Create(
81 Rbac::Principal principal) {
82 switch (principal.type) {
83 case Rbac::Principal::RuleType::kAnd: {
84 std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
85 matchers.reserve(principal.principals.size());
86 for (const auto& id : principal.principals) {
87 matchers.push_back(AuthorizationMatcher::Create(std::move(*id)));
88 }
89 return std::make_unique<AndAuthorizationMatcher>(std::move(matchers));
90 }
91 case Rbac::Principal::RuleType::kOr: {
92 std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
93 matchers.reserve(principal.principals.size());
94 for (const auto& id : principal.principals) {
95 matchers.push_back(AuthorizationMatcher::Create(std::move(*id)));
96 }
97 return std::make_unique<OrAuthorizationMatcher>(std::move(matchers));
98 }
99 case Rbac::Principal::RuleType::kNot:
100 return std::make_unique<NotAuthorizationMatcher>(
101 AuthorizationMatcher::Create(std::move(*principal.principals[0])));
102 case Rbac::Principal::RuleType::kAny:
103 return std::make_unique<AlwaysAuthorizationMatcher>();
104 case Rbac::Principal::RuleType::kPrincipalName:
105 return std::make_unique<AuthenticatedAuthorizationMatcher>(
106 std::move(principal.string_matcher));
107 case Rbac::Principal::RuleType::kSourceIp:
108 return std::make_unique<IpAuthorizationMatcher>(
109 IpAuthorizationMatcher::Type::kSourceIp, std::move(principal.ip));
110 case Rbac::Principal::RuleType::kDirectRemoteIp:
111 return std::make_unique<IpAuthorizationMatcher>(
112 IpAuthorizationMatcher::Type::kDirectRemoteIp,
113 std::move(principal.ip));
114 case Rbac::Principal::RuleType::kRemoteIp:
115 return std::make_unique<IpAuthorizationMatcher>(
116 IpAuthorizationMatcher::Type::kRemoteIp, std::move(principal.ip));
117 case Rbac::Principal::RuleType::kHeader:
118 return std::make_unique<HeaderAuthorizationMatcher>(
119 std::move(principal.header_matcher));
120 case Rbac::Principal::RuleType::kPath:
121 return std::make_unique<PathAuthorizationMatcher>(
122 std::move(principal.string_matcher.value()));
123 case Rbac::Principal::RuleType::kMetadata:
124 return std::make_unique<MetadataAuthorizationMatcher>(principal.invert);
125 }
126 return nullptr;
127 }
128
Matches(const EvaluateArgs & args) const129 bool AndAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
130 for (const auto& matcher : matchers_) {
131 if (!matcher->Matches(args)) {
132 return false;
133 }
134 }
135 return true;
136 }
137
Matches(const EvaluateArgs & args) const138 bool OrAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
139 for (const auto& matcher : matchers_) {
140 if (matcher->Matches(args)) {
141 return true;
142 }
143 }
144 return false;
145 }
146
Matches(const EvaluateArgs & args) const147 bool NotAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
148 return !matcher_->Matches(args);
149 }
150
Matches(const EvaluateArgs & args) const151 bool HeaderAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
152 std::string concatenated_value;
153 return matcher_.Match(
154 args.GetHeaderValue(matcher_.name(), &concatenated_value));
155 }
156
IpAuthorizationMatcher(Type type,Rbac::CidrRange range)157 IpAuthorizationMatcher::IpAuthorizationMatcher(Type type, Rbac::CidrRange range)
158 : type_(type), prefix_len_(range.prefix_len) {
159 auto address =
160 StringToSockaddr(range.address_prefix, 0); // Port does not matter here.
161 if (!address.ok()) {
162 gpr_log(GPR_DEBUG, "CidrRange address \"%s\" is not IPv4/IPv6. Error: %s",
163 range.address_prefix.c_str(), address.status().ToString().c_str());
164 memset(&subnet_address_, 0, sizeof(subnet_address_));
165 return;
166 }
167 subnet_address_ = *address;
168 grpc_sockaddr_mask_bits(&subnet_address_, prefix_len_);
169 }
170
Matches(const EvaluateArgs & args) const171 bool IpAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
172 grpc_resolved_address address;
173 switch (type_) {
174 case Type::kDestIp: {
175 address = args.GetLocalAddress();
176 break;
177 }
178 case Type::kSourceIp:
179 case Type::kDirectRemoteIp:
180 case Type::kRemoteIp: {
181 address = args.GetPeerAddress();
182 break;
183 }
184 default:
185 return false;
186 }
187 return grpc_sockaddr_match_subnet(&address, &subnet_address_, prefix_len_);
188 }
189
Matches(const EvaluateArgs & args) const190 bool PortAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
191 return port_ == args.GetLocalPort();
192 }
193
Matches(const EvaluateArgs & args) const194 bool AuthenticatedAuthorizationMatcher::Matches(
195 const EvaluateArgs& args) const {
196 if (args.GetTransportSecurityType() != GRPC_SSL_TRANSPORT_SECURITY_TYPE &&
197 args.GetTransportSecurityType() != GRPC_TLS_TRANSPORT_SECURITY_TYPE) {
198 // Connection is not authenticated.
199 return false;
200 }
201 if (!matcher_.has_value()) {
202 // Allows any authenticated user.
203 return true;
204 }
205 std::vector<absl::string_view> uri_sans = args.GetUriSans();
206 if (!uri_sans.empty()) {
207 for (const auto& uri : uri_sans) {
208 if (matcher_->Match(uri)) {
209 return true;
210 }
211 }
212 }
213 std::vector<absl::string_view> dns_sans = args.GetDnsSans();
214 if (!dns_sans.empty()) {
215 for (const auto& dns : dns_sans) {
216 if (matcher_->Match(dns)) {
217 return true;
218 }
219 }
220 }
221 return matcher_->Match(args.GetSubject());
222 }
223
Matches(const EvaluateArgs &) const224 bool ReqServerNameAuthorizationMatcher::Matches(const EvaluateArgs&) const {
225 // Currently we only support matching against an empty string.
226 return matcher_.Match("");
227 }
228
Matches(const EvaluateArgs & args) const229 bool PathAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
230 absl::string_view path = args.GetPath();
231 if (!path.empty()) {
232 return matcher_.Match(path);
233 }
234 return false;
235 }
236
Matches(const EvaluateArgs & args) const237 bool PolicyAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
238 return permissions_->Matches(args) && principals_->Matches(args);
239 }
240
241 } // namespace grpc_core
242