Skip to content
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

router: Create InternalRedirectPolicy in side RouteAction and extend it with pluggable predicates #10908

Merged

Conversation

penguingao
Copy link
Contributor

@penguingao penguingao commented Apr 22, 2020

Description: router: Create InternalRedirectPolicy to capture all internal redirect related options and extend it with pluggable predicates similar to retry plugins. The previous_routes and whitelisted_routes predicate allow creating a DAG of routes for internal redirects. Each node in the DAG is a route. whitelisted_routes defines the edges of each node. previous_routes serves as visited status keeper for each of the edge. This prevents infinite loop, while allowing loop to exist in the DAG.
Risk Level: Medium
Testing: Unit tests. Integration tests.
Docs Changes: Updated HCM architecture overview page. Added toctree for the predicates.
Release Notes: Updated version history.

pluggable predicates.

Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to api/.

🐱

Caused by: #10908 was opened by penguingao.

see: more, trace.

@penguingao
Copy link
Contributor Author

/assign @alyssawilk

Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
@penguingao
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

🔨 rebuilding ci/circleci: coverage (failed build)
🔨 rebuilding ci/circleci: api (failed build)
🔨 rebuilding ci/circleci: go_control_plane_mirror (failed build)
🔨 rebuilding ci/circleci: docs (failed build)

🐱

Caused by: a #10908 (comment) was created by @penguingao.

see: more, trace.

@penguingao
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

🔨 rebuilding ci/circleci: go_control_plane_mirror (failed build)
🔨 rebuilding ci/circleci: docs (failed build)
🔨 rebuilding ci/circleci: coverage (failed build)
🔨 rebuilding ci/circleci: api (failed build)

🐱

Caused by: a #10908 (comment) was created by @penguingao.

see: more, trace.

@penguingao
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

🔨 rebuilding ci/circleci: go_control_plane_mirror (failed build)
🔨 rebuilding ci/circleci: api (failed build)
🔨 rebuilding ci/circleci: docs (failed build)
🔨 rebuilding ci/circleci: coverage (failed build)

🐱

Caused by: a #10908 (comment) was created by @penguingao.

see: more, trace.

Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
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 looks reasonable, a few comments..

api/envoy/config/route/v3/route_components.proto Outdated Show resolved Hide resolved

// HTTP scheme combinations that are allowed to be handled as internal
// redirect. Downstream scheme comes first and redirect target URL scheme
// follows.
Copy link
Member

Choose a reason for hiding this comment

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

This seems pretty strange to be including the target URL scheme; why isn't is sufficient to include just the downstream?

For that matter, why do we even need this, given that the route match that leads to the redirect itself has a scheme matcher?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was from the preexisting behavior: it allows a HTTP downstream to be redirected to only HTTP targets; it allows HTTPS downstream to be redirected to any targets.

My understanding is that, if an origin redirect an HTTP request to an HTTPS target, there is a chance that the origin would like to move the downstream to a secure transport for sensitive payload.

While this is not always the case, certainly not our use case, I decided to make this configurable but preserving the existing behavior.

By "scheme matcher" did you mean VirtualHost. require_tls?

Copy link
Contributor

Choose a reason for hiding this comment

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

Scheme seems an odd one here IMO.
upstream scheme is generally just based on "is the connection to upstream secure or not"
I think in general we want to make sure that x-forwarded-proto matches the scheme of the redirect URI. If we want to say we only redirect https:// requests or http:// requests that'd be the request x-forwarded-proto header not scheme

Copy link
Contributor Author

@penguingao penguingao Apr 28, 2020

Choose a reason for hiding this comment

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

Ah, thanks @alyssawilk and @htuch!

I think I had misunderstood the purpose of the existing check on x-forwarded-proto vs redirect URI scheme. Our use case led me to think about the redirect URL more as a way to define the desired upstream for a request, but the redirect URL should really be treated purely as a property of the downstream, which makes the existing check make perfect sense, and indeed makes the scheme option here very odd. In other words, Upstream's scheme is completely orthogonal to what the downstream's scheme is.

I'll remove this option completely.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is now done. I removed this option.

I added an option to allow cross scheme redirect - I think this should be fine since as @hutch said, there are scheme match in routes, we can selectively allow certain route to be redirected to, across scheme boundary if we know this is safe.

Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
…-more-options

Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
behavior change is documented in the release note.

Signed-off-by: pengg <pengg@google.com>
Signed-off-by: pengg <pengg@google.com>
@penguingao
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

🔨 rebuilding ci/circleci: coverage (failed build)

🐱

Caused by: a #10908 (comment) was created by @penguingao.

see: more, trace.

Signed-off-by: pengg <pengg@google.com>
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.

Almost there!

repeated google.protobuf.Any predicates = 3;

// Disallow internal redirect to follow a target URI with a different scheme than the value of
// x-forwarded-proto. Default behavior is to follow such redirects.
Copy link
Contributor

Choose a reason for hiding this comment

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

Ugh, sorry I didn't comment earlier, but I don't think I like the default behavior being IMO sketchy (forwarding https content over http connections)
How about we either switch the default (last time I swear!) which means the behavioral change between the old and the new is the new is more strict, and folks can flip it and apply your predicate if they want old behavior?

* router: internal redirect configs are moved to the :ref`internal_redirect_policy
<envoy_api_field_router.RouterAction.internal_redirect_policy>` field, which defines more fine
grained control of the internal redirect behavior. This changes the default cross scheme redirect behavior.
All cross scheme redirect is allowed by default, but http downstream to https target is disallowed. To restore
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you also need to doc up the deprecated field in the Deprecated section and maybe move comments on how to preserve behavior there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@penguingao
Copy link
Contributor Author

It looks like I ran into windows 259 path length limit with the long predicate name.

windows path length limitation.

Change default behavior to be disallowing cross scheme redirect. Rename
the option to allow_cross_scheme (default to false).

Update tests.

Document implemeneted default behavior change.

Signed-off-by: pengg <pengg@google.com>
@penguingao
Copy link
Contributor Author

I renamed the predicate with a shorter name to get around window bazel path length limit as well. Thanks!

@alyssawilk
Copy link
Contributor

cc @wrowe anything we can do about the path limits? Given the directory names are fairly long I'm hoping we can find a workaround to not have to reduce readability

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.

LGTM modulo a few tiny nits. Huzzah!

api/envoy/config/route/v3/route_components.proto Outdated Show resolved Hide resolved
include/envoy/router/internal_redirect.h Show resolved Hide resolved
source/common/router/router.cc Outdated Show resolved Hide resolved
AllowListed -> Allow listed.

Signed-off-by: pengg <pengg@google.com>
Copy link
Contributor Author

@penguingao penguingao left a comment

Choose a reason for hiding this comment

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

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.

@mattklein123 or @htuch for final API changes?

@mattklein123 mattklein123 self-assigned this May 13, 2020
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.

API LGTM!

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

@alyssawilk alyssawilk merged commit 1ce0109 into envoyproxy:master May 14, 2020
@penguingao penguingao deleted the internal-redirect-more-options branch May 14, 2020 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants