-
Notifications
You must be signed in to change notification settings - Fork 285
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Lukasz Soszynski <[email protected]> Tests for roles recursive search for LDAP. Signed-off-by: Lukasz Soszynski <[email protected]> User impersonation tests for LDAP authentication. Signed-off-by: Lukasz Soszynski <[email protected]>
- Loading branch information
1 parent
7cad5e4
commit 20cc9de
Showing
25 changed files
with
1,875 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
124 changes: 124 additions & 0 deletions
124
src/integrationTest/java/org/opensearch/security/http/DirectoryInformationTrees.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
*/ | ||
package org.opensearch.security.http; | ||
|
||
import org.opensearch.test.framework.ldap.LdifBuilder; | ||
import org.opensearch.test.framework.ldap.LdifData; | ||
|
||
class DirectoryInformationTrees { | ||
|
||
public static final String DN_PEOPLE_TEST_ORG = "ou=people,o=test.org"; | ||
public static final String DN_OPEN_SEARCH_PEOPLE_TEST_ORG = "cn=Open Search,ou=people,o=test.org"; | ||
public static final String DN_CHRISTPHER_PEOPLE_TEST_ORG = "cn=Christpher,ou=people,o=test.org"; | ||
public static final String DN_KIRK_PEOPLE_TEST_ORG = "cn=Kirk,ou=people,o=test.org"; | ||
public static final String DN_CAPTAIN_SPOCK_PEOPLE_TEST_ORG = "cn=Captain Spock,ou=people,o=test.org"; | ||
public static final String DN_LEONARD_PEOPLE_TEST_ORG = "cn=Leonard,ou=people,o=test.org"; | ||
public static final String DN_JEAN_PEOPLE_TEST_ORG = "cn=Jean,ou=people,o=test.org"; | ||
public static final String DN_GROUPS_TEST_ORG = "ou=groups,o=test.org"; | ||
public static final String DN_BRIDGE_GROUPS_TEST_ORG = "cn=bridge,ou=groups,o=test.org"; | ||
|
||
public static final String USER_KIRK = "kirk"; | ||
public static final String PASSWORD_KIRK = "kirk-secret"; | ||
public static final String USER_SPOCK = "spock"; | ||
public static final String PASSWORD_SPOCK = "spocksecret"; | ||
public static final String USER_OPENS = "opens"; | ||
public static final String PASSWORD_OPEN_SEARCH = "open_search-secret"; | ||
public static final String USER_JEAN = "jean"; | ||
public static final String PASSWORD_JEAN = "jeansecret"; | ||
public static final String USER_LEONARD = "leonard"; | ||
public static final String PASSWORD_LEONARD = "Leonard-secret"; | ||
public static final String PASSWORD_CHRISTPHER = "christpher_secret"; | ||
|
||
public static final String CN_GROUP_ADMIN = "admin"; | ||
public static final String CN_GROUP_CREW = "crew"; | ||
public static final String CN_GROUP_BRIDGE = "bridge"; | ||
|
||
public static final String USER_SEARCH = "(uid={0})"; | ||
public static final String USERNAME_ATTRIBUTE = "uid"; | ||
|
||
static final LdifData LDIF_DATA = new LdifBuilder() | ||
.root("o=test.org") | ||
.dc("TEST") | ||
.classes("top", "domain") | ||
.newRecord(DN_PEOPLE_TEST_ORG) | ||
.ou("people") | ||
.classes("organizationalUnit", "top") | ||
.newRecord(DN_OPEN_SEARCH_PEOPLE_TEST_ORG) | ||
.classes("inetOrgPerson") | ||
.cn("Open Search") | ||
.sn("Search") | ||
.uid(USER_OPENS) | ||
.userPassword(PASSWORD_OPEN_SEARCH) | ||
.mail("[email protected]") | ||
.ou("Human Resources") | ||
.newRecord(DN_CAPTAIN_SPOCK_PEOPLE_TEST_ORG) | ||
.classes("inetOrgPerson") | ||
.cn("Captain Spock") | ||
.sn(USER_SPOCK) | ||
.uid(USER_SPOCK) | ||
.userPassword(PASSWORD_SPOCK) | ||
.mail("[email protected]") | ||
.ou("Human Resources") | ||
.newRecord(DN_KIRK_PEOPLE_TEST_ORG) | ||
.classes("inetOrgPerson") | ||
.cn("Kirk") | ||
.sn("Kirk") | ||
.uid(USER_KIRK) | ||
.userPassword(PASSWORD_KIRK) | ||
.mail("[email protected]") | ||
.ou("Human Resources") | ||
.newRecord(DN_CHRISTPHER_PEOPLE_TEST_ORG) | ||
.classes("inetOrgPerson") | ||
.cn("Christpher") | ||
.sn("Christpher") | ||
.uid("christpher") | ||
.userPassword(PASSWORD_CHRISTPHER) | ||
.mail("[email protected]") | ||
.ou("Human Resources") | ||
.newRecord(DN_LEONARD_PEOPLE_TEST_ORG) | ||
.classes("inetOrgPerson") | ||
.cn("Leonard") | ||
.sn("Leonard") | ||
.uid(USER_LEONARD) | ||
.userPassword(PASSWORD_LEONARD) | ||
.mail("[email protected]") | ||
.ou("Human Resources") | ||
.newRecord(DN_JEAN_PEOPLE_TEST_ORG) | ||
.classes("inetOrgPerson") | ||
.cn("Jean") | ||
.sn("Jean") | ||
.uid(USER_JEAN) | ||
.userPassword(PASSWORD_JEAN) | ||
.mail("[email protected]") | ||
.ou("Human Resources") | ||
.newRecord(DN_GROUPS_TEST_ORG) | ||
.ou("groups") | ||
.cn("groupsRoot") | ||
.classes("groupofuniquenames", "top") | ||
.newRecord("cn=admin,ou=groups,o=test.org") | ||
.ou("groups") | ||
.cn(CN_GROUP_ADMIN) | ||
.uniqueMember(DN_KIRK_PEOPLE_TEST_ORG) | ||
.classes("groupofuniquenames", "top") | ||
.newRecord("cn=crew,ou=groups,o=test.org") | ||
.ou("groups") | ||
.cn(CN_GROUP_CREW) | ||
.uniqueMember(DN_CAPTAIN_SPOCK_PEOPLE_TEST_ORG) | ||
.uniqueMember(DN_CHRISTPHER_PEOPLE_TEST_ORG) | ||
.uniqueMember(DN_BRIDGE_GROUPS_TEST_ORG) | ||
.classes("groupofuniquenames", "top") | ||
.newRecord(DN_BRIDGE_GROUPS_TEST_ORG) | ||
.ou("groups") | ||
.cn(CN_GROUP_BRIDGE) | ||
.uniqueMember(DN_JEAN_PEOPLE_TEST_ORG) | ||
.classes("groupofuniquenames", "top") | ||
.buildRecord() | ||
.buildLdif(); | ||
} |
112 changes: 112 additions & 0 deletions
112
src/integrationTest/java/org/opensearch/security/http/LdapAuthenticationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
*/ | ||
package org.opensearch.security.http; | ||
|
||
import java.util.List; | ||
|
||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; | ||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.junit.ClassRule; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.junit.rules.RuleChain; | ||
import org.junit.runner.RunWith; | ||
|
||
import org.opensearch.test.framework.LdapAuthenticationConfigBuilder; | ||
import org.opensearch.test.framework.TestSecurityConfig; | ||
import org.opensearch.test.framework.TestSecurityConfig.AuthcDomain; | ||
import org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AuthenticationBackend; | ||
import org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.HttpAuthenticator; | ||
import org.opensearch.test.framework.certificate.TestCertificates; | ||
import org.opensearch.test.framework.cluster.ClusterManager; | ||
import org.opensearch.test.framework.cluster.LocalCluster; | ||
import org.opensearch.test.framework.cluster.TestRestClient; | ||
import org.opensearch.test.framework.ldap.EmbeddedLDAPServer; | ||
import org.opensearch.test.framework.log.LogsRule; | ||
|
||
import static org.opensearch.security.http.DirectoryInformationTrees.DN_CAPTAIN_SPOCK_PEOPLE_TEST_ORG; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.DN_OPEN_SEARCH_PEOPLE_TEST_ORG; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.DN_PEOPLE_TEST_ORG; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.LDIF_DATA; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.PASSWORD_OPEN_SEARCH; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.PASSWORD_SPOCK; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.USERNAME_ATTRIBUTE; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.USER_SEARCH; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.USER_SPOCK; | ||
import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AUTHC_HTTPBASIC_INTERNAL; | ||
import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.BASIC_AUTH_DOMAIN_ORDER; | ||
import static org.opensearch.test.framework.TestSecurityConfig.Role.ALL_ACCESS; | ||
|
||
/** | ||
* Test uses plain (non TLS) connection between OpenSearch and LDAP server. | ||
*/ | ||
@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class) | ||
@ThreadLeakScope(ThreadLeakScope.Scope.NONE) | ||
public class LdapAuthenticationTest { | ||
|
||
private static final Logger log = LogManager.getLogger(LdapAuthenticationTest.class); | ||
|
||
private static final TestSecurityConfig.User ADMIN_USER = new TestSecurityConfig.User("admin").roles(ALL_ACCESS); | ||
|
||
private static final TestCertificates TEST_CERTIFICATES = new TestCertificates(); | ||
|
||
public static final EmbeddedLDAPServer embeddedLDAPServer = new EmbeddedLDAPServer(TEST_CERTIFICATES.getRootCertificateData(), | ||
TEST_CERTIFICATES.getLdapCertificateData(), LDIF_DATA); | ||
|
||
public static LocalCluster cluster = new LocalCluster.Builder() | ||
.testCertificates(TEST_CERTIFICATES) | ||
.clusterManager(ClusterManager.SINGLENODE).anonymousAuth(false) | ||
.authc(new AuthcDomain("ldap", BASIC_AUTH_DOMAIN_ORDER + 1, true) | ||
.httpAuthenticator(new HttpAuthenticator("basic").challenge(false)) | ||
.backend(new AuthenticationBackend("ldap") | ||
.config(() -> LdapAuthenticationConfigBuilder.config() | ||
// this port is available when embeddedLDAPServer is already started, therefore Supplier interface is used to postpone | ||
// execution of the code in this block. | ||
.enableSsl(false) | ||
.enableStartTls(false) | ||
.hosts(List.of("localhost:" + embeddedLDAPServer.getLdapNonTlsPort())) | ||
.bindDn(DN_OPEN_SEARCH_PEOPLE_TEST_ORG) | ||
.password(PASSWORD_OPEN_SEARCH) | ||
.userBase(DN_PEOPLE_TEST_ORG) | ||
.userSearch(USER_SEARCH) | ||
.usernameAttribute(USERNAME_ATTRIBUTE) | ||
.build()))) | ||
.authc(AUTHC_HTTPBASIC_INTERNAL) | ||
.users(ADMIN_USER) | ||
.build(); | ||
|
||
@ClassRule | ||
public static RuleChain ruleChain = RuleChain.outerRule(embeddedLDAPServer).around(cluster); | ||
|
||
@Rule | ||
public LogsRule logsRule = new LogsRule("com.amazon.dlic.auth.ldap.backend.LDAPAuthenticationBackend"); | ||
|
||
@Test | ||
public void shouldAuthenticateUserWithLdap_positive() { | ||
try (TestRestClient client = cluster.getRestClient(USER_SPOCK, PASSWORD_SPOCK)) { | ||
TestRestClient.HttpResponse response = client.getAuthInfo(); | ||
|
||
response.assertStatusCode(200); | ||
} | ||
} | ||
|
||
@Test | ||
public void shouldAuthenticateUserWithLdap_negativeWhenIncorrectPassword() { | ||
try (TestRestClient client = cluster.getRestClient(USER_SPOCK, "incorrect password")) { | ||
TestRestClient.HttpResponse response = client.getAuthInfo(); | ||
|
||
response.assertStatusCode(401); | ||
String expectedStackTraceFragment = "Unable to bind as user '".concat(DN_CAPTAIN_SPOCK_PEOPLE_TEST_ORG) | ||
.concat("' because the provided password was incorrect."); | ||
logsRule.assertThatStackTraceContain(expectedStackTraceFragment); | ||
} | ||
} | ||
} |
109 changes: 109 additions & 0 deletions
109
src/integrationTest/java/org/opensearch/security/http/LdapStartTlsAuthenticationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
*/ | ||
package org.opensearch.security.http; | ||
|
||
import java.util.List; | ||
|
||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; | ||
import org.junit.ClassRule; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.junit.rules.RuleChain; | ||
import org.junit.runner.RunWith; | ||
|
||
import org.opensearch.test.framework.LdapAuthenticationConfigBuilder; | ||
import org.opensearch.test.framework.TestSecurityConfig; | ||
import org.opensearch.test.framework.TestSecurityConfig.AuthcDomain; | ||
import org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AuthenticationBackend; | ||
import org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.HttpAuthenticator; | ||
import org.opensearch.test.framework.certificate.TestCertificates; | ||
import org.opensearch.test.framework.cluster.ClusterManager; | ||
import org.opensearch.test.framework.cluster.LocalCluster; | ||
import org.opensearch.test.framework.cluster.TestRestClient; | ||
import org.opensearch.test.framework.ldap.EmbeddedLDAPServer; | ||
import org.opensearch.test.framework.log.LogsRule; | ||
|
||
import static org.opensearch.security.http.DirectoryInformationTrees.DN_CAPTAIN_SPOCK_PEOPLE_TEST_ORG; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.DN_OPEN_SEARCH_PEOPLE_TEST_ORG; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.DN_PEOPLE_TEST_ORG; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.LDIF_DATA; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.PASSWORD_OPEN_SEARCH; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.PASSWORD_SPOCK; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.USERNAME_ATTRIBUTE; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.USER_SEARCH; | ||
import static org.opensearch.security.http.DirectoryInformationTrees.USER_SPOCK; | ||
import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AUTHC_HTTPBASIC_INTERNAL; | ||
import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.BASIC_AUTH_DOMAIN_ORDER; | ||
import static org.opensearch.test.framework.TestSecurityConfig.Role.ALL_ACCESS; | ||
|
||
/** | ||
* Test initiates plain (non-TLS) connection between OpenSearch and LDAP server and then in the course of the test connection is upgraded | ||
* to TLS. | ||
*/ | ||
@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class) | ||
@ThreadLeakScope(ThreadLeakScope.Scope.NONE) | ||
public class LdapStartTlsAuthenticationTest { | ||
|
||
private static final TestSecurityConfig.User ADMIN_USER = new TestSecurityConfig.User("admin").roles(ALL_ACCESS); | ||
|
||
private static final TestCertificates TEST_CERTIFICATES = new TestCertificates(); | ||
|
||
public static final EmbeddedLDAPServer embeddedLDAPServer = new EmbeddedLDAPServer(TEST_CERTIFICATES.getRootCertificateData(), | ||
TEST_CERTIFICATES.getLdapCertificateData(), LDIF_DATA); | ||
|
||
public static LocalCluster cluster = new LocalCluster.Builder() | ||
.testCertificates(TEST_CERTIFICATES) | ||
.clusterManager(ClusterManager.SINGLENODE).anonymousAuth(false) | ||
.authc(new AuthcDomain("ldap-config-id", BASIC_AUTH_DOMAIN_ORDER + 1, true) | ||
.httpAuthenticator(new HttpAuthenticator("basic").challenge(false)) | ||
.backend(new AuthenticationBackend("ldap") | ||
.config(() -> LdapAuthenticationConfigBuilder.config() | ||
// this port is available when embeddedLDAPServer is already started, therefore Supplier interface is used | ||
.hosts(List.of("localhost:" + embeddedLDAPServer.getLdapNonTlsPort())) | ||
.enableSsl(false) | ||
.enableStartTls(true) | ||
.bindDn(DN_OPEN_SEARCH_PEOPLE_TEST_ORG) | ||
.password(PASSWORD_OPEN_SEARCH) | ||
.userBase(DN_PEOPLE_TEST_ORG) | ||
.userSearch(USER_SEARCH) | ||
.usernameAttribute(USERNAME_ATTRIBUTE) | ||
.penTrustedCasFilePath(TEST_CERTIFICATES.getRootCertificate().getAbsolutePath()) | ||
.build()))) | ||
.authc(AUTHC_HTTPBASIC_INTERNAL) | ||
.users(ADMIN_USER) | ||
.build(); | ||
|
||
@ClassRule | ||
public static RuleChain ruleChain = RuleChain.outerRule(embeddedLDAPServer).around(cluster); | ||
|
||
@Rule | ||
public LogsRule logsRule = new LogsRule("com.amazon.dlic.auth.ldap.backend.LDAPAuthenticationBackend"); | ||
|
||
@Test | ||
public void shouldAuthenticateUserWithLdap_positive() { | ||
try (TestRestClient client = cluster.getRestClient(USER_SPOCK, PASSWORD_SPOCK)) { | ||
TestRestClient.HttpResponse response = client.getAuthInfo(); | ||
|
||
response.assertStatusCode(200); | ||
} | ||
} | ||
|
||
@Test | ||
public void shouldAuthenticateUserWithLdap_negativeWhenIncorrectPassword() { | ||
try (TestRestClient client = cluster.getRestClient(USER_SPOCK, "incorrect password")) { | ||
TestRestClient.HttpResponse response = client.getAuthInfo(); | ||
|
||
response.assertStatusCode(401); | ||
String expectedStackTraceFragment = "Unable to bind as user '".concat(DN_CAPTAIN_SPOCK_PEOPLE_TEST_ORG) | ||
.concat("' because the provided password was incorrect."); | ||
logsRule.assertThatStackTraceContain(expectedStackTraceFragment); | ||
} | ||
} | ||
} |
Oops, something went wrong.