rbac: add support for SNI based permissions#4662
Conversation
There was a problem hiding this comment.
shouldn't this be a reference as well?
rshriram
left a comment
There was a problem hiding this comment.
Thanks for the quick turn around. We need exact/prefix/regex matches for the SNI, similar to the string match constructs supported by the header matchers in rbac.
There was a problem hiding this comment.
is this a string equals function? For SNI specifically, we need prefix matches at lest. (like *.example.com) that matches foo.example.com and so on.. Didn't RBAC have some exact/prefix/regex match construct for strings/
There was a problem hiding this comment.
Can we potentially call this "requested_server_name_indication" to be super clear about what this is (or similar)? (With more detail in the comment about TLS, etc.)? WDYT?
There was a problem hiding this comment.
How about requested_sni_server_name?
There was a problem hiding this comment.
how about just SNI instead of all the workarounds?
There was a problem hiding this comment.
End users understand SNI much more than "requested server name". And in this PR, this requested server name is spilling into end user config, where we are better of using commonly known terms than the "technically" right term.
There was a problem hiding this comment.
I think we made name change from SNI to server names in FilterChainMatch, so it is not TLS specific? If here we're going to match same thing it shouldn't refer SNI directly. ref: #3454
cc @ggreenway @PiotrSikora
There was a problem hiding this comment.
That's correct. It was named this way so that it could also apply to HTTP Host header, or any other similar field in another protocol.
There was a problem hiding this comment.
Eh? RBAC already has dedicated fields for HTTP host. The fact that this specific thing applies to the SNI value presented in the ClientHello message means we need to be very explicit about what server name this refers to. If consistency is needed, then we need to stick with requested_Server_name. But as @mattklein123 points out, its still confusing, because there are one too many server names :).
How about tls_server_name ? Very little scope for confusion. I really don't want to give people the impression that this could also be a HTTP host header, as it receives separate treatment in RBAC.
There was a problem hiding this comment.
If we keep requested_server_name, my ask is that we make the documentation much more explicit. Basically call out that this is typically set via TLS SNI, and then explain how it might be set some other way (Listener filter, other?). Thank you.
There was a problem hiding this comment.
I don't think it could apply to HTTP Host header, but definitely similar field in another protocol. Any listener filter extension may set that. TLS inspector is the only one setting that here, but we may have other. +1 to https://github.com/envoyproxy/envoy/pull/4662/files#r224160788 make documentation explicit.
There was a problem hiding this comment.
If the expectation is that this only applies to SNI, then this code could do the wrong thing, depending on your configured filter chain:
- If you don't explicitly add the tls_inspector filter, and you don't have any FilterChainMatch matching on servername, this field will be empty
- A different listener filter could set this to something other than the SNI value
- This could be a non-TLS connection, in which case there is no SNI value.
Given all this, I think you should document exactly what this is filtering on. Link to the docs on how requestedServerName() is set, give an example for how to set this up for TLS, and note that some filter chain configurations could lead to different results.
There was a problem hiding this comment.
I don't think it could apply to HTTP Host header, but definitely similar field in another protocol. Any listener filter extension may set that. TLS inspector is the only one setting that here, but we may have other. +1 to https://github.com/envoyproxy/envoy/pull/4662/files#r224160788 make documentation explicit.
This commit adds support for SNI based permissions by matching over a connection's requested server name. Signed-off-by: Venil Noronha <veniln@vmware.com>
527170f to
74642f0
Compare
This commit replaces the existing string based SNI field with StringMatcher which provides much more flexibility for matching patterns. Signed-off-by: Venil Noronha <veniln@vmware.com>
| #include "common/http/header_utility.h" | ||
| #include "common/network/cidr_range.h" | ||
|
|
||
| #include "absl/strings/str_replace.h" |
|
Docs are on their way... |
This commit adds notes about how the requested_server_name field behaves in different situations. Signed-off-by: Venil Noronha <veniln@vmware.com>
| const Envoy::Http::HeaderMap&, | ||
| const envoy::api::v2::core::Metadata&) const { | ||
| absl::string_view requested_server_name = connection.requestedServerName(); | ||
| if (!requested_server_name.empty()) { // test for null string_view |
There was a problem hiding this comment.
is this needed? isn't "" a string?
There was a problem hiding this comment.
A couple of tests fail if this isn't in place.
There was a problem hiding this comment.
That's because you only passing the data() to StringMatcher::match, but this is still wrong. string_view doesn't have to be null terminated, so the string you passed in to Matcher could be longer than the string_view.
Can you change StringMatcher::match to take absl::string_view instead? That would avoid a copy too.
This commit adds tests cases to verify the RBAC filter behavior when the configured and a connection's requested server name is non/empty. Signed-off-by: Venil Noronha <veniln@vmware.com>
| const Envoy::Http::HeaderMap&, | ||
| const envoy::api::v2::core::Metadata&) const { | ||
| absl::string_view requested_server_name = connection.requestedServerName(); | ||
| if (!requested_server_name.empty()) { // test for null string_view |
There was a problem hiding this comment.
That's because you only passing the data() to StringMatcher::match, but this is still wrong. string_view doesn't have to be null terminated, so the string you passed in to Matcher could be longer than the string_view.
Can you change StringMatcher::match to take absl::string_view instead? That would avoid a copy too.
This commit updates the StringMatcher implementation to take absl::string_view inputs in place of the previous std::string& input for no-copy matching. Signed-off-by: Venil Noronha <veniln@vmware.com>
mattklein123
left a comment
There was a problem hiding this comment.
LGTM. Mostly comments on comments. @ggreenway can you also take another pass?
| // * A listener filter may overwrite a connection's requested server name | ||
| // within Envoy. | ||
| // | ||
| // Please refer to `this FAQ <https://www.envoyproxy.io/docs/envoy/latest/faq/sni>`_ |
There was a problem hiding this comment.
Instead of using an absolute URL here can you ref link to the faq page?
There was a problem hiding this comment.
Addressed all comments in 0e2ad38.
| // match, this permission would match. | ||
| Permission not_rule = 8; | ||
|
|
||
| // The requested TLS SNI server name from the client's connection request. |
There was a problem hiding this comment.
Per below this is not necessarily TLS SNI. Should it be something like:
"The request server from the client's connection request. This is typically TLS SNI." (Or something like that?)
| // a TLS connection's requested SNI server name will be treated as if it | ||
| // wasn't present. | ||
| // | ||
| // * A listener filter may overwrite a connection's requested server name |
There was a problem hiding this comment.
Link to listener filter arch docs?
| * http: no longer adding whitespace when appending X-Forwarded-For headers. **Warning**: this is not | ||
| compatible with 1.7.0 builds prior to `9d3a4eb4ac44be9f0651fcc7f87ad98c538b01ee <https://github.com/envoyproxy/envoy/pull/3610>`_. | ||
| See `#3611 <https://github.com/envoyproxy/envoy/issues/3611>`_ for details. | ||
| * rbac: added support for :ref:`TLS SNI based <envoy_api_field_config.rbac.v2alpha.Permission.requested_server_name>` permissions. |
There was a problem hiding this comment.
TLS SNI might be too specific per other comment? Make more general/clear?
| }; | ||
|
|
||
| /** | ||
| * Perform a match against the requested TLS SNI server name. |
There was a problem hiding this comment.
Same comment about specificity.
0e2ad38 to
9057cc3
Compare
This commit updates the comments related to the newly introduced requested_server_name configuration to more closely match its behavior. Signed-off-by: Venil Noronha <veniln@vmware.com>
9057cc3 to
5fe6e19
Compare
Description: This PR adds support for SNI based permissions by matching over a
connection's requested server name.
Risk Level: Low
Testing: Added 4 additional tests
Docs Changes: N/A
Release Notes: Added a note about this feature
Fixes #4515