Re-enable OpenLDAP tests and run against vagrant instance (elastic/x-pack-elasticsearch#2121)

This commit re-enables the OpenLDAP tests that were previously running against a one-off instance
in AWS but now run against a vagrant fixture. There were some IntegTests that would run against the
OpenLDAP instance randomly but with this change they no longer run against OpenLDAP. This is ok as
the functionality that is tested by these has coverage elsewhere.

relates elastic/x-pack-elasticsearch#1823

Original commit: elastic/x-pack-elasticsearch@ac9bc82297
This commit is contained in:
Jay Modi 2017-08-04 09:44:08 -06:00 committed by GitHub
parent 39bc5886f2
commit 8b0fb5eae8
20 changed files with 575 additions and 192 deletions

View File

@ -31,7 +31,11 @@ import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -89,33 +93,6 @@ public abstract class AbstractAdLdapRealmTestCase extends SecurityIntegTestCase
) )
}; };
private static final RoleMappingEntry[] OLDAP_ROLE_MAPPING = new RoleMappingEntry[] {
new RoleMappingEntry(
"SHIELD: [ \"cn=SHIELD,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com\" ]",
"{ \"roles\": [\"SHIELD\"], \"enabled\":true, \"rules\":" +
" {\"field\": {\"groups\": \"cn=SHIELD,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com\" } } }"
),
new RoleMappingEntry(
"Avengers: [ \"cn=Avengers,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com\" ]",
"{ \"roles\": [\"Avengers\"], \"enabled\":true, \"rules\":" +
" {\"field\": {\"groups\": \"cn=Avengers,ou=people,*\" } } }"
),
new RoleMappingEntry(
"Gods: [ \"cn=Gods,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com\" ]",
"{ \"roles\" : [ \"Gods\" ], \"enabled\":true, \"rules\" : { \"any\": [" +
" {\"field\": {\"groups\": \"cn=Gods,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com\" } }," +
" {\"field\": {\"groups\": \"cn=Deities,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com\" } } " +
"] } }"
),
new RoleMappingEntry(
"Philanthropists: [ \"cn=Philanthropists,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com\" ]",
"{ \"roles\" : [ \"Philanthropists\" ], \"enabled\":true, \"rules\" : { \"all\": [" +
" { \"field\": { \"groups\" : \"cn=Philanthropists,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com\" } }, " +
" { \"field\": { \"realm.name\" : \"external\" } } " +
"] } }"
)
};
protected static final String TESTNODE_KEYSTORE = "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"; protected static final String TESTNODE_KEYSTORE = "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks";
protected static RealmConfig realmConfig; protected static RealmConfig realmConfig;
protected static List<RoleMappingEntry> roleMappings; protected static List<RoleMappingEntry> roleMappings;
@ -141,7 +118,42 @@ public abstract class AbstractAdLdapRealmTestCase extends SecurityIntegTestCase
Path store = getDataPath(TESTNODE_KEYSTORE); Path store = getDataPath(TESTNODE_KEYSTORE);
Settings.Builder builder = Settings.builder(); Settings.Builder builder = Settings.builder();
if (useGlobalSSL) { if (useGlobalSSL) {
builder.put(super.nodeSettings(nodeOrdinal).filter((s) -> s.startsWith("xpack.ssl.") == false)); // don't use filter since it returns a prefixed secure setting instead of mock!
Settings settingsToAdd = super.nodeSettings(nodeOrdinal);
for (Map.Entry<String, String> settingsEntry : settingsToAdd.getAsMap().entrySet()) {
if (settingsEntry.getKey().startsWith("xpack.ssl.") == false) {
builder.put(settingsEntry.getKey(), settingsEntry.getValue());
}
}
MockSecureSettings mockSecureSettings = (MockSecureSettings) Settings.builder().put(settingsToAdd).getSecureSettings();
if (mockSecureSettings != null) {
MockSecureSettings filteredSecureSettings = new MockSecureSettings();
builder.setSecureSettings(filteredSecureSettings);
for (String secureSetting : mockSecureSettings.getSettingNames()) {
if (secureSetting.startsWith("xpack.ssl.") == false) {
SecureString secureString = mockSecureSettings.getString(secureSetting);
if (secureString == null) {
final byte[] fileBytes;
try (InputStream in = mockSecureSettings.getFile(secureSetting);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
int numRead;
byte[] bytes = new byte[1024];
while ((numRead = in.read(bytes)) != -1) {
byteArrayOutputStream.write(bytes, 0, numRead);
}
byteArrayOutputStream.flush();
fileBytes = byteArrayOutputStream.toByteArray();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
filteredSecureSettings.setFile(secureSetting, fileBytes);
} else {
filteredSecureSettings.setString(secureSetting, new String(secureString.getChars()));
}
}
}
}
addSslSettingsForStore(builder, store, "testnode"); addSslSettingsForStore(builder, store, "testnode");
} else { } else {
builder.put(super.nodeSettings(nodeOrdinal)); builder.put(super.nodeSettings(nodeOrdinal));
@ -166,8 +178,7 @@ public abstract class AbstractAdLdapRealmTestCase extends SecurityIntegTestCase
return; return;
} }
SecurityClient securityClient = securityClient(); SecurityClient securityClient = securityClient();
Map<String, ActionFuture<PutRoleMappingResponse>> futures Map<String, ActionFuture<PutRoleMappingResponse>> futures = new LinkedHashMap<>(content.size());
= new LinkedHashMap<>(content.size());
for (int i = 0; i < content.size(); i++) { for (int i = 0; i < content.size(); i++) {
final String name = "external_" + i; final String name = "external_" + i;
final PutRoleMappingRequestBuilder builder = securityClient.preparePutRoleMapping( final PutRoleMappingRequestBuilder builder = securityClient.preparePutRoleMapping(
@ -393,17 +404,6 @@ public abstract class AbstractAdLdapRealmTestCase extends SecurityIntegTestCase
.put(XPACK_SECURITY_AUTHC_REALMS_EXTERNAL + ".url", "ldaps://ad.test.elasticsearch.com:636") .put(XPACK_SECURITY_AUTHC_REALMS_EXTERNAL + ".url", "ldaps://ad.test.elasticsearch.com:636")
.putArray(XPACK_SECURITY_AUTHC_REALMS_EXTERNAL + ".user_dn_templates", .putArray(XPACK_SECURITY_AUTHC_REALMS_EXTERNAL + ".user_dn_templates",
"cn={0},CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com") "cn={0},CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com")
.build()),
OLDAP(false, OLDAP_ROLE_MAPPING,
Settings.builder()
.put(XPACK_SECURITY_AUTHC_REALMS_EXTERNAL + ".type", LdapRealm.LDAP_TYPE)
.put(XPACK_SECURITY_AUTHC_REALMS_EXTERNAL + ".url", "ldaps://54.200.235.244:636")
.put(XPACK_SECURITY_AUTHC_REALMS_EXTERNAL + ".group_search.base_dn",
"ou=people, dc=oldap, dc=test, dc=elasticsearch, dc=com")
.put(XPACK_SECURITY_AUTHC_REALMS_EXTERNAL + ".group_search.scope", randomBoolean() ? SUB_TREE : ONE_LEVEL)
.putArray(XPACK_SECURITY_AUTHC_REALMS_EXTERNAL + ".user_dn_templates",
"uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com")
.build()); .build());
final boolean mapGroupsAsRoles; final boolean mapGroupsAsRoles;

View File

@ -5,8 +5,6 @@
*/ */
package org.elasticsearch.integration.ldap; package org.elasticsearch.integration.ldap;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util.LuceneTestCase.AwaitsFix;
import org.elasticsearch.test.junit.annotations.Network; import org.elasticsearch.test.junit.annotations.Network;
import java.io.IOException; import java.io.IOException;
@ -16,7 +14,6 @@ import java.io.IOException;
* The super class will provide appropriate group mappings via configGroupMappings() * The super class will provide appropriate group mappings via configGroupMappings()
*/ */
@Network @Network
@AwaitsFix(bugUrl="https://github.com/elastic/x-pack-elasticsearch/issues/1823")
public class GroupMappingTests extends AbstractAdLdapRealmTestCase { public class GroupMappingTests extends AbstractAdLdapRealmTestCase {
public void testAuthcAuthz() throws IOException { public void testAuthcAuthz() throws IOException {
String avenger = realmConfig.loginWithCommonName ? "Natasha Romanoff" : "blackwidow"; String avenger = realmConfig.loginWithCommonName ? "Natasha Romanoff" : "blackwidow";

View File

@ -5,7 +5,6 @@
*/ */
package org.elasticsearch.integration.ldap; package org.elasticsearch.integration.ldap;
import org.apache.lucene.util.LuceneTestCase.AwaitsFix;
import org.elasticsearch.test.junit.annotations.Network; import org.elasticsearch.test.junit.annotations.Network;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -16,7 +15,6 @@ import java.util.ArrayList;
* This tests the mapping of multiple groups to a role in a file based role-mapping * This tests the mapping of multiple groups to a role in a file based role-mapping
*/ */
@Network @Network
@AwaitsFix(bugUrl="https://github.com/elastic/x-pack-elasticsearch/issues/1823")
public class MultiGroupMappingTests extends AbstractAdLdapRealmTestCase { public class MultiGroupMappingTests extends AbstractAdLdapRealmTestCase {
@BeforeClass @BeforeClass

View File

@ -5,7 +5,6 @@
*/ */
package org.elasticsearch.integration.ldap; package org.elasticsearch.integration.ldap;
import org.apache.lucene.util.LuceneTestCase.AwaitsFix;
import org.elasticsearch.common.logging.ESLoggerFactory; import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.junit.annotations.Network; import org.elasticsearch.test.junit.annotations.Network;
@ -23,7 +22,6 @@ import java.util.stream.Collectors;
* just their userid (the AuthenticationService tries them in order) * just their userid (the AuthenticationService tries them in order)
*/ */
@Network @Network
@AwaitsFix(bugUrl="https://github.com/elastic/x-pack-elasticsearch/issues/1823")
public class MultipleAdRealmTests extends AbstractAdLdapRealmTestCase { public class MultipleAdRealmTests extends AbstractAdLdapRealmTestCase {
private static RealmConfig secondaryRealmConfig; private static RealmConfig secondaryRealmConfig;

View File

@ -32,7 +32,7 @@ public abstract class GroupsResolverTestCase extends ESTestCase {
@Before @Before
public void setUpLdapConnection() throws Exception { public void setUpLdapConnection() throws Exception {
Path truststore = getDataPath("../ldap/support/ldaptrust.jks"); Path truststore = getDataPath("/org/elasticsearch/xpack/security/authc/ldap/support/ldaptrust.jks");
this.ldapConnection = LdapTestUtils.openConnection(ldapUrl(), bindDN(), bindPassword(), truststore); this.ldapConnection = LdapTestUtils.openConnection(ldapUrl(), bindDN(), bindPassword(), truststore);
} }

View File

@ -32,15 +32,11 @@ import org.elasticsearch.test.junit.annotations.Network;
import org.junit.Before; import org.junit.Before;
import java.nio.file.Path; import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.isEmptyString;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
@ -385,7 +381,6 @@ public class LdapUserSearchSessionFactoryTests extends LdapTestCase {
} }
@Network @Network
@AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1823")
public void testUserSearchWithActiveDirectory() throws Exception { public void testUserSearchWithActiveDirectory() throws Exception {
String groupSearchBase = "DC=ad,DC=test,DC=elasticsearch,DC=com"; String groupSearchBase = "DC=ad,DC=test,DC=elasticsearch,DC=com";
String userSearchBase = "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com"; String userSearchBase = "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com";
@ -397,7 +392,7 @@ public class LdapUserSearchSessionFactoryTests extends LdapTestCase {
.put("user_search.base_dn", userSearchBase) .put("user_search.base_dn", userSearchBase)
.put("bind_dn", "ironman@ad.test.elasticsearch.com") .put("bind_dn", "ironman@ad.test.elasticsearch.com")
.put("bind_password", ActiveDirectorySessionFactoryTests.PASSWORD) .put("bind_password", ActiveDirectorySessionFactoryTests.PASSWORD)
.put("user_search.attribute", "cn") .put("user_search.filter", "(cn={0})")
.put("user_search.pool.enabled", randomBoolean()) .put("user_search.pool.enabled", randomBoolean())
.build(); .build();
Settings.Builder builder = Settings.builder() Settings.Builder builder = Settings.builder()
@ -438,50 +433,6 @@ public class LdapUserSearchSessionFactoryTests extends LdapTestCase {
} }
} }
@Network
@AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1823")
public void testUserSearchwithBindUserOpenLDAP() throws Exception {
String groupSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
String userSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
RealmConfig config = new RealmConfig("oldap-test", Settings.builder()
.put(LdapTestCase.buildLdapSettings(new String[] { OpenLdapTests.OPEN_LDAP_URL }, Strings.EMPTY_ARRAY, groupSearchBase,
LdapSearchScope.ONE_LEVEL))
.put("user_search.base_dn", userSearchBase)
.put("bind_dn", "uid=blackwidow,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com")
.put("bind_password", OpenLdapTests.PASSWORD)
.put("user_search.pool.enabled", randomBoolean())
.build(), globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings));
Settings.Builder builder = Settings.builder()
.put(globalSettings);
for (Map.Entry<String, String> entry : config.settings().getAsMap().entrySet()) {
builder.put("xpack.security.authc.realms.ldap." + entry.getKey(), entry.getValue());
}
Settings settings = builder.build();
sslService = new SSLService(settings, new Environment(settings));
LdapUserSearchSessionFactory sessionFactory = new LdapUserSearchSessionFactory(config, sslService);
String[] users = new String[] { "cap", "hawkeye", "hulk", "ironman", "thor" };
try {
for (String user : users) {
//auth
try (LdapSession ldap = session(sessionFactory, user, new SecureString(OpenLdapTests.PASSWORD))) {
assertThat(ldap.userDn(), is(equalTo(new MessageFormat("uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com",
Locale.ROOT).format(new Object[]{user}, new StringBuffer(), null).toString())));
assertThat(groups(ldap), hasItem(containsString("Avengers")));
}
//lookup
try (LdapSession ldap = unauthenticatedSession(sessionFactory, user)) {
assertThat(ldap.userDn(), is(equalTo(new MessageFormat("uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com",
Locale.ROOT).format(new Object[]{user}, new StringBuffer(), null).toString())));
assertThat(groups(ldap), hasItem(containsString("Avengers")));
}
}
} finally {
sessionFactory.close();
}
}
public void testConnectionPoolDefaultSettings() throws Exception { public void testConnectionPoolDefaultSettings() throws Exception {
String groupSearchBase = "o=sevenSeas"; String groupSearchBase = "o=sevenSeas";
String userSearchBase = "o=sevenSeas"; String userSearchBase = "o=sevenSeas";

View File

@ -5,13 +5,6 @@
*/ */
package org.elasticsearch.xpack.security.authc.ldap.support; package org.elasticsearch.xpack.security.authc.ldap.support;
import javax.security.auth.DestroyFailedException;
import java.io.IOException;
import java.nio.file.Path;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -19,17 +12,10 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import com.unboundid.ldap.sdk.Attribute; import com.unboundid.ldap.sdk.Attribute;
import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.ldap.sdk.LDAPException;
import org.bouncycastle.operator.OperatorCreationException;
import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.xpack.security.authc.ldap.LdapTestUtils;
import org.elasticsearch.xpack.security.authc.ldap.OpenLdapTests;
import org.junit.After;
import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
@ -42,7 +28,6 @@ public class LdapMetaDataResolverTests extends ESTestCase {
private static final String HAWKEYE_DN = "uid=hawkeye,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; private static final String HAWKEYE_DN = "uid=hawkeye,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
private LdapMetaDataResolver resolver; private LdapMetaDataResolver resolver;
private LDAPConnection connection;
public void testParseSettings() throws Exception { public void testParseSettings() throws Exception {
resolver = new LdapMetaDataResolver(Settings.builder().putArray("metadata", "cn", "uid").build(), false); resolver = new LdapMetaDataResolver(Settings.builder().putArray("metadata", "cn", "uid").build(), false);
@ -85,52 +70,9 @@ public class LdapMetaDataResolverTests extends ESTestCase {
assertThat(map.get("uid"), equalTo("hawkeye")); assertThat(map.get("uid"), equalTo("hawkeye"));
} }
@Network
@AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1823")
public void testResolveSingleValuedAttributeFromConnection() throws Exception {
resolver = new LdapMetaDataResolver(Arrays.asList("givenName", "sn"), true);
setupOpenLdapConnection();
final Map<String, Object> map = resolve(null);
assertThat(map.size(), equalTo(2));
assertThat(map.get("givenName"), equalTo("Clint"));
assertThat(map.get("sn"), equalTo("Barton"));
}
@Network
@AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1823")
public void testResolveMultiValuedAttributeFromConnection() throws Exception {
resolver = new LdapMetaDataResolver(Arrays.asList("objectClass"), true);
setupOpenLdapConnection();
final Map<String, Object> map = resolve(null);
assertThat(map.size(), equalTo(1));
assertThat(map.get("objectClass"), instanceOf(List.class));
assertThat((List<?>) map.get("objectClass"), contains("top", "posixAccount", "inetOrgPerson"));
}
@Network
@AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1823")
public void testResolveMissingAttributeFromConnection() throws Exception {
resolver = new LdapMetaDataResolver(Arrays.asList("alias"), true);
setupOpenLdapConnection();
final Map<String, Object> map = resolve(null);
assertThat(map.size(), equalTo(0));
}
private Map<String, Object> resolve(Collection<Attribute> attributes) throws Exception { private Map<String, Object> resolve(Collection<Attribute> attributes) throws Exception {
final PlainActionFuture<Map<String, Object>> future = new PlainActionFuture<>(); final PlainActionFuture<Map<String, Object>> future = new PlainActionFuture<>();
resolver.resolve(connection, HAWKEYE_DN, TimeValue.timeValueSeconds(1), logger, attributes, future); resolver.resolve(null, HAWKEYE_DN, TimeValue.timeValueSeconds(1), logger, attributes, future);
return future.get(); return future.get();
} }
private void setupOpenLdapConnection() throws Exception {
Path truststore = getDataPath("./ldaptrust.jks");
this.connection = LdapTestUtils.openConnection(OpenLdapTests.OPEN_LDAP_URL, HAWKEYE_DN, OpenLdapTests.PASSWORD, truststore);
}
@After
public void tearDownLdapConnection() throws Exception {
if (connection != null) {
connection.close();
}
}
} }

View File

@ -0,0 +1,22 @@
apply plugin: 'elasticsearch.standalone-test'
apply plugin: 'elasticsearch.vagrantsupport'
dependencies {
testCompile project(path: ':x-pack-elasticsearch:plugin', configuration: 'runtime')
testCompile project(path: ':x-pack-elasticsearch:plugin', configuration: 'testArtifacts')
}
task openLdapFixture {
dependsOn "vagrantCheckVersion", "virtualboxCheckVersion", ":x-pack-elasticsearch:test:openldap-fixture:up"
}
if (project.rootProject.vagrantSupported) {
test.dependsOn openLdapFixture
} else {
test.enabled = false
}
namingConventions {
// integ tests use Tests instead of IT
skipIntegTestInDisguise = true
}

View File

@ -3,77 +3,88 @@
* or more contributor license agreements. Licensed under the Elastic License; * or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
package org.elasticsearch.xpack.security.authc.ldap; package org.elasticsearch.test;
import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.LDAPException;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util.LuceneTestCase.AwaitsFix;
import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.util.concurrent.UncategorizedExecutionException; import org.elasticsearch.common.util.concurrent.UncategorizedExecutionException;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.RealmConfig;
import org.elasticsearch.xpack.security.authc.ldap.LdapSessionFactory;
import org.elasticsearch.xpack.security.authc.ldap.LdapTestUtils;
import org.elasticsearch.xpack.security.authc.ldap.support.LdapMetaDataResolver;
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSearchScope; import org.elasticsearch.xpack.security.authc.ldap.support.LdapSearchScope;
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSession; import org.elasticsearch.xpack.security.authc.ldap.support.LdapSession;
import org.elasticsearch.xpack.security.authc.ldap.support.LdapTestCase; import org.elasticsearch.xpack.security.authc.ldap.support.LdapTestCase;
import org.elasticsearch.xpack.security.authc.ldap.support.SessionFactory; import org.elasticsearch.xpack.security.authc.ldap.support.SessionFactory;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.xpack.ssl.SSLService; import org.elasticsearch.xpack.ssl.SSLService;
import org.elasticsearch.xpack.ssl.VerificationMode; import org.elasticsearch.xpack.ssl.VerificationMode;
import org.junit.Before; import org.junit.Before;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.instanceOf;
@Network
@AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1823")
public class OpenLdapTests extends ESTestCase { public class OpenLdapTests extends ESTestCase {
public static final String OPEN_LDAP_URL = "ldaps://54.200.235.244:636"; public static final String OPEN_LDAP_URL = "ldaps://localhost:60636";
public static final String PASSWORD = "NickFuryHeartsES"; public static final String PASSWORD = "NickFuryHeartsES";
public static final SecureString PASSWORD_SECURE_STRING = new SecureString(PASSWORD.toCharArray()); private static final String HAWKEYE_DN = "uid=hawkeye,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
public static final String LDAPTRUST_PATH = "/org/elasticsearch/xpack/security/authc/ldap/support/ldaptrust.jks";
private static final SecureString PASSWORD_SECURE_STRING = new SecureString(PASSWORD.toCharArray());
private boolean useGlobalSSL; private boolean useGlobalSSL;
private SSLService sslService; private SSLService sslService;
private Settings globalSettings; private Settings globalSettings;
@Override
public boolean enableWarningsCheck() {
return false;
}
@Before @Before
public void initializeSslSocketFactory() throws Exception { public void initializeSslSocketFactory() throws Exception {
Path truststore = getDataPath("../ldap/support/ldaptrust.jks"); Path truststore = getDataPath(LDAPTRUST_PATH);
/* /*
* Prior to each test we reinitialize the socket factory with a new SSLService so that we get a new SSLContext. * Prior to each test we reinitialize the socket factory with a new SSLService so that we get a new SSLContext.
* If we re-use a SSLContext, previously connected sessions can get re-established which breaks hostname * If we re-use a SSLContext, previously connected sessions can get re-established which breaks hostname
* verification tests since a re-established connection does not perform hostname verification. * verification tests since a re-established connection does not perform hostname verification.
*/ */
useGlobalSSL = randomBoolean(); useGlobalSSL = randomBoolean();
MockSecureSettings mockSecureSettings = new MockSecureSettings();
Settings.Builder builder = Settings.builder().put("path.home", createTempDir()); Settings.Builder builder = Settings.builder().put("path.home", createTempDir());
if (useGlobalSSL) { if (useGlobalSSL) {
builder.put("xpack.ssl.truststore.path", truststore) builder.put("xpack.ssl.truststore.path", truststore);
.put("xpack.ssl.truststore.password", "changeit"); mockSecureSettings.setString("xpack.ssl.truststore.secure_password", "changeit");
// fake realm to load config with certificate verification mode // fake realm to load config with certificate verification mode
builder.put("xpack.security.authc.realms.bar.ssl.truststore.path", truststore); builder.put("xpack.security.authc.realms.bar.ssl.truststore.path", truststore);
builder.put("xpack.security.authc.realms.bar.ssl.truststore.password", "changeit"); mockSecureSettings.setString("xpack.security.authc.realms.bar.ssl.truststore.secure_password", "changeit");
builder.put("xpack.security.authc.realms.bar.ssl.verification_mode", VerificationMode.CERTIFICATE); builder.put("xpack.security.authc.realms.bar.ssl.verification_mode", VerificationMode.CERTIFICATE);
} else { } else {
// fake realms so ssl will get loaded // fake realms so ssl will get loaded
builder.put("xpack.security.authc.realms.foo.ssl.truststore.path", truststore); builder.put("xpack.security.authc.realms.foo.ssl.truststore.path", truststore);
builder.put("xpack.security.authc.realms.foo.ssl.truststore.password", "changeit"); mockSecureSettings.setString("xpack.security.authc.realms.foo.ssl.truststore.secure_password", "changeit");
builder.put("xpack.security.authc.realms.foo.ssl.verification_mode", VerificationMode.FULL); builder.put("xpack.security.authc.realms.foo.ssl.verification_mode", VerificationMode.FULL);
builder.put("xpack.security.authc.realms.bar.ssl.truststore.path", truststore); builder.put("xpack.security.authc.realms.bar.ssl.truststore.path", truststore);
builder.put("xpack.security.authc.realms.bar.ssl.truststore.password", "changeit"); mockSecureSettings.setString("xpack.security.authc.realms.bar.ssl.truststore.secure_password", "changeit");
builder.put("xpack.security.authc.realms.bar.ssl.verification_mode", VerificationMode.CERTIFICATE); builder.put("xpack.security.authc.realms.bar.ssl.verification_mode", VerificationMode.CERTIFICATE);
} }
globalSettings = builder.build(); globalSettings = builder.setSecureSettings(mockSecureSettings).build();
Environment environment = new Environment(globalSettings); Environment environment = new Environment(globalSettings);
sslService = new SSLService(globalSettings, environment); sslService = new SSLService(globalSettings, environment);
} }
@ -88,6 +99,7 @@ public class OpenLdapTests extends ESTestCase {
String[] users = new String[] { "blackwidow", "cap", "hawkeye", "hulk", "ironman", "thor" }; String[] users = new String[] { "blackwidow", "cap", "hawkeye", "hulk", "ironman", "thor" };
for (String user : users) { for (String user : users) {
logger.info("testing connect as user [{}]", user);
try (LdapSession ldap = session(sessionFactory, user, PASSWORD_SECURE_STRING)) { try (LdapSession ldap = session(sessionFactory, user, PASSWORD_SECURE_STRING)) {
assertThat(groups(ldap), hasItem(containsString("Avengers"))); assertThat(groups(ldap), hasItem(containsString("Avengers")));
} }
@ -105,9 +117,9 @@ public class OpenLdapTests extends ESTestCase {
String[] users = new String[] { "blackwidow", "cap", "hawkeye", "hulk", "ironman", "thor" }; String[] users = new String[] { "blackwidow", "cap", "hawkeye", "hulk", "ironman", "thor" };
for (String user : users) { for (String user : users) {
LdapSession ldap = session(sessionFactory, user, PASSWORD_SECURE_STRING); try (LdapSession ldap = session(sessionFactory, user, PASSWORD_SECURE_STRING)) {
assertThat(groups(ldap), hasItem(containsString("Avengers"))); assertThat(groups(ldap), hasItem(containsString("Avengers")));
ldap.close(); }
} }
} }
@ -116,7 +128,7 @@ public class OpenLdapTests extends ESTestCase {
String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
Settings settings = Settings.builder() Settings settings = Settings.builder()
.put(buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, LdapSearchScope.ONE_LEVEL)) .put(buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, LdapSearchScope.ONE_LEVEL))
.put("group_search.filter", "(&(objectclass=posixGroup)(memberUID={0}))") .put("group_search.filter", "(&(objectclass=posixGroup)(memberUid={0}))")
.put("group_search.user_attribute", "uid") .put("group_search.user_attribute", "uid")
.build(); .build();
RealmConfig config = new RealmConfig("oldap-test", settings, globalSettings, new ThreadContext(Settings.EMPTY)); RealmConfig config = new RealmConfig("oldap-test", settings, globalSettings, new ThreadContext(Settings.EMPTY));
@ -166,27 +178,67 @@ public class OpenLdapTests extends ESTestCase {
anyOf(containsString("Hostname verification failed"), containsString("peer not authenticated"))); anyOf(containsString("Hostname verification failed"), containsString("peer not authenticated")));
} }
Settings buildLdapSettings(String ldapUrl, String userTemplate, String groupSearchBase, LdapSearchScope scope) { public void testResolveSingleValuedAttributeFromConnection() throws Exception {
Settings baseSettings = LdapTestCase.buildLdapSettings(ldapUrl, userTemplate, groupSearchBase, scope); LdapMetaDataResolver resolver = new LdapMetaDataResolver(Settings.builder().putArray("metadata", "cn", "sn").build(), true);
if (useGlobalSSL) { try (LDAPConnection ldapConnection = setupOpenLdapConnection()) {
return baseSettings; final Map<String, Object> map = resolve(ldapConnection, resolver);
assertThat(map.size(), equalTo(2));
assertThat(map.get("cn"), equalTo("Clint Barton"));
assertThat(map.get("sn"), equalTo("Clint Barton"));
} }
return Settings.builder() }
.put(baseSettings)
.put("ssl.truststore.path", getDataPath("../ldap/support/ldaptrust.jks")) public void testResolveMultiValuedAttributeFromConnection() throws Exception {
LdapMetaDataResolver resolver = new LdapMetaDataResolver(Settings.builder().putArray("metadata", "objectClass").build(), true);
try (LDAPConnection ldapConnection = setupOpenLdapConnection()) {
final Map<String, Object> map = resolve(ldapConnection, resolver);
assertThat(map.size(), equalTo(1));
assertThat(map.get("objectClass"), instanceOf(List.class));
assertThat((List<?>) map.get("objectClass"), contains("top", "posixAccount", "inetOrgPerson"));
}
}
public void testResolveMissingAttributeFromConnection() throws Exception {
LdapMetaDataResolver resolver = new LdapMetaDataResolver(Settings.builder().putArray("metadata", "alias").build(), true);
try (LDAPConnection ldapConnection = setupOpenLdapConnection()) {
final Map<String, Object> map = resolve(ldapConnection, resolver);
assertThat(map.size(), equalTo(0));
}
}
private Settings buildLdapSettings(String ldapUrl, String userTemplate, String groupSearchBase, LdapSearchScope scope) {
Settings.Builder builder = Settings.builder()
.put(LdapTestCase.buildLdapSettings(ldapUrl, userTemplate, groupSearchBase, scope));
builder.put("group_search.user_attribute", "uid");
if (useGlobalSSL) {
return builder.build();
}
return builder
.put("ssl.truststore.path", getDataPath(LDAPTRUST_PATH))
.put("ssl.truststore.password", "changeit") .put("ssl.truststore.password", "changeit")
.build(); .build();
} }
protected LdapSession session(SessionFactory factory, String username, SecureString password) { private LdapSession session(SessionFactory factory, String username, SecureString password) {
PlainActionFuture<LdapSession> future = new PlainActionFuture<>(); PlainActionFuture<LdapSession> future = new PlainActionFuture<>();
factory.session(username, password, future); factory.session(username, password, future);
return future.actionGet(); return future.actionGet();
} }
protected List<String> groups(LdapSession ldapSession) { private List<String> groups(LdapSession ldapSession) {
PlainActionFuture<List<String>> future = new PlainActionFuture<>(); PlainActionFuture<List<String>> future = new PlainActionFuture<>();
ldapSession.groups(future); ldapSession.groups(future);
return future.actionGet(); return future.actionGet();
} }
private LDAPConnection setupOpenLdapConnection() throws Exception {
Path truststore = getDataPath(LDAPTRUST_PATH);
return LdapTestUtils.openConnection(OpenLdapTests.OPEN_LDAP_URL, HAWKEYE_DN, OpenLdapTests.PASSWORD, truststore);
}
private Map<String, Object> resolve(LDAPConnection connection, LdapMetaDataResolver resolver) throws Exception {
final PlainActionFuture<Map<String, Object>> future = new PlainActionFuture<>();
resolver.resolve(connection, HAWKEYE_DN, TimeValue.timeValueSeconds(1), logger, null, future);
return future.get();
}
} }

View File

@ -0,0 +1,123 @@
/*
* 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.ldap;
import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.env.Environment;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.OpenLdapTests;
import org.elasticsearch.xpack.security.authc.RealmConfig;
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSearchScope;
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSession;
import org.elasticsearch.xpack.security.authc.ldap.support.LdapTestCase;
import org.elasticsearch.xpack.security.authc.ldap.support.SessionFactory;
import org.elasticsearch.xpack.ssl.SSLService;
import org.junit.Before;
import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.test.OpenLdapTests.LDAPTRUST_PATH;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
public class OpenLdapUserSearchSessionFactoryTests extends ESTestCase {
private Settings globalSettings;
@Before
public void initializeSslSocketFactory() throws Exception {
Path keystore = getDataPath(LDAPTRUST_PATH);
/*
* Prior to each test we reinitialize the socket factory with a new SSLService so that we get a new SSLContext.
* If we re-use a SSLContext, previously connected sessions can get re-established which breaks hostname
* verification tests since a re-established connection does not perform hostname verification.
*/
globalSettings = Settings.builder()
.put("path.home", createTempDir())
.put("xpack.ssl.truststore.path", keystore)
.setSecureSettings(newSecureSettings("xpack.ssl.truststore.secure_password", "changeit"))
.build();
}
public void testUserSearchwithBindUserOpenLDAP() throws Exception {
String groupSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
String userSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
RealmConfig config = new RealmConfig("oldap-test", Settings.builder()
.put(LdapTestCase.buildLdapSettings(new String[] { OpenLdapTests.OPEN_LDAP_URL }, Strings.EMPTY_ARRAY, groupSearchBase,
LdapSearchScope.ONE_LEVEL))
.put("user_search.base_dn", userSearchBase)
.put("group_search.user_attribute", "uid")
.put("bind_dn", "uid=blackwidow,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com")
.put("bind_password", OpenLdapTests.PASSWORD)
.put("user_search.pool.enabled", randomBoolean())
.build(), globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings));
Settings.Builder builder = Settings.builder()
.put(globalSettings);
for (Map.Entry<String, String> entry : config.settings().getAsMap().entrySet()) {
builder.put("xpack.security.authc.realms.ldap." + entry.getKey(), entry.getValue());
}
Settings settings = builder.build();
SSLService sslService = new SSLService(settings, new Environment(settings));
String[] users = new String[] { "cap", "hawkeye", "hulk", "ironman", "thor" };
try (LdapUserSearchSessionFactory sessionFactory = new LdapUserSearchSessionFactory(config, sslService)) {
for (String user : users) {
//auth
try (LdapSession ldap = session(sessionFactory, user, new SecureString(OpenLdapTests.PASSWORD))) {
assertThat(ldap.userDn(), is(equalTo(new MessageFormat("uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com",
Locale.ROOT).format(new Object[]{user}, new StringBuffer(), null).toString())));
assertThat(groups(ldap), hasItem(containsString("Avengers")));
}
//lookup
try (LdapSession ldap = unauthenticatedSession(sessionFactory, user)) {
assertThat(ldap.userDn(), is(equalTo(new MessageFormat("uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com",
Locale.ROOT).format(new Object[]{user}, new StringBuffer(), null).toString())));
assertThat(groups(ldap), hasItem(containsString("Avengers")));
}
}
}
}
private MockSecureSettings newSecureSettings(String key, String value) {
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString(key, value);
return secureSettings;
}
private LdapSession session(SessionFactory factory, String username, SecureString password) {
PlainActionFuture<LdapSession> future = new PlainActionFuture<>();
factory.session(username, password, future);
return future.actionGet();
}
private List<String> groups(LdapSession ldapSession) {
Objects.requireNonNull(ldapSession);
PlainActionFuture<List<String>> future = new PlainActionFuture<>();
ldapSession.groups(future);
return future.actionGet();
}
private LdapSession unauthenticatedSession(SessionFactory factory, String username) {
PlainActionFuture<LdapSession> future = new PlainActionFuture<>();
factory.unauthenticatedSession(username, future);
return future.actionGet();
}
}

View File

@ -5,11 +5,10 @@
*/ */
package org.elasticsearch.xpack.security.authc.ldap; package org.elasticsearch.xpack.security.authc.ldap;
import org.apache.lucene.util.LuceneTestCase.AwaitsFix;
import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.test.junit.annotations.Network; import org.elasticsearch.test.OpenLdapTests;
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSearchScope; import org.elasticsearch.xpack.security.authc.ldap.support.LdapSearchScope;
import org.elasticsearch.xpack.security.support.NoOpLogger; import org.elasticsearch.xpack.security.support.NoOpLogger;
@ -21,15 +20,15 @@ import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
@Network @SuppressWarnings("unchecked")
@AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1823")
public class SearchGroupsResolverTests extends GroupsResolverTestCase { public class SearchGroupsResolverTests extends GroupsResolverTestCase {
public static final String BRUCE_BANNER_DN = "uid=hulk,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; private static final String BRUCE_BANNER_DN = "uid=hulk,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
public void testResolveSubTree() throws Exception { public void testResolveSubTree() throws Exception {
Settings settings = Settings.builder() Settings settings = Settings.builder()
.put("group_search.base_dn", "dc=oldap,dc=test,dc=elasticsearch,dc=com") .put("group_search.base_dn", "dc=oldap,dc=test,dc=elasticsearch,dc=com")
.put("group_search.user_attribute", "uid")
.build(); .build();
SearchGroupsResolver resolver = new SearchGroupsResolver(settings); SearchGroupsResolver resolver = new SearchGroupsResolver(settings);
@ -46,6 +45,7 @@ public class SearchGroupsResolverTests extends GroupsResolverTestCase {
Settings settings = Settings.builder() Settings settings = Settings.builder()
.put("group_search.base_dn", "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com") .put("group_search.base_dn", "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com")
.put("group_search.scope", LdapSearchScope.ONE_LEVEL) .put("group_search.scope", LdapSearchScope.ONE_LEVEL)
.put("group_search.user_attribute", "uid")
.build(); .build();
SearchGroupsResolver resolver = new SearchGroupsResolver(settings); SearchGroupsResolver resolver = new SearchGroupsResolver(settings);
@ -62,6 +62,7 @@ public class SearchGroupsResolverTests extends GroupsResolverTestCase {
Settings settings = Settings.builder() Settings settings = Settings.builder()
.put("group_search.base_dn", "cn=Avengers,ou=People,dc=oldap,dc=test,dc=elasticsearch,dc=com") .put("group_search.base_dn", "cn=Avengers,ou=People,dc=oldap,dc=test,dc=elasticsearch,dc=com")
.put("group_search.scope", LdapSearchScope.BASE) .put("group_search.scope", LdapSearchScope.BASE)
.put("group_search.user_attribute", "uid")
.build(); .build();
SearchGroupsResolver resolver = new SearchGroupsResolver(settings); SearchGroupsResolver resolver = new SearchGroupsResolver(settings);

0
test/build.gradle Normal file
View File

37
test/openldap-fixture/Vagrantfile vendored Normal file
View File

@ -0,0 +1,37 @@
# ELASTICSEARCH CONFIDENTIAL
# __________________
#
# [2017] Elasticsearch Incorporated. All Rights Reserved.
#
# NOTICE: All information contained herein is, and remains
# the property of Elasticsearch Incorporated and its suppliers,
# if any. The intellectual and technical concepts contained
# herein are proprietary to Elasticsearch Incorporated
# and its suppliers and may be covered by U.S. and Foreign Patents,
# patents in process, and are protected by trade secret or copyright law.
# Dissemination of this information or reproduction of this material
# is strictly forbidden unless prior written permission is obtained
# from Elasticsearch Incorporated.
# This Vagrantfile exists to define a virtual machine running OpenLDAP
# for usage as a testing fixture for the build process..
Vagrant.configure("2") do |config|
config.vm.define "openldap" do |config|
config.vm.box = "elastic/ubuntu-16.04-x86_64"
end
config.vm.hostname = "openldap.build.elastic.co"
if Vagrant.has_plugin?("vagrant-cachier")
config.cache.scope = :box
end
config.vm.network "forwarded_port", guest: 389, host: 60389, protocol: "tcp"
config.vm.network "forwarded_port", guest: 636, host: 60636, protocol: "tcp"
config.vm.provision "shell", path: "src/main/resources/provision/installopenldap.sh"
end

View File

@ -0,0 +1,43 @@
apply plugin: 'elasticsearch.build'
Map<String, String> vagrantEnvVars = [
'VAGRANT_CWD' : "${project.projectDir.absolutePath}",
'VAGRANT_VAGRANTFILE' : 'Vagrantfile',
'VAGRANT_PROJECT_DIR' : "${project.projectDir.absolutePath}"
]
String box = "openldap"
task update(type: org.elasticsearch.gradle.vagrant.VagrantCommandTask) {
command 'box'
subcommand 'update'
boxName box
environmentVars vagrantEnvVars
}
task up(type: org.elasticsearch.gradle.vagrant.VagrantCommandTask) {
command 'up'
args '--provision', '--provider', 'virtualbox'
boxName box
environmentVars vagrantEnvVars
dependsOn update
}
task halt(type: org.elasticsearch.gradle.vagrant.VagrantCommandTask) {
command 'halt'
boxName box
environmentVars vagrantEnvVars
}
task destroy(type: org.elasticsearch.gradle.vagrant.VagrantCommandTask) {
command 'destroy'
args '-f'
boxName box
environmentVars vagrantEnvVars
dependsOn halt
}
thirdPartyAudit.enabled = false
licenseHeaders.enabled = false
test.enabled = false
jarHell.enabled = false

View File

@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIJANOFCysZla1fMA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
A1UEChMHRWxhc3RpYzEWMBQGA1UECxMNRWxhc3RpY3NlYXJjaDERMA8GA1UEAxMI
T3BlbkxEQVAwHhcNMTcwNzI1MTY0MTE0WhcNMjcwNzIzMTY0MTE0WjBvMQswCQYD
VQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxEDAO
BgNVBAoTB0VsYXN0aWMxFjAUBgNVBAsTDUVsYXN0aWNzZWFyY2gxETAPBgNVBAMT
CE9wZW5MREFQMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAynN3UJkl
90OTBdChW9/pvPjzT7zNnbREFc1AjlcbuAUhaXhlFEiqLlniXcYVx5Kq2VWZam0i
WJFHLYE4G4ywM5qhP+QP0njN+QKT+ajLr23RXmb9EWTTW90OLpx1wvQBey/TkJli
WY7T3+mQoDeVnaQV51jZPYKaud5fl9EtfcQCy5FI/wW2d72SJxCT74h7UbjRKlAA
1QKzZWBcQIqRLAQX9ec6RvymplKR4JBIUZtaJII0nDwzm0sEEGzDJWUQhlr0K4NG
+fovlGRGJ4mMirHZSkUI5pQJLaIg44KL2X0HtGITvrifcBC5uLoiwt/fdNPln03M
ciyanMWDIF636wIDAQABo4HUMIHRMB0GA1UdDgQWBBR0R4Hxw7ZmYsHSpW3eCBz1
YWa+nTCBoQYDVR0jBIGZMIGWgBR0R4Hxw7ZmYsHSpW3eCBz1YWa+naFzpHEwbzEL
MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3
MRAwDgYDVQQKEwdFbGFzdGljMRYwFAYDVQQLEw1FbGFzdGljc2VhcmNoMREwDwYD
VQQDEwhPcGVuTERBUIIJANOFCysZla1fMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
AQEFBQADggEBAA1WQu1Rj0hYARjhNImL5h+EuLA5935w1aDaXAp+RzBBYNUZzo5p
m6nIowth/uUwLkgzJspBmEEUPtb0WYTyRPBmDoThwFtpkRXHncyrOFYnX6HknnjS
xV41IAfo325/2oGKN9eUI1Dg2zl2fTWEZK6HTbefS97PFbGAAfKtJl8S6uGs4v8G
bBJhjwL2NhpCwtm8y+SkQXZgRjTO4c84fQASxipyeYWm1Q8IY4IXmBy5znS2OYX7
+QrujJ58GPq98C/djeDrE1Zu687q8VRMvKj+p3j6/TBK1INTfdlHsyXtHbrJvi17
TmaJehNgJQsJEjnVPUj7wDWPduVU8v2Lo3Y=
-----END CERTIFICATE-----

View File

@ -0,0 +1,167 @@
#!/bin/bash
# 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.
set -ex
VDIR=/vagrant
RESOURCES=$VDIR/src/main/resources
PROV_DIR=$RESOURCES/provision
SSL_DIR=/etc/ssl/private
OLDAP_PASSWORD=NickFuryHeartsES
OLDAP_DOMAIN=oldap.test.elasticsearch.com
OLDAP_DOMAIN_DN=dc=oldap,dc=test,dc=elasticsearch,dc=com
MARKER_FILE=/etc/marker
if [ -f $MARKER_FILE ]; then
echo "Already provisioned..."
exit 0;
fi
# Update package manager
apt-get update -qqy
# /dev/random produces output very slowly on Ubuntu VM's. Install haveged to increase entropy.
apt-get install -qqy haveged
haveged
# set the openldap configuration options
debconf-set-selections <<EOF
slapd slapd/password1 password $OLDAP_PASSWORD
slapd slapd/password2 password $OLDAP_PASSWORD
slapd slapd/domain string $OLDAP_DOMAIN
slapd shared/organization string test
EOF
# install openldap (slapd)
apt-get install -qqy slapd ldap-utils
# copy certs and update permissions
cp $PROV_DIR/*.pem $SSL_DIR
groupadd -f ssl-cert
chgrp ssl-cert $SSL_DIR
chgrp ssl-cert $SSL_DIR/key.pem
chgrp ssl-cert $SSL_DIR/cert.pem
chmod g+X $SSL_DIR
chmod g+r $SSL_DIR/key.pem
chmod g+r $SSL_DIR/cert.pem
adduser openldap ssl-cert
sudo -u openldap cat /etc/ssl/private/cert.pem
# restart to pick up new permissions
service slapd restart
# set TLS file locations
ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
dn: cn=config
add: olcTLSCertificateFile
olcTLSCertificateFile: $SSL_DIR/cert.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: $SSL_DIR/key.pem
EOF
# add ldaps
cp /etc/default/slapd /etc/default/slapd.orig
cat /etc/default/slapd | sed -e "s/SLAPD_SERVICES=\"ldap:\/\/\/ ldapi:\/\/\/\"/SLAPD_SERVICES=\"ldap:\/\/\/ ldapi:\/\/\/ ldaps:\/\/\/\"/" > /tmp/slapd
mv /tmp/slapd /etc/default/slapd
# restart to listen on port 636
service slapd restart
# create the people container
ldapadd -D "cn=admin,dc=oldap,dc=test,dc=elasticsearch,dc=com" -w $OLDAP_PASSWORD <<EOF
dn: ou=people,$OLDAP_DOMAIN_DN
objectClass: organizationalUnit
ou: people
EOF
uidNum=1000
# add user entries
function add_person {
local uid=$1; shift
local name=$1; shift
ldapadd -D "cn=admin,dc=oldap,dc=test,dc=elasticsearch,dc=com" -w $OLDAP_PASSWORD <<EOF
dn: uid=$uid,ou=people,$OLDAP_DOMAIN_DN
objectClass: top
objectClass: posixAccount
objectClass: inetOrgPerson
userPassword: $(slappasswd -s $OLDAP_PASSWORD)
uid: $uid
uidNumber: $((++uidNum))
gidNumber: $uidNum
homeDirectory: /home/$uid
mail: $name@$OLDAP_DOMAIN
cn: $name
sn: $name
EOF
}
add_person "kraken" "Commander Kraken"
add_person "hulk" "Bruce Banner"
add_person "hawkeye" "Clint Barton"
add_person "jarvis" "Jarvis"
add_person "blackwidow" "Natasha Romanova"
add_person "fury" "Nick Fury"
add_person "phil" "Phil Colson"
add_person "cap" "Steve Rogers"
add_person "thor" "Thor Odinson"
add_person "ironman" "Tony Stark"
add_person "odin" "Gods"
add_person "selvig" "Erik Selvig"
# add group entries
function add_group {
local name=$1; shift
local gid=$1; shift
local uids=("$1"); shift
local uidsSection=""
for uid in ${uids[@]}
do
uidsSection=$uidsSection"memberUid: ${uid}"$'\n'
done
echo $uidsSection
ldapadd -D "cn=admin,dc=oldap,dc=test,dc=elasticsearch,dc=com" -w $OLDAP_PASSWORD <<EOF
dn: cn=$name,ou=people,$OLDAP_DOMAIN_DN
cn: $name
objectClass: top
objectClass: posixGroup
gidNumber: $gid
$uidsSection
EOF
}
add_group "Hydra" "101" "kraken"
group_members=("hulk" "ironman" "selvig")
add_group "Geniuses" "102" "$(echo ${group_members[@]})"
group_members=("hulk" "hawkeye" "blackwidow" "fury" "phil" "cap" "thor" "ironman")
add_group "SHIELD" "103" "$(echo ${group_members[@]})"
group_members=("hulk" "thor" "ironman")
add_group "Philanthropists" "104" "$(echo ${group_members[@]})"
group_members=("hulk" "hawkeye" "blackwidow" "fury" "cap" "thor" "ironman")
add_group "Avengers" "105" "$(echo ${group_members[@]})"
group_members=("thor" "odin")
add_group "Gods" "106" "$(echo ${group_members[@]})"
group_members=("ironman")
add_group "Playboys" "107" "$(echo ${group_members[@]})"
add_group "Billionaries" "108" "$(echo ${group_members[@]})"
# search for users and print some of their attributes.
ldapsearch -x -LLL -b $OLDAP_DOMAIN_DN '(objectClass=person)' cn mail uid
# search for groups
ldapsearch -x -LLL -b $OLDAP_DOMAIN_DN '(objectClass=posixGroup)' memberUid
# touch the marker file
touch $MARKER_FILE

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAynN3UJkl90OTBdChW9/pvPjzT7zNnbREFc1AjlcbuAUhaXhl
FEiqLlniXcYVx5Kq2VWZam0iWJFHLYE4G4ywM5qhP+QP0njN+QKT+ajLr23RXmb9
EWTTW90OLpx1wvQBey/TkJliWY7T3+mQoDeVnaQV51jZPYKaud5fl9EtfcQCy5FI
/wW2d72SJxCT74h7UbjRKlAA1QKzZWBcQIqRLAQX9ec6RvymplKR4JBIUZtaJII0
nDwzm0sEEGzDJWUQhlr0K4NG+fovlGRGJ4mMirHZSkUI5pQJLaIg44KL2X0HtGIT
vrifcBC5uLoiwt/fdNPln03MciyanMWDIF636wIDAQABAoIBAHw8GTb7lEHFVP6X
hb2UjaIqf10qNl+VlMZwOzJeICNv+o33lMe6w7xH6lKzUQA0b+WI0ultaUtCc5Ro
HJ9DWYmBVXyYnmEBQxyQyW/GdqAD2xx8RMYcwls4LxDJcLae+B25PrIYfjMJI9nf
QaIgGg8v90UNz9ogQITZAn5uneTzgXbPYV/xlX9xjLgzHvxNeOZA80hyEeE5iBES
xZRUUaR0GEKlMOGi+A5WDPPeptpowyvn3EZUTgSdnc1K7+o+Di7Xp0FeBvIvwCqH
ilUrii91bxY7dHcRgAI7lrYCSZgzum86fZOPT4fQxNMA1hPZ71Orme4i6x7Hz/ae
qED2u/ECgYEA5yGgI7LIsGYrR+uPa+bhJxkzIZJL494K4jd6jp7Ai+PZ6icY2GbN
OWzjTSxWmfknU6sHG5yIJe5O9VO6w/31/rfN71Vzj7cUZV2MMveb38KG75sKyPEj
Ol8OAAFcdMXJ4RRas2eqH6D85KWrznFx8ONvbYnqwTsEQ+z/9grpB7kCgYEA4Dvb
y3QbBd8Cns4+BmVev6cL+Yn3GZ1W8nkjdhzPDk9ATp+cF38P2XrbtWlWjnrHPMLo
BBmMwDVfmRw19tiQ37R0F1JE2lCIzQhIUxEIAA+y5RP4aEl6T50nQPysd7oiuIJY
3KalEUPwbg0BK+L5yvZHehcgKQOd53DiHsDrhsMCgYEAlWY81xZndu5zp4dyK3MP
snAthtPDzkTmkBcAV1PybfoYD6y5+JdqrGXf/zBbwic07nYsoAJsVuhVjWpT3QA5
lC5HJR79FbZnrqXrS76VuOtKwXJcZErKVJ7As+wtUSXQOncnsbOeWdd74GfeSBE4
b1bz3cA6SDDXrvhw8x9WRbECgYBRIHcKKgyo2CGbkSTRrZVVI7vqYaccBlfxzDAv
SIcFN1kd2RNhUOBMH+4juWPOks9IxX+qFBBfbjATNii0EXCA70ndMi+lCOQlwixg
mVXap9NinBIQsRzmdwY/tes0Ogzb0pUR59zq3Ti8qEnXNfyIGQiNPJavIBbeKHI3
DDdqfwKBgA8h/wgWWecEJrUr0nteY//6LJSCM9bIW1wH1hQ6h9UczfHDF7eBKI51
qKL1Srw12bGGNddTnYoM3SD+DWT3PbWoGRGOrW4pWJTKkR0Zk7FCBPOHbeobC8Ni
7bykBe8FxLzXe9reM+tbJAQ1CGJaltFN34H6Pl2+4chl9H7fOziI
-----END RSA PRIVATE KEY-----