Skip to content

Add level parameter validation in rest layer.#94136

Merged
DaveCTurner merged 29 commits intoelastic:mainfrom
TencentCloudES:valid_level
Mar 21, 2023
Merged

Add level parameter validation in rest layer.#94136
DaveCTurner merged 29 commits intoelastic:mainfrom
TencentCloudES:valid_level

Conversation

@howardhuanghua
Copy link
Copy Markdown
Contributor

This PR is going to fix #93981.
Validate ?level= up-front in rest layer, also keeps validation in transport layer.

@elasticsearchmachine
Copy link
Copy Markdown
Collaborator

@howardhuanghua please enable the option "Allow edits and access to secrets by maintainers" on your PR. For more information, see the documentation.

@elasticsearchmachine elasticsearchmachine added v8.8.0 external-contributor Pull request authored by a developer outside the Elasticsearch team needs:triage Requires assignment of a team area label labels Feb 26, 2023
@thecoop thecoop added >bug :Core/Infra/REST API REST infrastructure and utilities and removed needs:triage Requires assignment of a team area label labels Feb 27, 2023
@elasticsearchmachine elasticsearchmachine added the Team:Core/Infra Meta label for core/infra team label Feb 27, 2023
@elasticsearchmachine
Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-core-infra (Team:Core/Infra)

@thecoop
Copy link
Copy Markdown
Member

thecoop commented Feb 27, 2023

Thanks for the PR @howardhuanghua. This could really do with tests being added. All the Action classes have got associated Test classes; could you add tests for valid/invalid parameters to those classes please.

@howardhuanghua
Copy link
Copy Markdown
Contributor Author

Thanks for the PR @howardhuanghua. This could really do with tests being added. All the Action classes have got associated Test classes; could you add tests for valid/invalid parameters to those classes please.

Hi @thecoop, thanks. I am going to add test case, just to make sure should be in org.elasticsearch.client.RestClientTests or org.elasticsearch.rest.action.RestActionsTests ? Could you please give me some suggestions?

final ClusterHealthRequest clusterHealthRequest = fromRequest(request);
return channel -> client.admin().cluster().health(clusterHealthRequest, new RestStatusToXContentListener<>(channel));
return channel -> {
ActionListener<ClusterHealthResponse> listener = new RestStatusToXContentListener<>(channel);
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.

Rather than checking here, ActionRequest has a validate method that checks if the request is valid, the checking should be done there. eg for RestClusterHealthAction, its in the ClusterHealthRequest.validate() method.

}
}

public static void validateClusterResponseLevel(final String level) {
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.

These methods are too specific to go into ActionResponse, ideally in some subclass of ActionRequest common to all the request classes using the level parameter.

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.

Actually I'm not sure there is a good place for the common code, as some Request classes have their own separate way of representing level. We may just need to keep each implementation separate for now, and not have a common method.

@thecoop thecoop requested a review from DaveCTurner February 27, 2023 11:02
@thecoop
Copy link
Copy Markdown
Member

thecoop commented Feb 27, 2023

The tests should be in the corresponding classes for the request - eg ClusterHealthRequestTests. See IndexRequestTests calling the validate method for a good example.

@howardhuanghua
Copy link
Copy Markdown
Contributor Author

OK. Thanks, I would update PR later.

Copy link
Copy Markdown
Member

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

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

I reckon we should have an enum for the level parameter rather than having all these string constants around.

Also I think we should require response params to be validated while reading the request, i.e. that we should drop the filter line here:

// validate unconsumed params, but we must exclude params used to format the response
// use a sorted set so the unconsumed parameters appear in a reliable sorted order
final SortedSet<String> unconsumedParams = request.unconsumedParams()
.stream()
.filter(p -> responseParams(request.getRestApiVersion()).contains(p) == false)
.collect(Collectors.toCollection(TreeSet::new));

@howardhuanghua
Copy link
Copy Markdown
Contributor Author

Also I think we should require response params to be validated while reading the request, i.e. that we should drop the filter line here:

Thanks @DaveCTurner , just want to double check that in prepareRequest:

RestRequest request;
request.param("level", "node")

Above request.param would also contains response parameters? So we validate level in prepareRequest is enough?
If we drop the above filter line, that user input response parameter like level would be treated as unrecognized parameters?

@DaveCTurner
Copy link
Copy Markdown
Member

If we drop the above filter line, that user input response parameter like level would be treated as unrecognized parameters?

Only if we don't validate them in prepareRequest. Which IMO we should do: there's no point in handling the request if we're just going to throw an exception when we get around to sending back the response.

@howardhuanghua
Copy link
Copy Markdown
Contributor Author

Update PR based on suggestions. Please help to review again, thank you.

@howardhuanghua howardhuanghua requested review from DaveCTurner and thecoop and removed request for DaveCTurner and thecoop March 1, 2023 16:27
Copy link
Copy Markdown
Member

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

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

I would prefer to keep the change you proposed to BaseRestHandler, and adjust the other REST handlers accordingly.

@DaveCTurner
Copy link
Copy Markdown
Member

I will submit another PR to remove base rest handler response paramter filter logic and related cases.

Ah ok I didn't see this comment until after my previous one. A follow-up PR would be fine too. Let me take another look.

@howardhuanghua
Copy link
Copy Markdown
Contributor Author

Ah ok I didn't see this comment until after my previous one. A follow-up PR would be fine too. Let me take another look.

Hmm, I think remove the response filter would cause lots of case failed. So I will do it in a follow-up PR.

Copy link
Copy Markdown
Member

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

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

Ok I like it, LGTM (assuming CI is happy)

Copy link
Copy Markdown
Member

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

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

Ah sorry, LGTM except those two small nits. I'll enable CI anyway.

@DaveCTurner DaveCTurner self-assigned this Mar 20, 2023
@DaveCTurner
Copy link
Copy Markdown
Member

@elasticmachine ok to test

howardhuanghua and others added 2 commits March 20, 2023 18:30
…l.java

Co-authored-by: David Turner <david.turner@elastic.co>
Co-authored-by: David Turner <david.turner@elastic.co>
@DaveCTurner
Copy link
Copy Markdown
Member

DaveCTurner commented Mar 20, 2023

I don't have permission to fix the changelog, but here's the patch I'd like you to apply:

diff --git a/docs/changelog/94136.yaml b/docs/changelog/94136.yaml
index 94b55c7f4b4..6b63723b039 100644
--- a/docs/changelog/94136.yaml
+++ b/docs/changelog/94136.yaml
@@ -1,5 +1,5 @@
 pr: 94136
-summary: Add level parameter validation in rest layer.
-area: REST API
+summary: Add level parameter validation in REST layer
+area: Infra/REST API
 type: bug
 issues: [93981]

@howardhuanghua
Copy link
Copy Markdown
Contributor Author

It seems all the tests passed finally. ^^

Copy link
Copy Markdown
Member

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

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

Nice work, I like it. I left a few tiny suggestions.

PARSER.declareString(constructorArg(), new ParseField(STATUS));
// Can be absent if LEVEL == 'indices' or 'cluster'
PARSER.declareNamedObjects(optionalConstructorArg(), SHARD_PARSER, new ParseField(SHARDS));
PARSER.declareNamedObjects(optionalConstructorArg(), SHARD_PARSER, new ParseField(ClusterStatsLevel.SHARDS.getLevel()));
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.

Hmm it is true that it's the same literal string, but that's something of a coincidence. I don't think we should link the field names in the response to the query parameters in the request like this.

PARSER.declareString(constructorArg(), new ParseField(STATUS));
// Can be absent if LEVEL == 'cluster'
PARSER.declareNamedObjects(optionalConstructorArg(), INDEX_PARSER, new ParseField(INDICES));
PARSER.declareNamedObjects(optionalConstructorArg(), INDEX_PARSER, new ParseField(ClusterStatsLevel.INDICES.getLevel()));
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.

Likewise here - it is true that it's the same literal string, but that's something of a coincidence. I don't think we should link the field names in the response to the query parameters in the request like this.

Copy link
Copy Markdown
Member

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

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

Great, LGTM

@howardhuanghua
Copy link
Copy Markdown
Contributor Author

Great, LGTM

Thanks for the patient help.

@howardhuanghua
Copy link
Copy Markdown
Contributor Author

I have added a independent PR to remove base rest handler parameter filter logic.
#94711

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

>bug :Core/Infra/REST API REST infrastructure and utilities external-contributor Pull request authored by a developer outside the Elasticsearch team Team:Core/Infra Meta label for core/infra team v8.8.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validate response parameters up-front (especially for chunked APIs)

4 participants