org.elasticsearch.xpack.security.authc.esnative.tool.SetupPasswordToolIT.java Source code

Java tutorial

Introduction

Here is the source code for org.elasticsearch.xpack.security.authc.esnative.tool.SetupPasswordToolIT.java

Source

/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License;
 * you may not use this file except in compliance with the Elastic License.
 */
package org.elasticsearch.xpack.security.authc.esnative.tool;

import org.apache.http.message.BasicHeader;
import org.elasticsearch.cli.MockTerminal;
import org.elasticsearch.client.Response;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.network.InetAddresses;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.test.rest.ESRestTestCase;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;

public class SetupPasswordToolIT extends ESRestTestCase {

    @Override
    protected Settings restClientSettings() {
        String token = basicAuthHeaderValue("test_admin", new SecureString("x-pack-test-password".toCharArray()));
        return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build();
    }

    @SuppressWarnings("unchecked")
    public void testSetupPasswordToolAutoSetup() throws Exception {
        final String testConfigDir = System.getProperty("tests.config.dir");
        logger.info("--> CONF: {}", testConfigDir);
        final Path configPath = PathUtils.get(testConfigDir);
        setSystemPropsForTool(configPath);

        Response nodesResponse = client().performRequest("GET", "/_nodes/http");
        Map<String, Object> nodesMap = entityAsMap(nodesResponse);

        Map<String, Object> nodes = (Map<String, Object>) nodesMap.get("nodes");
        Map<String, Object> firstNode = (Map<String, Object>) nodes.entrySet().iterator().next().getValue();
        Map<String, Object> firstNodeHttp = (Map<String, Object>) firstNode.get("http");
        String nodePublishAddress = (String) firstNodeHttp.get("publish_address");
        final int lastColonIndex = nodePublishAddress.lastIndexOf(':');
        InetAddress actualPublishAddress = InetAddresses.forString(nodePublishAddress.substring(0, lastColonIndex));
        InetAddress expectedPublishAddress = new NetworkService(Collections.emptyList())
                .resolvePublishHostAddresses(Strings.EMPTY_ARRAY);
        final int port = Integer.valueOf(nodePublishAddress.substring(lastColonIndex + 1));

        List<String> lines = Files.readAllLines(configPath.resolve("elasticsearch.yml"));
        lines = lines.stream()
                .filter(s -> s.startsWith("http.port") == false && s.startsWith("http.publish_port") == false)
                .collect(Collectors.toList());
        lines.add(randomFrom("http.port", "http.publish_port") + ": " + port);
        if (expectedPublishAddress.equals(actualPublishAddress) == false) {
            lines.add("http.publish_address: " + InetAddresses.toAddrString(actualPublishAddress));
        }
        Files.write(configPath.resolve("elasticsearch.yml"), lines, StandardCharsets.UTF_8,
                StandardOpenOption.TRUNCATE_EXISTING);

        MockTerminal mockTerminal = new MockTerminal();
        SetupPasswordTool tool = new SetupPasswordTool();
        final int status;
        if (randomBoolean()) {
            mockTerminal.addTextInput("y"); // answer yes to continue prompt
            status = tool.main(new String[] { "auto" }, mockTerminal);
        } else {
            status = tool.main(new String[] { "auto", "--batch" }, mockTerminal);
        }
        assertEquals(0, status);
        String output = mockTerminal.getOutput();
        logger.info("CLI TOOL OUTPUT:\n{}", output);
        String[] outputLines = output.split("\\n");
        Map<String, String> userPasswordMap = new HashMap<>();
        Arrays.asList(outputLines).forEach(line -> {
            if (line.startsWith("PASSWORD ")) {
                String[] pieces = line.split(" ");
                String user = pieces[1];
                String password = pieces[pieces.length - 1];
                logger.info("user [{}] password [{}]", user, password);
                userPasswordMap.put(user, password);
            }
        });

        assertEquals(4, userPasswordMap.size());
        userPasswordMap.entrySet().forEach(entry -> {
            final String basicHeader = "Basic " + Base64.getEncoder()
                    .encodeToString((entry.getKey() + ":" + entry.getValue()).getBytes(StandardCharsets.UTF_8));
            try {
                Response authenticateResponse = client().performRequest("GET", "/_xpack/security/_authenticate",
                        new BasicHeader("Authorization", basicHeader));
                assertEquals(200, authenticateResponse.getStatusLine().getStatusCode());
                Map<String, Object> userInfoMap = entityAsMap(authenticateResponse);
                assertEquals(entry.getKey(), userInfoMap.get("username"));
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        });
    }

    @SuppressForbidden(reason = "need to set sys props for CLI tool")
    private void setSystemPropsForTool(Path configPath) {
        System.setProperty("es.path.conf", configPath.toString());
        System.setProperty("es.path.home", configPath.getParent().toString());
    }
}