-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
filter: add conditions to access control filter #7716
Conversation
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
PR needs the bazel update in #7622 |
|
||
int size() const override { return 0; } | ||
bool empty() const override { return false; } | ||
const CelList* ListKeys() const override { return nullptr; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are all listkeys returning null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not implemented. For wrappers, it's undesired. For headers, it might be useful for comprehension operations (forall
, equality, or concatenating all header values), which I suppose is not common.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
quick skim. Merge master and I'll take another look.
return {}; | ||
} | ||
auto value = key.StringOrDie().value(); | ||
if (value == kRequestedServerName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can those be something like flat_hash_map<string_view, std::function>? I think we do similar in access_log_formatter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll need to measure it. std::function are surprisingly expensive in terms of unexpected allocations. The way it's done here is trivially allocation-free.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't have to create a map every time, have a static map like: flat_hash_map<string_view, std::function<CelValue(const StreamInfo&)>>, so you just call them every time, not allocating.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that's more readable. Anyways, I need to measure before making the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lizan, is this what you had in mind https://github.com/kyessenov/envoy/blob/abac_filter_feedback/test/extensions/filters/common/expr/context_speed_test.cc#L34?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, thanks for testing that out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After adding all functions to the flat_hash_map, here is the performance comparison:
2019-08-05 14:33:56
Running bazel-bin/test/extensions/filters/common/expr/context_speed_test
Run on (16 X 2200 MHz CPU s)
CPU Caches:
L1 Data 32K (x8)
L1 Instruction 32K (x8)
L2 Unified 256K (x8)
L3 Unified 56320K (x1)
Load Average: 1.14, 1.13, 1.19
---------------------------------------------------------
Benchmark Time CPU Iterations
---------------------------------------------------------
BM_Context 17.6 ns 17.6 ns 39715762
BM_TestContext 17.2 ns 17.2 ns 42524637
So it's roughly the same (I couldn't trivially wire a memory allocation profiler), and it comes down to readability and code style.
WDYT? Should we change it to a hashmap of functions?
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Great, I was looking at https://264581-65214191-gh.circle-artifacts.com/0/coverage/index.html, can you try to improve coverage for expr/{context,evaluator}.cc a bit more, esp. for error or empty cases? |
Signed-off-by: Kuat Yessenov <[email protected]>
Cool, added more tests to bump up the coverage. |
@lizan Anything else that needs to be done? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, one question.
com_googlesource_code_re2 = dict( | ||
sha256 = "f31db9cd224d018a7e4fe88ef84aaa874b0b3ed91d4d98ee5a1531101d3fdc64", | ||
strip_prefix = "re2-87e2ad45e7b18738e1551474f7ee5886ff572059", | ||
urls = ["https://github.com/google/re2/archive/87e2ad45e7b18738e1551474f7ee5886ff572059.tar.gz"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kyessenov qq: does cel-cpp rely on specific commit of re2? Asking because it might conflict with #7878, or latest release (2019-08-01) is fine? cc @mattklein123
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be no difference between which version is used. I think I chose the latest version which I started this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK that's fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was going to ask the same question. I'll switch this back a release version of re2 on a subsequent dependency PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will just fix this when I merge master.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Happy to help if necessary. Google3 doesn't really have versions for its repositories, and the upstream cel-cpp is continuously tested against head.
@kyessenov do you know how well the CEL parser is fuzzed? CC @asraa. |
There's no parser involved in this PR. The input is an AST in proto form. The AST is very simple, so it's human readable, and is generally correct by construction. There're two parsers for CEL available to generate AST: an internal in Java, and an external ANTLR-based golang one https://github.com/google/cel-go/tree/master/parser. |
@kyessenov two other security considerations:
|
@htuch I don't know if fuzzing was done on the evaluator. The code runs in production though, and I can share the relevant contacts. CEL was designed for security policies:
We only use standard builtin functions so I think those have been inspected to conform to that goal. |
Thanks, let's sync offline on this, I'm happy with the above answer on a security due diligence front. |
I can add some clarity here ... Evaluation CostThe cpu and memory impact of a CEL expression can be tuned by adjusting the environment (functions, macros) available to the expression itself. That is, if you don't want to support the function or macro, you can remove it from CEL environment declaration. Here are some common considerations with respect to the builtin features MemoryMost operations are have no additional allocation costs beyond the memory required to represent the value within the runtime. There are a couple of exceptions to this rule:
CPUThe majority of CEL functions and macros are O(1) or O(n), with a couple of exceptions.
TuningIn many cases, the The Some environments disable the Most of the performance critical use cases for CEL disable macros entirely, though there are a couple of linear-time macros currently supported in Istio. With the above recommendations, you'll have fixed allocation size operations that run in linear or sub-linear time. If you want to support FuzzingBuiltin functions are fuzzed within Google-internal tests., but we should open source the tests and augment them if desired. |
@kyessenov do you think it's reasonable to add the restrictions suggested ^^ under "Tuning"? Ideally we are as conservative as possible and then relax these in a deliberative fashion. @TristonianJones do we have plumbing to control something like https://github.com/envoyproxy/envoy/pull/7878/files#diff-c45c47ac26956b7b0f3f771bdf273fc2R25 in RE2? Or some CEL-level equivalent? Ideally we can provide operator control that bounds complexity. |
(and BTW, thanks @TristonianJones for that super detailed and helpful writeup) |
@htuch It might be better to delegate the restrictions to the management server. It's already expected that the expressions are type checked ahead of time, so it should be another pass to validate the bounded complexity. We can provide a library in Thanks for the write-up! I am going to send a doc update PR for RBAC, and will include the considerations above. |
@kyessenov a general Envoy principle that we've been trying to deduce recently is to try and simplify things on the management server; there will be O(100) or O(1k) management server implementations, and not all will use |
@htuch there aren't any specific controls to limit the size of the regex pattern, but it is restricted to what RE2 supports. There are a handful of lint checks that should be easy to implement as an AST traversal and checked in management server, or wherever makes sense. We haven't built a linting framework, but it's on our wish list. Note, removing the |
@htuch Sure, we can add extra controls in the C++ run-time. This work can be done in the upstream project. We can probably re-use some existing work from CEL CPP clients. Some more sophisticated linting can be done in CEL GO. It's a shared library that should be easy to include in any management server. |
@kyessenov where should we track this? In some Envoy issue, or do you folks have this scheduled? |
Filed google/cel-cpp#37. |
@kyessenov thanks, let's track there. |
This adds a fuzzer for CEL expression matching. These conditions are used in the RBAC filter for complementing the existing principal/permission model. About a quarter of the execution time is coming from google::api::expr::runtime::RegisterBuiltinFunctions. The test runs locally at about 250 exec/sec. See: #7716 Risk Level: Low Testing: Converted unit tests into corpus entries Signed-off-by: Asra Ali <[email protected]>
Signed-off-by: Kuat Yessenov [email protected]
Introduces a generic expression-based admission filter using https://github.com/google/cel-cpp.
This is a follow-up to discussion in #6751.
The advantage of this approach is:
metadata
. Companion filters can populate metadata about requests and resources that affect policy decisions.The dis-advantage of this approach is that its performance is lower than domain-optimized interpreters. On a fair example, the interpreter evaluates in around 1ms (see https://github.com/google/cel-cpp/blob/master/eval/tests/benchmark_test.cc#L591) vs ~150ns for hand-written C++ native code. There is space for improvement (especially if WASM can be used as a compilation target), but ultimately the generic expression form carries a cost.
Conditions are added to support RBAC filter for complementing the existing principal/permission model. They add support for the extended checks (e.g. time of query, resource-bound), but add no cost unless used.
Description: add expression-based admission filter
Risk Level: low
Testing:
Docs Changes:
Release Notes: