Skip to content

Commit f639d96

Browse files
committed
Retrieve public SSH keys from LDAP.
Add new class `LdapPublicKeyManager` which retrieves public SSH keys from LDAP. The attribute can be configured with the new configuration option `realm.ldap.sshPublicKey`. The setting can be a simple attribute name, like `sshPublicKey`, or an attribute name and a prefix for the value, like `altSecurityIdentities:SshKey`, in which case attributes are selected that have the name `altSecurityIdentities` and whose values start with `SshKey:`.
1 parent 967c242 commit f639d96

File tree

6 files changed

+1248
-37
lines changed

6 files changed

+1248
-37
lines changed

src/main/distrib/data/defaults.properties

+12
Original file line numberDiff line numberDiff line change
@@ -1935,6 +1935,18 @@ realm.ldap.email = email
19351935
# SINCE 1.0.0
19361936
realm.ldap.uid = uid
19371937

1938+
# Attribute on the USER record that indicates their public SSH key.
1939+
# Leave blank when public SSH keys shall not be retrieved from LDAP.
1940+
#
1941+
# This may be a simple attribute or an attribute and a value prefix. Examples:
1942+
# sshPublicKey - Use the attribute 'sshPublicKey' on the user record.
1943+
# altSecurityIdentities:SshKey - Use the attribute 'altSecurityIdentities'
1944+
# on the user record, for which the record value
1945+
# starts with 'SshKey:', followed by the SSH key entry.
1946+
#
1947+
# SINCE 1.9.0
1948+
realm.ldap.sshPublicKey =
1949+
19381950
# Defines whether to synchronize all LDAP users and teams into the user service
19391951
# This requires either anonymous LDAP access or that a specific account is set
19401952
# in realm.ldap.username and realm.ldap.password, that has permission to read

src/main/java/com/gitblit/auth/LdapAuthProvider.java

+4-7
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ public synchronized void sync() {
107107
}
108108

109109
try {
110-
String accountBase = settings.getString(Keys.realm.ldap.accountBase, "");
111110
String uidAttribute = settings.getString(Keys.realm.ldap.uid, "uid");
112-
String accountPattern = settings.getString(Keys.realm.ldap.accountPattern, "(&(objectClass=person)(sAMAccountName=${username}))");
111+
String accountBase = ldapConnection.getAccountBase();
112+
String accountPattern = ldapConnection.getAccountPattern();
113113
accountPattern = StringUtils.replace(accountPattern, "${username}", "*");
114114

115115
SearchResult result = doSearch(ldapConnection, accountBase, accountPattern);
@@ -275,11 +275,7 @@ public UserModel authenticate(String username, char[] password) {
275275

276276
try {
277277
// Find the logging in user's DN
278-
String accountBase = settings.getString(Keys.realm.ldap.accountBase, "");
279-
String accountPattern = settings.getString(Keys.realm.ldap.accountPattern, "(&(objectClass=person)(sAMAccountName=${username}))");
280-
accountPattern = StringUtils.replace(accountPattern, "${username}", LdapConnection.escapeLDAPSearchFilter(simpleUsername));
281-
282-
SearchResult result = doSearch(ldapConnection, accountBase, accountPattern);
278+
SearchResult result = ldapConnection.searchUser(simpleUsername);
283279
if (result != null && result.getEntryCount() == 1) {
284280
SearchResultEntry loggingInUser = result.getSearchEntries().get(0);
285281
String loggingInUserDN = loggingInUser.getDN();
@@ -527,6 +523,7 @@ private SearchResult doSearch(LdapConnection ldapConnection, String base, String
527523

528524

529525

526+
530527
/**
531528
* Returns a simple username without any domain prefixes.
532529
*

src/main/java/com/gitblit/ldap/LdapConnection.java

+80-30
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/*
2+
* Copyright 2016 gitblit.com.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
116
package com.gitblit.ldap;
217

318
import java.net.URI;
@@ -69,6 +84,16 @@ public static final String escapeLDAPSearchFilter(String filter) {
6984

7085

7186

87+
public static String getAccountBase(IStoredSettings settings) {
88+
return settings.getString(Keys.realm.ldap.accountBase, "");
89+
}
90+
91+
public static String getAccountPattern(IStoredSettings settings) {
92+
return settings.getString(Keys.realm.ldap.accountPattern, "(&(objectClass=person)(sAMAccountName=${username}))");
93+
}
94+
95+
96+
7297
public LdapConnection(IStoredSettings settings) {
7398
this.settings = settings;
7499

@@ -82,6 +107,16 @@ public LdapConnection(IStoredSettings settings) {
82107

83108

84109

110+
public String getAccountBase() {
111+
return getAccountBase(settings);
112+
}
113+
114+
public String getAccountPattern() {
115+
return getAccountPattern(settings);
116+
}
117+
118+
119+
85120
public boolean connect() {
86121
try {
87122
URI ldapUrl = new URI(settings.getRequiredString(Keys.realm.ldap.server));
@@ -198,36 +233,6 @@ public boolean rebindAsUser() {
198233

199234

200235

201-
public SearchResult search(SearchRequest request) {
202-
try {
203-
return conn.search(request);
204-
} catch (LDAPSearchException e) {
205-
logger.error("Problem Searching LDAP [{}]", e.getResultCode());
206-
return e.getSearchResult();
207-
}
208-
}
209-
210-
211-
public SearchResult search(String base, boolean dereferenceAliases, String filter, List<String> attributes) {
212-
try {
213-
SearchRequest searchRequest = new SearchRequest(base, SearchScope.SUB, filter);
214-
if (dereferenceAliases) {
215-
searchRequest.setDerefPolicy(DereferencePolicy.SEARCHING);
216-
}
217-
if (attributes != null) {
218-
searchRequest.setAttributes(attributes);
219-
}
220-
SearchResult result = search(searchRequest);
221-
return result;
222-
223-
} catch (LDAPException e) {
224-
logger.error("Problem creating LDAP search", e);
225-
return null;
226-
}
227-
}
228-
229-
230-
231236
public boolean isAuthenticated(String userDn, String password) {
232237
verifyCurrentBinding();
233238

@@ -267,6 +272,51 @@ public boolean isAuthenticated(String userDn, String password) {
267272

268273

269274

275+
276+
public SearchResult search(SearchRequest request) {
277+
try {
278+
return conn.search(request);
279+
} catch (LDAPSearchException e) {
280+
logger.error("Problem Searching LDAP [{}]", e.getResultCode());
281+
return e.getSearchResult();
282+
}
283+
}
284+
285+
286+
public SearchResult search(String base, boolean dereferenceAliases, String filter, List<String> attributes) {
287+
try {
288+
SearchRequest searchRequest = new SearchRequest(base, SearchScope.SUB, filter);
289+
if (dereferenceAliases) {
290+
searchRequest.setDerefPolicy(DereferencePolicy.SEARCHING);
291+
}
292+
if (attributes != null) {
293+
searchRequest.setAttributes(attributes);
294+
}
295+
SearchResult result = search(searchRequest);
296+
return result;
297+
298+
} catch (LDAPException e) {
299+
logger.error("Problem creating LDAP search", e);
300+
return null;
301+
}
302+
}
303+
304+
305+
public SearchResult searchUser(String username, List<String> attributes) {
306+
307+
String accountPattern = getAccountPattern();
308+
accountPattern = StringUtils.replace(accountPattern, "${username}", escapeLDAPSearchFilter(username));
309+
310+
return search(getAccountBase(), false, accountPattern, attributes);
311+
}
312+
313+
314+
public SearchResult searchUser(String username) {
315+
return searchUser(username, null);
316+
}
317+
318+
319+
270320
private boolean verifyCurrentBinding() {
271321
BindRequest lastBind = conn.getLastBindRequest();
272322
if (lastBind == currentBindRequest) {

0 commit comments

Comments
 (0)