/*
 * 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.integration.ldap;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.junit.annotations.Network;
import org.junit.BeforeClass;

/**
 * This tests that configurations that contain two AD realms work correctly.
 * The required behaviour is that users from both realms (directory servers) can be authenticated using
 * just their userid (the AuthenticationService tries them in order)
 */
@Network
public class MultipleAdRealmTests extends AbstractAdLdapRealmTestCase {

    private static RealmConfig secondaryRealmConfig;

    @BeforeClass
    public static void setupSecondaryRealm() {
        // It's easier to test 2 realms when using file based role mapping, and for the purposes of
        // this test, there's no need to test native mappings.
        AbstractAdLdapRealmTestCase.roleMappings = realmConfig.selectRoleMappings(() -> true);

        // Pick a secondary realm that has the inverse value for 'loginWithCommonName' compare with the primary realm
        final List<RealmConfig> configs = Arrays.stream(RealmConfig.values())
                .filter(config -> config.loginWithCommonName != AbstractAdLdapRealmTestCase.realmConfig.loginWithCommonName)
                .collect(Collectors.toList());
        secondaryRealmConfig = randomFrom(configs);
        ESLoggerFactory.getLogger("test")
                .info("running test with secondary realm configuration [{}], with direct group to role mapping [{}]. Settings [{}]",
                        secondaryRealmConfig, secondaryRealmConfig.mapGroupsAsRoles, secondaryRealmConfig.settings.getAsMap());
    }

    @Override
    protected Settings nodeSettings(int nodeOrdinal) {
        Settings.Builder builder = Settings.builder();
        builder.put(super.nodeSettings(nodeOrdinal));

        Path store = getDataPath(TESTNODE_KEYSTORE);
        final Settings secondarySettings = super.buildRealmSettings(secondaryRealmConfig, store);
        secondarySettings.getAsMap().forEach((name, value) -> {
            name = name.replace(XPACK_SECURITY_AUTHC_REALMS_EXTERNAL, XPACK_SECURITY_AUTHC_REALMS_EXTERNAL + "2");
            builder.put(name, value);
        });

        return builder.build();
    }

    /**
     * Test that both realms support user login. Implementation wise, this means that if the first realm reject the authentication attempt,
     * then the second realm will be tried.
     * Because one realm is using "common name" (cn) for login, and the other uses the "userid" (sAMAccountName) [see
     * {@link #setupSecondaryRealm()}], this is simply a matter of checking that we can authenticate with both identifiers.
     */
    public void testCanAuthenticateAgainstBothRealms() throws IOException {
        assertAccessAllowed("Natasha Romanoff", "avengers");
        assertAccessAllowed("blackwidow", "avengers");
    }

}

@@ -335,16 +335,44 @@
 e.Path;%0A
+import java.util.ArrayList;%0A
 import j
@@ -388,16 +388,16 @@
 Arrays;%0A
-
 import j
@@ -1106,267 +1106,8 @@
 ) %7B%0A
-        // It's easier to test 2 realms when using file based role mapping, and for the purposes of%0A        // this test, there's no need to test native mappings.%0A        AbstractAdLdapRealmTestCase.roleMappings = realmConfig.selectRoleMappings(() -%3E true);%0A%0A
     
@@ -1697,16 +1697,16 @@
  %5B%7B%7D%5D%22,%0A
-
         
@@ -1820,24 +1820,410 @@
 getAsMap());
+%0A%0A        // It's easier to test 2 realms when using file based role mapping, and for the purposes of%0A        // this test, there's no need to test native mappings.%0A        AbstractAdLdapRealmTestCase.roleMappings = new ArrayList%3C%3E(realmConfig.selectRoleMappings(() -%3E true));%0A        AbstractAdLdapRealmTestCase.roleMappings.addAll(secondaryRealmConfig.selectRoleMappings(() -%3E true));
 %0A    %7D%0A%0A    

Fix problem with AD integration test