You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by to...@apache.org on 2017/08/25 18:44:08 UTC
kudu git commit: [java] KUDU-2103 Canonicalize hostnames in client
Repository: kudu
Updated Branches:
refs/heads/branch-1.3.x debe44421 -> 672e42065
[java] KUDU-2103 Canonicalize hostnames in client
When Kerberos is used the service principal contains the
hostname of the service. This means that if a user wants to use
an alias for the master_addresses in a Kerberized environment
it won't be able to connect as the service principal name is not
found in the Kerberos database.
This patch adds canonicalization for the hostnames to make sure
the principal name the service ticket is requested for matches
the one used by the master servers.
Change-Id: I77204a185c1ab8e21cc833afb645543cbc0e340f
Reviewed-on: http://gerrit.cloudera.org:8080/7815
Tested-by: Todd Lipcon <to...@apache.org>
Reviewed-by: Todd Lipcon <to...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/672e4206
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/672e4206
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/672e4206
Branch: refs/heads/branch-1.3.x
Commit: 672e4206557c697fb0384649ba333221fc056136
Parents: debe444
Author: Attila Bukor <ab...@cloudera.com>
Authored: Wed Aug 23 14:43:12 2017 +0200
Committer: Todd Lipcon <to...@apache.org>
Committed: Fri Aug 25 18:43:34 2017 +0000
----------------------------------------------------------------------
.../java/org/apache/kudu/client/ServerInfo.java | 14 ++--
.../org/apache/kudu/client/TabletClient.java | 2 +-
.../java/org/apache/kudu/client/FakeDNS.java | 28 +++++++
.../org/apache/kudu/client/TestServerInfo.java | 86 ++++++++++++++++++++
4 files changed, 124 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/kudu/blob/672e4206/java/kudu-client/src/main/java/org/apache/kudu/client/ServerInfo.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/ServerInfo.java b/java/kudu-client/src/main/java/org/apache/kudu/client/ServerInfo.java
index 6d26b8f..36a6d81 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/ServerInfo.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/ServerInfo.java
@@ -18,6 +18,7 @@
package org.apache.kudu.client;
import java.net.InetAddress;
+import java.net.UnknownHostException;
import com.google.common.net.HostAndPort;
@@ -57,12 +58,15 @@ public class ServerInfo {
}
/**
- * Returns this server's hostname. We might get many hostnames from the master for a single
- * TS, and this is the one we picked to connect to originally.
- * @return a string that contains this server's hostname
+ * Returns this server's canonical hostname.
+ * @return a string that contains this server's canonical hostname
*/
- public String getHostname() {
- return hostPort.getHostText();
+ public String getAndCanonicalizeHostname() {
+ try {
+ return InetAddress.getByName(hostPort.getHostText()).getCanonicalHostName().toLowerCase();
+ } catch (UnknownHostException e) {
+ return hostPort.getHostText();
+ }
}
/**
http://git-wip-us.apache.org/repos/asf/kudu/blob/672e4206/java/kudu-client/src/main/java/org/apache/kudu/client/TabletClient.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/TabletClient.java b/java/kudu-client/src/main/java/org/apache/kudu/client/TabletClient.java
index 24e80f8..b4afc7c 100644
--- a/java/kudu-client/src/main/java/org/apache/kudu/client/TabletClient.java
+++ b/java/kudu-client/src/main/java/org/apache/kudu/client/TabletClient.java
@@ -586,7 +586,7 @@ public class TabletClient extends SimpleChannelUpstreamHandler {
final ChannelStateEvent e) {
assert chan != null;
Channels.write(chan, ChannelBuffers.wrappedBuffer(CONNECTION_HEADER));
- Negotiator negotiator = new Negotiator(serverInfo.getHostname(),
+ Negotiator negotiator = new Negotiator(serverInfo.getAndCanonicalizeHostname(),
kuduClient.getSecurityContext());
ctx.getPipeline().addBefore(ctx.getName(), "negotiation", negotiator);
negotiator.sendHello(chan);
http://git-wip-us.apache.org/repos/asf/kudu/blob/672e4206/java/kudu-client/src/test/java/org/apache/kudu/client/FakeDNS.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/FakeDNS.java b/java/kudu-client/src/test/java/org/apache/kudu/client/FakeDNS.java
index 6ac8939..8613224 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/FakeDNS.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/FakeDNS.java
@@ -20,8 +20,10 @@ package org.apache.kudu.client;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.annotation.concurrent.GuardedBy;
import com.google.common.base.Throwables;
@@ -46,6 +48,12 @@ import sun.net.spi.nameservice.NameService;
public class FakeDNS {
static FakeDNS instance = new FakeDNS();
+ @GuardedBy("this")
+ private Map<String, InetAddress> forwardResolutions = new HashMap<>();
+
+ @GuardedBy("this")
+ private Map<InetAddress, String> reverseResolutions = new HashMap<>();
+
/** whether the fake resolver has been installed */
@GuardedBy("this")
private boolean installed = false;
@@ -55,6 +63,14 @@ public class FakeDNS {
return instance;
}
+ public synchronized void addForwardResolution(String hostname, InetAddress ip) {
+ forwardResolutions.put(hostname, ip);
+ }
+
+ public synchronized void addReverseResolution(InetAddress ip, String hostname) {
+ reverseResolutions.put(ip, hostname);
+ }
+
/**
* Install the fake DNS resolver into the Java runtime.
*/
@@ -76,6 +92,12 @@ public class FakeDNS {
@Override
public InetAddress[] lookupAllHostAddr(String host)
throws UnknownHostException {
+
+ InetAddress inetAddress = forwardResolutions.get(host);
+ if (inetAddress != null) {
+ return new InetAddress[]{inetAddress};
+ }
+
// JDK chains to the next provider automatically.
throw new UnknownHostException();
}
@@ -85,6 +107,12 @@ public class FakeDNS {
if (addr[0] == 127) {
return InetAddresses.toAddrString(InetAddress.getByAddress(addr));
}
+
+ String hostname = reverseResolutions.get(InetAddress.getByAddress(addr));
+ if (hostname != null) {
+ return hostname;
+ }
+
throw new UnknownHostException();
}
}
http://git-wip-us.apache.org/repos/asf/kudu/blob/672e4206/java/kudu-client/src/test/java/org/apache/kudu/client/TestServerInfo.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestServerInfo.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestServerInfo.java
new file mode 100644
index 0000000..d948955
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestServerInfo.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. See accompanying LICENSE file.
+ */
+package org.apache.kudu.client;
+
+import com.google.common.net.HostAndPort;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+public class TestServerInfo {
+ /**
+ * Test for KUDU-1982 Java client calls NetworkInterface.getByInetAddress too often.
+ */
+ @Test(timeout = 500)
+ public void testConstructorNotSlow() throws Exception {
+ String uuid = "nevermind";
+ HostAndPort hap = HostAndPort.fromString("nevermind");
+ // ip to force NetworkInterface.getByInetAddress call
+ InetAddress ia = InetAddress.getByName("8.8.8.8");
+ for (int i = 0; i < 100; ++i) {
+ new ServerInfo(uuid, hap, ia);
+ }
+ }
+
+ /**
+ * Test for KUDU-2103. Checks if the original hostnames is returned if unknown.
+ */
+ @Test
+ public void testGetAndCanonicalizeUnknownHostname() throws Exception {
+ installFakeDNS("master1.example.com", "server123.example.com", "10.1.2.3");
+
+ ServerInfo serverInfo = new ServerInfo(
+ "nevermind",
+ HostAndPort.fromHost("master2.example.com"),
+ InetAddress.getByName("10.1.2.3"));
+
+ Assert.assertEquals("master2.example.com", serverInfo.getAndCanonicalizeHostname());
+ }
+
+ /**
+ * Test for KUDU-2103. Checks if the canonical hostname is returned instead
+ * of the one it's set to.
+ */
+ @Test
+ public void testGetAndCanonicalizeHostname() throws Exception {
+ installFakeDNS("master1.example.com", "server123.example.com", "10.1.2.3");
+
+ ServerInfo serverInfo = new ServerInfo(
+ "nevermind",
+ HostAndPort.fromHost("master1.example.com"),
+ InetAddress.getByName("10.1.2.3"));
+
+ Assert.assertEquals("server123.example.com", serverInfo.getAndCanonicalizeHostname());
+ }
+
+ /**
+ * Helper method to install FakeDNS with the expected values for the tests
+ *
+ * @param alias alias to be set for forward resolution
+ * @param canonical canonical to be set for reverse resolution
+ * @param ip IP both hostnames point to
+ * @throws UnknownHostException if the "ip" is an unknown host
+ */
+ private void installFakeDNS(String alias, String canonical, String ip)
+ throws UnknownHostException {
+ FakeDNS fakeDNS = FakeDNS.getInstance();
+ fakeDNS.install();
+ InetAddress inetAddress = InetAddress.getByName(ip);
+ fakeDNS.addForwardResolution(alias, inetAddress);
+ fakeDNS.addForwardResolution(canonical, inetAddress);
+ fakeDNS.addReverseResolution(inetAddress, canonical);
+ }
+}