Skip to content
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

Closed
wants to merge 3 commits into from

Conversation

rajinisivaram
Copy link
Contributor

@rajinisivaram rajinisivaram commented Dec 7, 2017

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)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

@rajinisivaram
Copy link
Contributor Author

@ijuma Can you review, please? Thank you!

@ijuma
Copy link
Contributor

ijuma commented Dec 7, 2017

Thanks @rajinisivaram. What do we do about the invalid json strings that have already been stored?

@rajinisivaram
Copy link
Contributor Author

@ijuma Have updated to handle non-escaped backslash in configs persisted by 1.0 code.

Copy link
Contributor

@ijuma ijuma left a 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
Copy link
Contributor

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 }
Copy link
Contributor

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)?

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

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 : (\\, \\+ \\\" \\\\ \\< \\> \\; ')"
Copy link
Contributor

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)
Copy link
Contributor

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?

Copy link
Contributor Author

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 : (\\, \\+ \\\" \\\\ \\< \\> \\; ')"))
Copy link
Contributor

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)
}
}
Copy link
Contributor

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\""))
Copy link
Contributor

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.

@rajinisivaram
Copy link
Contributor Author

@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.
Copy link
Contributor

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""""))
Copy link
Contributor

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.

Copy link
Contributor

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. :)

Copy link
Contributor Author

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.

@ijuma
Copy link
Contributor

ijuma commented Dec 12, 2017

retest this please

Copy link
Contributor

@ijuma ijuma left a 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?

@rajinisivaram
Copy link
Contributor Author

@ijuma Thanks for the review. Fixed the description.

@ijuma
Copy link
Contributor

ijuma commented Dec 12, 2017

Merged to trunk and 1.0 branches.

asfgit pushed a commit that referenced this pull request Dec 12, 2017
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>
@asfgit asfgit closed this in 651c6e4 Dec 12, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants