001package org.apache.archiva.rest.services;
002/*
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 */
020
021import org.apache.archiva.admin.model.RepositoryAdminException;
022import org.apache.archiva.admin.model.beans.LdapConfiguration;
023import org.apache.archiva.admin.model.beans.RedbackRuntimeConfiguration;
024import org.apache.archiva.admin.model.runtime.RedbackRuntimeConfigurationAdmin;
025import org.apache.archiva.redback.authentication.Authenticator;
026import org.apache.archiva.redback.common.ldap.connection.LdapConnection;
027import org.apache.archiva.redback.common.ldap.connection.LdapConnectionConfiguration;
028import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory;
029import org.apache.archiva.redback.common.ldap.connection.LdapException;
030import org.apache.archiva.redback.common.ldap.user.LdapUserMapper;
031import org.apache.archiva.redback.components.cache.Cache;
032import org.apache.archiva.redback.policy.CookieSettings;
033import org.apache.archiva.redback.policy.PasswordRule;
034import org.apache.archiva.redback.rbac.RBACManager;
035import org.apache.archiva.redback.role.RoleManager;
036import org.apache.archiva.redback.users.UserManager;
037import org.apache.archiva.rest.api.model.RBACManagerImplementationInformation;
038import org.apache.archiva.rest.api.model.RedbackImplementationsInformations;
039import org.apache.archiva.rest.api.model.UserManagerImplementationInformation;
040import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
041import org.apache.archiva.rest.api.services.RedbackRuntimeConfigurationService;
042import org.apache.commons.lang.StringUtils;
043import org.springframework.context.ApplicationContext;
044import org.springframework.stereotype.Service;
045
046import javax.inject.Inject;
047import javax.inject.Named;
048import javax.naming.InvalidNameException;
049import java.util.ArrayList;
050import java.util.Collection;
051import java.util.Collections;
052import java.util.List;
053import java.util.Map;
054import java.util.Properties;
055
056/**
057 * @author Olivier Lamy
058 * @since 1.4-M4
059 */
060@Service("redbackRuntimeConfigurationService#rest")
061public class DefaultRedbackRuntimeConfigurationService
062    extends AbstractRestService
063    implements RedbackRuntimeConfigurationService
064{
065
066    @Inject
067    private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin;
068
069    @Inject
070    @Named(value = "userManager#configurable")
071    private UserManager userManager;
072
073    @Inject
074    @Named(value = "rbacManager#default")
075    private RBACManager rbacManager;
076
077    @Inject
078    private RoleManager roleManager;
079
080    @Inject
081    private ApplicationContext applicationContext;
082
083    @Inject
084    @Named(value = "ldapConnectionFactory#configurable")
085    private LdapConnectionFactory ldapConnectionFactory;
086
087    @Inject
088    @Named(value = "cache#users")
089    private Cache usersCache;
090
091    @Inject
092    private LdapUserMapper ldapUserMapper;
093
094
095    @Override
096    public RedbackRuntimeConfiguration getRedbackRuntimeConfiguration()
097        throws ArchivaRestServiceException
098    {
099        try
100        {
101            RedbackRuntimeConfiguration redbackRuntimeConfiguration =
102                redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration();
103
104            log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
105
106            return redbackRuntimeConfiguration;
107        }
108        catch ( RepositoryAdminException e )
109        {
110            throw new ArchivaRestServiceException( e.getMessage(), e );
111        }
112    }
113
114    @Override
115    public Boolean updateRedbackRuntimeConfiguration( RedbackRuntimeConfiguration redbackRuntimeConfiguration )
116        throws ArchivaRestServiceException
117    {
118        try
119        {
120            // has user manager impl changed ?
121            boolean userManagerChanged = redbackRuntimeConfiguration.getUserManagerImpls().size()
122                != redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration().getUserManagerImpls().size();
123
124            userManagerChanged =
125                userManagerChanged || ( redbackRuntimeConfiguration.getUserManagerImpls().toString().hashCode()
126                    != redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration().getUserManagerImpls().toString().hashCode() );
127
128            boolean rbacManagerChanged = redbackRuntimeConfiguration.getRbacManagerImpls().size()
129                != redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration().getRbacManagerImpls().size();
130
131            rbacManagerChanged =
132                rbacManagerChanged || ( redbackRuntimeConfiguration.getRbacManagerImpls().toString().hashCode()
133                    != redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration().getRbacManagerImpls().toString().hashCode() );
134
135            boolean ldapConfigured = false;
136            for (String um : redbackRuntimeConfiguration.getUserManagerImpls()) {
137                if (um.contains("ldap")) {
138                    ldapConfigured=true;
139                }
140            }
141            if (!ldapConfigured) {
142                for (String rbm : redbackRuntimeConfiguration.getRbacManagerImpls()) {
143                    if (rbm.contains("ldap")) {
144                        ldapConfigured = true;
145                    }
146                }
147            }
148
149            redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration );
150
151            if ( userManagerChanged )
152            {
153                log.info( "user managerImpls changed to {} so reload it",
154                          redbackRuntimeConfiguration.getUserManagerImpls() );
155                userManager.initialize();
156            }
157
158            if ( rbacManagerChanged )
159            {
160                log.info( "rbac manager changed to {}?so reload it",
161                          redbackRuntimeConfiguration.getRbacManagerImpls() );
162                rbacManager.initialize();
163                roleManager.initialize();
164            }
165
166            if (ldapConfigured) {
167                try {
168                    ldapConnectionFactory.initialize();
169                } catch (Exception e) {
170                    ArchivaRestServiceException newEx = new ArchivaRestServiceException(e.getMessage(), e);
171                    newEx.setErrorKey("error.ldap.connectionFactory.init.failed");
172                    throw newEx;
173                }
174            }
175            Collection<PasswordRule> passwordRules = applicationContext.getBeansOfType( PasswordRule.class ).values();
176
177            for ( PasswordRule passwordRule : passwordRules )
178            {
179                passwordRule.initialize();
180            }
181
182            Collection<CookieSettings> cookieSettingsList =
183                applicationContext.getBeansOfType( CookieSettings.class ).values();
184
185            for ( CookieSettings cookieSettings : cookieSettingsList )
186            {
187                cookieSettings.initialize();
188            }
189
190            Collection<Authenticator> authenticators =
191                applicationContext.getBeansOfType( Authenticator.class ).values();
192
193            for ( Authenticator authenticator : authenticators )
194            {
195                try {
196                    log.debug("Initializing authenticatior "+authenticator.getId());
197                    authenticator.initialize();
198                } catch (Exception e) {
199                    log.error("Initialization of authenticator failed "+authenticator.getId(),e);
200                }
201            }
202
203            // users cache
204            usersCache.setTimeToIdleSeconds(
205                redbackRuntimeConfiguration.getUsersCacheConfiguration().getTimeToIdleSeconds() );
206            usersCache.setTimeToLiveSeconds(
207                redbackRuntimeConfiguration.getUsersCacheConfiguration().getTimeToLiveSeconds() );
208            usersCache.setMaxElementsInMemory(
209                redbackRuntimeConfiguration.getUsersCacheConfiguration().getMaxElementsInMemory() );
210            usersCache.setMaxElementsOnDisk(
211                redbackRuntimeConfiguration.getUsersCacheConfiguration().getMaxElementsOnDisk() );
212
213            if (ldapConfigured) {
214                try {
215                    ldapUserMapper.initialize();
216                } catch (Exception e) {
217                    ArchivaRestServiceException newEx = new ArchivaRestServiceException(e.getMessage(), e);
218                    newEx.setErrorKey("error.ldap.userMapper.init.failed");
219                    throw newEx;
220                }
221            }
222
223            //check repositories roles are here !!!
224
225            return Boolean.TRUE;
226        }
227        catch (ArchivaRestServiceException e) {
228            log.error(e.getMessage(), e);
229            throw e;
230        } catch ( Exception e )
231        {
232            log.error( e.getMessage(), e );
233            throw new ArchivaRestServiceException(e.getMessage(), e);
234        }
235    }
236
237    @Override
238    public List<UserManagerImplementationInformation> getUserManagerImplementationInformations()
239        throws ArchivaRestServiceException
240    {
241
242        Map<String, UserManager> beans = applicationContext.getBeansOfType( UserManager.class );
243
244        if ( beans.isEmpty() )
245        {
246            return Collections.emptyList();
247        }
248
249        List<UserManagerImplementationInformation> informations = new ArrayList<>( beans.size() );
250
251        for ( Map.Entry<String, UserManager> entry : beans.entrySet() )
252        {
253            UserManager userManager = applicationContext.getBean( entry.getKey(), UserManager.class );
254            if ( userManager.isFinalImplementation() )
255            {
256                UserManagerImplementationInformation information = new UserManagerImplementationInformation();
257                information.setBeanId( StringUtils.substringAfter( entry.getKey(), "#" ) );
258                information.setDescriptionKey( userManager.getDescriptionKey() );
259                information.setReadOnly( userManager.isReadOnly() );
260                informations.add( information );
261            }
262        }
263
264        return informations;
265    }
266
267    @Override
268    public List<RBACManagerImplementationInformation> getRbacManagerImplementationInformations()
269        throws ArchivaRestServiceException
270    {
271        Map<String, RBACManager> beans = applicationContext.getBeansOfType( RBACManager.class );
272
273        if ( beans.isEmpty() )
274        {
275            return Collections.emptyList();
276        }
277
278        List<RBACManagerImplementationInformation> informations = new ArrayList<>( beans.size() );
279
280        for ( Map.Entry<String, RBACManager> entry : beans.entrySet() )
281        {
282            RBACManager rbacManager = applicationContext.getBean( entry.getKey(), RBACManager.class );
283            if ( rbacManager.isFinalImplementation() )
284            {
285                RBACManagerImplementationInformation information = new RBACManagerImplementationInformation();
286                information.setBeanId( StringUtils.substringAfter( entry.getKey(), "#" ) );
287                information.setDescriptionKey( rbacManager.getDescriptionKey() );
288                information.setReadOnly( rbacManager.isReadOnly() );
289                informations.add( information );
290            }
291        }
292
293        return informations;
294    }
295
296    @Override
297    public RedbackImplementationsInformations getRedbackImplementationsInformations()
298        throws ArchivaRestServiceException
299    {
300        return new RedbackImplementationsInformations( getUserManagerImplementationInformations(),
301                                                       getRbacManagerImplementationInformations() );
302    }
303
304    @Override
305    public Boolean checkLdapConnection()
306        throws ArchivaRestServiceException
307    {
308        LdapConnection ldapConnection = null;
309        try
310        {
311            ldapConnection = ldapConnectionFactory.getConnection();
312        }
313        catch ( LdapException e )
314        {
315            log.warn( "fail to get ldapConnection: {}", e.getMessage(), e );
316            throw new ArchivaRestServiceException( e.getMessage(), e );
317        }
318        finally
319        {
320
321            if ( ldapConnection != null )
322            {
323                ldapConnection.close();
324            }
325        }
326
327        return Boolean.TRUE;
328    }
329
330    @Override
331    public Boolean checkLdapConnection( LdapConfiguration ldapConfiguration )
332        throws ArchivaRestServiceException
333    {
334        LdapConnection ldapConnection = null;
335        try
336        {
337            LdapConnectionConfiguration ldapConnectionConfiguration =
338                new LdapConnectionConfiguration( ldapConfiguration.getHostName(), ldapConfiguration.getPort(),
339                                                 ldapConfiguration.getBaseDn(), ldapConfiguration.getContextFactory(),
340                                                 ldapConfiguration.getBindDn(), ldapConfiguration.getPassword(),
341                                                 ldapConfiguration.getAuthenticationMethod(),
342                                                 toProperties( ldapConfiguration.getExtraProperties() ) );
343            ldapConnectionConfiguration.setSsl( ldapConfiguration.isSsl() );
344
345            ldapConnection = ldapConnectionFactory.getConnection( ldapConnectionConfiguration );
346
347            ldapConnection.close();
348
349            // verify groups dn value too
350
351            ldapConnectionConfiguration =
352                new LdapConnectionConfiguration( ldapConfiguration.getHostName(), ldapConfiguration.getPort(),
353                                                 ldapConfiguration.getBaseGroupsDn(),
354                                                 ldapConfiguration.getContextFactory(), ldapConfiguration.getBindDn(),
355                                                 ldapConfiguration.getPassword(),
356                                                 ldapConfiguration.getAuthenticationMethod(),
357                                                 toProperties( ldapConfiguration.getExtraProperties() ) );
358
359            ldapConnectionConfiguration.setSsl( ldapConfiguration.isSsl() );
360
361            ldapConnection = ldapConnectionFactory.getConnection( ldapConnectionConfiguration );
362        }
363        catch ( InvalidNameException e )
364        {
365            log.warn( "fail to get ldapConnection: {}", e.getMessage(), e );
366            throw new ArchivaRestServiceException( e.getMessage(), e );
367        }
368        catch ( LdapException e )
369        {
370            log.warn( "fail to get ldapConnection: {}", e.getMessage(), e );
371            throw new ArchivaRestServiceException( e.getMessage(), e );
372        }
373        finally
374        {
375
376            if ( ldapConnection != null )
377            {
378                ldapConnection.close();
379            }
380        }
381
382        return Boolean.TRUE;
383    }
384
385    private Properties toProperties( Map<String, String> map )
386    {
387        Properties properties = new Properties();
388        if ( map == null || map.isEmpty() )
389        {
390            return properties;
391        }
392        for ( Map.Entry<String, String> entry : map.entrySet() )
393        {
394            properties.put( entry.getKey(), entry.getValue() );
395        }
396        return properties;
397    }
398
399}
400
401