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 "src/core/lib/security/authorization/matchers.h"
16
17 #include <grpc/grpc_security_constants.h>
18 #include <grpc/support/port_platform.h>
19 #include <string.h>
20
21 #include <string>
22
23 #include "absl/log/log.h"
24 #include "absl/status/status.h"
25 #include "absl/status/statusor.h"
26 #include "absl/strings/string_view.h"
27 #include "src/core/lib/address_utils/parse_address.h"
28 #include "src/core/lib/address_utils/sockaddr_utils.h"
29
30 namespace grpc_core {
31
Create(Rbac::Permission permission)32 std::unique_ptr<AuthorizationMatcher> AuthorizationMatcher::Create(
33 Rbac::Permission permission) {
34 switch (permission.type) {
35 case Rbac::Permission::RuleType::kAnd: {
36 std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
37 matchers.reserve(permission.permissions.size());
38 for (const auto& rule : permission.permissions) {
39 matchers.push_back(AuthorizationMatcher::Create(std::move(*rule)));
40 }
41 return std::make_unique<AndAuthorizationMatcher>(std::move(matchers));
42 }
43 case Rbac::Permission::RuleType::kOr: {
44 std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
45 matchers.reserve(permission.permissions.size());
46 for (const auto& rule : permission.permissions) {
47 matchers.push_back(AuthorizationMatcher::Create(std::move(*rule)));
48 }
49 return std::make_unique<OrAuthorizationMatcher>(std::move(matchers));
50 }
51 case Rbac::Permission::RuleType::kNot:
52 return std::make_unique<NotAuthorizationMatcher>(
53 AuthorizationMatcher::Create(std::move(*permission.permissions[0])));
54 case Rbac::Permission::RuleType::kAny:
55 return std::make_unique<AlwaysAuthorizationMatcher>();
56 case Rbac::Permission::RuleType::kHeader:
57 return std::make_unique<HeaderAuthorizationMatcher>(
58 std::move(permission.header_matcher));
59 case Rbac::Permission::RuleType::kPath:
60 return std::make_unique<PathAuthorizationMatcher>(
61 std::move(permission.string_matcher));
62 case Rbac::Permission::RuleType::kDestIp:
63 return std::make_unique<IpAuthorizationMatcher>(
64 IpAuthorizationMatcher::Type::kDestIp, std::move(permission.ip));
65 case Rbac::Permission::RuleType::kDestPort:
66 return std::make_unique<PortAuthorizationMatcher>(permission.port);
67 case Rbac::Permission::RuleType::kMetadata:
68 return std::make_unique<MetadataAuthorizationMatcher>(permission.invert);
69 case Rbac::Permission::RuleType::kReqServerName:
70 return std::make_unique<ReqServerNameAuthorizationMatcher>(
71 std::move(permission.string_matcher));
72 }
73 return nullptr;
74 }
75
Create(Rbac::Principal principal)76 std::unique_ptr<AuthorizationMatcher> AuthorizationMatcher::Create(
77 Rbac::Principal principal) {
78 switch (principal.type) {
79 case Rbac::Principal::RuleType::kAnd: {
80 std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
81 matchers.reserve(principal.principals.size());
82 for (const auto& id : principal.principals) {
83 matchers.push_back(AuthorizationMatcher::Create(std::move(*id)));
84 }
85 return std::make_unique<AndAuthorizationMatcher>(std::move(matchers));
86 }
87 case Rbac::Principal::RuleType::kOr: {
88 std::vector<std::unique_ptr<AuthorizationMatcher>> matchers;
89 matchers.reserve(principal.principals.size());
90 for (const auto& id : principal.principals) {
91 matchers.push_back(AuthorizationMatcher::Create(std::move(*id)));
92 }
93 return std::make_unique<OrAuthorizationMatcher>(std::move(matchers));
94 }
95 case Rbac::Principal::RuleType::kNot:
96 return std::make_unique<NotAuthorizationMatcher>(
97 AuthorizationMatcher::Create(std::move(*principal.principals[0])));
98 case Rbac::Principal::RuleType::kAny:
99 return std::make_unique<AlwaysAuthorizationMatcher>();
100 case Rbac::Principal::RuleType::kPrincipalName:
101 return std::make_unique<AuthenticatedAuthorizationMatcher>(
102 std::move(principal.string_matcher));
103 case Rbac::Principal::RuleType::kSourceIp:
104 return std::make_unique<IpAuthorizationMatcher>(
105 IpAuthorizationMatcher::Type::kSourceIp, std::move(principal.ip));
106 case Rbac::Principal::RuleType::kDirectRemoteIp:
107 return std::make_unique<IpAuthorizationMatcher>(
108 IpAuthorizationMatcher::Type::kDirectRemoteIp,
109 std::move(principal.ip));
110 case Rbac::Principal::RuleType::kRemoteIp:
111 return std::make_unique<IpAuthorizationMatcher>(
112 IpAuthorizationMatcher::Type::kRemoteIp, std::move(principal.ip));
113 case Rbac::Principal::RuleType::kHeader:
114 return std::make_unique<HeaderAuthorizationMatcher>(
115 std::move(principal.header_matcher));
116 case Rbac::Principal::RuleType::kPath:
117 return std::make_unique<PathAuthorizationMatcher>(
118 std::move(principal.string_matcher.value()));
119 case Rbac::Principal::RuleType::kMetadata:
120 return std::make_unique<MetadataAuthorizationMatcher>(principal.invert);
121 }
122 return nullptr;
123 }
124
Matches(const EvaluateArgs & args) const125 bool AndAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
126 for (const auto& matcher : matchers_) {
127 if (!matcher->Matches(args)) {
128 return false;
129 }
130 }
131 return true;
132 }
133
Matches(const EvaluateArgs & args) const134 bool OrAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
135 for (const auto& matcher : matchers_) {
136 if (matcher->Matches(args)) {
137 return true;
138 }
139 }
140 return false;
141 }
142
Matches(const EvaluateArgs & args) const143 bool NotAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
144 return !matcher_->Matches(args);
145 }
146
Matches(const EvaluateArgs & args) const147 bool HeaderAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
148 std::string concatenated_value;
149 return matcher_.Match(
150 args.GetHeaderValue(matcher_.name(), &concatenated_value));
151 }
152
IpAuthorizationMatcher(Type type,Rbac::CidrRange range)153 IpAuthorizationMatcher::IpAuthorizationMatcher(Type type, Rbac::CidrRange range)
154 : type_(type), prefix_len_(range.prefix_len) {
155 auto address =
156 StringToSockaddr(range.address_prefix, 0); // Port does not matter here.
157 if (!address.ok()) {
158 VLOG(2) << "CidrRange address \"" << range.address_prefix
159 << "\" is not IPv4/IPv6. Error: " << address.status();
160 memset(&subnet_address_, 0, sizeof(subnet_address_));
161 return;
162 }
163 subnet_address_ = *address;
164 grpc_sockaddr_mask_bits(&subnet_address_, prefix_len_);
165 }
166
Matches(const EvaluateArgs & args) const167 bool IpAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
168 grpc_resolved_address address;
169 switch (type_) {
170 case Type::kDestIp: {
171 address = args.GetLocalAddress();
172 break;
173 }
174 case Type::kSourceIp:
175 case Type::kDirectRemoteIp:
176 case Type::kRemoteIp: {
177 address = args.GetPeerAddress();
178 break;
179 }
180 default:
181 return false;
182 }
183 return grpc_sockaddr_match_subnet(&address, &subnet_address_, prefix_len_);
184 }
185
Matches(const EvaluateArgs & args) const186 bool PortAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
187 return port_ == args.GetLocalPort();
188 }
189
Matches(const EvaluateArgs & args) const190 bool AuthenticatedAuthorizationMatcher::Matches(
191 const EvaluateArgs& args) const {
192 if (args.GetTransportSecurityType() != GRPC_SSL_TRANSPORT_SECURITY_TYPE &&
193 args.GetTransportSecurityType() != GRPC_TLS_TRANSPORT_SECURITY_TYPE) {
194 // Connection is not authenticated.
195 return false;
196 }
197 if (!matcher_.has_value()) {
198 // Allows any authenticated user.
199 return true;
200 }
201 std::vector<absl::string_view> uri_sans = args.GetUriSans();
202 if (!uri_sans.empty()) {
203 for (const auto& uri : uri_sans) {
204 if (matcher_->Match(uri)) {
205 return true;
206 }
207 }
208 }
209 std::vector<absl::string_view> dns_sans = args.GetDnsSans();
210 if (!dns_sans.empty()) {
211 for (const auto& dns : dns_sans) {
212 if (matcher_->Match(dns)) {
213 return true;
214 }
215 }
216 }
217 return matcher_->Match(args.GetSubject());
218 }
219
Matches(const EvaluateArgs &) const220 bool ReqServerNameAuthorizationMatcher::Matches(const EvaluateArgs&) const {
221 // Currently we only support matching against an empty string.
222 return matcher_.Match("");
223 }
224
Matches(const EvaluateArgs & args) const225 bool PathAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
226 absl::string_view path = args.GetPath();
227 if (!path.empty()) {
228 return matcher_.Match(path);
229 }
230 return false;
231 }
232
Matches(const EvaluateArgs & args) const233 bool PolicyAuthorizationMatcher::Matches(const EvaluateArgs& args) const {
234 return permissions_->Matches(args) && principals_->Matches(args);
235 }
236
237 } // namespace grpc_core
238