Skip to content

rbac: add support for upstream ip policy.#17645

Merged
mattklein123 merged 78 commits intoenvoyproxy:mainfrom
conqerAtapple:rbac-upstream-dynamic-proxy
Sep 29, 2021
Merged

rbac: add support for upstream ip policy.#17645
mattklein123 merged 78 commits intoenvoyproxy:mainfrom
conqerAtapple:rbac-upstream-dynamic-proxy

Conversation

@conqerAtapple
Copy link
Contributor

@conqerAtapple conqerAtapple commented Aug 9, 2021

Based on the dicsussion in the issue #17410, this PR adds
implementation for ability to add rbac policy to filter upstream ip addresses for dynamically
resolved domains (by dynamic proxy filter).

risk: Medium
testing: Manual testing
api: added upstream_ip to RBAC::Policy::Permission

Signed-off-by: Jojy G Varghese jojy_varghese@apple.com

Commit Message:
Additional Description:
Risk Level:
Testing:
Docs Changes:
Release Notes:
Platform Specific Features:
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Deprecated:]
[Optional API Considerations:]

@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to api/envoy/.
envoyproxy/api-shepherds assignee is @htuch
CC @envoyproxy/api-watchers: FYI only for changes made to api/envoy/.

🐱

Caused by: #17645 was opened by conqerAtapple.

see: more, trace.

@conqerAtapple
Copy link
Contributor Author

PTAL @alyssawilk @htuch @yangminzhu.

Copy link
Contributor

@yangminzhu yangminzhu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I think this should at least be covered in unit tests (preferably also in integration tests), could you add some tests?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder should we add a generic filter state matcher (similar to the dynamic metadata matcher) so that it can support other use cases in the future without the need to change the rbac API everytime?

cc @htuch for API review

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be 13?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@conqerAtapple
Copy link
Contributor Author

Also I think this should at least be covered in unit tests (preferably also in integration tests), could you add some tests?

Thanks for looking :). Wanted to have a first pass to make sure that the changes are ok in general before I add tests.

@conqerAtapple conqerAtapple force-pushed the rbac-upstream-dynamic-proxy branch from 4ef7357 to 357904d Compare August 12, 2021 00:57
Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some API comments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain in the documentation here what the resolution semantics are? What happens if there is a change in resolution during processing? What is the v4/v6 story? etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@htuch
Copy link
Member

htuch commented Aug 12, 2021

Tagging @alyssawilk (dynamic forward DNS) @lizan (RBAC) for implementation review.

@conqerAtapple
Copy link
Contributor Author

@htuch thanks for reviewing the PR.

Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks solid at a high level - let's add unit tests and an integration test to make sure it all hangs together!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd actually like @mattklein123 's thoughts on this.
I'd mildly prefer to have rbac just look up the ip:host mapping to copying it all into stream info for every request, but that'd be a hard dep on the dynamic proxy code which may be worse in the long run.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it were up to me I would probably leave this as is, but config guard tracking this in filter state to avoid the perf hit for people that don't care.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the right thing to do here to add the address, or replace the address?
I'd think if we did recreateStream (internal redirect) we'd want to remove old addresses rather than append to them, to make sure we only had the addresses we wanted to use

Copy link
Contributor Author

@conqerAtapple conqerAtapple Aug 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we should add a clear API so that the caller can then call clear and add? Or is it better to replace the set with a single address? The idea here is to have a set of resolved addresses for the upstream and if any of them match.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I think in the long run we're going to want to support multiple addresses, but also handle recreateStream, so either overwrite an existing set, or clear it and add new data.
(if that doesn't make sense please ping me on slack)

@conqerAtapple
Copy link
Contributor Author

@alyssawilk thanks for reviewing. I have resolved most of the suggestions and comments. There is still some questions which I do not have clear answers for. Would appreciate your input.

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm api

Comment on lines 222 to 227
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit hesitate to add a field to support an extension while dfp might be an exception here. Though shouldn't this be an example that we should have an upstream HTTP filter for RBAC? while I know the current upstream filter doesn't support this yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that this could be solved with a upstream filter. As discussed in the issue, this is a DFP specific targeted changed to solve a particular use case. We probably need to revisit this when upstream filters are more powerful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @lizan for reviewing

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sounds reasonable for now. Shall we name the field more explicitly, or do we expect other filter might set that filter state as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lizan I think the construct could be used in a general context when we have upstream filters in their full form. When we generalize the RBAC policy to act on ANY of the upstream ip addresses, I think the address set could be the source of truth for it. WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'm not crazy about this hard coding either which is effectively going to live forever. I have a vague idea that I'm going to throw out there that we might want to explore.

What if we had some type of generic matcher extension mechanism. Basically this becomes a typed_extension_config. One of the things the extension matcher gets access to when it matches is filter state. The config for the typed extension can be whatever it wants including a string name, hard coded, etc. (If you upstream the extension it needs to be more generic but if you just have an internal extension you can hard code it all.)

@alyssawilk
Copy link
Contributor

mind checking out the coverage fail? Looks like it's legit and this is missing some unit testing.
/wait

@conqerAtapple
Copy link
Contributor Author

mind checking out the coverage fail? Looks like it's legit and this is missing some unit testing.
/wait

Will add unit + integration tests.

@conqerAtapple
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #17645 (comment) was created by @conqerAtapple.

see: more, trace.

@mattklein123 mattklein123 self-assigned this Aug 19, 2021
Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the improved testing! Here's some follow up thoughts

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

javadoc comments for envoy/ functions if you leave them here

Alternately looking at another example filterSate object we just use the impl everywhere and don't have an abstract base class. I think that'd be fine here too, especially if we add a key() function so all the files using the class have to include the Impl anyway

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like in at least one other use case, the Filterstate::Object had
static const std::string& key();

which is nice because then only components who care about that object pull that key. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would ENVOY_LOG_TO_LOGGER(Envoy::Logger::Registry::getLog(Envoy::Logger::Id::rbac) work over the MISC logger macro?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I think in the long run we're going to want to support multiple addresses, but also handle recreateStream, so either overwrite an existing set, or clear it and add new data.
(if that doesn't make sense please ping me on slack)

Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
@conqerAtapple
Copy link
Contributor Author

@htuch @mattklein123 I have added port as additional matching parameter in the matcher. Also, removed the upstream ip set.

htuch
htuch previously requested changes Sep 26, 2021
Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API LGTM modulo nit. Thanks!

Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
@conqerAtapple
Copy link
Contributor Author

@mattklein123 @htuch @alyssawilk @ggreenway I think this PR should be ready now. I am not sure why the dependency CI checks are failing.

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

/lgtm api

@ggreenway
Copy link
Member

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #17645 (comment) was created by @ggreenway.

see: more, trace.

Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks LGTM with small remaining comments.

/wait


"envoy.rbac.matchers.upstream_ip": "//source/extensions/filters/common/rbac/matchers:upstream_ip_lib",
"envoy.rbac.matchers.upstream_ip_port": "//source/extensions/filters/common/rbac/matchers:upstream_ip_port_lib",
"envoy.rbac.matchers.upstream_port": "//source/extensions/filters/common/rbac/matchers:upstream_port_lib",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to get removed? Or is this staying to match on ports only? Would it be better to just have a single matcher and allow address to be optional and if so any address will match? So basically either port, address, or both need to be set?

Copy link
Contributor Author

@conqerAtapple conqerAtapple Sep 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mattklein123 .
I can see how having both could be confusing but I have kept the ip-port matcher to qualify IP with Port for matching IP & Port (if provided). Wanted to keep Port matcher separate so that a) be independent (no dependency on IP) b) Have IP as first class citizen of the IP-Port matcher a Port as an added qualifier.

Please let me know if that makes sense.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really follow. You have port optional in one of them. Why can't address be optional? Logically then shouldn't you have an address only matcher? I would remove the dedicated port matcher and just make a single matcher that requires either to be set or both.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hoping that we can avoid configurations where neither IP or Port are provided.

Will change to combine the matchers 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just reject that case in code and I think that will turn out great, thank you.

Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
@alyssawilk
Copy link
Contributor

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #17645 (comment) was created by @alyssawilk.

see: more, trace.

Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there, thanks!

/wait

- Added configuration check.

Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/wait

UpstreamIpPortMatcher::UpstreamIpPortMatcher(
const envoy::extensions::rbac::matchers::upstream_ip_port::v3::UpstreamIpPortMatcher& proto) {
if (!proto.has_upstream_ip() && !proto.has_upstream_port_range()) {
throw EnvoyException("Invalid UpstreamIpPortMatcher configuration - missing `upstream_ip` and "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw EnvoyException("Invalid UpstreamIpPortMatcher configuration - missing `upstream_ip` and "
throw EnvoyException("Invalid UpstreamIpPortMatcher configuration - missing `upstream_ip` and/or "

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, update the docs to make it more clear that one or both are required (I already mentioned this), thanks.

Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/wait

Comment on lines +19 to +20
// Note that although both fields are optional, an exception will be thrown during configuration
// load time if none of the fields are provided.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Users don't care about exceptions)

Suggested change
// Note that although both fields are optional, an exception will be thrown during configuration
// load time if none of the fields are provided.
// Note that although both fields are optional, at least one of IP or port must be supplied. If only one is supplied the other is a wildcard match.

Signed-off-by: Jojy George Varghese <jojy_varghese@apple.com>
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thanks!

Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your patience slogging through this - looks great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deps Approval required for changes to Envoy's external dependencies

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants