| | |
| | | import java.net.URI; |
| | | import java.net.URISyntaxException; |
| | | import java.security.GeneralSecurityException; |
| | | import java.text.MessageFormat; |
| | | import java.util.Arrays; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.ScheduledExecutorService; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.atomic.AtomicLong; |
| | | |
| | | import com.gitblit.Constants; |
| | | import com.gitblit.Constants.AccountType; |
| | |
| | | */ |
| | | public class LdapAuthProvider extends UsernamePasswordAuthenticationProvider { |
| | | |
| | | private final AtomicLong lastLdapUserSync = new AtomicLong(0L); |
| | | private final ScheduledExecutorService scheduledExecutorService; |
| | | |
| | | public LdapAuthProvider() { |
| | | super("ldap"); |
| | | |
| | | scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); |
| | | } |
| | | |
| | | private long getSynchronizationPeriodInMilliseconds(String name) { |
| | | final String cacheDuration = settings.getString(name, "2 MINUTES"); |
| | | private long getSynchronizationPeriodInMilliseconds() { |
| | | String period = settings.getString(Keys.realm.ldap.syncPeriod, null); |
| | | if (StringUtils.isEmpty(period)) { |
| | | period = settings.getString("realm.ldap.ldapCachePeriod", null); |
| | | if (StringUtils.isEmpty(period)) { |
| | | period = "5 MINUTES"; |
| | | } else { |
| | | logger.warn("realm.ldap.ldapCachePeriod is obsolete!"); |
| | | logger.warn(MessageFormat.format("Please set {0}={1} in gitblit.properties!", Keys.realm.ldap.syncPeriod, period)); |
| | | settings.overrideSetting(Keys.realm.ldap.syncPeriod, period); |
| | | } |
| | | } |
| | | |
| | | try { |
| | | final String[] s = cacheDuration.split(" ", 2); |
| | | final String[] s = period.split(" ", 2); |
| | | long duration = Math.abs(Long.parseLong(s[0])); |
| | | TimeUnit timeUnit = TimeUnit.valueOf(s[1]); |
| | | return timeUnit.toMillis(duration); |
| | | } catch (RuntimeException ex) { |
| | | throw new IllegalArgumentException(name + " must have format '<long> <TimeUnit>' where <TimeUnit> is one of 'MILLISECONDS', 'SECONDS', 'MINUTES', 'HOURS', 'DAYS'"); |
| | | throw new IllegalArgumentException(Keys.realm.ldap.syncPeriod + " must have format '<long> <TimeUnit>' where <TimeUnit> is one of 'MILLISECONDS', 'SECONDS', 'MINUTES', 'HOURS', 'DAYS'"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void setup() { |
| | | synchronizeLdapUsers(); |
| | | configureLdapSyncService(); |
| | | configureSyncService(); |
| | | } |
| | | |
| | | public void synchronizeWithLdapService() { |
| | | synchronizeLdapUsers(); |
| | | @Override |
| | | public void stop() { |
| | | scheduledExecutorService.shutdownNow(); |
| | | } |
| | | |
| | | protected synchronized void synchronizeLdapUsers() { |
| | | final boolean enabled = settings.getBoolean(Keys.realm.ldap.synchronizeUsers.enable, false); |
| | | public synchronized void sync() { |
| | | final boolean enabled = settings.getBoolean(Keys.realm.ldap.synchronize, false); |
| | | if (enabled) { |
| | | if (System.currentTimeMillis() > (lastLdapUserSync.get() + getSynchronizationPeriodInMilliseconds(Keys.realm.ldap.ldapCachePeriod))) { |
| | | logger.info("Synchronizing with LDAP @ " + settings.getRequiredString(Keys.realm.ldap.server)); |
| | | final boolean deleteRemovedLdapUsers = settings.getBoolean(Keys.realm.ldap.synchronizeUsers.removeDeleted, true); |
| | | final boolean deleteRemovedLdapUsers = settings.getBoolean(Keys.realm.ldap.removeDeletedUsers, true); |
| | | LDAPConnection ldapConnection = getLdapConnection(); |
| | | if (ldapConnection != null) { |
| | | try { |
| | |
| | | logger.debug("detecting removed LDAP users..."); |
| | | |
| | | for (UserModel userModel : userManager.getAllUsers()) { |
| | | if (Constants.EXTERNAL_ACCOUNT.equals(userModel.password)) { |
| | | if (AccountType.LDAP == userModel.accountType) { |
| | | if (!ldapUsers.containsKey(userModel.username)) { |
| | | logger.info("deleting removed LDAP user " + userModel.username + " from user service"); |
| | | userManager.deleteUser(userModel.username); |
| | |
| | | if (!supportsTeamMembershipChanges()) { |
| | | getEmptyTeamsFromLdap(ldapConnection); |
| | | } |
| | | lastLdapUserSync.set(System.currentTimeMillis()); |
| | | } finally { |
| | | ldapConnection.close(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | private void getEmptyTeamsFromLdap(LDAPConnection ldapConnection) { |
| | | logger.info("Start fetching empty teams form ldap."); |
| | | logger.info("Start fetching empty teams from ldap."); |
| | | String groupBase = settings.getString(Keys.realm.ldap.groupBase, ""); |
| | | String groupMemberPattern = settings.getString(Keys.realm.ldap.groupEmptyMemberPattern, "(&(objectClass=group)(!(member=*)))"); |
| | | |
| | |
| | | } |
| | | } |
| | | } |
| | | logger.info("Finished fetching empty teams form ldap."); |
| | | logger.info("Finished fetching empty teams from ldap."); |
| | | } |
| | | |
| | | private TeamModel createTeamFromLdap(SearchResultEntry teamEntry) { |
| | |
| | | return sb.toString(); |
| | | } |
| | | |
| | | private void configureLdapSyncService() { |
| | | logger.info("Start configuring ldap sync service"); |
| | | private void configureSyncService() { |
| | | LdapSyncService ldapSyncService = new LdapSyncService(settings, this); |
| | | if (ldapSyncService.isReady()) { |
| | | long ldapSyncPeriod = getSynchronizationPeriodInMilliseconds(Keys.realm.ldap.synchronizeUsers.ldapSyncPeriod); |
| | | long ldapCachePeriod = getSynchronizationPeriodInMilliseconds(Keys.realm.ldap.synchronizeUsers.ldapSyncPeriod); |
| | | if (ldapSyncPeriod < ldapCachePeriod) { |
| | | ldapSyncPeriod = ldapCachePeriod; |
| | | } |
| | | long ldapSyncPeriod = getSynchronizationPeriodInMilliseconds(); |
| | | int delay = 1; |
| | | ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); |
| | | logger.info("Ldap sync service will update users and groups every {} minutes.", ldapSyncPeriod); |
| | | scheduledExecutorService.scheduleAtFixedRate(ldapSyncService, delay, ldapSyncPeriod, TimeUnit.MILLISECONDS); |
| | | logger.info("Ldap sync service will update user and groups every {} minutes.", ldapSyncPeriod); |
| | | logger.info("Next scheduled ldap sync is in {} minutes", delay); |
| | | } else { |
| | | logger.info("Ldap sync service is disabled."); |
| | | } |
| | | logger.info("Finished configuring ldap sync service"); |
| | | } |
| | | |
| | | } |