-
Notifications
You must be signed in to change notification settings - Fork 1k
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
feat: New ksql.properties.overrides.denylist to deny clients configs overrides #5877
Conversation
ksqldb-common/src/test/java/io/confluent/ksql/properties/DenyListPropertyValidatorTest.java
Outdated
Show resolved
Hide resolved
@@ -214,15 +219,21 @@ private EndpointResponse handleStatement( | |||
statement.getStatement()) | |||
); | |||
|
|||
final Map<String, Object> requestProperties = request.getRequestProperties(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems weird to need to do this validation at each endpoint, what if we add another one in the future? is there a place in the engine we can do this validation in one place that would work for all endpoints?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's hard to find a good place for this. I initially wanted the validation to happen inside the getRequestProperties
, but I need a KsqlConfig
inside the request which is created by the Vert.x endpoint code. Will require some refactoring just to pass the KsqlConfig.
I looked doing it in the engine.execute(), but it's risky too if the request properties are obtained before calling the execute. See the below code as an example:
final KsqlEntityList entities = handler.execute(
securityContext,
statements,
new SessionProperties(
configProperties,
localHost,
localUrl,
requestConfig.getBoolean(KsqlRequestConfig.KSQL_REQUEST_INTERNAL_REQUEST)
)
);
The requestConfig.getBoolean(KsqlRequestConfig.KSQL_REQUEST_INTERNAL_REQUEST)
won't be validated if we do the properties validation inside the Engine. If we encapsulate it in the Engine, then developers won't know there is some validation done inside. Here at least, if someone looks at the endpoint to add another endpoint, they could see there is some validation to do in the properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The engine is littered with code that passes the KsqlConfig ksqlConfig
and Map<String, ?> overrides
pair around. I think the overrides is now mostly being correctly applied before the config is used... but... it's pretty ugly and unclear if the config you've got has overrides or not.
I've thought for a while that it would be much cleaner to have:
KsqlConfig
which is always the server config.SessionConfig
which wraps aKsqlConfig
and a map of overrides.
Headless mode just has a single session, where as each user request can build its own SessionConfig and pass this around, rather than the two params.
Ideally, the engine would take SessionConfig
, not KsqlConfig
. SessionConfig
can have a very similar / same interface as KsqlConfig
.
The SessionConfig
constructor, which takes the server's KsqlConfig
and the map of overrides can then validate the overrides, i.e. only one place for override validation.
The SessionConfig
would allow access to the serverConfig
, then overrides
and then 'mergedConfig`. Different parts of the code need each of these, if memory serves me right.
Of course, this is a much bigger change. Simple, but wide ranging. However, I wonder if this PR could start us down this road (Assuming we agree it's a good idea). For example, this PR could add the SessionConfig
class, and pass this around in the rest-server model, before converting to a KsqlConfig
that's passed to the engine. If you want to also switch the engine to use SessionConfig
, then awesome - but maybe in follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I addressed the rest of the feedback except this. I found there is an existing SessionProperties
that is passed to the KsqlEngine
to execute the request and we could use it. I will create a Builder for it that accepts the DenyListPropertyValidator on its constructor, and then build the SessionProperties
on every request. The build
will fail if the request contains overrides that are prohibited.
I will added in a another commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@big-andy-coates I'd like to do this change in a follow-up PR to close this deny list task. The SessionProperties is only supported in the KsqlResource, and I need changes in the StreamedQueryResource and WSQueryEndpoint and other internal methods, so better doing it as a different patch.
If you're good with this current PR, could you approve it?
2a6e624
to
d4e555d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this idea @spena. I think it'll be very useful.
Couple of suggestions below.
ksqldb-common/src/main/java/io/confluent/ksql/properties/DenyListPropertyValidator.java
Outdated
Show resolved
Hide resolved
@@ -316,6 +316,12 @@ | |||
.put(KSQL_STREAMS_PREFIX + StreamsConfig.MAX_TASK_IDLE_MS_CONFIG, 500L) | |||
.build(); | |||
|
|||
public static final String KSQL_PROPERTIES_OVERRIDES_DENYLIST = | |||
"ksql.properties.overrides.denylist"; | |||
public static final String KSQL_PROPERTIES_OVERRIDES_DENYLIST_DEFAULT = ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this can be inlined. It isn't referenced from else where.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
ksqldb-common/src/main/java/io/confluent/ksql/util/KsqlConfig.java
Outdated
Show resolved
Hide resolved
ksqldb-common/src/test/java/io/confluent/ksql/properties/DenyListPropertyValidatorTest.java
Outdated
Show resolved
Hide resolved
ksqldb-rest-app/src/main/java/io/confluent/ksql/rest/server/resources/KsqlResource.java
Outdated
Show resolved
Hide resolved
@@ -214,15 +219,21 @@ private EndpointResponse handleStatement( | |||
statement.getStatement()) | |||
); | |||
|
|||
final Map<String, Object> requestProperties = request.getRequestProperties(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The engine is littered with code that passes the KsqlConfig ksqlConfig
and Map<String, ?> overrides
pair around. I think the overrides is now mostly being correctly applied before the config is used... but... it's pretty ugly and unclear if the config you've got has overrides or not.
I've thought for a while that it would be much cleaner to have:
KsqlConfig
which is always the server config.SessionConfig
which wraps aKsqlConfig
and a map of overrides.
Headless mode just has a single session, where as each user request can build its own SessionConfig and pass this around, rather than the two params.
Ideally, the engine would take SessionConfig
, not KsqlConfig
. SessionConfig
can have a very similar / same interface as KsqlConfig
.
The SessionConfig
constructor, which takes the server's KsqlConfig
and the map of overrides can then validate the overrides, i.e. only one place for override validation.
The SessionConfig
would allow access to the serverConfig
, then overrides
and then 'mergedConfig`. Different parts of the code need each of these, if memory serves me right.
Of course, this is a much bigger change. Simple, but wide ranging. However, I wonder if this PR could start us down this road (Assuming we agree it's a good idea). For example, this PR could add the SessionConfig
class, and pass this around in the rest-server model, before converting to a KsqlConfig
that's passed to the engine. If you want to also switch the engine to use SessionConfig
, then awesome - but maybe in follow up PR.
ksqldb-rest-app/src/test/java/io/confluent/ksql/rest/server/resources/KsqlResourceTest.java
Outdated
Show resolved
Hide resolved
@@ -228,7 +233,7 @@ private KsqlRequest parseRequest(final MultiMap requestParams) { | |||
throw new IllegalArgumentException("\"ksql\" field of \"request\" must be populated"); | |||
} | |||
// To validate props: | |||
request.getConfigOverrides(); | |||
denyListPropertyValidator.validateAll(request.getConfigOverrides()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing a unit test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -245,6 +250,7 @@ private KsqlRequest parseRequest(final MultiMap requestParams) { | |||
|
|||
private void handleQuery(final RequestContext info, final Query query) { | |||
final Map<String, Object> clientLocalProperties = info.request.getConfigOverrides(); | |||
denyListPropertyValidator.validateAll(clientLocalProperties); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing a unit test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
ksqldb-rest-app/src/main/java/io/confluent/ksql/rest/server/resources/KsqlResource.java
Show resolved
Hide resolved
d4e555d
to
27d2643
Compare
- change error message for a more descriptive error
- inject DenyListPropertyValidator to Resource classes - add unit tests for WSQueryEndpoint - validate only streamProperties (no requestProperties) - minor fixes
27d2643
to
978c79a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Looks forward to the follow up PR!
Description
Added a new configuration
ksql.properties.overrides.denylist
to specify which server properties cannot be overridden by the KSQL clients/users.There is currently an internal hard-coded list of properties that cannot be overriden. However, there are KSQL admins that also want other properties to be in the list. To make this dynamic, this new denylist property allow those admins to specify which properties should not be overridden, without making changes in the code.
The only disadvantage on this dynamic property over the hard-coded is the validation happens only until executing a DDL or query statements.
Testing done
Reviewer checklist