hudson.plugins.active_directory.docker.TheFlintstonesTest.java Source code

Java tutorial

Introduction

Here is the source code for hudson.plugins.active_directory.docker.TheFlintstonesTest.java

Source

/*
 * The MIT License
 *
 * Copyright (c) 2017, Felix Belzunce Arcos, CloudBees, Inc., and contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package hudson.plugins.active_directory.docker;

import hudson.plugins.active_directory.ActiveDirectoryDomain;
import hudson.plugins.active_directory.ActiveDirectorySecurityRealm;
import hudson.plugins.active_directory.GroupLookupStrategy;
import hudson.util.Secret;
import jenkins.model.Jenkins;
import org.acegisecurity.AuthenticationServiceException;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.apache.commons.io.FileUtils;
import org.jenkinsci.test.acceptance.docker.DockerContainer;
import org.jenkinsci.test.acceptance.docker.DockerFixture;
import org.jenkinsci.test.acceptance.docker.DockerRule;

import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;

import javax.naming.CommunicationException;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertTrue;

import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;

import hudson.security.GroupDetails;
import hudson.util.RingBufferLogHandler;
import org.jvnet.hudson.test.recipes.LocalData;

/**
 * Integration tests with Docker
 */
public class TheFlintstonesTest {

    @Rule
    public DockerRule<TheFlintstones> docker = new DockerRule<>(TheFlintstones.class);

    @Rule
    public JenkinsRule j = new JenkinsRule();

    public final static String AD_DOMAIN = "samdom.example.com";
    public final static String AD_MANAGER_DN = "CN=Administrator,CN=Users,DC=SAMDOM,DC=EXAMPLE,DC=COM";
    public final static String AD_MANAGER_DN_PASSWORD = "ia4uV1EeKait";
    public final static int MAX_RETRIES = 30;
    public String dockerIp;
    public int dockerPort;

    public void dynamicSetUp() throws Exception {
        TheFlintstones d = docker.get();
        dockerIp = d.ipBound(3268);
        dockerPort = d.port(3268);
        ActiveDirectoryDomain activeDirectoryDomain = new ActiveDirectoryDomain(AD_DOMAIN,
                dockerIp + ":" + dockerPort, null, AD_MANAGER_DN, AD_MANAGER_DN_PASSWORD);
        List<ActiveDirectoryDomain> domains = new ArrayList<>(1);
        domains.add(activeDirectoryDomain);
        ActiveDirectorySecurityRealm activeDirectorySecurityRealm = new ActiveDirectorySecurityRealm(null, domains,
                null, null, null, null, GroupLookupStrategy.RECURSIVE, false, true, null, false, null, null);
        j.getInstance().setSecurityRealm(activeDirectorySecurityRealm);
        while (!FileUtils.readFileToString(d.getLogfile()).contains("custom (exit status 0; expected)")) {
            Thread.sleep(1000);
        }
        UserDetails userDetails = null;
        int i = 0;
        while (i < MAX_RETRIES && userDetails == null) {
            try {
                userDetails = j.jenkins.getSecurityRealm().loadUserByUsername("Fred");
            } catch (AuthenticationServiceException e) {
                Thread.sleep(1000);
            }
            i++;
        }
    }

    public void manualSetUp() throws Exception {
        TheFlintstones d = docker.get();
        dockerIp = d.ipBound(3268);
        dockerPort = d.port(3268);

        ActiveDirectorySecurityRealm activeDirectorySecurityRealm = (ActiveDirectorySecurityRealm) j.jenkins
                .getSecurityRealm();
        for (ActiveDirectoryDomain activeDirectoryDomain : activeDirectorySecurityRealm.getDomains()) {
            activeDirectoryDomain.bindPassword = Secret.fromString(AD_MANAGER_DN_PASSWORD);
            activeDirectoryDomain.servers = dockerIp + ":" + dockerPort;
        }

        while (!FileUtils.readFileToString(d.getLogfile()).contains("custom (exit status 0; expected)")) {
            Thread.sleep(1000);
        }
        UserDetails userDetails = null;
        int i = 0;
        while (i < MAX_RETRIES && userDetails == null) {
            try {
                userDetails = j.jenkins.getSecurityRealm().loadUserByUsername("Fred");
            } catch (AuthenticationServiceException e) {
                Thread.sleep(1000);
            }
            i++;
        }
    }

    @Test
    public void simpleLoginSuccessful() throws Exception {
        dynamicSetUp();
        UserDetails userDetails = j.jenkins.getSecurityRealm().loadUserByUsername("Fred");
        assertThat(userDetails.getUsername(), is("Fred"));
    }

    @Test
    public void simpleLoginFails() throws Exception {
        dynamicSetUp();
        try {
            j.jenkins.getSecurityRealm().loadUserByUsername("Homer");
        } catch (UsernameNotFoundException e) {
            assertTrue(e.getMessage()
                    .contains("Authentication was successful but cannot locate the user information for Homer"));
        }
    }

    @Issue("JENKINS-36148")
    @Test
    public void checkDomainHealth() throws Exception {
        dynamicSetUp();
        ActiveDirectorySecurityRealm securityRealm = (ActiveDirectorySecurityRealm) Jenkins.getInstance()
                .getSecurityRealm();
        ActiveDirectoryDomain domain = securityRealm.getDomain(AD_DOMAIN);
        assertEquals("NS: dc1.samdom.example.com.", domain.getRecordFromDomain().toString().trim());
    }

    @Issue("JENKINS-36148")
    @Test
    public void validateCustomDomainController() throws ServletException, NamingException, IOException, Exception {
        dynamicSetUp();
        ActiveDirectoryDomain.DescriptorImpl adDescriptor = new ActiveDirectoryDomain.DescriptorImpl();
        assertEquals("OK: Success", adDescriptor.doValidateTest(AD_DOMAIN, dockerIp + ":" + dockerPort, null,
                AD_MANAGER_DN, AD_MANAGER_DN_PASSWORD, null).toString().trim());
    }

    @Issue("JENKINS-36148")
    @Test
    public void validateDomain() throws ServletException, NamingException, IOException, Exception {
        dynamicSetUp();
        ActiveDirectoryDomain.DescriptorImpl adDescriptor = new ActiveDirectoryDomain.DescriptorImpl();
        assertEquals("OK: Success",
                adDescriptor.doValidateTest(AD_DOMAIN, null, null, AD_MANAGER_DN, AD_MANAGER_DN_PASSWORD, null)
                        .toString().trim());

    }

    @Issue("JENKINS-45576")
    @Test
    public void loadGroupFromGroupname() throws Exception {
        dynamicSetUp();
        String groupname = "The Rubbles";
        GroupDetails group = j.jenkins.getSecurityRealm().loadGroupByGroupname(groupname);
        assertThat(group.getName(), is("The Rubbles"));
    }

    @Issue("JENKINS-45576")
    @Test
    public void loadGroupFromAlias() throws Exception {
        dynamicSetUp();
        // required to monitor the log messages, removing this line the test will fail
        List<String> logMessages = captureLogMessages(20);

        String aliasname = "Rubbles";
        boolean isAlias = false;
        try {
            j.jenkins.getSecurityRealm().loadGroupByGroupname(aliasname);
        } catch (Exception e) {
        } finally {
            Collection<String> filter = Collections2.filter(logMessages,
                    Predicates.containsPattern("JENKINS-45576"));
            isAlias = !filter.isEmpty();
        }

        assertTrue(isAlias);
    }

    private List<String> captureLogMessages(int size) {
        final List<String> logMessages = new ArrayList<>(size);
        Logger logger = Logger.getLogger("");
        logger.setLevel(Level.ALL);

        RingBufferLogHandler ringHandler = new RingBufferLogHandler(size) {

            final Formatter f = new SimpleFormatter(); // placeholder instance for what should have been a static method perhaps

            @Override
            public synchronized void publish(LogRecord record) {
                super.publish(record);
                String message = f.formatMessage(record);
                Throwable x = record.getThrown();
                logMessages.add(message == null && x != null ? x.toString() : message);
            }
        };
        logger.addHandler(ringHandler);

        return logMessages;
    }

    // ReadResolve tlsConfiguration migration tests

    @LocalData
    @Test
    public void testSimpleLoginSuccessfulAfterReadResolveTlsConfigurationSingleDomain() throws Exception {
        manualSetUp();
        UserDetails userDetails = j.jenkins.getSecurityRealm().loadUserByUsername("Fred");
        assertThat(userDetails.getUsername(), is("Fred"));
    }

    @LocalData
    @Test
    public void testSimpleLoginFailsAfterReadResolveTlsConfigurationSingleDomain() throws Exception {
        manualSetUp();
        try {
            j.jenkins.getSecurityRealm().loadUserByUsername("Homer");
        } catch (UsernameNotFoundException e) {
            assertTrue(e.getMessage()
                    .contains("Authentication was successful but cannot locate the user information for Homer"));
        }
    }

    @LocalData
    @Test
    public void testSimpleLoginSuccessAfterReadResolveTlsConfigurationMultipleDomainsOneDomain() throws Exception {
        manualSetUp();
        UserDetails userDetails = j.jenkins.getSecurityRealm().loadUserByUsername("Fred");
        assertThat(userDetails.getUsername(), is("Fred"));
    }

    @LocalData
    @Test
    public void testSimpleLoginFailsAfterReadResolveTlsConfigurationMultipleDomainsOneDomain() throws Exception {
        manualSetUp();
        try {
            j.jenkins.getSecurityRealm().loadUserByUsername("Homer");
        } catch (UsernameNotFoundException e) {
            assertTrue(e.getMessage()
                    .contains("Authentication was successful but cannot locate the user information for Homer"));
        }
    }

    // TlsConfiguration tests
    @LocalData
    @Test
    public void testSimpleLoginSuccessfulTrustingAllCertificates() throws Exception {
        manualSetUp();
        UserDetails userDetails = j.jenkins.getSecurityRealm().loadUserByUsername("Fred");
        assertThat(userDetails.getUsername(), is("Fred"));
    }

    @LocalData
    @Test
    public void testSimpleLoginFailsTrustingJDKTrustStore() throws Exception {
        try {
            manualSetUp();
        } catch (CommunicationException e) {
            assertTrue(e.getMessage().contains("simple bind failed"));
        }
    }

    @DockerFixture(id = "ad-dc", ports = { 135, 138, 445, 39, 464, 389, 3268 }, udpPorts = {
            53 }, matchHostPorts = true)
    public static class TheFlintstones extends DockerContainer {

    }

}