io.crate.operation.auth.HostBasedAuthenticationTest.java Source code

Java tutorial

Introduction

Here is the source code for io.crate.operation.auth.HostBasedAuthenticationTest.java

Source

/*
 * This file is part of a module with proprietary Enterprise Features.
 *
 * Licensed to Crate.io Inc. ("Crate.io") under one or more contributor
 * license agreements.  See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 *
 * Unauthorized copying of this file, via any medium is strictly prohibited.
 *
 * To use this file, Crate.io must have given you permission to enable and
 * use such Enterprise Features and you must have a valid Enterprise or
 * Subscription Agreement with Crate.io.  If you enable or use the Enterprise
 * Features, you represent and warrant that you have a valid Enterprise or
 * Subscription Agreement with Crate.io.  Your use of the Enterprise Features
 * if governed by the terms and conditions of your Enterprise or Subscription
 * Agreement with Crate.io.
 */

package io.crate.operation.auth;

import com.google.common.collect.ImmutableMap;
import io.crate.protocols.postgres.ConnectionProperties;
import io.crate.test.integration.CrateUnitTest;
import io.netty.buffer.ByteBufAllocator;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import org.apache.commons.lang3.RandomStringUtils;
import org.elasticsearch.common.network.InetAddresses;
import org.elasticsearch.common.settings.Settings;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import javax.net.ssl.SSLSession;
import java.net.InetAddress;
import java.security.cert.Certificate;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import static io.crate.operation.auth.HostBasedAuthentication.Matchers.isValidAddress;
import static io.crate.operation.auth.HostBasedAuthentication.Matchers.isValidProtocol;
import static io.crate.operation.auth.HostBasedAuthentication.Matchers.isValidUser;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.core.Is.is;
import static org.mockito.Mockito.when;

public class HostBasedAuthenticationTest extends CrateUnitTest {

    private static final ImmutableMap<String, String> HBA_1 = ImmutableMap.<String, String>builder()
            .put("user", "crate").put("address", "127.0.0.1").put("method", "trust").put("protocol", "pg").build();

    private static final ImmutableMap<String, String> HBA_2 = ImmutableMap.<String, String>builder()
            .put("user", "crate").put("address", "0.0.0.0/0").put("method", "fake").put("protocol", "pg").build();

    private static final ImmutableMap<String, String> HBA_3 = ImmutableMap.<String, String>builder()
            .put("address", "127.0.0.1").put("method", "md5").put("protocol", "pg").build();

    private static final InetAddress LOCALHOST = InetAddresses.forString("127.0.0.1");

    private HostBasedAuthentication authService;
    private SSLSession sslSession;

    @Before
    private void setUpTest() throws Exception {
        Settings settings = Settings.builder().put(AuthSettings.AUTH_HOST_BASED_ENABLED_SETTING.getKey(), true)
                .build();
        authService = new HostBasedAuthentication(settings, null);

        SelfSignedCertificate ssc = new SelfSignedCertificate();
        SslHandler sslHandler = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
                .trustManager(InsecureTrustManagerFactory.INSTANCE).startTls(false).build()
                .newHandler(ByteBufAllocator.DEFAULT);
        sslSession = sslHandler.engine().getSession();
    }

    @SafeVarargs
    private static Map<String, Map<String, String>> createHbaConf(Map<String, String>... entries) {
        ImmutableMap.Builder<String, Map<String, String>> builder = ImmutableMap.builder();
        int idx = 0;
        for (Map<String, String> entry : entries) {
            builder.put(String.valueOf(idx), entry);
            idx++;
        }
        return builder.build();
    }

    @Test
    public void testMissingUserOrAddress() throws Exception {
        authService.updateHbaConfig(Collections.emptyMap());
        AuthenticationMethod method;
        method = authService.resolveAuthenticationType(null,
                new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, null));
        assertNull(method);
        method = authService.resolveAuthenticationType("crate",
                new ConnectionProperties(null, Protocol.POSTGRES, null));
        assertNull(method);
    }

    @Test
    public void testEmptyHbaConf() throws Exception {
        authService.updateHbaConfig(Collections.emptyMap());
        AuthenticationMethod method = authService.resolveAuthenticationType("crate",
                new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, null));
        assertNull(method);
    }

    @Test
    public void testResolveAuthMethod() throws Exception {
        authService.updateHbaConfig(createHbaConf(HBA_1));
        AuthenticationMethod method = authService.resolveAuthenticationType("crate",
                new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, null));
        assertThat(method, instanceOf(TrustAuthenticationMethod.class));
    }

    @Test
    public void testFilterEntriesSimple() throws Exception {
        authService.updateHbaConfig(createHbaConf(HBA_1));
        Optional entry;

        entry = authService.getEntry("crate", new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, null));
        assertThat(entry.isPresent(), is(true));

        entry = authService.getEntry("cr8", new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, null));
        assertThat(entry.isPresent(), is(false));

        entry = authService.getEntry("crate",
                new ConnectionProperties(InetAddresses.forString("10.0.0.1"), Protocol.POSTGRES, null));
        assertThat(entry.isPresent(), is(false));
    }

    @Test
    public void testFilterEntriesCIDR() throws Exception {
        authService.updateHbaConfig(createHbaConf(HBA_2, HBA_3));
        Optional<Map.Entry<String, Map<String, String>>> entry;

        entry = authService.getEntry("crate",
                new ConnectionProperties(InetAddresses.forString("123.45.67.89"), Protocol.POSTGRES, null));
        assertTrue(entry.isPresent());
        assertThat(entry.get().getValue().get("method"), is("fake"));

        entry = authService.getEntry("cr8",
                new ConnectionProperties(InetAddresses.forString("127.0.0.1"), Protocol.POSTGRES, null));
        assertTrue(entry.isPresent());
        assertThat(entry.get().getValue().get("method"), is("md5"));

        entry = authService.getEntry("cr8",
                new ConnectionProperties(InetAddresses.forString("123.45.67.89"), Protocol.POSTGRES, null));
        assertThat(entry.isPresent(), is(false));
    }

    @Test
    public void testMatchUser() throws Exception {
        // only "crate" matches
        Map.Entry<String, Map<String, String>> entry = new HashMap.SimpleEntry<>("0",
                Collections.singletonMap("user", "crate"));
        assertTrue(isValidUser(entry, "crate"));
        assertFalse(isValidUser(entry, "postgres"));

        // any user matches
        entry = new HashMap.SimpleEntry<>("0", Collections.emptyMap() // key "user" not present in map
        );
        assertTrue(isValidUser(entry, RandomStringUtils.random(8)));
    }

    @Test
    public void testMatchProtocol() throws Exception {
        assertTrue(isValidProtocol("pg", Protocol.POSTGRES));
        assertFalse(isValidProtocol("http", Protocol.POSTGRES));
        assertTrue(isValidProtocol(null, Protocol.POSTGRES));
    }

    @Test
    public void testMatchAddress() throws Exception {
        String hbaAddress = "10.0.1.100";
        assertTrue(isValidAddress(hbaAddress, InetAddresses.forString("10.0.1.100")));
        assertFalse(isValidAddress(hbaAddress, InetAddresses.forString("10.0.1.99")));
        assertFalse(isValidAddress(hbaAddress, InetAddresses.forString("10.0.1.101")));

        hbaAddress = "10.0.1.0/24"; // 10.0.1.0 -- 10.0.1.255
        assertTrue(isValidAddress(hbaAddress, InetAddresses.forString("10.0.1.0")));
        assertTrue(isValidAddress(hbaAddress, InetAddresses.forString("10.0.1.255")));
        assertFalse(isValidAddress(hbaAddress, InetAddresses.forString("10.0.0.255")));
        assertFalse(isValidAddress(hbaAddress, InetAddresses.forString("10.0.2.0")));

        assertTrue(isValidAddress(null, InetAddresses.forString(
                String.format("%s.%s.%s.%s", randomInt(255), randomInt(255), randomInt(255), randomInt(255)))));
    }

    @Test
    public void testConvertSettingsToConf() throws Exception {
        Settings settings = Settings.builder().put("auth.host_based.enabled", true)
                .put("auth.host_based.config", "0", new String[] { "user", "address", "method", "protocol" },
                        new String[] { "crate", "127.0.0.1", "trust", "pg" })
                .put("auth.host_based.config", "1", new String[] { "user", "address", "method", "protocol" },
                        new String[] { "crate", "0.0.0.0/0", "fake", "pg" })
                .put("auth.host_based.config", "2", new String[] {}, new String[] {}) // ignored because empty
                .build();

        HostBasedAuthentication authService = new HostBasedAuthentication(settings, null);
        assertThat(authService.hbaConf(), is(createHbaConf(HBA_1, HBA_2)));
    }

    @Test
    public void testPSQLSslOption() {
        Map<String, String> sslConfig;

        sslConfig = ImmutableMap.<String, String>builder().putAll(HBA_1)
                .put(HostBasedAuthentication.SSL_OPTIONS.KEY, HostBasedAuthentication.SSL_OPTIONS.OPTIONAL.VALUE)
                .build();
        authService.updateHbaConfig(createHbaConf(sslConfig));
        assertThat(authService.getEntry("crate", new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, null)),
                not(Optional.empty()));
        assertThat(
                authService.getEntry("crate", new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, sslSession)),
                not(Optional.empty()));

        sslConfig = ImmutableMap.<String, String>builder().putAll(HBA_1)
                .put(HostBasedAuthentication.SSL_OPTIONS.KEY, HostBasedAuthentication.SSL_OPTIONS.REQUIRED.VALUE)
                .build();
        authService.updateHbaConfig(createHbaConf(sslConfig));
        assertThat(authService.getEntry("crate", new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, null)),
                is(Optional.empty()));
        assertThat(
                authService.getEntry("crate", new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, sslSession)),
                not(Optional.empty()));

        sslConfig = ImmutableMap.<String, String>builder().putAll(HBA_1)
                .put(HostBasedAuthentication.SSL_OPTIONS.KEY, HostBasedAuthentication.SSL_OPTIONS.NEVER.VALUE)
                .build();
        authService.updateHbaConfig(createHbaConf(sslConfig));
        assertThat(authService.getEntry("crate", new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, null)),
                not(Optional.empty()));
        assertThat(
                authService.getEntry("crate", new ConnectionProperties(LOCALHOST, Protocol.POSTGRES, sslSession)),
                is(Optional.empty()));
    }

    @Test
    public void testHttpSSLOption() throws Exception {
        Map<String, String> baseConfig = new HashMap<>();
        baseConfig.putAll(HBA_1);
        baseConfig.put(HostBasedAuthentication.KEY_PROTOCOL, "http");

        SSLSession sslSession = Mockito.mock(SSLSession.class);
        when(sslSession.getPeerCertificates()).thenReturn(new Certificate[0]);
        ConnectionProperties sslConnProperties = new ConnectionProperties(LOCALHOST, Protocol.HTTP, sslSession);
        ConnectionProperties noSslConnProperties = new ConnectionProperties(LOCALHOST, Protocol.HTTP, null);

        Map<String, String> sslConfig;

        sslConfig = ImmutableMap.<String, String>builder().putAll(baseConfig)
                .put(HostBasedAuthentication.SSL_OPTIONS.KEY, HostBasedAuthentication.SSL_OPTIONS.OPTIONAL.VALUE)
                .build();
        authService.updateHbaConfig(createHbaConf(sslConfig));
        assertThat(authService.getEntry("crate", noSslConnProperties), not(Optional.empty()));
        assertThat(authService.getEntry("crate", sslConnProperties), not(Optional.empty()));

        sslConfig = ImmutableMap.<String, String>builder().putAll(baseConfig)
                .put(HostBasedAuthentication.SSL_OPTIONS.KEY, HostBasedAuthentication.SSL_OPTIONS.REQUIRED.VALUE)
                .build();
        authService.updateHbaConfig(createHbaConf(sslConfig));
        assertThat(authService.getEntry("crate", noSslConnProperties), is(Optional.empty()));
        assertThat(authService.getEntry("crate", sslConnProperties), not(Optional.empty()));

        sslConfig = ImmutableMap.<String, String>builder().putAll(baseConfig)
                .put(HostBasedAuthentication.SSL_OPTIONS.KEY, HostBasedAuthentication.SSL_OPTIONS.NEVER.VALUE)
                .build();
        authService.updateHbaConfig(createHbaConf(sslConfig));
        assertThat(authService.getEntry("crate", noSslConnProperties), not(Optional.empty()));
        assertThat(authService.getEntry("crate", sslConnProperties), is(Optional.empty()));
    }
}