org.apache.hadoop.security.TestSecurityUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.security.TestSecurityUtil.java

Source

/**
 * 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");
    }
}