Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with this * work for additional information regarding copyright ownership. The ASF * licenses this file to you 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. */ package org.apache.hadoop.security; import static org.junit.Assert.*; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URI; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.io.Text; import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.security.token.Token; import org.junit.Test; import org.mockito.Mockito; public class TestSecurityUtil { public static final Log LOG = LogFactory.getLog(TestSecurityUtil.class); @Test public void isOriginalTGTReturnsCorrectValues() { assertTrue(SecurityUtil.isOriginalTGT("krbtgt/foo@foo")); assertTrue(SecurityUtil.isOriginalTGT("krbtgt/foo.bar.bat@foo.bar.bat")); assertFalse(SecurityUtil.isOriginalTGT(null)); assertFalse(SecurityUtil.isOriginalTGT("blah")); assertFalse(SecurityUtil.isOriginalTGT("")); assertFalse(SecurityUtil.isOriginalTGT("krbtgt/hello")); assertFalse(SecurityUtil.isOriginalTGT("/@")); assertFalse(SecurityUtil.isOriginalTGT("this@is/notright")); assertFalse(SecurityUtil.isOriginalTGT("krbtgt/foo@FOO")); } private void verify(String original, String hostname, String expected) throws IOException { assertEquals(expected, SecurityUtil.getServerPrincipal(original, hostname)); InetAddress addr = mockAddr(hostname); assertEquals(expected, SecurityUtil.getServerPrincipal(original, addr)); } private InetAddress mockAddr(String reverseTo) { InetAddress mock = Mockito.mock(InetAddress.class); Mockito.doReturn(reverseTo).when(mock).getCanonicalHostName(); return mock; } @Test public void testGetServerPrincipal() throws IOException { String service = "hdfs/"; String realm = "@REALM"; String hostname = "foohost"; String userPrincipal = "foo@FOOREALM"; String shouldReplace = service + SecurityUtil.HOSTNAME_PATTERN + realm; String replaced = service + hostname + realm; verify(shouldReplace, hostname, replaced); String shouldNotReplace = service + SecurityUtil.HOSTNAME_PATTERN + "NAME" + realm; verify(shouldNotReplace, hostname, shouldNotReplace); verify(userPrincipal, hostname, userPrincipal); // testing reverse DNS lookup doesn't happen InetAddress notUsed = Mockito.mock(InetAddress.class); assertEquals(shouldNotReplace, SecurityUtil.getServerPrincipal(shouldNotReplace, notUsed)); Mockito.verify(notUsed, Mockito.never()).getCanonicalHostName(); } @Test public void testPrincipalsWithLowerCaseHosts() throws IOException { String service = "xyz/"; String realm = "@REALM"; String principalInConf = service + SecurityUtil.HOSTNAME_PATTERN + realm; String hostname = "FooHost"; String principal = service + hostname.toLowerCase() + realm; verify(principalInConf, hostname, principal); } @Test public void testLocalHostNameForNullOrWild() throws Exception { String local = SecurityUtil.getLocalHostName(); assertEquals("hdfs/" + local + "@REALM", SecurityUtil.getServerPrincipal("hdfs/_HOST@REALM", (String) null)); assertEquals("hdfs/" + local + "@REALM", SecurityUtil.getServerPrincipal("hdfs/_HOST@REALM", "0.0.0.0")); } @Test public void testGetHostFromPrincipal() { assertEquals("host", SecurityUtil.getHostFromPrincipal("service/host@realm")); assertEquals(null, SecurityUtil.getHostFromPrincipal("service@realm")); } @Test public void testBuildDTServiceName() { assertEquals("127.0.0.1:123", SecurityUtil.buildDTServiceName(URI.create("test://LocalHost"), 123)); assertEquals("127.0.0.1:123", SecurityUtil.buildDTServiceName(URI.create("test://LocalHost:123"), 456)); assertEquals("127.0.0.1:123", SecurityUtil.buildDTServiceName(URI.create("test://127.0.0.1"), 123)); assertEquals("127.0.0.1:123", SecurityUtil.buildDTServiceName(URI.create("test://127.0.0.1:123"), 456)); } @Test public void testBuildTokenServiceSockAddr() { assertEquals("127.0.0.1:123", SecurityUtil.buildTokenService(new InetSocketAddress("LocalHost", 123)).toString()); assertEquals("127.0.0.1:123", SecurityUtil.buildTokenService(new InetSocketAddress("127.0.0.1", 123)).toString()); // what goes in, comes out assertEquals("127.0.0.1:123", SecurityUtil.buildTokenService(NetUtils.createSocketAddr("127.0.0.1", 123)).toString()); } @Test public void testGoodHostsAndPorts() { InetSocketAddress compare = NetUtils.makeSocketAddr("localhost", 123); runGoodCases(compare, "localhost", 123); runGoodCases(compare, "localhost:", 123); runGoodCases(compare, "localhost:123", 456); } void runGoodCases(InetSocketAddress addr, String host, int port) { assertEquals(addr, NetUtils.createSocketAddr(host, port)); assertEquals(addr, NetUtils.createSocketAddr("hdfs://" + host, port)); assertEquals(addr, NetUtils.createSocketAddr("hdfs://" + host + "/path", port)); } @Test public void testBadHostsAndPorts() { runBadCases("", true); runBadCases(":", false); runBadCases("hdfs/", false); runBadCases("hdfs:/", false); runBadCases("hdfs://", true); } void runBadCases(String prefix, boolean validIfPosPort) { runBadPortPermutes(prefix, false); runBadPortPermutes(prefix + "*", false); runBadPortPermutes(prefix + "localhost", validIfPosPort); runBadPortPermutes(prefix + "localhost:-1", false); runBadPortPermutes(prefix + "localhost:-123", false); runBadPortPermutes(prefix + "localhost:xyz", false); runBadPortPermutes(prefix + "localhost/xyz", validIfPosPort); runBadPortPermutes(prefix + "localhost/:123", validIfPosPort); runBadPortPermutes(prefix + ":123", false); runBadPortPermutes(prefix + ":xyz", false); } void runBadPortPermutes(String arg, boolean validIfPosPort) { int ports[] = { -123, -1, 123 }; boolean bad = false; try { NetUtils.createSocketAddr(arg); } catch (IllegalArgumentException e) { bad = true; } finally { assertTrue("should be bad: '" + arg + "'", bad); } for (int port : ports) { if (validIfPosPort && port > 0) continue; bad = false; try { NetUtils.createSocketAddr(arg, port); } catch (IllegalArgumentException e) { bad = true; } finally { assertTrue("should be bad: '" + arg + "' (default port:" + port + ")", bad); } } } // check that the socket addr has: // 1) the InetSocketAddress has the correct hostname, ie. exact host/ip given // 2) the address is resolved, ie. has an ip // 3,4) the socket's InetAddress has the same hostname, and the correct ip // 5) the port is correct private void verifyValues(InetSocketAddress addr, String host, String ip, int port) { assertTrue(!addr.isUnresolved()); // don't know what the standard resolver will return for hostname. // should be host for host; host or ip for ip is ambiguous if (!SecurityUtil.useIpForTokenService) { assertEquals(host, addr.getHostName()); assertEquals(host, addr.getAddress().getHostName()); } assertEquals(ip, addr.getAddress().getHostAddress()); assertEquals(port, addr.getPort()); } // check: // 1) buildTokenService honors use_ip setting // 2) setTokenService & getService works // 3) getTokenServiceAddr decodes to the identical socket addr private void verifyTokenService(InetSocketAddress addr, String host, String ip, int port, boolean useIp) { LOG.info("address:" + addr + " host:" + host + " ip:" + ip + " port:" + port); SecurityUtil.setTokenServiceUseIp(useIp); String serviceHost = useIp ? ip : host.toLowerCase(); Token token = new Token(); Text service = new Text(serviceHost + ":" + port); assertEquals(service, SecurityUtil.buildTokenService(addr)); SecurityUtil.setTokenService(token, addr); assertEquals(service, token.getService()); InetSocketAddress serviceAddr = SecurityUtil.getTokenServiceAddr(token); assertNotNull(serviceAddr); verifyValues(serviceAddr, serviceHost, ip, port); } // check: // 1) socket addr is created with fields set as expected // 2) token service with ips // 3) token service with the given host or ip private void verifyAddress(InetSocketAddress addr, String host, String ip, int port) { verifyValues(addr, host, ip, port); LOG.info("test that token service uses ip"); verifyTokenService(addr, host, ip, port, true); LOG.info("test that token service uses host"); verifyTokenService(addr, host, ip, port, false); } // check: // 1-4) combinations of host and port // this will construct a socket addr, verify all the fields, build the // service to verify the use_ip setting is honored, set the token service // based on addr and verify the token service is set correctly, decode // the token service and ensure all the fields of the decoded addr match private void verifyServiceAddr(String host, String ip) { InetSocketAddress addr; int port = 123; // test host, port tuple LOG.info("test tuple (" + host + "," + port + ")"); addr = NetUtils.makeSocketAddr(host, port); verifyAddress(addr, host, ip, port); // test authority with no default port LOG.info("test authority '" + host + ":" + port + "'"); addr = NetUtils.createSocketAddr(host + ":" + port); verifyAddress(addr, host, ip, port); // test authority with a default port, make sure default isn't used LOG.info("test authority '" + host + ":" + port + "' with ignored default port"); addr = NetUtils.createSocketAddr(host + ":" + port, port + 1); verifyAddress(addr, host, ip, port); // test host-only authority, using port as default port LOG.info("test host:" + host + " port:" + port); addr = NetUtils.createSocketAddr(host, port); verifyAddress(addr, host, ip, port); } @Test public void testSocketAddrWithName() { String staticHost = "my"; NetUtils.addStaticResolution(staticHost, "localhost"); verifyServiceAddr("LocalHost", "127.0.0.1"); } @Test public void testSocketAddrWithIP() { verifyServiceAddr("127.0.0.1", "127.0.0.1"); } @Test public void testSocketAddrWithNameToStaticName() { String staticHost = "host1"; NetUtils.addStaticResolution(staticHost, "localhost"); verifyServiceAddr(staticHost, "127.0.0.1"); } @Test public void testSocketAddrWithNameToStaticIP() { String staticHost = "host3"; NetUtils.addStaticResolution(staticHost, "255.255.255.255"); verifyServiceAddr(staticHost, "255.255.255.255"); } // this is a bizarre case, but it's if a test tries to remap an ip address @Test public void testSocketAddrWithIPToStaticIP() { String staticHost = "1.2.3.4"; NetUtils.addStaticResolution(staticHost, "255.255.255.255"); verifyServiceAddr(staticHost, "255.255.255.255"); } }