Skip to content

http: check virtual host-specific typed per filter config#15135

Merged
htuch merged 6 commits intoenvoyproxy:mainfrom
soulxu:check_unsupported_per_filter_config
Mar 2, 2021
Merged

http: check virtual host-specific typed per filter config#15135
htuch merged 6 commits intoenvoyproxy:mainfrom
soulxu:check_unsupported_per_filter_config

Conversation

@soulxu
Copy link
Copy Markdown
Member

@soulxu soulxu commented Feb 22, 2021

Commit Message: http: check virtual host-specific typed per filter config
Additional Description:
When filter doesn't support virtual host-specific typed per filter config,
the envoy should reject any per filter config for that filter.

Also, adds new runtime config envoy.reloadable_features.check_unsupported_typed_per_filter_config
for backward-compatible. The default value is true, only when the value is true,
the check will be executed.

Risk Level: low
Testing: unit test added
Docs Changes: n/a
Release Notes: note new feature
Runtime guard: envoy.reloadable_features.check_unsupported_typed_per_filter_config
Fixes #15043

Signed-off-by: He Jie Xu hejie.xu@intel.com

When filter doesn't support virtual host-specific typed per filter config,
the envoy should reject any per filter config for that filter.

Also, adds new runtime config `envoy.reloadable_features.check_unsupported_typed_per_filter_config`
for backward-compatible. The default value is false, only whe value is true,
the check will be executed.

Risk Level: low
Testing: unit tests added
Doc Changes: n/a
Release Notes: note new feature

Signed-off-by: He Jie Xu <hejie.xu@intel.com>
@repokitteh-read-only
Copy link
Copy Markdown

Hi @soulxu, welcome and thank you for your contribution.

We will try to review your Pull Request as quickly as possible.

In the meantime, please take a look at the contribution guidelines if you have not done so already.

🐱

Caused by: #15135 was opened by soulxu.

see: more, trace.

Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Copy link
Copy Markdown
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.

Welcome to Envoy and thanks for the improvement to config validation. I'm not that familiar with all the interactions between config components and object factories, so hopefully @htuch can help fill in my gaps in understanding.

# processing.
EXCEPTION_ALLOWLIST = ("./source/common/config/utility.h")
EXCEPTION_ALLOWLIST = ("./source/common/config/utility.h",
"./source/extensions/filters/http/common/factory_base.h")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@ahedberg @htuch

We may have some problems here depending on the intent behind this check. It seems to me that headers in this list may need to be restricted so they are not included from other headers in other to prevent multiple definitions in builds that partially disable exceptions at a per-library basis. That said, there seems to be no restrictions in place that control where source/common/config/utility.h is included from or the use of those functions in header files.

This PR introduces an exception that is thrown from a base class method of a class that seems to be widely used. I think this change could break compilation of libraries that disable exceptions.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Another option is we can fix it here

for (const auto& it : typed_configs) {
// TODO(zuercher): canonicalization may be removed when deprecated filter names are removed
const auto& name =
Extensions::HttpFilters::Common::FilterNameUtil::canonicalFilterName(it.first);
auto object = createRouteSpecificFilterConfig(
name, it.second, ProtobufWkt::Struct::default_instance(), factory_context, validator);
if (object != nullptr) {
configs_[name] = std::move(object);
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we decide to have createRouteSpecificFilterConfigTyped throw an exception, the throw statement should be in the .cc file instead of the .h file. Then we don't need to add it to the exception allowlist.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FactoryBase is a template class, the throw can't be moved to a cc file (well, except possibly by adding a helper function)

Returning null and doing the validation in config_impl.cc seems attractive. Is that the only place where this factory method is called from?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Returning null and doing the validation in config_impl.cc seems attractive. Is that the only place where this factory method is called from?

Yes, that is the only place I found at least.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think config_impl.cc is more robust in any case, since regardless of inheritance hierarchy, if there is no config, we can fire the exception.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It would be really helpful to some of us if exceptions were only thrown from cc files. Could you do the new config validation in config_impl.cc instead of the template factory class?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, I will update, thanks for the feedback!

// Sentinel and test flag.
"envoy.reloadable_features.test_feature_false",
// Reject virtual host-specific configuration when filter doesn't support it.
"envoy.reloadable_features.check_unsupported_typed_per_filter_config",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

My understanding is that runtime features should default to true. They provide a way for devs affected by a breaking change to temporarily rollback the behavior. Once we have given time to find and address all the breakages, we'll remove the runtime feature checks and only keep the new behavior.

Out of curiosity, are there any existing tests that fail when this runtime feature is enabled?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

My understanding is that runtime features should default to true. They provide a way for devs affected by a breaking change to temporarily rollback the behavior. Once we have given time to find and address all the breakages, we'll remove the runtime feature checks and only keep the new behavior.

As https://github.com/envoyproxy/envoy/issues/15043#issuecomment-778703531 said, I thought we should set ti as false default, then it won't break existing user. But I may miss understanding that.

Out of curiosity, are there any existing tests that fail when this runtime feature is enabled?

I tested with the default value is true. In my env, only get one test failed 'IoSocketHandleImplIntegration.LastRoundTripIntegrationTest', I don't think it is related.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

cc @htuch

Having the runtime flag so affected devs can disable the functionality while they fixed their config should be enough. I think that the default should be true.

And I agree that the 'IoSocketHandleImplIntegration.LastRoundTripIntegrationTest' failure is not related to this change. That's a non-hermetic test that does network communication. I think I'll file an issue about it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think default true is fine, as long as we have the runtime for now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

cc @htuch

Having the runtime flag so affected devs can disable the functionality while they fixed their config should be enough. I think that the default should be true.

And I agree that the 'IoSocketHandleImplIntegration.LastRoundTripIntegrationTest' failure is not related to this change. That's a non-hermetic test that does network communication. I think I'll file an issue about it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

let me change the default value as true, thanks.

ProtobufTypes::MessagePtr config = factory.createEmptyRouteConfigProto();

EXPECT_EQ(nullptr, factory.createRouteSpecificFilterConfig(
*config, context, ProtobufMessage::getNullValidationVisitor()));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It would be good to have some e2e integration tests that cover this functionality. I don't know exactly what existing types would fail config load if you tried to provide per-route config for them. It seems that Envoy::Extensions::HttpFilters::HealthCheck::HealthCheckFilterConfig doesn't implement an override for createRouteSpecificFilterConfigTyped, perhaps that is a good extension to write a test against?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yea, HealthCheckFilterConfig doesn't implement override, let me add integration tests.

"The filter {} doesn't support virtual host-specific configurations. Set runtime "
"config `envoy.reloadable_features.check_unsupported_typed_per_filter_config` as "
"true to reject any invalid virtual-host specific configuration.",
name())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The continuous integration test run detected a build breakage on this line due to missing ; at the end of the line.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

thanks

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

/wait

Build still looks broken. Did you implement a fix but didn't "git push" it out?

Copy link
Copy Markdown
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 for taking this on!

// Sentinel and test flag.
"envoy.reloadable_features.test_feature_false",
// Reject virtual host-specific configuration when filter doesn't support it.
"envoy.reloadable_features.check_unsupported_typed_per_filter_config",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think default true is fine, as long as we have the runtime for now.

# processing.
EXCEPTION_ALLOWLIST = ("./source/common/config/utility.h")
EXCEPTION_ALLOWLIST = ("./source/common/config/utility.h",
"./source/extensions/filters/http/common/factory_base.h")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think config_impl.cc is more robust in any case, since regardless of inheritance hierarchy, if there is no config, we can fire the exception.

@htuch
Copy link
Copy Markdown
Member

htuch commented Feb 24, 2021

@markdroth does this match your intended behavior?

@markdroth
Copy link
Copy Markdown
Contributor

Yes, this looks right to me. Thanks for doing this!

Signed-off-by: He Jie Xu <hejie.xu@intel.com>
@antoniovicente
Copy link
Copy Markdown
Contributor

/wait

Please look into the build breakages.

@soulxu
Copy link
Copy Markdown
Member Author

soulxu commented Mar 2, 2021

thanks for all the review! let me work on the update.

soulxu added 2 commits March 2, 2021 10:20
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Copy link
Copy Markdown
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, thanks!

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.

api: Envoy should NACK typed_per_filter_config entries for filters that don't support override configs

6 participants