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 #ifndef GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MATCHERS_H
16 #define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MATCHERS_H
17 
18 #include <grpc/support/port_platform.h>
19 
20 #include <memory>
21 
22 #include "src/core/lib/matchers/matchers.h"
23 #include "src/core/lib/security/authorization/evaluate_args.h"
24 #include "src/core/lib/security/authorization/rbac_policy.h"
25 
26 namespace grpc_core {
27 
28 // Describes the rules for matching permission or principal.
29 class AuthorizationMatcher {
30  public:
31   virtual ~AuthorizationMatcher() = default;
32 
33   // Returns whether or not the permission/principal matches the rules of the
34   // matcher.
35   virtual bool Matches(const EvaluateArgs& args) const = 0;
36 
37   // Creates an instance of a matcher based off the rules defined in Permission
38   // config.
39   static std::unique_ptr<AuthorizationMatcher> Create(
40       Rbac::Permission permission);
41 
42   // Creates an instance of a matcher based off the rules defined in Principal
43   // config.
44   static std::unique_ptr<AuthorizationMatcher> Create(
45       Rbac::Principal principal);
46 };
47 
48 class AlwaysAuthorizationMatcher : public AuthorizationMatcher {
49  public:
50   explicit AlwaysAuthorizationMatcher() = default;
51 
Matches(const EvaluateArgs &)52   bool Matches(const EvaluateArgs&) const override { return true; }
53 };
54 
55 class AndAuthorizationMatcher : public AuthorizationMatcher {
56  public:
AndAuthorizationMatcher(std::vector<std::unique_ptr<AuthorizationMatcher>> matchers)57   explicit AndAuthorizationMatcher(
58       std::vector<std::unique_ptr<AuthorizationMatcher>> matchers)
59       : matchers_(std::move(matchers)) {}
60 
61   bool Matches(const EvaluateArgs& args) const override;
62 
63  private:
64   std::vector<std::unique_ptr<AuthorizationMatcher>> matchers_;
65 };
66 
67 class OrAuthorizationMatcher : public AuthorizationMatcher {
68  public:
OrAuthorizationMatcher(std::vector<std::unique_ptr<AuthorizationMatcher>> matchers)69   explicit OrAuthorizationMatcher(
70       std::vector<std::unique_ptr<AuthorizationMatcher>> matchers)
71       : matchers_(std::move(matchers)) {}
72 
73   bool Matches(const EvaluateArgs& args) const override;
74 
75  private:
76   std::vector<std::unique_ptr<AuthorizationMatcher>> matchers_;
77 };
78 
79 // Negates matching the provided permission/principal.
80 class NotAuthorizationMatcher : public AuthorizationMatcher {
81  public:
NotAuthorizationMatcher(std::unique_ptr<AuthorizationMatcher> matcher)82   explicit NotAuthorizationMatcher(
83       std::unique_ptr<AuthorizationMatcher> matcher)
84       : matcher_(std::move(matcher)) {}
85 
86   bool Matches(const EvaluateArgs& args) const override;
87 
88  private:
89   std::unique_ptr<AuthorizationMatcher> matcher_;
90 };
91 
92 // TODO(ashithasantosh): Add matcher implementation for metadata field.
93 
94 // Perform a match against HTTP headers.
95 class HeaderAuthorizationMatcher : public AuthorizationMatcher {
96  public:
HeaderAuthorizationMatcher(HeaderMatcher matcher)97   explicit HeaderAuthorizationMatcher(HeaderMatcher matcher)
98       : matcher_(std::move(matcher)) {}
99 
100   bool Matches(const EvaluateArgs& args) const override;
101 
102  private:
103   const HeaderMatcher matcher_;
104 };
105 
106 // Perform a match against IP Cidr Range.
107 class IpAuthorizationMatcher : public AuthorizationMatcher {
108  public:
109   enum class Type {
110     kDestIp,
111     kSourceIp,
112     kDirectRemoteIp,
113     kRemoteIp,
114   };
115 
116   IpAuthorizationMatcher(Type type, Rbac::CidrRange range);
117 
118   bool Matches(const EvaluateArgs& args) const override;
119 
120  private:
121   const Type type_;
122   // Subnet masked address.
123   grpc_resolved_address subnet_address_;
124   const uint32_t prefix_len_;
125 };
126 
127 // Perform a match against port number of the destination (local) address.
128 class PortAuthorizationMatcher : public AuthorizationMatcher {
129  public:
PortAuthorizationMatcher(int port)130   explicit PortAuthorizationMatcher(int port) : port_(port) {}
131 
132   bool Matches(const EvaluateArgs& args) const override;
133 
134  private:
135   const int port_;
136 };
137 
138 // Matches the principal name as described in the peer certificate. Uses URI SAN
139 // or DNS SAN in that order, otherwise uses subject field.
140 class AuthenticatedAuthorizationMatcher : public AuthorizationMatcher {
141  public:
AuthenticatedAuthorizationMatcher(StringMatcher auth)142   explicit AuthenticatedAuthorizationMatcher(StringMatcher auth)
143       : matcher_(std::move(auth)) {}
144 
145   bool Matches(const EvaluateArgs& args) const override;
146 
147  private:
148   const StringMatcher matcher_;
149 };
150 
151 // Perform a match against the request server from the client's connection
152 // request. This is typically TLS SNI. Currently unsupported.
153 class ReqServerNameAuthorizationMatcher : public AuthorizationMatcher {
154  public:
ReqServerNameAuthorizationMatcher(StringMatcher requested_server_name)155   explicit ReqServerNameAuthorizationMatcher(
156       StringMatcher requested_server_name)
157       : matcher_(std::move(requested_server_name)) {}
158 
159   bool Matches(const EvaluateArgs&) const override;
160 
161  private:
162   const StringMatcher matcher_;
163 };
164 
165 // Perform a match against the path header of HTTP request.
166 class PathAuthorizationMatcher : public AuthorizationMatcher {
167  public:
PathAuthorizationMatcher(StringMatcher path)168   explicit PathAuthorizationMatcher(StringMatcher path)
169       : matcher_(std::move(path)) {}
170 
171   bool Matches(const EvaluateArgs& args) const override;
172 
173  private:
174   const StringMatcher matcher_;
175 };
176 
177 // Performs a match for policy field in RBAC, which is a collection of
178 // permission and principal matchers. Policy matches iff, we find a match in one
179 // of its permissions and a match in one of its principals.
180 class PolicyAuthorizationMatcher : public AuthorizationMatcher {
181  public:
PolicyAuthorizationMatcher(Rbac::Policy policy)182   explicit PolicyAuthorizationMatcher(Rbac::Policy policy)
183       : permissions_(
184             AuthorizationMatcher::Create(std::move(policy.permissions))),
185         principals_(
186             AuthorizationMatcher::Create(std::move(policy.principals))) {}
187 
188   bool Matches(const EvaluateArgs& args) const override;
189 
190  private:
191   std::unique_ptr<AuthorizationMatcher> permissions_;
192   std::unique_ptr<AuthorizationMatcher> principals_;
193 };
194 
195 }  // namespace grpc_core
196 
197 #endif  // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MATCHERS_H
198