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

api: add field to allow clients to ignore unknown HTTP filters #14982

Merged
merged 6 commits into from Feb 11, 2021

Conversation

markdroth
Copy link
Contributor

Signed-off-by: Mark D. Roth roth@google.com

Commit Message: api: add field to allow clients to ignore unknown HTTP filters
Additional Description: This allows control planes to tell clients that a given HTTP filter is okay to ignore if it is not supported. This is useful in environments where the clients are not centrally controlled and therefore cannot be upgraded at will, where it is desirable to start using a new filter for clients that do support the new filter without breaking older clients. Unlike a client-capability-based approach, where the client tells the server which filters it supports, this avoids cache pollution and resource-name-based complexity on the server. And because the control plane can set this on a per-filter basis, this approach does not impose risk that clients will silently fail to apply filters that provide mandatory functionality (e.g., authz policies).
Risk Level: Low
Testing: N/A (actual functionality will be implemented in a subsequent PR)
Docs Changes: Included in PR
Release Notes: N/A
Platform Specific Features: N/A

CC @htuch @ejona86 @dfawley @lidizheng @dapengzhang0

Signed-off-by: Mark D. Roth <roth@google.com>
@repokitteh-read-only
Copy link

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

🐱

Caused by: #14982 was opened by markdroth.

see: more, trace.

@@ -816,7 +816,7 @@ message ScopedRds {
[(validate.rules).message = {required: true}];
}

// [#next-free-field: 6]
// [#next-free-field: 7]
message HttpFilter {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not specific to gRPC: Should we also add this "optional" functionality to upstream filters in cluster? Then if one day Envoy decided to implement this feature, they will have all proto changes needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In general, I think it would be useful to do this for all types of filters (also including L4 filters and listener filters). But right now, we are primarily concerned about HTTP filters, so let's focus this PR on that functionality.

Signed-off-by: Mark D. Roth <roth@google.com>
Signed-off-by: Mark D. Roth <roth@google.com>
Signed-off-by: Mark D. Roth <roth@google.com>
…tional

Signed-off-by: Mark D. Roth <roth@google.com>
Copy link
Contributor

@antoniovicente antoniovicente left a comment

Choose a reason for hiding this comment

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

cc @htuch @lizan

Tagging other api-shepherds since Matt is on paternity leave.

// [#not-implemented-hide:]
message OptionalFilterConfig {
google.protobuf.Any config = 1;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this wrapper needed? Setting is_optional=true ought to disable parsing of config for filters that are optional and not build into the binary. It should be possible to ignore this config without wrapping it in an extra layer of messages.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem is that at the time that we receive the RouteConfiguration from RDS, we don't necessarily know which HCM config it's going to be matched up with, because there could be a new LDS response waiting to be swapped in, so we can't depend on the is_optional=true that was set there. See my comment in #12274 for details.

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 think this is unavoidable given the nature of xDS resource independence.

// filter but otherwise accept the config.
// Otherwise, clients that do not support this filter must reject the config.
// [#not-implemented-hide:]
bool is_optional = 6;
Copy link
Contributor

Choose a reason for hiding this comment

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

What does the rest of the implementation look like? Is there a natural place to ignore the config for optional filters that are not built into the binary?

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 said this probably wouldn't be hard to implement.

I'm guessing that we'll do it when validating the LDS response. Presumably, that's the point at which we're checking that we have a filter registered for the type of the config in the typed_config field, and we'll NACK the config if we don't have one. The purpose of the is_optional field is to have that check ignore the filter instead of NACKing the config.

// to indicate that the filter is optional. In this case, if the client does not support the filter,
// it may ignore the map entry rather than rejecting the config.
// [#not-implemented-hide:]
message OptionalFilterConfig {
Copy link
Member

Choose a reason for hiding this comment

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

A downside of this wrapper is that it adds exactly one feature, and leaves no room for future expansion. If we need another feature in the future, we'll need two levels of wrapping. (Actually, we already do have another level of wrapping in the TypedStruct feature.)

Instead of this limited-purpose wrapper, maybe we should have one that holds all future expandability instead?

message FilterConfig {
  oneof config_type {
    proto.Any typed_config = 1;  // Would never contain a TypedStruct
    udpa.type.v1.TypedStruct struct_config = 2;
    config.core.v3.ExtensionConfigSource config_discovery = 3; // ? (from HttpFilter)
  }
  bool optional = 4;
  // room for future expansion
}

Also, optionally & more invasively, we could update HttpFilter to deprecate config_type and reference this new FilterConfig message to unify things further.

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 like the idea of making this more general-purpose so that we can add additional per-filter options later! Done.

I didn't include the TypedStruct field, because I think the established way of dealing with TypedStruct in xDS is to embed it inside of an Any field, since that makes the JSON representation more natural.

I also didn't include the ExtensionConfigSource field, since I don't see any existing option for using ECDS here in the typed_per_filter_config fields. I suspect the two are mutually exclusive, but @htuch can confirm.

Signed-off-by: Mark D. Roth <roth@google.com>
@htuch
Copy link
Member

htuch commented Feb 10, 2021

LGTM. @lizan can you provide a non-Google API review here, want to sanity check we're not over-fitting to Google needs?

@htuch htuch assigned lizan and unassigned mattklein123 Feb 10, 2021
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.

None yet

7 participants