Skip to content

Commit 0c13d43

Browse files
Add support for multiple ldap connections (#315)
* Add support for multiple ldap connections * Old ldap properties removed, no backwards compatibility
1 parent 8d03997 commit 0c13d43

File tree

14 files changed

+242
-96
lines changed

14 files changed

+242
-96
lines changed

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,13 @@
345345
<version>5.4.1</version>
346346
</dependency>
347347

348+
<dependency>
349+
<groupId>org.zapodot</groupId>
350+
<artifactId>embedded-ldap-junit</artifactId>
351+
<version>0.7</version>
352+
<scope>test</scope>
353+
</dependency>
354+
348355
<!-- Cucumber -->
349356
<dependency>
350357
<groupId>io.cucumber</groupId>

src/functionaltests/java/com/ericsson/ei/subscriptions/authentication/AuthenticationSteps.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
/*
2+
Copyright 2019 Ericsson AB.
3+
For a full list of individual contributors, please see the commit history.
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
*/
114
package com.ericsson.ei.subscriptions.authentication;
215

316
import static org.junit.Assert.assertEquals;
@@ -11,15 +24,13 @@
1124
import org.springframework.boot.web.server.LocalServerPort;
1225
import org.springframework.http.HttpStatus;
1326
import org.springframework.http.ResponseEntity;
14-
import org.springframework.test.context.ContextConfiguration;
1527
import org.springframework.test.context.TestPropertySource;
1628

1729
import com.ericsson.ei.controller.model.GetSubscriptionResponse;
1830
import com.ericsson.ei.utils.FunctionalTestBase;
1931
import com.ericsson.ei.utils.HttpExecutor;
2032
import com.ericsson.ei.utils.HttpRequest;
2133
import com.ericsson.ei.utils.HttpRequest.HttpMethod;
22-
import com.ericsson.ei.utils.TestLDAPInitializer;
2334
import com.fasterxml.jackson.databind.ObjectMapper;
2435

2536
import cucumber.api.java.Before;
@@ -33,12 +44,7 @@
3344
"missedNotificationDataBaseName: AuthenticationSteps-missedNotifications",
3445
"rabbitmq.exchange.name: AuthenticationSteps-exchange",
3546
"rabbitmq.consumerName: AuthenticationStepsConsumer",
36-
"ldap.enabled: true",
37-
"ldap.url: ldap://ldap.forumsys.com:389/dc=example,dc=com",
38-
"ldap.base.dn: dc=example,dc=com",
39-
"ldap.username : cn=read-only-admin,dc=example,dc=com",
40-
"ldap.user.filter: uid={0}" })
41-
@ContextConfiguration(initializers = TestLDAPInitializer.class)
47+
"ldap.enabled: true" })
4248
public class AuthenticationSteps extends FunctionalTestBase {
4349

4450
private static final String SUBSCRIPTION = "src/functionaltests/resources/subscription_single.json";
Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,50 @@
1+
/*
2+
Copyright 2019 Ericsson AB.
3+
For a full list of individual contributors, please see the commit history.
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
*/
114
package com.ericsson.ei.subscriptions.authentication;
215

16+
import org.junit.BeforeClass;
17+
import org.junit.runner.RunWith;
18+
19+
import com.ericsson.ei.utils.TestLDAPStarter;
20+
321
import cucumber.api.CucumberOptions;
422
import cucumber.api.junit.Cucumber;
5-
import org.junit.runner.RunWith;
623

724
@RunWith(Cucumber.class)
8-
@CucumberOptions(features = "src/functionaltests/resources/features/authentication.feature", glue = {
9-
"com.ericsson.ei.subscriptions.authentication" }, plugin = { "pretty",
10-
"html:target/cucumber-reports/TestAuthenticationRunner" })
11-
public class TestAuthenticationRunner {
25+
@CucumberOptions(features = { "src/functionaltests/resources/features/authentication.feature",
26+
"src/functionaltests/resources/features/authenticationMultiLDAP.feature" }, glue = {
27+
"com.ericsson.ei.subscriptions.authentication" }, plugin = { "pretty",
28+
"html:target/cucumber-reports/TestAuthenticationRunner" })
29+
public class TestAuthenticationRunner extends TestLDAPStarter {
1230

31+
@BeforeClass
32+
public static void configureLdapProperties() {
33+
int ldapPort1 = TestLDAPStarter.embeddedLdapRule1.embeddedServerPort();
34+
int ldapPort2 = TestLDAPStarter.embeddedLdapRule2.embeddedServerPort();
35+
System.setProperty("ldap.server.list", "[{" +
36+
"\"url\":\"ldap://localhost:" + ldapPort1 + "/dc=example,dc=com\"," +
37+
"\"base.dn\":\"\"," +
38+
"\"username\":\"\"," +
39+
"\"password\":\"\"," +
40+
"\"user.filter\":\"uid={0}\"" +
41+
"}," +
42+
"{" +
43+
"\"url\":\"ldap://localhost:" + ldapPort2 + "/dc=example,dc=com\"," +
44+
"\"base.dn\":\"\"," +
45+
"\"username\":\"\"," +
46+
"\"password\":\"\"," +
47+
"\"user.filter\":\"uid={0}\"" +
48+
"}]");
49+
}
1350
}

src/functionaltests/java/com/ericsson/ei/utils/TestLDAPInitializer.java

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
Copyright 2019 Ericsson AB.
3+
For a full list of individual contributors, please see the commit history.
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
*/
14+
package com.ericsson.ei.utils;
15+
16+
import org.junit.ClassRule;
17+
import org.zapodot.junit.ldap.EmbeddedLdapRule;
18+
import org.zapodot.junit.ldap.EmbeddedLdapRuleBuilder;
19+
20+
public class TestLDAPStarter {
21+
private static final String DOMAIN_DSN = "dc=example,dc=com";
22+
@ClassRule
23+
public static EmbeddedLdapRule embeddedLdapRule1 = EmbeddedLdapRuleBuilder.newInstance().usingDomainDsn(DOMAIN_DSN)
24+
.importingLdifs("ldap-users-first.ldif").build();
25+
@ClassRule
26+
public static EmbeddedLdapRule embeddedLdapRule2 = EmbeddedLdapRuleBuilder.newInstance().usingDomainDsn(DOMAIN_DSN)
27+
.importingLdifs("ldap-users-second.ldif").build();
28+
}

src/functionaltests/resources/features/authentication.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Feature: Test Authentication
3737
@RESTWithTokenId
3838
Scenario: Call an REST API with session credentials
3939
Given LDAP is activated
40-
When a GET request is prepared for REST API "/auth/logout"
40+
When a GET request is prepared for REST API "/auth/logout"
4141
And request is sent
4242
When a GET request is prepared for REST API "/auth/login"
4343
And request is sent
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Author: christoffer.cortes.sjowall@ericsson.com
2+
3+
@AuthenticationMultiLDAP
4+
Feature: Test Authentication with multiple LDAP servers
5+
6+
@RESTWithUniqueUsersInDifferentLDAPServers
7+
Scenario: Login using unique users from two different LDAP servers
8+
Given LDAP is activated
9+
When a GET request is prepared for REST API "/auth/login"
10+
And username "gauss" and password "password" is used as credentials
11+
And request is sent
12+
Then response code 200 is received
13+
When a GET request is prepared for REST API "/auth/logout"
14+
And request is sent
15+
When a GET request is prepared for REST API "/auth/login"
16+
And username "einstein" and password "e=mc2" is used as credentials
17+
And request is sent
18+
Then response code 200 is received
19+
20+
@RESTWithIdenticalUsernamesInDifferentLDAPServers
21+
Scenario: Login using identical usernames with different passwords from two different LDAP servers
22+
Given LDAP is activated
23+
When a GET request is prepared for REST API "/auth/login"
24+
And username "newton" and password "password" is used as credentials
25+
And request is sent
26+
Then response code 200 is received
27+
When a GET request is prepared for REST API "/auth/logout"
28+
And request is sent
29+
When a GET request is prepared for REST API "/auth/login"
30+
And username "newton" and password "password2" is used as credentials
31+
And request is sent
32+
Then response code 200 is received
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
dn: dc=example,dc=com
2+
objectClass: domain
3+
objectClass: top
4+
dc: example
5+
6+
dn: uid=gausss,dc=example,dc=com
7+
objectClass: inetOrgPerson
8+
objectClass: organizationalPerson
9+
objectClass: person
10+
objectClass: top
11+
cn: gauss
12+
sn: 1
13+
uid: gauss
14+
userPassword: password
15+
16+
dn: uid=newton,dc=example,dc=com
17+
objectClass: inetOrgPerson
18+
objectClass: organizationalPerson
19+
objectClass: person
20+
objectClass: top
21+
cn: newton
22+
sn: 2
23+
uid: newton
24+
userPassword: password
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
dn: dc=example,dc=com
2+
objectClass: domain
3+
objectClass: top
4+
dc: example
5+
6+
dn: uid=einstein,dc=example,dc=com
7+
objectClass: inetOrgPerson
8+
objectClass: organizationalPerson
9+
objectClass: person
10+
objectClass: top
11+
cn: einstein
12+
sn: 1
13+
uid: einstein
14+
userPassword: e=mc2
15+
16+
dn: uid=newton,dc=example,dc=com
17+
objectClass: inetOrgPerson
18+
objectClass: organizationalPerson
19+
objectClass: person
20+
objectClass: top
21+
cn: newton
22+
sn: 2
23+
uid: newton
24+
userPassword: password2

src/main/java/com/ericsson/ei/EndpointSecurity.java

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
import org.apache.tomcat.util.codec.binary.Base64;
2121
import org.apache.tomcat.util.codec.binary.StringUtils;
22+
import org.json.JSONArray;
23+
import org.json.JSONObject;
2224
import org.slf4j.Logger;
2325
import org.slf4j.LoggerFactory;
2426
import org.springframework.beans.factory.annotation.Value;
@@ -39,20 +41,8 @@ public class EndpointSecurity extends WebSecurityConfigurerAdapter {
3941
@Value("${ldap.enabled:false}")
4042
private boolean ldapEnabled;
4143

42-
@Value("${ldap.url}")
43-
private String ldapUrl;
44-
45-
@Value("${ldap.base.dn}")
46-
private String ldapBaseDn;
47-
48-
@Value("${ldap.username}")
49-
private String ldapUsername;
50-
51-
@Value("${ldap.password}")
52-
private String ldapPassword;
53-
54-
@Value("${ldap.user.filter}")
55-
private String ldapUserFilter;
44+
@Value("${ldap.server.list:}")
45+
private String ldapServerList;
5646

5747
@Override
5848
protected void configure(HttpSecurity http) throws Exception {
@@ -84,20 +74,28 @@ protected void configure(HttpSecurity http) throws Exception {
8474

8575
@Override
8676
public void configure(AuthenticationManagerBuilder auth) throws Exception {
87-
if(ldapEnabled) {
88-
auth
89-
.eraseCredentials(false)
90-
.ldapAuthentication()
91-
.userSearchFilter(ldapUserFilter)
92-
.contextSource()
93-
.url(ldapUrl)
94-
.root(ldapBaseDn)
95-
.managerDn(ldapUsername)
96-
.managerPassword(decodeBase64(ldapPassword));
77+
if (ldapEnabled && !ldapServerList.isEmpty()) {
78+
JSONArray serverList = new JSONArray(ldapServerList);
79+
addLDAPServersFromList(serverList, auth);
9780
}
9881
}
9982

10083
private String decodeBase64(String password) {
10184
return StringUtils.newStringUtf8(Base64.decodeBase64(password));
10285
}
86+
87+
private void addLDAPServersFromList(JSONArray serverList, AuthenticationManagerBuilder auth) throws Exception {
88+
for (int i = 0; i < serverList.length(); i++) {
89+
JSONObject server = (JSONObject) serverList.get(i);
90+
auth
91+
.eraseCredentials(false)
92+
.ldapAuthentication()
93+
.userSearchFilter(server.getString("user.filter"))
94+
.contextSource()
95+
.url(server.getString("url"))
96+
.root(server.getString("base.dn"))
97+
.managerDn(server.getString("username"))
98+
.managerPassword(decodeBase64(server.getString("password")));
99+
}
100+
}
103101
}

0 commit comments

Comments
 (0)