-
Notifications
You must be signed in to change notification settings - Fork 24.7k
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
Ensures watch definitions are valid json #30692
Changes from 2 commits
36d0c12
6da9e8b
7252b00
9a4db9f
dcd9b86
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
*/ | ||
package org.elasticsearch.xpack.watcher.watch; | ||
|
||
import com.fasterxml.jackson.core.JsonParseException; | ||
import org.elasticsearch.ElasticsearchParseException; | ||
import org.elasticsearch.common.Nullable; | ||
import org.elasticsearch.common.bytes.BytesReference; | ||
|
@@ -174,6 +175,13 @@ public Watch parse(String id, boolean includeStatus, WatcherXContentParser parse | |
throw new ElasticsearchParseException("could not parse watch [{}]. unexpected field [{}]", id, currentFieldName); | ||
} | ||
} | ||
/* Make sure we are at the end of the available input data -- certain types of JSON errors will not manifest | ||
until we try to consume additional tokens. | ||
*/ | ||
if (parser.nextToken() != null) { | ||
throw new ElasticsearchParseException("could not parse watch [{}]. unexpected data beyond [line: {}, column: {}]", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor nit: maybe we can come up with a more explaining error message here, as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @spinscale Actually it is this code that enables the JsonParseException for the original test case. Ryan asked that the code for the test case be changed, which resulted in a different error path. However, the key factor is that we now attempt to grab the next token beyond what we believe to be the last token of the watch definition. A previous revision of this code made that fact clear, at the expense of some more complex code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yea I think what @spinscale is saying is that he would like the error message changed. Maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @hub-cap I was trying to respond to @spinscale's comment above in the LGTM -- I'll rework the error message |
||
id, parser.getTokenLocation().lineNumber, parser.getTokenLocation().columnNumber); | ||
} | ||
if (trigger == null) { | ||
throw new ElasticsearchParseException("could not parse watch [{}]. missing required field [{}]", id, | ||
WatchField.TRIGGER.getPreferredName()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
import org.elasticsearch.action.support.WriteRequest; | ||
import org.elasticsearch.client.Client; | ||
import org.elasticsearch.common.ParseField; | ||
import org.elasticsearch.common.bytes.BytesArray; | ||
import org.elasticsearch.common.bytes.BytesReference; | ||
import org.elasticsearch.common.logging.Loggers; | ||
import org.elasticsearch.common.settings.Settings; | ||
|
@@ -143,6 +144,8 @@ | |
import static org.elasticsearch.xpack.watcher.input.InputBuilders.searchInput; | ||
import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.templateRequest; | ||
import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule; | ||
|
||
import static org.hamcrest.Matchers.containsString; | ||
import static org.hamcrest.Matchers.equalTo; | ||
import static org.hamcrest.Matchers.hasSize; | ||
import static org.hamcrest.Matchers.instanceOf; | ||
|
@@ -296,6 +299,35 @@ public void testParserBadActions() throws Exception { | |
} | ||
} | ||
|
||
public void testParserConsumesEntireDefinition() throws Exception { | ||
WatchParser wp = createWatchparser(); | ||
String watchDef="{\n" + | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typically we use XContentBuilder to build the json (see the test below for an example). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WatcherXContentParser is not different -- the real issue is that we do not consume enough tokens to encounter an actual error. The real crux of this PR is line 183 -- consuming an additional token beyond what we "think" is the end of the watch definition to ensure that we have looked at the whole thing. In the example test, we have an extra closing curly brace. Up to and including that curly brace, the json is invalid -- we have to consume beyond the erroneous end brace to get the error. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Re: XContentBuilder -- XContentBuilder won't let me build an invalid JSON. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use XContentBuilder to build valid json, and then append an extra token (eg comma as you have). This will ensure there isn't malformed json in the middle which tricks the test. |
||
" \"trigger\": {\n" + | ||
" \"schedule\": {\n" + | ||
" \"interval\": \"10s\"\n" + | ||
" }\n" + | ||
" },\n" + | ||
" \"input\": {\n" + | ||
" \"simple\": {}\n" + | ||
" }},\n" + /* NOTICE EXTRA CLOSING CURLY BRACE */ | ||
" \"condition\": {\n" + | ||
" \"script\": {\n" + | ||
" \"inline\": \"return false\"\n" + | ||
" }\n" + | ||
" },\n" + | ||
" \"actions\": {\n" + | ||
" \"logging\": {\n" + | ||
" \"logging\": {\n" + | ||
" \"text\": \"{{ctx.payload}}\"\n" + | ||
" }\n" + | ||
" }\n" + | ||
" }\n" + | ||
"}"; | ||
IOException e = expectThrows(IOException.class, () -> | ||
wp.parseWithSecrets("failure", false, new BytesArray(watchDef), new DateTime(), XContentType.JSON, true)); | ||
assertThat(e.getMessage(), containsString("could not parse watch")); | ||
} | ||
|
||
public void testParserDefaults() throws Exception { | ||
Schedule schedule = randomSchedule(); | ||
ScheduleRegistry scheduleRegistry = registry(schedule); | ||
|
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.
minor nit: can you use a
//
comment like the other comments in the methods as well and add new lines before and after?