Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 79B64200D0D for ; Fri, 25 Aug 2017 20:44:14 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 7844916D0AD; Fri, 25 Aug 2017 18:44:14 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 9888116D0AB for ; Fri, 25 Aug 2017 20:44:13 +0200 (CEST) Received: (qmail 35877 invoked by uid 500); 25 Aug 2017 18:44:11 -0000 Mailing-List: contact commits-help@kudu.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@kudu.apache.org Delivered-To: mailing list commits@kudu.apache.org Received: (qmail 35868 invoked by uid 99); 25 Aug 2017 18:44:11 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 25 Aug 2017 18:44:11 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 58958E109B; Fri, 25 Aug 2017 18:44:11 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: todd@apache.org To: commits@kudu.apache.org Message-Id: <74eb4694ef3e4cda9dff2da23248890f@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: kudu git commit: [java] KUDU-2103 Canonicalize hostnames in client Date: Fri, 25 Aug 2017 18:44:11 +0000 (UTC) archived-at: Fri, 25 Aug 2017 18:44:14 -0000 Repository: kudu Updated Branches: refs/heads/branch-1.4.x aa7bacc81 -> 9bc63e534 [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/7812 Tested-by: Todd Lipcon Reviewed-by: Todd Lipcon Project: http://git-wip-us.apache.org/repos/asf/kudu/repo Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/9bc63e53 Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/9bc63e53 Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/9bc63e53 Branch: refs/heads/branch-1.4.x Commit: 9bc63e53482b91225eda9679e2a25e34ad73838c Parents: aa7bacc Author: Attila Bukor Authored: Wed Aug 23 14:43:12 2017 +0200 Committer: Todd Lipcon Committed: Fri Aug 25 18:42:53 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 | 51 ++++++++++++++++++++ 4 files changed, 89 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kudu/blob/9bc63e53/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 8ba09a5..b0c9d5d 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 java.util.concurrent.ConcurrentHashMap; import com.google.common.net.HostAndPort; @@ -65,12 +66,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/9bc63e53/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 6220633..5213ec7 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 @@ -588,7 +588,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/9bc63e53/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 forwardResolutions = new HashMap<>(); + + @GuardedBy("this") + private Map 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/9bc63e53/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 index ad11d05..d948955 100644 --- 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 @@ -14,9 +14,11 @@ 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 { /** @@ -32,4 +34,53 @@ public class TestServerInfo { 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); + } }