Skip to content

Commit efb5082

Browse files
author
Vladimir Kotal
committed
LdapUser should be an attribute wrapper
1 parent f23b4d5 commit efb5082

File tree

7 files changed

+102
-116
lines changed

7 files changed

+102
-116
lines changed

plugins/src/opengrok/auth/entity/LdapUser.java

Lines changed: 18 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -26,94 +26,53 @@
2626
import java.util.HashMap;
2727
import java.util.Map;
2828
import java.util.Set;
29-
import java.util.TreeSet;
3029

3130
/**
31+
* LDAP user represented as a set of attributes
3232
*
3333
* @author Krystof Tulinger
3434
*/
3535
public class LdapUser implements Serializable {
3636

37-
private String mail;
38-
private String uid;
39-
private Set<String> ou;
40-
private final Map<String, Set<String>> attrs = new HashMap<>();
37+
private final Map<String, Set<String>> attributes;
4138

4239
// Use default serial ID value. If the serialized form of the object
4340
// changes, feel free to start from 1L.
44-
private static final long serialVersionUID = -8207597677599370334L;
41+
private static final long serialVersionUID = 1161431688782569843L;
4542

46-
public LdapUser(String mail, String uid, Set<String> ou) {
47-
this.mail = mail;
48-
this.uid = uid;
49-
this.ou = ou == null ? new TreeSet<>() : ou;
43+
public LdapUser() {
44+
this(null);
5045
}
5146

52-
public String getMail() {
53-
return mail;
54-
}
55-
56-
public void setMail(String mail) {
57-
this.mail = mail;
58-
}
59-
60-
public String getUid() {
61-
return uid;
62-
}
63-
64-
public void setUid(String uid) {
65-
this.uid = uid;
66-
}
67-
68-
public Set<String> getOu() {
69-
return ou;
70-
}
71-
72-
public void setOu(Set<String> ou) {
73-
this.ou = ou == null ? new TreeSet<>() : ou;
74-
}
75-
76-
public boolean hasOu(String name) {
77-
return this.ou.contains(name);
47+
public LdapUser(Map<String, Set<String>> attrs) {
48+
if (attrs == null) {
49+
this.attributes = new HashMap<>();
50+
} else {
51+
this.attributes = attrs;
52+
}
7853
}
7954

8055
/**
81-
* Get custom user property.
56+
* set attribute value
8257
*
8358
* @param key the key
84-
* @return the the value associated with the key
85-
*/
86-
public Object getAttribute(String key) {
87-
return attrs.get(key);
88-
}
89-
90-
/**
91-
* Set custom user property.
92-
*
93-
* @param key the key
94-
* @param value the value
59+
* @param value set of values
9560
* @return the value previously associated with the key
9661
*/
9762
public Object setAttribute(String key, Set<String> value) {
98-
return attrs.put(key, value);
63+
return attributes.put(key, value);
9964
}
10065

101-
/**
102-
* Remote custom user property.
103-
*
104-
* @param key the key
105-
* @return the value previously associated with the key
106-
*/
107-
public Object removeAttribute(String key) {
108-
return attrs.remove(key);
66+
public Set<String> getAttribute(String key) {
67+
return attributes.get(key);
10968
}
11069

11170
public Map<String, Set<String>> getAttributes() {
112-
return this.attrs;
71+
return this.attributes;
11372
}
11473

11574
@Override
11675
public String toString() {
117-
return "LdapUser{" + "mail=" + mail + ", uid=" + uid + ", ou=" + ou + '}';
76+
return "LdapUser{attributes=" + attributes + '}';
11877
}
11978
}

plugins/src/opengrok/auth/plugin/LdapAttrPlugin.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
*/
4343
public class LdapAttrPlugin extends AbstractLdapPlugin {
4444

45-
protected static final String ATTR_PARAM = "attribute";
45+
protected static final String ATTR_PARAM = "attribute"; // LDAP attribute name to check
4646
protected static final String FILE_PARAM = "file";
4747

4848
private static final String SESSION_ALLOWED_PREFIX = "opengrok-attr-plugin-allowed";
@@ -87,33 +87,31 @@ public void fillSession(HttpServletRequest req, User user) {
8787
Boolean sessionAllowed = false;
8888
LdapUser ldapUser;
8989
Map<String, Set<String>> records;
90-
Set<String> attributes;
90+
Set<String> attributeValues;
9191

9292
updateSession(req, sessionAllowed);
9393

9494
if ((ldapUser = (LdapUser) req.getSession().getAttribute(LdapUserPlugin.SESSION_ATTR)) == null) {
95+
// TODO log
9596
return;
9697
}
9798

98-
if (ldapAttr.equals("mail")) {
99-
sessionAllowed = whitelist.contains(ldapUser.getMail());
100-
} else if (ldapAttr.equals("uid")) {
101-
sessionAllowed = whitelist.contains(ldapUser.getUid());
102-
} else if (ldapAttr.equals("ou")) {
103-
sessionAllowed = ldapUser.getOu().stream().anyMatch((t) -> whitelist.contains(t));
104-
} else if ((attributes = (Set<String>) ldapUser.getAttribute(ldapAttr)) != null) {
105-
sessionAllowed = attributes.stream().anyMatch((t) -> whitelist.contains(t));
99+
// Check attributes cached in LDAP user object first, then query LDAP server
100+
// (and if found, cache the result in the LDAP user object).
101+
attributeValues = ldapUser.getAttribute(ldapAttr);
102+
if (attributeValues != null) {
103+
sessionAllowed = attributeValues.stream().anyMatch((t) -> whitelist.contains(t));
106104
} else {
107105
if ((records = getLdapProvider().lookupLdapContent(user, new String[]{ldapAttr})) == null) {
108106
return;
109107
}
110108

111-
if (records.isEmpty() || (attributes = records.get(ldapAttr)) == null) {
109+
if (records.isEmpty() || (attributeValues = records.get(ldapAttr)) == null) {
112110
return;
113111
}
114112

115-
ldapUser.setAttribute(ldapAttr, attributes);
116-
sessionAllowed = attributes.stream().anyMatch((t) -> whitelist.contains(t));
113+
ldapUser.setAttribute(ldapAttr, attributeValues);
114+
sessionAllowed = attributeValues.stream().anyMatch((t) -> whitelist.contains(t));
117115
}
118116

119117
updateSession(req, sessionAllowed);

plugins/src/opengrok/auth/plugin/LdapFilterPlugin.java

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,6 @@ public void fillSession(HttpServletRequest req, User user) {
8383
return;
8484
}
8585

86-
if (ldapUser.getUid() == null) {
87-
LOGGER.log(Level.FINER, "failed to get uid");
88-
return;
89-
}
90-
9186
String expandedFilter = expandFilter(ldapFilter, ldapUser, user);
9287
LOGGER.log(Level.FINER, "expanded filter for user {0} into ''{1}''",
9388
new Object[]{user, expandedFilter});
@@ -103,30 +98,25 @@ public void fillSession(HttpServletRequest req, User user) {
10398
}
10499

105100
/**
106-
* Insert the special values into the filter.
101+
* Expand LdapUser attribute values into the filter.
107102
*
108103
* Special values are:
109104
* <ul>
110-
* <li>%uid% - to be replaced with LDAP uid value</li>
111-
* <li>%mail% - to be replaced with LDAP mail value</li>
112-
* <li>%username% - to be replaced with OSSO user value</li>
113-
* <li>%guid% - to be replaced with OSSO guid value</li>
105+
* <li>%username% - to be replaced with username value from the User object</li>
106+
* <li>%guid% - to be replaced with guid value from the User object</li>
114107
* </ul>
115108
*
116109
* Use \% for printing the '%' character.
117-
* Also replaces any other LDAP attribute that would not be ambiguous.
118110
*
119111
* @param filter basic filter containing the special values
120112
* @param ldapUser user from LDAP
121113
* @param user user from the request
122114
* @return replaced result
123115
*/
124116
protected String expandFilter(String filter, LdapUser ldapUser, User user) {
125-
filter = filter.replaceAll("(?<!\\\\)%uid(?<!\\\\)%", ldapUser.getUid());
126-
filter = filter.replaceAll("(?<!\\\\)%mail(?<!\\\\)%", ldapUser.getMail());
127117
filter = filter.replaceAll("(?<!\\\\)%username(?<!\\\\)%", user.getUsername());
128118
filter = filter.replaceAll("(?<!\\\\)%guid(?<!\\\\)%", user.getId());
129-
119+
130120
for (Entry<String, Set<String>> entry : ldapUser.getAttributes().entrySet()) {
131121
if (entry.getValue().size() == 1) {
132122
try {
@@ -137,7 +127,6 @@ protected String expandFilter(String filter, LdapUser ldapUser, User user) {
137127
LOGGER.log(Level.WARNING, "The pattern for expanding is not valid", ex);
138128
}
139129
}
140-
141130
}
142131

143132
filter = filter.replaceAll("\\\\%", "%");

plugins/src/opengrok/auth/plugin/LdapUserPlugin.java

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
*/
2323
package opengrok.auth.plugin;
2424

25+
import java.util.HashMap;
2526
import java.util.Map;
2627
import java.util.Set;
2728
import java.util.logging.Level;
@@ -37,6 +38,7 @@
3738

3839
/**
3940
* Authorization plug-in to extract user's LDAP attributes.
41+
* The attributes can be then used by the other LDAP plugins down the stack.
4042
*
4143
* @author Krystof Tulinger
4244
*/
@@ -45,9 +47,19 @@ public class LdapUserPlugin extends AbstractLdapPlugin {
4547
private static final Logger LOGGER = Logger.getLogger(LdapUserPlugin.class.getName());
4648

4749
public static final String SESSION_ATTR = "opengrok-ldap-plugin-user";
50+
51+
/**
52+
* configuration names
53+
* <ul>
54+
* <li><code>objectclass</code> is LDAP object class</li>
55+
* <li><code>attributes</code> is comma separated list of LDAP attributes</li>
56+
* </ul>
57+
*/
4858
protected static final String OBJECT_CLASS = "objectclass";
59+
protected static final String ATTRIBUTES = "attributes";
4960

5061
private String objectClass;
62+
private String[] attributes;
5163
private final Pattern usernameCnPattern = Pattern.compile("(cn=[a-zA-Z0-9_-]+)");
5264

5365
@Override
@@ -63,9 +75,17 @@ public void load(Map<String, Object> parameters) {
6375
throw new NullPointerException("object class '" + objectClass +
6476
"' contains non-alphanumeric characters");
6577
}
66-
67-
LOGGER.log(Level.FINE, "LdapUser plugin loaded with objectclass={0}",
68-
objectClass);
78+
79+
String attributesVal;
80+
if ((attributesVal = (String) parameters.get(ATTRIBUTES)) == null) {
81+
throw new NullPointerException("Missing param [" + ATTRIBUTES +
82+
"] in the setup");
83+
}
84+
attributes = attributesVal.split(",");
85+
86+
LOGGER.log(Level.FINE, "LdapUser plugin loaded with objectclass={0}, " +
87+
"attributes={1}",
88+
new Object[]{objectClass, String.join(", ", attributes)});
6989
}
7090

7191
/**
@@ -108,14 +128,15 @@ public void fillSession(HttpServletRequest req, User user) {
108128
updateSession(req, null);
109129

110130
if (getLdapProvider() == null) {
131+
LOGGER.log(Level.WARNING, "cannot get LDAP provider for LdapUser plugin");
111132
return;
112133
}
113134

114135
String filter = getFilter(user);
115-
if ((records = getLdapProvider().lookupLdapContent(null, filter,
116-
new String[]{"uid", "mail", "ou"})) == null) {
117-
LOGGER.log(Level.WARNING, "failed to get LDAP contents for user ''{0}'' with filter ''{1}''",
118-
new Object[]{user, filter});
136+
if ((records = getLdapProvider().lookupLdapContent(null, filter, attributes)) == null) {
137+
LOGGER.log(Level.WARNING, "failed to get LDAP attributes ''{3}'' for user ''{0}'' " +
138+
"with filter ''{1}''",
139+
new Object[]{user, filter, String.join(", ", attributes)});
119140
return;
120141
}
121142

@@ -125,22 +146,19 @@ public void fillSession(HttpServletRequest req, User user) {
125146
return;
126147
}
127148

128-
if (!records.containsKey("uid") || records.get("uid").isEmpty()) {
129-
LOGGER.log(Level.WARNING, "uid record for user {0} is not present or empty",
130-
user);
131-
return;
149+
for (String attrName : attributes) {
150+
if (!records.containsKey(attrName) || records.get(attrName).isEmpty()) {
151+
LOGGER.log(Level.WARNING, "{0} record for user {1} is not present or empty",
152+
new Object[]{attrName, user});
153+
}
132154
}
133155

134-
if (!records.containsKey("mail") || records.get("mail").isEmpty()) {
135-
LOGGER.log(Level.WARNING, "mail record for user {0} is not present or empty",
136-
user);
137-
return;
156+
Map<String, Set<String>> attrSet = new HashMap<>();
157+
for (String attrName : attributes) {
158+
attrSet.put(attrName, records.get(attrName));
138159
}
139160

140-
updateSession(req, new LdapUser(
141-
records.get("mail").iterator().next(),
142-
records.get("uid").iterator().next(),
143-
records.get("ou")));
161+
updateSession(req, new LdapUser(attrSet));
144162
}
145163

146164
/**

plugins/test/opengrok/auth/plugin/LdapAttrPluginTest.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.io.Writer;
3030
import java.nio.file.Files;
3131
import java.util.Arrays;
32+
import java.util.Collections;
33+
import java.util.HashSet;
3234
import java.util.Map;
3335
import java.util.TreeMap;
3436
import java.util.TreeSet;
@@ -78,11 +80,16 @@ public void setUp() {
7880
plugin.load(parameters);
7981
}
8082

83+
@SuppressWarnings("unchecked")
8184
private void prepareRequest(String username, String mail, String... ous) {
8285
dummyRequest = new DummyHttpServletRequestLdap();
83-
dummyRequest.setAttribute(UserPlugin.REQUEST_ATTR, new User(username, "123", null, false));
84-
dummyRequest.getSession().setAttribute(LdapUserPlugin.SESSION_ATTR, new LdapUser(mail, "123",
85-
new TreeSet<>(Arrays.asList(ous))));
86+
dummyRequest.setAttribute(UserPlugin.REQUEST_ATTR,
87+
new User(username, "123", null, false));
88+
LdapUser ldapUser = new LdapUser();
89+
ldapUser.setAttribute("mail", new TreeSet<>(Collections.singletonList(mail)));
90+
ldapUser.setAttribute("uid", new TreeSet<>(Collections.singletonList("123")));
91+
ldapUser.setAttribute("ou", new TreeSet<>(Arrays.asList(ous)));
92+
dummyRequest.getSession().setAttribute(LdapUserPlugin.SESSION_ATTR, ldapUser);
8693
plugin.setSessionEstablished(dummyRequest, true);
8794
plugin.setSessionUsername(dummyRequest, username);
8895
}
@@ -104,7 +111,7 @@ private Group makeGroup(String name) {
104111
*/
105112
@Test
106113
public void testIsAllowed() {
107-
/**
114+
/*
108115
* whitelist[mail] => [[email protected], [email protected], just_a_text]
109116
*/
110117
prepareRequest("007", "[email protected]", "MI6", "MI7");

0 commit comments

Comments
 (0)