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

Add knobs for allowed modifications in ext_authz and ext_proc #14789

Closed
gbrail opened this issue Jan 22, 2021 · 10 comments
Closed

Add knobs for allowed modifications in ext_authz and ext_proc #14789

gbrail opened this issue Jan 22, 2021 · 10 comments

Comments

@gbrail
Copy link
Contributor

gbrail commented Jan 22, 2021

Title: Add knobs to control which headers ext_authz and ext_proc servers can modify

Description:

Today, the ext_authz filter allows the remote server to request that any header, including internal headers (prefixed with ":"), and x-envoy headers be modified.

The in-progress ext_proc filter does not allow these filters to be modified, but we expect that in some cases users will wish to support this.

We should give both of these filters configurable controls for this. One way would be to create a new enum and use it in the configuration of both filters.

I'd propose an enum with the following modes:

  • DEFAULT: In this mode, headers may not be modified if they are expected to cause problems later that cannot be resolved. That means that no x-envoy header may be set, and a few specific headers such as ":scheme" may not be set. However, other internal headers, including ":path", ":method", ":authority", and "host" may be set. This may cause routes to have to be recalculated, which each filter should account for, ideally without requiring the user to do anything specifically. (i.e. the filter should know that, if ":path" was changed, that the route cache might need refreshing). This will be the default mode of the ext_proc filter.
  • UNRESTRICTED: In this mode, any header may be set, including x-envoy, "host", and any internal headers. This will be the default mode for the ext_authz filter since this is how it works today.
  • RESTRICTED: In this mode, no internal headers may be set, the host header may not be set, and no x-envoy header may be set. This provides the maximum safety for embedding in other products or for multi-tenant environments.

If these three options are not sufficient, then an alternative would be to support a set of booleans like:

  • allow_internal_headers
  • allow_x_envoy_headers
  • allow_host_header

And if THAT is not sufficient then we could allow the user to specify an allow list and a deny list, complete with wildcards. However this might be overly complex.

@gbrail gbrail added enhancement Feature requests. Not bugs or questions. triage Issue requires triage labels Jan 22, 2021
@gbrail
Copy link
Contributor Author

gbrail commented Jan 22, 2021

@alyssawilk @htuch we were discussing this for possible usage of ext_authz in an embedded product.

@gbrail
Copy link
Contributor Author

gbrail commented Jan 22, 2021

Based on some other discussions, we might need another mode, like "DISABLED," which disallows all modifications and just lets the filter only decide whether to accept or reject.

@htuch
Copy link
Member

htuch commented Jan 25, 2021

The bools seem slightly better as they provide mechanism rather than policy, which is preferable in the API.

Arguably, having controls like this would also make sense for dynamic code like Lua/Wasm, since you could control what sandboxed code was capable of. But, if we design this right, and don't make the proto message restricted to ext_*, that can always be added later.

@alyssawilk
Copy link
Contributor

As said on email earlier, I think this would be useful in a number of places. If we do booleans let's encapsulate in a base level proto so we can apply it to other places we do header modifications. I could imagine a cloud provider tacking on "no changing host" rules to ensure that client xDS config didn't change disallowed fields for per-route config for example.

Since I think bools are false by default, I'd be inclined to flip semantics and have
disallow_thing_a
disallow_thing_b
so by default everything is allowed and you filter by flipping explicit config, but you can also use Boolean and allow_thing.

cc @lizan and @PiotrSikora for wasm and @markdroth for gRPC thoughts (e.g. x-envoy: does gRPC have an equivalent?)

For naming, :scheme :method etc. are pseudo-headers (https://tools.ietf.org/html/rfc7540#section-8.1.2.1 : I think what you were calling internal?) and we should comment it also applies to http/1.1 equivalents like host:

For x-envoy there's the header_prefix knob in Envoy bootstrap that lets Envoy change its prefix from x-envoy to x-foo so we'd want to make sure we comment and sanitize based on the actual header prefix if it's not the default:
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/bootstrap/v3/bootstrap.proto#envoy-v3-api-msg-config-bootstrap-v3-bootstrap

@PiotrSikora
Copy link
Contributor

See parameter sanitization in Proxy-Wasm capabilities (#13911).

@markdroth
Copy link
Contributor

@alyssawilk gRPC does not have its own equivalent of x-envoy headers; we generally have APIs for the application to configure things instead. Although interestingly, as part of the xDS support we're adding, there are some cases where we're going to support some x-envoy headers for compatibility with Envoy. :/

Is the idea here that these knobs would be defined in some sort of wrapper that can be applied to any filter? How can the settings of these knobs be enforced that way? Or is the idea that we'd need each individual filter to support these knobs as appropriate?

CC @ejona86 @dfawley

@alyssawilk
Copy link
Contributor

My mental model was we'd have a proto of "what is disallowed" (everything being allowed by default) and different areas of the code base could add it over time to things like request_headers_to_add, or ext_proc. There'd be a utility which took in that proto (or parsed config) and applied the checks, and that'd be added to sites with the API additions.
Totally open to options if there's a model which works better for grpc. For example rather than x-envoy header we could do a generic "no headers with this prefix" and use x-envoy in the examples.

@mattklein123 mattklein123 added area/ext_authz area/ext_proc help wanted Needs help! and removed enhancement Feature requests. Not bugs or questions. triage Issue requires triage labels Jan 31, 2021
@antoniovicente
Copy link
Contributor

It may be useful to add some controls that specify what should be done if the external filter attempts to modify a disallowed header. Some options include:

  1. emit some logging or stats
  2. ignore the disallowed modifications
  3. error out the request

@gbrail
Copy link
Contributor Author

gbrail commented Nov 30, 2021

Check out #19141 which adds a proto to start to address this issue

htuch pushed a commit that referenced this issue Jan 7, 2022
This protobuf will be used initialy by the ext_proc filter to control
which headers may be changed by an external processing server.

This begins to address #14789 .

If the proto and the location are OK, I'll go on to add a common library to test a proposed header mutation against these rules and then incorporate them into the ext_proc filter.

The eventual result is that, by default, an external processor for ext_proc will be able to modify any header, but there will be controls that an administrator can use when connecting to a processor to control whether that processor is actually allowed to make all possible changes.

Risk Level: Low -- just the proto for now

Signed-off-by: Gregory Brail <[email protected]>
@gbrail
Copy link
Contributor Author

gbrail commented Jan 29, 2022

As of #19622, this has now been merged to main and is supported. See the new "mutation_rules" field in the filter configuration.

@gbrail gbrail closed this as completed Jan 29, 2022
joshperry pushed a commit to joshperry/envoy that referenced this issue Feb 13, 2022
This protobuf will be used initialy by the ext_proc filter to control
which headers may be changed by an external processing server.

This begins to address envoyproxy#14789 .

If the proto and the location are OK, I'll go on to add a common library to test a proposed header mutation against these rules and then incorporate them into the ext_proc filter.

The eventual result is that, by default, an external processor for ext_proc will be able to modify any header, but there will be controls that an administrator can use when connecting to a processor to control whether that processor is actually allowed to make all possible changes.

Risk Level: Low -- just the proto for now

Signed-off-by: Gregory Brail <[email protected]>
Signed-off-by: Josh Perry <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants