/proc/self/cwd/source/extensions/filters/common/rbac/matchers.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include <memory> |
4 | | |
5 | | #include "envoy/config/core/v3/address.pb.h" |
6 | | #include "envoy/config/rbac/v3/rbac.pb.h" |
7 | | #include "envoy/config/route/v3/route_components.pb.h" |
8 | | #include "envoy/http/header_map.h" |
9 | | #include "envoy/network/connection.h" |
10 | | #include "envoy/type/matcher/v3/path.pb.h" |
11 | | #include "envoy/type/matcher/v3/string.pb.h" |
12 | | |
13 | | #include "source/common/common/matchers.h" |
14 | | #include "source/common/http/header_utility.h" |
15 | | #include "source/common/network/cidr_range.h" |
16 | | #include "source/extensions/filters/common/expr/evaluator.h" |
17 | | |
18 | | namespace Envoy { |
19 | | namespace Extensions { |
20 | | namespace Filters { |
21 | | namespace Common { |
22 | | namespace RBAC { |
23 | | |
24 | | class Matcher; |
25 | | using MatcherConstSharedPtr = std::shared_ptr<const Matcher>; |
26 | | |
27 | | /** |
28 | | * Matchers describe the rules for matching either a permission action or principal. |
29 | | */ |
30 | | class Matcher { |
31 | | public: |
32 | 40.9k | virtual ~Matcher() = default; |
33 | | |
34 | | /** |
35 | | * Returns whether or not the permission/principal matches the rules of the matcher. |
36 | | * |
37 | | * @param connection the downstream connection used to match against. |
38 | | * @param headers the request headers used to match against. An empty map should be used if |
39 | | * there are none headers available. |
40 | | * @param info the additional information about the action/principal. |
41 | | */ |
42 | | virtual bool matches(const Network::Connection& connection, |
43 | | const Envoy::Http::RequestHeaderMap& headers, |
44 | | const StreamInfo::StreamInfo& info) const PURE; |
45 | | |
46 | | /** |
47 | | * Creates a shared instance of a matcher based off the rules defined in the Permission config |
48 | | * proto message. |
49 | | */ |
50 | | static MatcherConstSharedPtr create(const envoy::config::rbac::v3::Permission& permission, |
51 | | ProtobufMessage::ValidationVisitor& validation_visitor); |
52 | | |
53 | | /** |
54 | | * Creates a shared instance of a matcher based off the rules defined in the Principal config |
55 | | * proto message. |
56 | | */ |
57 | | static MatcherConstSharedPtr create(const envoy::config::rbac::v3::Principal& principal); |
58 | | }; |
59 | | |
60 | | /** |
61 | | * Always matches, returning true for any input. |
62 | | */ |
63 | | class AlwaysMatcher : public Matcher { |
64 | | public: |
65 | | bool matches(const Network::Connection&, const Envoy::Http::RequestHeaderMap&, |
66 | 23.0k | const StreamInfo::StreamInfo&) const override { |
67 | 23.0k | return true; |
68 | 23.0k | } |
69 | | }; |
70 | | |
71 | | /** |
72 | | * A composite matcher where all sub-matchers must match for this to return true. Evaluation |
73 | | * short-circuits on the first non-match. |
74 | | */ |
75 | | class AndMatcher : public Matcher { |
76 | | public: |
77 | | AndMatcher(const envoy::config::rbac::v3::Permission::Set& rules, |
78 | | ProtobufMessage::ValidationVisitor& validation_visitor); |
79 | | AndMatcher(const envoy::config::rbac::v3::Principal::Set& ids); |
80 | | |
81 | | bool matches(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, |
82 | | const StreamInfo::StreamInfo&) const override; |
83 | | |
84 | | private: |
85 | | std::vector<MatcherConstSharedPtr> matchers_; |
86 | | }; |
87 | | |
88 | | /** |
89 | | * A composite matcher where only one sub-matcher must match for this to return true. Evaluation |
90 | | * short-circuits on the first match. |
91 | | */ |
92 | | class OrMatcher : public Matcher { |
93 | | public: |
94 | | OrMatcher(const envoy::config::rbac::v3::Permission::Set& set, |
95 | | ProtobufMessage::ValidationVisitor& validation_visitor) |
96 | 867 | : OrMatcher(set.rules(), validation_visitor) {} |
97 | 1.78k | OrMatcher(const envoy::config::rbac::v3::Principal::Set& set) : OrMatcher(set.ids()) {} |
98 | | OrMatcher(const Protobuf::RepeatedPtrField<envoy::config::rbac::v3::Permission>& rules, |
99 | | ProtobufMessage::ValidationVisitor& validation_visitor); |
100 | | OrMatcher(const Protobuf::RepeatedPtrField<envoy::config::rbac::v3::Principal>& ids); |
101 | | |
102 | | bool matches(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, |
103 | | const StreamInfo::StreamInfo&) const override; |
104 | | |
105 | | private: |
106 | | std::vector<MatcherConstSharedPtr> matchers_; |
107 | | }; |
108 | | |
109 | | class NotMatcher : public Matcher { |
110 | | public: |
111 | | NotMatcher(const envoy::config::rbac::v3::Permission& permission, |
112 | | ProtobufMessage::ValidationVisitor& validation_visitor) |
113 | 851 | : matcher_(Matcher::create(permission, validation_visitor)) {} |
114 | | NotMatcher(const envoy::config::rbac::v3::Principal& principal) |
115 | 1.59k | : matcher_(Matcher::create(principal)) {} |
116 | | |
117 | | bool matches(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, |
118 | | const StreamInfo::StreamInfo&) const override; |
119 | | |
120 | | private: |
121 | | MatcherConstSharedPtr matcher_; |
122 | | }; |
123 | | |
124 | | /** |
125 | | * Perform a match against any HTTP header (or pseudo-header, such as `:path` or `:authority`). Will |
126 | | * always fail to match on any non-HTTP connection. |
127 | | */ |
128 | | class HeaderMatcher : public Matcher { |
129 | | public: |
130 | 68 | HeaderMatcher(const envoy::config::route::v3::HeaderMatcher& matcher) : header_(matcher) {} |
131 | | |
132 | | bool matches(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, |
133 | | const StreamInfo::StreamInfo&) const override; |
134 | | |
135 | | private: |
136 | | const Envoy::Http::HeaderUtility::HeaderData header_; |
137 | | }; |
138 | | |
139 | | /** |
140 | | * Perform a match against an IP CIDR range. This rule can be applied to connection remote, |
141 | | * downstream local address, downstream direct remote address or downstream remote address. |
142 | | */ |
143 | | class IPMatcher : public Matcher { |
144 | | public: |
145 | | enum Type { ConnectionRemote = 0, DownstreamLocal, DownstreamDirectRemote, DownstreamRemote }; |
146 | | |
147 | | IPMatcher(const envoy::config::core::v3::CidrRange& range, Type type) |
148 | 1.29k | : range_(Network::Address::CidrRange::create(range)), type_(type) {} |
149 | | |
150 | | bool matches(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, |
151 | | const StreamInfo::StreamInfo& info) const override; |
152 | | |
153 | | private: |
154 | | const Network::Address::CidrRange range_; |
155 | | const Type type_; |
156 | | }; |
157 | | |
158 | | /** |
159 | | * Matches the port number of the destination (local) address. |
160 | | */ |
161 | | class PortMatcher : public Matcher { |
162 | | public: |
163 | 5.51k | PortMatcher(const uint32_t port) : port_(port) {} |
164 | | |
165 | | bool matches(const Network::Connection&, const Envoy::Http::RequestHeaderMap&, |
166 | | const StreamInfo::StreamInfo& info) const override; |
167 | | |
168 | | private: |
169 | | const uint32_t port_; |
170 | | }; |
171 | | |
172 | | class PortRangeMatcher : public Matcher { |
173 | | public: |
174 | | PortRangeMatcher(const ::envoy::type::v3::Int32Range& range); |
175 | | |
176 | | bool matches(const Network::Connection&, const Envoy::Http::RequestHeaderMap&, |
177 | | const StreamInfo::StreamInfo& info) const override; |
178 | | |
179 | | private: |
180 | | const uint32_t start_; |
181 | | const uint32_t end_; |
182 | | }; |
183 | | |
184 | | /** |
185 | | * Matches the principal name as described in the peer certificate. Uses the URI SAN first. If that |
186 | | * field is not present, uses the subject instead. |
187 | | */ |
188 | | class AuthenticatedMatcher : public Matcher { |
189 | | public: |
190 | | AuthenticatedMatcher(const envoy::config::rbac::v3::Principal::Authenticated& auth) |
191 | | : matcher_(auth.has_principal_name() |
192 | | ? absl::make_optional< |
193 | | Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>>( |
194 | | auth.principal_name()) |
195 | 4.16k | : absl::nullopt) {} |
196 | | |
197 | | bool matches(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, |
198 | | const StreamInfo::StreamInfo&) const override; |
199 | | |
200 | | private: |
201 | | const absl::optional<Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>> |
202 | | matcher_; |
203 | | }; |
204 | | |
205 | | /** |
206 | | * Matches a Policy which is a collection of permission and principal matchers. If any action |
207 | | * matches a permission, the principals are then checked for a match. |
208 | | * The condition is a conjunction clause. |
209 | | */ |
210 | | class PolicyMatcher : public Matcher, NonCopyable { |
211 | | public: |
212 | | PolicyMatcher(const envoy::config::rbac::v3::Policy& policy, Expr::Builder* builder, |
213 | | ProtobufMessage::ValidationVisitor& validation_visitor) |
214 | | : permissions_(policy.permissions(), validation_visitor), principals_(policy.principals()), |
215 | 4.72k | condition_(policy.condition()) { |
216 | 4.72k | if (policy.has_condition()) { |
217 | 4.19k | expr_ = Expr::createExpression(*builder, condition_); |
218 | 4.19k | } |
219 | 4.72k | } |
220 | | |
221 | | bool matches(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, |
222 | | const StreamInfo::StreamInfo&) const override; |
223 | | |
224 | | private: |
225 | | const OrMatcher permissions_; |
226 | | const OrMatcher principals_; |
227 | | const google::api::expr::v1alpha1::Expr condition_; |
228 | | Expr::ExpressionPtr expr_; |
229 | | }; |
230 | | |
231 | | class MetadataMatcher : public Matcher { |
232 | | public: |
233 | 415 | MetadataMatcher(const Envoy::Matchers::MetadataMatcher& matcher) : matcher_(matcher) {} |
234 | | |
235 | | bool matches(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, |
236 | | const StreamInfo::StreamInfo& info) const override; |
237 | | |
238 | | private: |
239 | | const Envoy::Matchers::MetadataMatcher matcher_; |
240 | | }; |
241 | | |
242 | | class FilterStateMatcher : public Matcher { |
243 | | public: |
244 | | FilterStateMatcher(const envoy::type::matcher::v3::FilterStateMatcher& matcher) |
245 | 17 | : matcher_(matcher) {} |
246 | | |
247 | | bool matches(const Network::Connection&, const Envoy::Http::RequestHeaderMap&, |
248 | | const StreamInfo::StreamInfo& info) const override; |
249 | | |
250 | | private: |
251 | | const Envoy::Matchers::FilterStateMatcher matcher_; |
252 | | }; |
253 | | |
254 | | /** |
255 | | * Perform a match against the request server from the client's connection |
256 | | * request. This is typically TLS SNI. |
257 | | */ |
258 | | class RequestedServerNameMatcher |
259 | | : public Matcher, |
260 | | Envoy::Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher> { |
261 | | public: |
262 | | RequestedServerNameMatcher(const envoy::type::matcher::v3::StringMatcher& requested_server_name) |
263 | | : Envoy::Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>( |
264 | 889 | requested_server_name) {} |
265 | | |
266 | | bool matches(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, |
267 | | const StreamInfo::StreamInfo&) const override; |
268 | | }; |
269 | | |
270 | | /** |
271 | | * Perform a match against the path header on the HTTP request. The query and fragment string are |
272 | | * removed from the path header before matching. |
273 | | */ |
274 | | class PathMatcher : public Matcher { |
275 | | public: |
276 | | PathMatcher(const envoy::type::matcher::v3::PathMatcher& path_matcher) |
277 | 255 | : path_matcher_(path_matcher) {} |
278 | | |
279 | | bool matches(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, |
280 | | const StreamInfo::StreamInfo&) const override; |
281 | | |
282 | | private: |
283 | | const Matchers::PathMatcher path_matcher_; |
284 | | }; |
285 | | |
286 | | } // namespace RBAC |
287 | | } // namespace Common |
288 | | } // namespace Filters |
289 | | } // namespace Extensions |
290 | | } // namespace Envoy |