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(bool not_rule = false) not_rule_(not_rule)51 : not_rule_(not_rule) {} 52 Matches(const EvaluateArgs &)53 bool Matches(const EvaluateArgs&) const override { return !not_rule_; } 54 55 private: 56 // Negates matching the provided permission/principal. 57 const bool not_rule_; 58 }; 59 60 class AndAuthorizationMatcher : public AuthorizationMatcher { 61 public: 62 explicit AndAuthorizationMatcher( 63 std::vector<std::unique_ptr<Rbac::Permission>> rules, 64 bool not_rule = false); 65 explicit AndAuthorizationMatcher( 66 std::vector<std::unique_ptr<Rbac::Principal>> ids, bool not_rule = false); 67 68 bool Matches(const EvaluateArgs& args) const override; 69 70 private: 71 std::vector<std::unique_ptr<AuthorizationMatcher>> matchers_; 72 // Negates matching the provided permission/principal. 73 const bool not_rule_; 74 }; 75 76 class OrAuthorizationMatcher : public AuthorizationMatcher { 77 public: 78 explicit OrAuthorizationMatcher( 79 std::vector<std::unique_ptr<Rbac::Permission>> rules, 80 bool not_rule = false); 81 explicit OrAuthorizationMatcher( 82 std::vector<std::unique_ptr<Rbac::Principal>> ids, bool not_rule = false); 83 84 bool Matches(const EvaluateArgs& args) const override; 85 86 private: 87 std::vector<std::unique_ptr<AuthorizationMatcher>> matchers_; 88 // Negates matching the provided permission/principal. 89 const bool not_rule_; 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: 97 explicit HeaderAuthorizationMatcher(HeaderMatcher matcher, 98 bool not_rule = false) matcher_(std::move (matcher))99 : matcher_(std::move(matcher)), not_rule_(not_rule) {} 100 101 bool Matches(const EvaluateArgs& args) const override; 102 103 private: 104 const HeaderMatcher matcher_; 105 // Negates matching the provided permission/principal. 106 const bool not_rule_; 107 }; 108 109 // Perform a match against IP Cidr Range. 110 // TODO(ashithasantosh): Handle type of Ip or use seperate matchers for each 111 // type. Implement Match functionality, this would require updating EvaluateArgs 112 // getters, to return format of IP as well. 113 class IpAuthorizationMatcher : public AuthorizationMatcher { 114 public: 115 explicit IpAuthorizationMatcher(Rbac::CidrRange range, bool not_rule = false) range_(std::move (range))116 : range_(std::move(range)), not_rule_(not_rule) {} 117 118 bool Matches(const EvaluateArgs&) const override; 119 120 private: 121 const Rbac::CidrRange range_; 122 // Negates matching the provided permission/principal. 123 const bool not_rule_; 124 }; 125 126 // Perform a match against port number of the destination (local) address. 127 class PortAuthorizationMatcher : public AuthorizationMatcher { 128 public: 129 explicit PortAuthorizationMatcher(int port, bool not_rule = false) port_(port)130 : port_(port), not_rule_(not_rule) {} 131 132 bool Matches(const EvaluateArgs& args) const override; 133 134 private: 135 const int port_; 136 // Negates matching the provided permission/principal. 137 const bool not_rule_; 138 }; 139 140 // Matches the principal name as described in the peer certificate. Uses URI SAN 141 // or DNS SAN in that order, otherwise uses subject field. 142 class AuthenticatedAuthorizationMatcher : public AuthorizationMatcher { 143 public: 144 explicit AuthenticatedAuthorizationMatcher(StringMatcher auth, 145 bool not_rule = false) matcher_(std::move (auth))146 : matcher_(std::move(auth)), not_rule_(not_rule) {} 147 148 bool Matches(const EvaluateArgs& args) const override; 149 150 private: 151 const StringMatcher matcher_; 152 // Negates matching the provided permission/principal. 153 const bool not_rule_; 154 }; 155 156 // Perform a match against the request server from the client's connection 157 // request. This is typically TLS SNI. Currently unsupported. 158 class ReqServerNameAuthorizationMatcher : public AuthorizationMatcher { 159 public: 160 explicit ReqServerNameAuthorizationMatcher( 161 StringMatcher requested_server_name, bool not_rule = false) matcher_(std::move (requested_server_name))162 : matcher_(std::move(requested_server_name)), not_rule_(not_rule) {} 163 164 bool Matches(const EvaluateArgs&) const override; 165 166 private: 167 const StringMatcher matcher_; 168 // Negates matching the provided permission/principal. 169 const bool not_rule_; 170 }; 171 172 // Perform a match against the path header of HTTP request. 173 class PathAuthorizationMatcher : public AuthorizationMatcher { 174 public: 175 explicit PathAuthorizationMatcher(StringMatcher path, bool not_rule = false) matcher_(std::move (path))176 : matcher_(std::move(path)), not_rule_(not_rule) {} 177 178 bool Matches(const EvaluateArgs& args) const override; 179 180 private: 181 const StringMatcher matcher_; 182 // Negates matching the provided permission/principal. 183 const bool not_rule_; 184 }; 185 186 // Performs a match for policy field in RBAC, which is a collection of 187 // permission and principal matchers. Policy matches iff, we find a match in one 188 // of its permissions and a match in one of its principals. 189 class PolicyAuthorizationMatcher : public AuthorizationMatcher { 190 public: PolicyAuthorizationMatcher(Rbac::Policy policy)191 explicit PolicyAuthorizationMatcher(Rbac::Policy policy) 192 : permissions_( 193 AuthorizationMatcher::Create(std::move(policy.permissions))), 194 principals_( 195 AuthorizationMatcher::Create(std::move(policy.principals))) {} 196 197 bool Matches(const EvaluateArgs& args) const override; 198 199 private: 200 std::unique_ptr<AuthorizationMatcher> permissions_; 201 std::unique_ptr<AuthorizationMatcher> principals_; 202 }; 203 204 } // namespace grpc_core 205 206 #endif // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MATCHERS_H 207