]> source.dussan.org Git - archiva.git/blob
be76f3164ba9f1c4fcc97a2b0c179a0ea8c4eaf0
[archiva.git] /
1 package org.apache.archiva.rest.services.v2;/*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an
13  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14  * KIND, either express or implied.  See the License for the
15  * specific language governing permissions and limitations
16  * under the License.
17  */
18
19 import org.apache.archiva.admin.model.RepositoryAdminException;
20 import org.apache.archiva.admin.model.beans.RedbackRuntimeConfiguration;
21 import org.apache.archiva.admin.model.runtime.RedbackRuntimeConfigurationAdmin;
22 import org.apache.archiva.components.cache.Cache;
23 import org.apache.archiva.components.rest.model.PagedResult;
24 import org.apache.archiva.components.rest.model.PropertyEntry;
25 import org.apache.archiva.components.rest.util.PagingHelper;
26 import org.apache.archiva.components.rest.util.QueryHelper;
27 import org.apache.archiva.redback.authentication.Authenticator;
28 import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory;
29 import org.apache.archiva.redback.common.ldap.user.LdapUserMapper;
30 import org.apache.archiva.redback.policy.CookieSettings;
31 import org.apache.archiva.redback.policy.PasswordRule;
32 import org.apache.archiva.redback.rbac.RBACManager;
33 import org.apache.archiva.redback.role.RoleManager;
34 import org.apache.archiva.redback.users.UserManager;
35 import org.apache.archiva.rest.api.model.UserManagerImplementationInformation;
36 import org.apache.archiva.rest.api.model.v2.BeanInformation;
37 import org.apache.archiva.rest.api.model.v2.CacheConfiguration;
38 import org.apache.archiva.rest.api.model.v2.LdapConfiguration;
39 import org.apache.archiva.rest.api.model.v2.SecurityConfiguration;
40 import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
41 import org.apache.archiva.rest.api.services.v2.ErrorMessage;
42 import org.apache.archiva.rest.api.services.v2.SecurityConfigurationService;
43 import org.apache.commons.collections4.CollectionUtils;
44 import org.apache.commons.collections4.ListUtils;
45 import org.apache.commons.lang3.StringUtils;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.context.ApplicationContext;
49 import org.springframework.stereotype.Service;
50
51 import javax.annotation.PostConstruct;
52 import javax.inject.Inject;
53 import javax.inject.Named;
54 import javax.management.Query;
55 import javax.ws.rs.core.Response;
56 import java.util.ArrayList;
57 import java.util.Collection;
58 import java.util.Collections;
59 import java.util.Comparator;
60 import java.util.List;
61 import java.util.Map;
62 import java.util.Objects;
63 import java.util.ResourceBundle;
64 import java.util.function.Predicate;
65 import java.util.stream.Collectors;
66
67 import static org.apache.archiva.rest.services.v2.ErrorKeys.REPOSITORY_ADMIN_ERROR;
68
69 /**
70  * @author Martin Stockhammer <martin_s@apache.org>
71  */
72 @Service( "v2.defaultSecurityConfigurationService" )
73 public class DefaultSecurityConfigurationService implements SecurityConfigurationService
74 {
75     private static final Logger log = LoggerFactory.getLogger( DefaultSecurityConfigurationService.class );
76
77     private static final QueryHelper<PropertyEntry> PROP_QUERY_HELPER = new QueryHelper( new String[]{"key"} );
78     private static final PagingHelper PROP_PAGING_HELPER = new PagingHelper( );
79     static {
80         PROP_QUERY_HELPER.addStringFilter( "key", PropertyEntry::getKey );
81         PROP_QUERY_HELPER.addStringFilter( "value", PropertyEntry::getValue );
82         PROP_QUERY_HELPER.addNullsafeFieldComparator( "key", PropertyEntry::getKey );
83         PROP_QUERY_HELPER.addNullsafeFieldComparator( "value", PropertyEntry::getValue );
84
85     }
86
87     private ResourceBundle bundle;
88
89
90     @Inject
91     private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin;
92
93     @Inject
94     private ApplicationContext applicationContext;
95
96     @Inject
97     @Named(value = "userManager#default")
98     private UserManager userManager;
99
100     @Inject
101     @Named(value = "rbacManager#default")
102     private RBACManager rbacManager;
103
104     @Inject
105     private RoleManager roleManager;
106
107     @Inject
108     @Named(value = "ldapConnectionFactory#configurable")
109     private LdapConnectionFactory ldapConnectionFactory;
110
111     @Inject
112     private LdapUserMapper ldapUserMapper;
113
114     @Inject
115     @Named(value = "cache#users")
116     private Cache usersCache;
117
118
119     @PostConstruct
120     void init() {
121         bundle = ResourceBundle.getBundle( "org.apache.archiva.rest.RestBundle" );
122     }
123
124     @Override
125     public SecurityConfiguration getConfiguration( ) throws ArchivaRestServiceException
126     {
127         try
128         {
129             RedbackRuntimeConfiguration redbackRuntimeConfiguration =
130                 redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
131
132             log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
133
134             return SecurityConfiguration.ofRedbackConfiguration( redbackRuntimeConfiguration );
135         }
136         catch ( RepositoryAdminException e )
137         {
138             throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
139         }
140     }
141     private void updateConfig(SecurityConfiguration newConfig, RedbackRuntimeConfiguration rbConfig) {
142         rbConfig.setUserManagerImpls( newConfig.getActiveUserManagers() );
143         rbConfig.setRbacManagerImpls( newConfig.getActiveRbacManagers() );
144         rbConfig.setUseUsersCache( newConfig.isUserCacheEnabled() );
145         Map<String, String> props = rbConfig.getConfigurationProperties( );
146         for ( Map.Entry<String,String> newProp : newConfig.getProperties().entrySet() ) {
147             props.put( newProp.getKey( ), newProp.getValue( ) );
148         }
149     }
150
151     private void updateConfig(LdapConfiguration newConfig, RedbackRuntimeConfiguration rbConfig) {
152         org.apache.archiva.admin.model.beans.LdapConfiguration ldapConfig = rbConfig.getLdapConfiguration( );
153         ldapConfig.setBaseDn( newConfig.getBaseDn( ) );
154         ldapConfig.setAuthenticationMethod( newConfig.getAuthenticationMethod() );
155         ldapConfig.setBindAuthenticatorEnabled( newConfig.isBindAuthenticatorEnabled( ) );
156         ldapConfig.setBindDn( newConfig.getBindDn() );
157         ldapConfig.setSsl( newConfig.isSslEnabled( ) );
158         ldapConfig.setBaseGroupsDn( newConfig.getGroupsBaseDn() );
159         ldapConfig.setHostName( newConfig.getHostName() );
160         ldapConfig.setPort( newConfig.getPort() );
161         ldapConfig.setPassword( newConfig.getBindPassword() );
162         ldapConfig.setUseRoleNameAsGroup( newConfig.isUseRoleNameAsGroup() );
163         ldapConfig.setWritable( newConfig.isWritable( ) );
164
165         Map<String, String> props = ldapConfig.getExtraProperties( );
166         for ( Map.Entry<String,String> newProp : newConfig.getProperties().entrySet() ) {
167             props.put( newProp.getKey( ), newProp.getValue( ) );
168         }
169     }
170
171     private void updateConfig(CacheConfiguration newConfig, RedbackRuntimeConfiguration rbConfig) {
172         org.apache.archiva.admin.model.beans.CacheConfiguration cacheConfig = rbConfig.getUsersCacheConfiguration( );
173         cacheConfig.setMaxElementsInMemory( newConfig.getMaxEntriesInMemory());
174         cacheConfig.setMaxElementsOnDisk( newConfig.getMaxEntriesOnDisk() );
175         cacheConfig.setTimeToLiveSeconds( newConfig.getTimeToLiveSeconds() );
176         cacheConfig.setTimeToIdleSeconds( newConfig.getTimeToIdleSeconds() );
177     }
178
179     @Override
180     public Response updateConfiguration( SecurityConfiguration newConfiguration ) throws ArchivaRestServiceException
181     {
182         try
183         {
184             RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
185             boolean userManagerChanged = !CollectionUtils.isEqualCollection( newConfiguration.getActiveUserManagers( ), conf.getUserManagerImpls() );
186             boolean rbacManagerChanged = !CollectionUtils.isEqualCollection( newConfiguration.getActiveRbacManagers( ), conf.getRbacManagerImpls( ) );
187
188             boolean ldapConfigured = false;
189             for (String um : newConfiguration.getActiveUserManagers()) {
190                 if (um.contains("ldap")) {
191                     ldapConfigured=true;
192                 }
193             }
194             if (!ldapConfigured) {
195                 for (String rbm : newConfiguration.getActiveRbacManagers()) {
196                     if (rbm.contains("ldap")) {
197                         ldapConfigured = true;
198                     }
199                 }
200             }
201
202             updateConfig( newConfiguration, conf);
203             redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( conf );
204
205             if ( userManagerChanged )
206             {
207                 log.info( "user managerImpls changed to {} so reload it",
208                     newConfiguration.getActiveUserManagers() );
209                 userManager.initialize();
210             }
211
212             if ( rbacManagerChanged )
213             {
214                 log.info( "rbac manager changed to {} so reload it",
215                     newConfiguration.getActiveRbacManagers() );
216                 rbacManager.initialize();
217                 roleManager.initialize();
218             }
219
220             if (ldapConfigured) {
221                 try {
222                     ldapConnectionFactory.initialize();
223                 } catch (Exception e) {
224                     log.error( "Could not initialize LDAP connection factory: {}", e.getMessage( ) );
225                     throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_CF_INIT_FAILED, e.getMessage() ) );
226                 }
227             }
228             Collection<PasswordRule> passwordRules = applicationContext.getBeansOfType( PasswordRule.class ).values();
229
230             for ( PasswordRule passwordRule : passwordRules )
231             {
232                 passwordRule.initialize();
233             }
234
235             Collection<CookieSettings> cookieSettingsList =
236                 applicationContext.getBeansOfType( CookieSettings.class ).values();
237
238             for ( CookieSettings cookieSettings : cookieSettingsList )
239             {
240                 cookieSettings.initialize();
241             }
242
243             Collection<Authenticator> authenticators =
244                 applicationContext.getBeansOfType( Authenticator.class ).values();
245
246             for ( Authenticator authenticator : authenticators )
247             {
248                 try {
249                     log.debug("Initializing authenticatior "+authenticator.getId());
250                     authenticator.initialize();
251                 } catch (Exception e) {
252                     log.error("Initialization of authenticator failed "+authenticator.getId(),e);
253                 }
254             }
255
256             if (ldapConfigured) {
257                 try {
258                     ldapUserMapper.initialize();
259                 } catch (Exception e) {
260                     throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_USER_MAPPER_INIT_FAILED, e.getMessage( ) ) );
261                 }
262             }
263         }
264         catch ( RepositoryAdminException e )
265         {
266             throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
267         }
268         return Response.ok( ).build();
269     }
270
271     @Override
272     public PagedResult<PropertyEntry> getConfigurationProperties( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws ArchivaRestServiceException
273     {
274         try
275         {
276             RedbackRuntimeConfiguration redbackRuntimeConfiguration =
277                 redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
278
279             log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
280
281             boolean ascending = PROP_QUERY_HELPER.isAscending( order );
282             Predicate<PropertyEntry> filter = PROP_QUERY_HELPER.getQueryFilter( searchTerm );
283             Comparator<PropertyEntry> comparator = PROP_QUERY_HELPER.getComparator( orderBy, ascending );
284             Map<String, String> props = redbackRuntimeConfiguration.getConfigurationProperties( );
285             int totalCount = props.size( );
286             List<PropertyEntry> result = props.entrySet( ).stream( ).map(
287                 entry -> new PropertyEntry( entry.getKey( ), entry.getValue( ) )
288             ).filter( filter )
289                 .sorted( comparator )
290                 .skip( offset ).limit( limit )
291                 .collect( Collectors.toList( ) );
292             return new PagedResult<>( totalCount, offset, limit, result );
293         }
294         catch ( RepositoryAdminException e )
295         {
296             throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
297         }
298     }
299
300     @Override
301     public PropertyEntry getConfigurationProperty( String propertyName ) throws ArchivaRestServiceException
302     {
303         try
304         {
305             RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
306             if (conf.getConfigurationProperties().containsKey( propertyName )) {
307                 String value = conf.getConfigurationProperties( ).get( propertyName );
308                 return new PropertyEntry( propertyName, value );
309             } else {
310                 throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PROPERTY_NOT_FOUND ), 404 );
311             }
312
313         }
314         catch ( RepositoryAdminException e )
315         {
316             throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
317         }
318
319     }
320
321     @Override
322     public Response updateConfigurationProperty( String propertyName, PropertyEntry propertyValue ) throws ArchivaRestServiceException
323     {
324         try
325         {
326             RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
327             if (conf.getConfigurationProperties().containsKey( propertyName )) {
328                 conf.getConfigurationProperties( ).put( propertyName, propertyValue.getValue( ) );
329                 redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( conf );
330                 return Response.ok( ).build( );
331             } else {
332                 throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PROPERTY_NOT_FOUND ), 404 );
333             }
334
335         }
336         catch ( RepositoryAdminException e )
337         {
338             throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
339         }
340     }
341
342     @Override
343     public LdapConfiguration getLdapConfiguration( ) throws ArchivaRestServiceException
344     {
345         try
346         {
347             RedbackRuntimeConfiguration redbackRuntimeConfiguration =
348                 redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
349
350             log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
351
352             return LdapConfiguration.of( redbackRuntimeConfiguration.getLdapConfiguration() );
353         }
354         catch ( RepositoryAdminException e )
355         {
356             throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
357         }
358
359     }
360
361     @Override
362     public Response updateLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException
363     {
364         try
365         {
366             RedbackRuntimeConfiguration redbackRuntimeConfiguration =
367                 redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
368
369             log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
370
371             updateConfig( configuration, redbackRuntimeConfiguration );
372
373             redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration );
374
375             return Response.ok( ).build( );
376
377         }
378         catch ( RepositoryAdminException e )
379         {
380             throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
381         }
382     }
383
384     @Override
385     public CacheConfiguration getCacheConfiguration( ) throws ArchivaRestServiceException
386     {
387         try
388         {
389             RedbackRuntimeConfiguration redbackRuntimeConfiguration =
390                 redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
391
392             log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
393
394             return CacheConfiguration.of( redbackRuntimeConfiguration.getUsersCacheConfiguration() );
395         }
396         catch ( RepositoryAdminException e )
397         {
398             throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
399         }
400
401     }
402
403     @Override
404     public Response updateCacheConfiguration( CacheConfiguration cacheConfiguration ) throws ArchivaRestServiceException
405     {
406         try
407         {
408             RedbackRuntimeConfiguration redbackRuntimeConfiguration =
409                 redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( );
410
411             log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration );
412             updateConfig( cacheConfiguration, redbackRuntimeConfiguration );
413             redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration );
414             return Response.ok( ).build( );
415         }
416         catch ( RepositoryAdminException e )
417         {
418             throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) );
419         }
420     }
421
422     @Override
423     public List<BeanInformation> getAvailableUserManagers( ) throws ArchivaRestServiceException
424     {
425         Map<String, UserManager> beans = applicationContext.getBeansOfType( UserManager.class );
426
427         if ( beans.isEmpty() )
428         {
429             return Collections.emptyList();
430         }
431
432         return beans.entrySet( ).stream( )
433             .filter( entry -> entry.getValue().isFinalImplementation() )
434             .map( (Map.Entry<String, UserManager> entry) -> {
435                 UserManager um = entry.getValue( );
436                 String id = StringUtils.substringAfter( entry.getKey( ), "#" );
437                 String displayName = bundle.getString( "user_manager." + id + ".display_name" );
438                 String description = bundle.getString( "user_manager." + id + ".description" );
439                 return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, um.getDescriptionKey( ), description, um.isReadOnly( ) );
440             } ).collect( Collectors.toList());
441     }
442
443     @Override
444     public List<BeanInformation> getAvailableRbacManagers( ) throws ArchivaRestServiceException
445     {
446         Map<String, RBACManager> beans = applicationContext.getBeansOfType( RBACManager.class );
447
448         if ( beans.isEmpty() )
449         {
450             return Collections.emptyList();
451         }
452
453         return beans.entrySet( ).stream( )
454             .filter( entry -> entry.getValue().isFinalImplementation() )
455             .map( (Map.Entry<String, RBACManager> entry) -> {
456                 RBACManager rm = entry.getValue( );
457                 String id = StringUtils.substringAfter( entry.getKey( ), "#" );
458                 String displayName = bundle.getString( "rbac_manager." + id + ".display_name" );
459                 String description = bundle.getString( "rbac_manager." + id + ".description" );
460                 return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, rm.getDescriptionKey( ), description, rm.isReadOnly( ) );
461             } ).collect( Collectors.toList());
462     }
463 }