-
Notifications
You must be signed in to change notification settings - Fork 15.2k
KAFKA-20617: add validation for cluster-id in Formatter #22384
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
base: trunk
Are you sure you want to change the base?
Changes from 2 commits
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 |
|---|---|---|
|
|
@@ -229,13 +229,33 @@ public BootstrapMetadata bootstrapMetadata() { | |
| return bootstrapMetadata; | ||
| } | ||
|
|
||
| /** | ||
| * Validates the correctness of the given cluster id. A valid cluster id is a base64, urlencoded, no padding | ||
| * representation of a {@link Uuid}. These checks do not validate the absence of <code>-</code> character as | ||
| * {@link Uuid#randomUuid()} avoids them only for convenience reasons. | ||
| */ | ||
| private void validateClusterId(String clusterId) { | ||
| if (clusterId == null) { | ||
| throw new FormatterException("You must specify the cluster id."); | ||
| } | ||
| if (clusterId.contains("=")) { | ||
| throw new FormatterException("The specified cluster id, " + clusterId + " is invalid: contains padding"); | ||
| } | ||
| try { | ||
| Uuid uuid = Uuid.fromString(clusterId); | ||
| if (Uuid.RESERVED.contains(uuid)) { | ||
| throw new FormatterException("The specified cluster id, " + clusterId + " is reserved"); | ||
| } | ||
|
Member
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. Let's also validate the starting
Contributor
Author
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. I think these are cosmetic improvemenst that've been added over time but have no bearing on correctness. Failing validation on them would hinder migration from older clusters where The motivation for avoiding Lately, https://issues.apache.org/jira/browse/KAFKA-20072 avoided
Contributor
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. Good point. Let's add a comment about this for future reference. |
||
| } catch (IllegalArgumentException e) { | ||
| throw new FormatterException("The specified cluster id, " + clusterId + " is invalid", e); | ||
| } | ||
| } | ||
|
|
||
| public void run() throws Exception { | ||
| if (nodeId < 0) { | ||
| throw new RuntimeException("You must specify a valid non-negative node ID."); | ||
| } | ||
| if (clusterId == null) { | ||
| throw new FormatterException("You must specify the cluster id."); | ||
| } | ||
| validateClusterId(clusterId); | ||
| if (directories.isEmpty()) { | ||
| throw new FormatterException("You must specify at least one directory to format"); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -587,4 +587,28 @@ public void testFormatWithNoInitialControllers() throws Exception { | |
| assertNotNull(logDirProps1); | ||
| } | ||
| } | ||
|
|
||
| @ParameterizedTest | ||
| @ValueSource(strings = {"unrvTtQISjar0JUWGU/8Pg", "igNUVIdeSPO5JCZYFhOh7Q==", "AAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAAQ"}) | ||
| public void testFormatWithInvalidClusterId(String clusterId) throws Exception { | ||
|
Contributor
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. There's no corresponding positive test showing that a valid CID passes validation. This would guard against the validation being too aggressive. |
||
| try (TestEnv testEnv = new TestEnv(2)) { | ||
| FormatterContext formatter1 = testEnv.newFormatter(); | ||
| formatter1.formatter.setClusterId(clusterId); | ||
| String expectedPrefix = "The specified cluster id, " + clusterId; | ||
| assertEquals(expectedPrefix, | ||
| assertThrows(FormatterException.class, | ||
| formatter1.formatter::run). | ||
| getMessage().substring(0, expectedPrefix.length())); | ||
|
Contributor
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. Wouldn't be easier to rewrite like: assertTrue(message.startsWith(expectedPrefix))
Contributor
Author
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. I'm indifferent here - I followed the convention used in another test in the same class |
||
| } | ||
| } | ||
|
|
||
| @ParameterizedTest | ||
| @ValueSource(strings = {"iIygKoNNSpGzNeAEr_QW7w", "-w_KF-snTmuEnKPqZ0RDzA", "dZMgZA7nTLqZTdzb0zbvSQ", "hxqHyN2OSSmPajVhm_DR-Q"}) | ||
| public void testFormatWithValidClusterId(String clusterId) throws Exception { | ||
| try (TestEnv testEnv = new TestEnv(2)) { | ||
| FormatterContext formatter1 = testEnv.newFormatter(); | ||
| formatter1.formatter.setClusterId(clusterId); | ||
| formatter1.formatter.run(); | ||
| } | ||
| } | ||
| } | ||
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 would explicitly mention support for already generated CIDs. Basically it's for historical reasons.