-
Notifications
You must be signed in to change notification settings - Fork 13.9k
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
KAFKA-6319: Quote strings stored in JSON configs #4303
Conversation
@ijuma Can you review, please? Thank you! |
Thanks @rajinisivaram. What do we do about the invalid json strings that have already been stored? |
9518f46
to
dd03670
Compare
@ijuma Have updated to handle non-escaped backslash in configs persisted by 1.0 code. |
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.
Thanks for the PR, looks good overall, just a few minor comments.
catch { case _: JsonProcessingException => None } | ||
catch { | ||
case _: JsonProcessingException => | ||
// In 1.0, Json#encode did not escape backslash or any other special characters. SSL principals |
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.
We should probably say, "Before 1.0.1, ..."
// Note that this does not handle all special characters (e.g. non-escaped double quotes are not supported) | ||
val escapedInput = input.replaceAll("\\\\", "\\\\\\\\") | ||
try Option(mapper.readTree(escapedInput)).map(JsonValue(_)) | ||
catch { case _: JsonProcessingException => None } |
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.
Can we file a JIRA to move this so that it only applies to ACLs in trunk (for 1.1)?
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.
@@ -19,6 +19,7 @@ package kafka.utils | |||
import java.nio.charset.StandardCharsets | |||
|
|||
import com.fasterxml.jackson.core.JsonProcessingException | |||
import com.fasterxml.jackson.core.io.JsonStringEncoder |
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 think this is not used any more.
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.
Removed.
// | ||
// Leading and trailing spaces in Kafka principal dont work with ACLs, but we can workaround by using | ||
// a PrincipalBuilder that removes/replaces them. | ||
private val clientCn = "\\#A client with special chars in CN : (\\, \\+ \\\" \\\\ \\< \\> \\; ')" |
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.
Use triple quotes to avoid the need for Java escaping?
@Before | ||
override def setUp() { | ||
startSasl(jaasSections(List.empty, None, ZkSasl)) | ||
super.setUp() | ||
} | ||
|
||
override def clientSecurityProps(certAlias: String): Properties = { | ||
val props = TestUtils.securityConfigs(Mode.CLIENT, securityProtocol, trustStoreFile, certAlias, clientCn, clientSaslProperties) | ||
props.remove(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG) |
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.
Do we have endpoint identification enabled anywhere?
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.
No, but since we may decide to make HTTPS the default value and this test would fail with endpoint validation enabled, I thought it was better to explicitly remove it.
private val Users = Set(KafkaPrincipal.fromString("User:CN=writeuser,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown"), KafkaPrincipal.fromString("User:test2")) | ||
private val Users = Set(KafkaPrincipal.fromString("User:CN=writeuser,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown"), | ||
KafkaPrincipal.fromString("User:test2"), | ||
KafkaPrincipal.fromString("User:CN=\\#User with special chars in CN : (\\, \\+ \\\" \\\\ \\< \\> \\; ')")) |
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.
Triple quotes to avoid Java escaping.
}.mkString(",") + "}" | ||
case o => Json.encode(o) | ||
} | ||
} |
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.
Simple this is a reasonably simple string, can we not just provide the full string without encoding instead of implementing this method?
@@ -61,6 +85,8 @@ class JsonTest { | |||
assertEquals("{}", Json.encode(Map())) | |||
assertEquals("{\"a\":1,\"b\":2}", Json.encode(Map("a" -> 1, "b" -> 2))) | |||
assertEquals("{\"a\":[1,2],\"c\":[3,4]}", Json.encode(Map("a" -> Seq(1,2), "c" -> Seq(3,4)))) | |||
assertEquals("\"str1\\\\,str2\"", Json.encode("str1\\,str2")) | |||
assertEquals("\"\\\"quoted\\\"\"", Json.encode("\"quoted\"")) |
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.
Triple quotes in both lines.
dd03670
to
f3d08b2
Compare
@ijuma Thank you for the review. I have made the updates. |
@@ -39,7 +38,7 @@ object Json { | |||
try Option(mapper.readTree(input)).map(JsonValue(_)) | |||
catch { | |||
case _: JsonProcessingException => | |||
// In 1.0, Json#encode did not escape backslash or any other special characters. SSL principals | |||
// Before 1.0.1, Json#encode did not escape backslash or any other special characters. SSL principals | |||
// stored in ACLs may contain backslash as an escape char, making the JSON generated in 1.0 invalid. |
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.
We probably want to replace 1.0 as well.
assertEquals("\"str1\\\\,str2\"", Json.encode("str1\\,str2")) | ||
assertEquals("\"\\\"quoted\\\"\"", Json.encode("\"quoted\"")) | ||
assertEquals(""""str1\\,str2"""", Json.encode("""str1\,str2""")) | ||
assertEquals(""""\"quoted\""""", Json.encode(""""quoted"""")) |
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.
Ouch, maybe my suggestion was bad in this line.
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.
A bit unclear to be honest. Both options seem hard to read. :)
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.
Shall I leave it as is or do you want me to change it back - I don't mind either way.
retest this please |
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.
Thanks for the PR, LGTM. Can you please update the PR description to remove the automatically generated text?
@ijuma Thanks for the review. Fixed the description. |
Merged to trunk and 1.0 branches. |
This is required for ACLs where SSL principals contain special characters (e.g. comma) that are escaped using backslash. The strings need to be quoted for JSON to ensure that the JSON stored in ZK is valid. Also converted `SslEndToEndAuthorizationTest` to use a principal with special characters to ensure that this path is tested. Author: Rajini Sivaram <rajinisivaram@googlemail.com> Reviewers: Ismael Juma <ismael@juma.me.uk> Closes #4303 from rajinisivaram/KAFKA-6319 (cherry picked from commit 651c6e4) Signed-off-by: Ismael Juma <ismael@juma.me.uk>
This is required for ACLs where SSL principals contain special characters (e.g. comma) that are escaped using backslash. The strings need to be quoted for JSON to ensure that the JSON stored in ZK is valid. Since ACLs may have been stored in ZK without escaping with previous versions of Kafka, a workaround has been added to parse those.
Also converted
SslEndToEndAuthorizationTest
to use a principal with special characters to ensure that this path is tested.Committer Checklist (excluded from commit message)