001package co.codewizards.cloudstore.rest.server.ldap;
002
003import java.util.List;
004
005import org.slf4j.Logger;
006import org.slf4j.LoggerFactory;
007
008import co.codewizards.cloudstore.core.config.ConfigImpl;
009import co.codewizards.cloudstore.core.otp.LdapPasswordOneTimePadRegistry;
010import co.codewizards.cloudstore.core.otp.OneTimePadRegistry;
011import co.codewizards.cloudstore.core.util.StringUtil;
012
013/**
014 * Fail-safe initializer of choosen LdapClient implementation.
015 * <p>
016 * Since LDAP-based authentication is optional - this class won't throw any Exception
017 * during initialization, until you call getClient().
018 * <p>
019 * Choice of proper LdapClient implementation is based on configuration in cloudstore.properties config file.
020 *
021 * @author Wojtek Wilk - wilk.wojtek at gmail.com
022 */
023public class LdapClientProvider {
024
025        private static final Logger log = LoggerFactory.getLogger(LdapClientProvider.class);
026
027        public static final String LDAP_TEMPLATE_PATTERN = "ldap.bindDnTemplate[%d]";
028
029        public static final String LDAP_URL = "ldap.url";
030        private static final String LDAP_URL_DEFAULT = "ldap://localhost:389";
031
032        public static final String LDAP_QUERY = "ldap.query";
033        public static final String LDAP_ADMIN_DN = "ldap.adminDn";
034        public static final String LDAP_QUERY_DN = "ldap.queryDn";
035
036        private LdapClient ldapClient;
037
038        protected LdapClientProvider(){
039                this(new LdapPasswordOneTimePadRegistry());
040        }
041
042        protected LdapClientProvider(OneTimePadRegistry adminPasswordRegistry){
043                try{
044                        final String url = ConfigImpl.getInstance().getProperty(LDAP_URL, LDAP_URL_DEFAULT);
045                        final String query = ConfigImpl.getInstance().getProperty(LDAP_QUERY, "");
046                        if(StringUtil.isEmpty(query)){
047                                ldapClient = createSimpleLdapClient(url);
048                        } else{
049                                ldapClient = createQueryLdapClient(adminPasswordRegistry, query, url);
050                        }
051                } catch(Exception e){
052                        log.warn("LDAP client initialization failed. If you don't use LDAP you can ignore this warning, otherwise you can increase logging to DEBUG in order to see what is the cause of this failure.");
053                        log.debug("LDAP client initialization failed", e);
054                }
055        }
056
057        public LdapClient getClient(){
058                if(ldapClient == null){
059                        throw new IllegalStateException("LDAP is not properly configured. Maybe you forgot to put LDAP properties inside cloudstore.properties?");
060                }
061                return ldapClient;
062        }
063
064        public static LdapClientProvider getInstance(){
065                return Helper.INSTANCE;
066        }
067
068        private static class Helper{
069                private static final LdapClientProvider INSTANCE = new LdapClientProvider();
070        }
071
072        private SimpleLdapClient createSimpleLdapClient(final String url){
073                final List<String> templates = new DnTemplateCollector().collect();
074                return new SimpleLdapClient(templates, url);
075        }
076
077        private QueryLdapClient createQueryLdapClient(final OneTimePadRegistry adminPasswordRegistry,
078                        final String query, final String url){
079                final char[] password = adminPasswordRegistry.readFromFileAndDecrypt();
080                final String queryDn = ConfigImpl.getInstance().getProperty(LDAP_QUERY_DN, null);
081                final String adminDn = ConfigImpl.getInstance().getProperty(LDAP_ADMIN_DN, null);
082                return new QueryLdapClient(query, queryDn, url, adminDn, password);
083        }
084}