Merge "Refactored yang-maven-plugin. Updated tests. Removed backup files."
[controller.git] / opendaylight / usermanager / src / main / java / org / opendaylight / controller / usermanager / internal / UserManagerImpl.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.usermanager.internal;
10
11 import java.io.FileNotFoundException;
12 import java.io.IOException;
13 import java.io.ObjectInputStream;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.Date;
17 import java.util.EnumSet;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.concurrent.ConcurrentHashMap;
24 import java.util.concurrent.ConcurrentMap;
25
26 import org.apache.commons.lang3.StringUtils;
27 import org.eclipse.osgi.framework.console.CommandInterpreter;
28 import org.eclipse.osgi.framework.console.CommandProvider;
29 import org.opendaylight.controller.clustering.services.CacheConfigException;
30 import org.opendaylight.controller.clustering.services.CacheExistException;
31 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
32 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
33 import org.opendaylight.controller.clustering.services.IClusterServices;
34 import org.opendaylight.controller.configuration.IConfigurationAware;
35 import org.opendaylight.controller.containermanager.IContainerAuthorization;
36 import org.opendaylight.controller.sal.authorization.AuthResultEnum;
37 import org.opendaylight.controller.sal.authorization.IResourceAuthorization;
38 import org.opendaylight.controller.sal.authorization.UserLevel;
39 import org.opendaylight.controller.sal.utils.StatusCode;
40 import org.opendaylight.controller.sal.utils.GlobalConstants;
41 import org.opendaylight.controller.sal.utils.IObjectReader;
42 import org.opendaylight.controller.sal.utils.ObjectReader;
43 import org.opendaylight.controller.sal.utils.ObjectWriter;
44 import org.opendaylight.controller.sal.utils.Status;
45 import org.opendaylight.controller.usermanager.AuthResponse;
46 import org.opendaylight.controller.usermanager.IAAAProvider;
47 import org.opendaylight.controller.usermanager.ISessionManager;
48 import org.opendaylight.controller.usermanager.IUserManager;
49 import org.opendaylight.controller.usermanager.security.SessionManager;
50 import org.opendaylight.controller.usermanager.security.UserSecurityContextRepository;
51 import org.osgi.framework.BundleContext;
52 import org.osgi.framework.FrameworkUtil;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55 import org.springframework.security.authentication.AuthenticationProvider;
56 import org.springframework.security.authentication.AuthenticationServiceException;
57 import org.springframework.security.authentication.BadCredentialsException;
58 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
59 import org.springframework.security.core.Authentication;
60 import org.springframework.security.core.AuthenticationException;
61 import org.springframework.security.core.userdetails.User;
62 import org.springframework.security.core.userdetails.UserDetails;
63 import org.springframework.security.core.userdetails.UsernameNotFoundException;
64 import org.springframework.security.web.context.SecurityContextRepository;
65
66 /**
67  * The internal implementation of the User Manager.
68  */
69 public class UserManagerImpl implements IUserManager, IObjectReader,
70         IConfigurationAware, ICacheUpdateAware<Long, String>, CommandProvider,
71         AuthenticationProvider {
72     private static final Logger logger = LoggerFactory
73             .getLogger(UserManagerImpl.class);
74     private static final String defaultAdmin = "admin";
75     private static final String defaultAdminPassword = "admin";
76     private static final String defaultAdminRole = UserLevel.NETWORKADMIN
77             .toString();
78     private static final String ROOT = GlobalConstants.STARTUPHOME.toString();
79     private static final String SAVE = "save";
80     private static final String usersFileName = ROOT + "users.conf";
81     private static final String serversFileName = ROOT + "servers.conf";
82     private static final String authFileName = ROOT + "authorization.conf";
83     private ConcurrentMap<String, UserConfig> localUserConfigList;
84     private ConcurrentMap<String, ServerConfig> remoteServerConfigList;
85     // local authorization info for remotely authenticated users
86     private ConcurrentMap<String, AuthorizationConfig> authorizationConfList; 
87     private ConcurrentMap<String, AuthenticatedUser> activeUsers;
88     private ConcurrentMap<String, IAAAProvider> authProviders;
89     private ConcurrentMap<Long, String> localUserListSaveConfigEvent,
90             remoteServerSaveConfigEvent, authorizationSaveConfigEvent;
91     private IClusterGlobalServices clusterGlobalService = null;
92     private SecurityContextRepository securityContextRepo = new UserSecurityContextRepository();
93     private IContainerAuthorization containerAuthorizationClient;
94     private Set<IResourceAuthorization> applicationAuthorizationClients;
95     private ISessionManager sessionMgr = new SessionManager();
96
97     public boolean addAAAProvider(IAAAProvider provider) {
98         if (provider == null || provider.getName() == null
99                 || provider.getName().trim().isEmpty()) {
100             return false;
101         }
102         if (authProviders.get(provider.getName()) != null) {
103             return false;
104         }
105
106         authProviders.put(provider.getName(), provider);
107         return true;
108     }
109
110     public void removeAAAProvider(IAAAProvider provider) {
111         authProviders.remove(provider.getName());
112     }
113
114     public IAAAProvider getAAAProvider(String name) {
115         return authProviders.get(name);
116     }
117
118     public Set<String> getAAAProviderNames() {
119         return authProviders.keySet();
120     }
121
122     @SuppressWarnings("deprecation")
123     private void allocateCaches() {
124         this.applicationAuthorizationClients = Collections
125                 .synchronizedSet(new HashSet<IResourceAuthorization>());
126         if (clusterGlobalService == null) {
127             logger.error("un-initialized clusterGlobalService, can't create cache");
128             return;
129         }
130
131         try {
132             clusterGlobalService.createCache("usermanager.localUserConfigList",
133                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
134
135             clusterGlobalService.createCache(
136                     "usermanager.remoteServerConfigList",
137                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
138
139             clusterGlobalService.createCache(
140                     "usermanager.authorizationConfList",
141                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
142
143             clusterGlobalService.createCache("usermanager.activeUsers",
144                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
145
146             clusterGlobalService.createCache(
147                     "usermanager.localUserSaveConfigEvent",
148                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
149
150             clusterGlobalService.createCache(
151                     "usermanager.remoteServerSaveConfigEvent",
152                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
153
154             clusterGlobalService.createCache(
155                     "usermanager.authorizationSaveConfigEvent",
156                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
157         } catch (CacheConfigException cce) {
158             logger.error("\nCache configuration invalid - check cache mode");
159         } catch (CacheExistException ce) {
160             logger.error("\nCache already exits - destroy and recreate if needed");
161         }
162     }
163
164     @SuppressWarnings({ "unchecked", "deprecation" })
165     private void retrieveCaches() {
166         if (clusterGlobalService == null) {
167             logger.error("un-initialized clusterService, can't retrieve cache");
168             return;
169         }
170
171         activeUsers = (ConcurrentMap<String, AuthenticatedUser>) clusterGlobalService
172                 .getCache("usermanager.activeUsers");
173         if (activeUsers == null) {
174             logger.error("\nFailed to get cache for activeUsers");
175         }
176
177         localUserConfigList = (ConcurrentMap<String, UserConfig>) clusterGlobalService
178                 .getCache("usermanager.localUserConfigList");
179         if (localUserConfigList == null) {
180             logger.error("\nFailed to get cache for localUserConfigList");
181         }
182
183         remoteServerConfigList = (ConcurrentMap<String, ServerConfig>) clusterGlobalService
184                 .getCache("usermanager.remoteServerConfigList");
185         if (remoteServerConfigList == null) {
186             logger.error("\nFailed to get cache for remoteServerConfigList");
187         }
188
189         authorizationConfList = (ConcurrentMap<String, AuthorizationConfig>) clusterGlobalService
190                 .getCache("usermanager.authorizationConfList");
191         if (authorizationConfList == null) {
192             logger.error("\nFailed to get cache for authorizationConfList");
193         }
194
195         localUserListSaveConfigEvent = (ConcurrentMap<Long, String>) clusterGlobalService
196                 .getCache("usermanager.localUserSaveConfigEvent");
197         if (localUserListSaveConfigEvent == null) {
198             logger.error("\nFailed to get cache for localUserSaveConfigEvent");
199         }
200
201         remoteServerSaveConfigEvent = (ConcurrentMap<Long, String>) clusterGlobalService
202                 .getCache("usermanager.remoteServerSaveConfigEvent");
203         if (remoteServerSaveConfigEvent == null) {
204             logger.error("\nFailed to get cache for remoteServerSaveConfigEvent");
205         }
206
207         authorizationSaveConfigEvent = (ConcurrentMap<Long, String>) clusterGlobalService
208                 .getCache("usermanager.authorizationSaveConfigEvent");
209         if (authorizationSaveConfigEvent == null) {
210             logger.error("\nFailed to get cache for authorizationSaveConfigEvent");
211         }
212     }
213
214     private void loadConfigurations() {
215         // To encode and decode user and server configuration objects
216         loadSecurityKeys();
217
218         /*
219          * Do not load local startup file if we already got the configurations
220          * synced from another cluster node
221          */
222         if (localUserConfigList.isEmpty()) {
223             loadUserConfig();
224         }
225         if (remoteServerConfigList.isEmpty()) {
226             loadServerConfig();
227         }
228         if (authorizationConfList.isEmpty()) {
229             loadAuthConfig();
230         }
231     }
232
233     private void loadSecurityKeys() {
234
235     }
236
237     private void checkDefaultNetworkAdmin() {
238         // If startup config is not there, it's old or it was deleted,
239         // need to add Default Admin
240         if (!localUserConfigList.containsKey(defaultAdmin)) {
241             List<String> roles = new ArrayList<String>(1);
242             roles.add(defaultAdminRole);
243             localUserConfigList.put(defaultAdmin, new UserConfig(defaultAdmin,
244                     defaultAdminPassword, roles));
245         }
246     }
247
248     @Override
249     public AuthResultEnum authenticate(String userName, String password) {
250         IAAAProvider aaaClient;
251         AuthResponse rcResponse = null;
252         AuthenticatedUser result;
253         boolean remotelyAuthenticated = false;
254         boolean authorizationInfoIsPresent = false;
255         boolean authorized = false;
256
257         /*
258          * Attempt remote authentication first if server is configured
259          */
260         for (ServerConfig aaaServer : remoteServerConfigList.values()) {
261             String protocol = aaaServer.getProtocol();
262             aaaClient = this.getAAAProvider(protocol);
263             if (aaaClient != null) {
264                 rcResponse = aaaClient.authService(userName, password,
265                         aaaServer.getAddress(), aaaServer.getSecret());
266                 if (rcResponse.getStatus() == AuthResultEnum.AUTH_ACCEPT) {
267                     logger.info(
268                             "Remote Authentication Succeeded for User: \"{}\", by Server: {}",
269                             userName, aaaServer.getAddress());
270                     remotelyAuthenticated = true;
271                     break;
272                 } else if (rcResponse.getStatus() == AuthResultEnum.AUTH_REJECT) {
273                     logger.info(
274                             "Remote Authentication Rejected User: \"{}\", from Server: {}, Reason:{}",
275                             new Object[] {userName, aaaServer.getAddress(),
276                             rcResponse.getStatus().toString()});
277                 } else {
278                     logger.info(
279                             "Remote Authentication Failed for User: \"{}\", from Server: {}, Reason:{}",
280                             new Object[] {userName, aaaServer.getAddress(),
281                             rcResponse.getStatus().toString()});
282                 }
283             }
284         }
285
286         if (!remotelyAuthenticated) {
287             UserConfig localUser = this.localUserConfigList.get(userName);
288             if (localUser == null) {
289                 logger.info(
290                         "Local Authentication Failed for User:\"{}\", Reason: "
291                                 + "user not found in Local Database", userName);
292                 return (AuthResultEnum.AUTH_INVALID_LOC_USER);
293             }
294             rcResponse = localUser.authenticate(password);
295             if (rcResponse.getStatus() != AuthResultEnum.AUTH_ACCEPT_LOC) {
296                 logger.info(
297                         "Local Authentication Failed for User: \"{}\", Reason: {}",
298                         userName, rcResponse.getStatus().toString());
299
300                 return (rcResponse.getStatus());
301             }
302             logger.info("Local Authentication Succeeded for User: \"{}\"",
303                     userName);
304         }
305
306         /*
307          * Authentication succeeded
308          */
309         result = new AuthenticatedUser(userName);
310
311         /*
312          * Extract attributes from response All the information we are
313          * interested in is in the first Cisco VSA (vendor specific attribute).
314          * Just process the first VSA and return
315          */
316         String attributes = (rcResponse.getData() != null && !rcResponse
317                 .getData().isEmpty()) ? rcResponse.getData().get(0) : null;
318
319         /*
320          * Check if the authorization information is present
321          */
322         authorizationInfoIsPresent = checkAuthorizationInfo(attributes);
323
324         /*
325          * The AAA server was only used to perform the authentication Look for
326          * locally stored authorization info for this user If found, add the
327          * data to the rcResponse
328          */
329         if (remotelyAuthenticated && !authorizationInfoIsPresent) {
330             logger.info(
331                     "No Remote Authorization Info provided by Server for User: \"{}\"",
332                     userName);
333             logger.info(
334                     "Looking for Local Authorization Info for User: \"{}\"",
335                     userName);
336
337             AuthorizationConfig resource = authorizationConfList.get(userName);
338             if (resource != null) {
339                 logger.info("Found Local Authorization Info for User: \"{}\"",
340                         userName);
341                 attributes = resource.getRolesString();
342
343             }
344             authorizationInfoIsPresent = checkAuthorizationInfo(attributes);
345         }
346
347         /*
348          * Common response parsing for local & remote authenticated user Looking
349          * for authorized resources, detecting attributes' validity
350          */
351         if (authorizationInfoIsPresent) {
352             // Identifying the administrative role
353             result.setRoleList(attributes.split(" "));
354             authorized = true;
355         } else {
356             logger.info("Not able to find Authorization Info for User: \"{}\"",
357                     userName);
358         }
359
360         /*
361          * Add profile for authenticated user
362          */
363         putUserInActiveList(userName, result);
364         if (authorized) {
365             logger.info("User \"{}\" authorized for the following role(s): {}",
366                         userName, result.getUserRoles());
367         } else {
368             logger.info("User \"{}\" Not Authorized for any role ", userName);
369         }
370
371         return rcResponse.getStatus();
372     }
373
374     // Check in the attributes string whether or not authorization information
375     // is present
376     private boolean checkAuthorizationInfo(String attributes) {
377         return (attributes != null && !attributes.isEmpty());
378     }
379
380     private void putUserInActiveList(String user, AuthenticatedUser result) {
381         activeUsers.put(user, result);
382     }
383
384     private void removeUserFromActiveList(String user) {
385         if (!activeUsers.containsKey(user)) {
386             // as cookie persists in cache, we can get logout for unexisting
387             // active users
388             return;
389         }
390         activeUsers.remove(user);
391     }
392
393     public Status saveLocalUserList() {
394         // Publish the save config event to the cluster nodes
395         localUserListSaveConfigEvent.put(new Date().getTime(), SAVE);
396         return saveLocalUserListInternal();
397     }
398
399     private Status saveLocalUserListInternal() {
400         ObjectWriter objWriter = new ObjectWriter();
401         return objWriter.write(new ConcurrentHashMap<String, UserConfig>(
402                 localUserConfigList), usersFileName);
403     }
404
405     public Status saveAAAServerList() {
406         // Publish the save config event to the cluster nodes
407         remoteServerSaveConfigEvent.put(new Date().getTime(), SAVE);
408         return saveAAAServerListInternal();
409     }
410
411     private Status saveAAAServerListInternal() {
412         ObjectWriter objWriter = new ObjectWriter();
413         return objWriter.write(new ConcurrentHashMap<String, ServerConfig>(
414                 remoteServerConfigList), serversFileName);
415     }
416
417     public Status saveAuthorizationList() {
418         // Publish the save config event to the cluster nodes
419         authorizationSaveConfigEvent.put(new Date().getTime(), SAVE);
420         return saveAuthorizationListInternal();
421     }
422
423     private Status saveAuthorizationListInternal() {
424         ObjectWriter objWriter = new ObjectWriter();
425         return objWriter.write(
426                 new ConcurrentHashMap<String, AuthorizationConfig>(
427                         authorizationConfList), authFileName);
428     }
429
430     @Override
431     public Object readObject(ObjectInputStream ois)
432             throws FileNotFoundException, IOException, ClassNotFoundException {
433         // Perform the class deserialization locally, from inside the package
434         // where the class is defined
435         return ois.readObject();
436     }
437
438     @SuppressWarnings("unchecked")
439     private void loadUserConfig() {
440         ObjectReader objReader = new ObjectReader();
441         ConcurrentMap<String, UserConfig> confList = (ConcurrentMap<String, UserConfig>) objReader
442                 .read(this, usersFileName);
443
444         if (confList == null) {
445             return;
446         }
447
448         for (UserConfig conf : confList.values()) {
449             addLocalUser(conf);
450         }
451     }
452
453     @SuppressWarnings("unchecked")
454     private void loadServerConfig() {
455         ObjectReader objReader = new ObjectReader();
456         ConcurrentMap<String, ServerConfig> confList = (ConcurrentMap<String, ServerConfig>) objReader
457                 .read(this, serversFileName);
458
459         if (confList == null) {
460             return;
461         }
462
463         for (ServerConfig conf : confList.values()) {
464             addAAAServer(conf);
465         }
466     }
467
468     @SuppressWarnings("unchecked")
469     private void loadAuthConfig() {
470         ObjectReader objReader = new ObjectReader();
471         ConcurrentMap<String, AuthorizationConfig> confList = (ConcurrentMap<String, AuthorizationConfig>) objReader
472                 .read(this, authFileName);
473
474         if (confList == null) {
475             return;
476         }
477
478         for (AuthorizationConfig conf : confList.values()) {
479             addAuthInfo(conf);
480         }
481     }
482
483     /*
484      * Interaction with GUI START
485      */
486     public Status addRemoveLocalUser(UserConfig AAAconf, boolean delete) {
487         // UserConfig Validation check
488         Status validCheck = AAAconf.validate();
489         if (!validCheck.isSuccess()) {
490             return validCheck;
491         }
492
493         // Update Config database
494         if (delete) {
495             if (AAAconf.getUser().equals(UserManagerImpl.defaultAdmin)) {
496                 String msg = "Invalid Request: Default Network Admin  User "
497                         + "cannot be deleted";
498                 logger.debug(msg);
499                 return new Status(StatusCode.NOTALLOWED, msg);
500             }
501             localUserConfigList.remove(AAAconf.getUser());
502             /*
503              * A user account has been removed form local database, we assume
504              * admin does not want this user to stay connected, in case he has
505              * an open session. So we clean the active list as well.
506              */
507             removeUserFromActiveList(AAAconf.getUser());
508         } else {
509             if (AAAconf.getUser().equals(UserManagerImpl.defaultAdmin)) {
510                 String msg = "Invalid Request: Default Network Admin  User "
511                         + "cannot be added";
512                 logger.debug(msg);
513                 return new Status(StatusCode.NOTALLOWED, msg);
514             }
515             localUserConfigList.put(AAAconf.getUser(), AAAconf);
516         }
517
518         return new Status(StatusCode.SUCCESS, null);
519     }
520
521     private Status addRemoveAAAServer(ServerConfig AAAconf, boolean delete) {
522         // Validation check
523         if (!AAAconf.isValid()) {
524             String msg = "Invalid Server configuration";
525             logger.warn(msg);
526             return new Status(StatusCode.BADREQUEST, msg);
527         }
528
529         // Update configuration database
530         if (delete) {
531             remoteServerConfigList.remove(AAAconf.getAddress());
532         } else {
533             remoteServerConfigList.put(AAAconf.getAddress(), AAAconf);
534         }
535
536         return new Status(StatusCode.SUCCESS, null);
537     }
538
539     private Status addRemoveAuthInfo(AuthorizationConfig AAAconf, boolean delete) {
540         Status configCheck = AAAconf.validate();
541         if (!configCheck.isSuccess()) {
542             String msg = "Invalid Authorization configuration: "
543                     + configCheck.getDescription();
544             logger.warn(msg);
545             return new Status(StatusCode.BADREQUEST, msg);
546         }
547
548         // Update configuration database
549         if (delete) {
550             authorizationConfList.remove(AAAconf.getUser());
551         } else {
552             authorizationConfList.put(AAAconf.getUser(), AAAconf);
553         }
554
555         return new Status(StatusCode.SUCCESS, null);
556     }
557
558     @Override
559     public Status addLocalUser(UserConfig AAAconf) {
560         return addRemoveLocalUser(AAAconf, false);
561     }
562
563     @Override
564     public Status removeLocalUser(UserConfig AAAconf) {
565         return addRemoveLocalUser(AAAconf, true);
566     }
567
568     @Override
569     public Status removeLocalUser(String userName) {
570         if (userName == null || userName.trim().isEmpty()) {
571             return new Status(StatusCode.BADREQUEST, "Invalid user name");
572         }
573         if (!localUserConfigList.containsKey(userName)) {
574             return new Status(StatusCode.NOTFOUND, "User does not exist");
575         }
576         return addRemoveLocalUser(localUserConfigList.get(userName), true);
577     }
578
579     @Override
580     public Status addAAAServer(ServerConfig AAAconf) {
581         return addRemoveAAAServer(AAAconf, false);
582     }
583
584     @Override
585     public Status removeAAAServer(ServerConfig AAAconf) {
586         return addRemoveAAAServer(AAAconf, true);
587     }
588
589     @Override
590     public Status addAuthInfo(AuthorizationConfig AAAconf) {
591         return addRemoveAuthInfo(AAAconf, false);
592     }
593
594     @Override
595     public Status removeAuthInfo(AuthorizationConfig AAAconf) {
596         return addRemoveAuthInfo(AAAconf, true);
597     }
598
599     @Override
600     public List<UserConfig> getLocalUserList() {
601         return new ArrayList<UserConfig>(localUserConfigList.values());
602     }
603
604     @Override
605     public List<ServerConfig> getAAAServerList() {
606         return new ArrayList<ServerConfig>(remoteServerConfigList.values());
607     }
608
609     @Override
610     public List<AuthorizationConfig> getAuthorizationList() {
611         return new ArrayList<AuthorizationConfig>(
612                 authorizationConfList.values());
613     }
614
615     @Override
616     public Status changeLocalUserPassword(String user, String curPassword,
617             String newPassword) {
618         UserConfig targetConfigEntry = null;
619
620         // update configuration entry
621         targetConfigEntry = localUserConfigList.get(user);
622         if (targetConfigEntry == null) {
623             return new Status(StatusCode.NOTFOUND, "User not found");
624         }
625         Status status = targetConfigEntry
626                 .update(curPassword, newPassword, null);
627         if (!status.isSuccess()) {
628             return status;
629         }
630         // Trigger cluster update
631         localUserConfigList.put(user, targetConfigEntry); 
632
633         logger.info("Password changed for User \"{}\"", user);
634
635         return status;
636     }
637
638     @Override
639     public void userLogout(String userName) {
640         // TODO: if user was authenticated through AAA server, send
641         // Acct-Status-Type=stop message to server with logout as reason
642         removeUserFromActiveList(userName);
643         logger.info("User \"{}\" logged out", userName);
644     }
645
646     /*
647      * This function will get called by http session mgr when session times out
648      */
649     @Override
650     public void userTimedOut(String userName) {
651         // TODO: if user was authenticated through AAA server, send
652         // Acct-Status-Type=stop message to server with timeout as reason
653         removeUserFromActiveList(userName);
654         logger.info("User \"{}\" timed out", userName);
655     }
656
657     @Override
658     public String getAccessDate(String user) {
659         return this.activeUsers.get(user).getAccessDate();
660     }
661
662     @Override
663     public synchronized Map<String, List<String>> getUserLoggedIn() {
664         Map<String, List<String>> loggedInList = new HashMap<String, List<String>>();
665         for (Map.Entry<String, AuthenticatedUser> user : activeUsers.entrySet()) {
666             String userNameShow = user.getKey();
667             loggedInList.put(userNameShow, user.getValue().getUserRoles());
668         }
669         return loggedInList;
670     }
671
672     /*
673      * Interaction with GUI END
674      */
675
676     /*
677      * Cluster notifications
678      */
679
680     @Override
681     public void entryCreated(Long key, String cacheName, boolean originLocal) {
682         // don't react on this event
683     }
684
685     @Override
686     public void entryUpdated(Long key, String new_value, String cacheName,
687             boolean originLocal) {
688         if (cacheName.equals("localUserSaveConfigEvent")) {
689             this.saveLocalUserListInternal();
690         } else if (cacheName.equals("remoteServerSaveConfigEvent")) {
691             this.saveAAAServerListInternal();
692         } else if (cacheName.equals("authorizationSaveConfigEvent")) {
693             this.saveAuthorizationListInternal();
694         }
695     }
696
697     @Override
698     public void entryDeleted(Long key, String cacheName, boolean originLocal) {
699         // don't react on this event
700     }
701
702     public void _umAddUser(CommandInterpreter ci) {
703         String userName = ci.nextArgument();
704         String password = ci.nextArgument();
705         String role = ci.nextArgument();
706         
707         List<String> roles = new ArrayList<String>();
708         while (role != null) {
709             if (!role.trim().isEmpty()) {
710                 roles.add(role);
711             }
712             role = ci.nextArgument();
713         }
714
715         if (userName == null || userName.trim().isEmpty() || password == null
716                 || password.trim().isEmpty() || roles == null
717                 || roles.isEmpty()) {
718             ci.println("Invalid Arguments");
719             ci.println("umAddUser <user_name> <password> <user_role>");
720             return;
721         }
722         ci.print(this.addLocalUser(new UserConfig(userName, password, roles)));
723     }
724
725     public void _umRemUser(CommandInterpreter ci) {
726         String userName = ci.nextArgument();
727
728         if (userName == null || userName.trim().isEmpty()) {
729             ci.println("Invalid Arguments");
730             ci.println("umRemUser <user_name>");
731             return;
732         }
733         UserConfig target = localUserConfigList.get(userName);
734         if (target == null) {
735             ci.println("User not found");
736             return;
737         }       
738         ci.println(this.removeLocalUser(target));
739     }
740
741     public void _umGetUsers(CommandInterpreter ci) {
742         for (UserConfig conf : this.getLocalUserList()) {
743             ci.println(conf.getUser() + " " + conf.getRoles());
744         }
745     }
746
747     public void _addAAAServer(CommandInterpreter ci) {
748         String server = ci.nextArgument();
749         String secret = ci.nextArgument();
750         String protocol = ci.nextArgument();
751
752         if (server == null || secret == null || protocol == null) {
753             ci.println("Usage : addAAAServer <server> <secret> <protocol>");
754             return;
755         }
756         ServerConfig s = new ServerConfig(server, secret, protocol);
757         addAAAServer(s);
758     }
759
760     public void _removeAAAServer(CommandInterpreter ci) {
761         String server = ci.nextArgument();
762         String secret = ci.nextArgument();
763         String protocol = ci.nextArgument();
764
765         if (server == null || secret == null || protocol == null) {
766             ci.println("Usage : addAAAServer <server> <secret> <protocol>");
767             return;
768         }
769         ServerConfig s = new ServerConfig(server, secret, protocol);
770         removeAAAServer(s);
771     }
772
773     public void _printAAAServers(CommandInterpreter ci) {
774         for (ServerConfig aaaServer : remoteServerConfigList.values()) {
775             ci.println(aaaServer.getAddress() + "-" + aaaServer.getProtocol());
776         }
777     }
778
779     @Override
780     public String getHelp() {
781         StringBuffer help = new StringBuffer();
782         return help.toString();
783     }
784
785     void setClusterGlobalService(IClusterGlobalServices s) {
786         logger.debug("Cluster Service Global set");
787         this.clusterGlobalService = s;
788     }
789
790     void unsetClusterGlobalService(IClusterGlobalServices s) {
791         if (this.clusterGlobalService == s) {
792             logger.debug("Cluster Service Global removed!");
793             this.clusterGlobalService = null;
794         }
795     }
796
797     void unsetContainerAuthClient(IContainerAuthorization s) {
798         if (this.containerAuthorizationClient == s) {
799             this.containerAuthorizationClient = null;
800         }
801     }
802
803     void setContainerAuthClient(IContainerAuthorization s) {
804         this.containerAuthorizationClient = s;
805     }
806
807     void setAppAuthClient(IResourceAuthorization s) {
808         this.applicationAuthorizationClients.add(s);
809     }
810
811     void unsetAppAuthClient(IResourceAuthorization s) {
812         this.applicationAuthorizationClients.remove(s);
813     }
814
815     /**
816      * Function called by the dependency manager when all the required
817      * dependencies are satisfied
818      * 
819      */
820     void init() {
821     }
822
823     /**
824      * Function called by the dependency manager when at least one dependency
825      * become unsatisfied or when the component is shutting down because for
826      * example bundle is being stopped.
827      * 
828      */
829     void destroy() {
830     }
831
832     /**
833      * Function called by dependency manager after "init ()" is called and after
834      * the services provided by the class are registered in the service registry
835      * 
836      */
837     void start() {
838         authProviders = new ConcurrentHashMap<String, IAAAProvider>();
839         // Instantiate cluster synced variables
840         allocateCaches();
841         retrieveCaches();
842
843         // Read startup configuration and populate databases
844         loadConfigurations();
845
846         // Make sure default Network Admin account is there
847         checkDefaultNetworkAdmin();
848         BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
849                 .getBundleContext();
850         bundleContext.registerService(CommandProvider.class.getName(), this,
851                 null);
852     }
853
854     /**
855      * Function called by the dependency manager before the services exported by
856      * the component are unregistered, this will be followed by a "destroy ()"
857      * calls
858      * 
859      */
860     void stop() {
861     }
862
863     @Override
864     public List<String> getUserRoles(String userName) {
865         if (userName == null) {
866             return new ArrayList<String>(0);
867         }
868         AuthenticatedUser locatedUser = activeUsers.get(userName);
869         return (locatedUser == null) ? new ArrayList<String>(0) : locatedUser
870                 .getUserRoles();
871     }
872
873     @Override
874     public UserLevel getUserLevel(String username) {
875         // Returns the controller well-know user level for the passed user
876         List<String> rolesNames = null;
877
878         // First check in active users then in local configured users
879         if (activeUsers.containsKey(username)) {
880             List<String> roles = activeUsers.get(username).getUserRoles();
881             rolesNames = (roles == null || roles.isEmpty()) ? null : roles;
882         } else if (localUserConfigList.containsKey(username)) {
883             UserConfig config = localUserConfigList.get(username);
884             rolesNames = (config == null) ? null : config.getRoles();
885         }
886
887         if (rolesNames == null) {
888             return UserLevel.NOUSER;
889         }
890
891         // Check against the well known controller roles first
892         if (rolesNames.contains(UserLevel.SYSTEMADMIN.toString())) {
893             return UserLevel.SYSTEMADMIN;
894         }
895         if (rolesNames.contains(UserLevel.NETWORKADMIN.toString())) {
896             return UserLevel.NETWORKADMIN;
897         }
898         if (rolesNames.contains(UserLevel.NETWORKOPERATOR.toString())) {
899             return UserLevel.NETWORKOPERATOR;
900         }
901         // Check if container user now
902         if (containerAuthorizationClient != null) {
903             for (String roleName : rolesNames) {
904                 if (containerAuthorizationClient.isApplicationRole(roleName)) {
905                     return UserLevel.CONTAINERUSER;
906                 }
907             }
908         }
909         // Finally check if application user
910         if (applicationAuthorizationClients != null) {
911             for (String roleName : rolesNames) {
912                 for (IResourceAuthorization client : this.applicationAuthorizationClients) {
913                     if (client.isApplicationRole(roleName)) {
914                         return UserLevel.APPUSER;
915                     }
916                 }
917             }
918         }
919         return UserLevel.NOUSER;
920     }
921
922     @Override
923     public Status saveConfiguration() {
924         boolean success = true;
925         Status ret = saveLocalUserList();
926         if (!ret.isSuccess()) {
927             success = false;
928         }
929         ret = saveAAAServerList();
930         if (!ret.isSuccess()) {
931             success = false;
932         }
933         ret = saveAuthorizationList();
934         if (!ret.isSuccess()) {
935             success = false;
936         }
937
938         if (success) {
939             return new Status(StatusCode.SUCCESS, null);
940         }
941
942         return new Status(StatusCode.INTERNALERROR,
943                 "Failed to save user configurations");
944     }
945
946     @Override
947     public UserDetails loadUserByUsername(String username)
948             throws UsernameNotFoundException {
949         AuthenticatedUser user = activeUsers.get(username);
950
951         if (user != null) {
952             boolean enabled = true;
953             boolean accountNonExpired = true;
954             boolean credentialsNonExpired = true;
955             boolean accountNonLocked = true;
956
957             return new User(username, localUserConfigList.get(username)
958                     .getPassword(), enabled, accountNonExpired,
959                     credentialsNonExpired, accountNonLocked,
960                     user.getGrantedAuthorities(getUserLevel(username)));
961         } else
962             throw new UsernameNotFoundException("User not found " + username);
963     }
964
965     @Override
966     public boolean supports(Class<?> authentication) {
967         return UsernamePasswordAuthenticationToken.class
968                 .isAssignableFrom(authentication);
969
970     }
971
972     @Override
973     public SecurityContextRepository getSecurityContextRepo() {
974         return securityContextRepo;
975     }
976
977     public void setSecurityContextRepo(
978             SecurityContextRepository securityContextRepo) {
979         this.securityContextRepo = securityContextRepo;
980     }
981
982     @Override
983     public Authentication authenticate(Authentication authentication)
984             throws AuthenticationException {
985
986         if (StringUtils.isBlank((String) authentication.getCredentials())
987                 || StringUtils.isBlank((String) authentication.getPrincipal())) {
988             throw new BadCredentialsException(
989                     "Username or credentials did not match");
990         }
991
992         AuthResultEnum result = authenticate(
993                 (String) authentication.getPrincipal(),
994                 (String) authentication.getCredentials());
995         if (result.equals(AuthResultEnum.AUTHOR_PASS)
996                 || result.equals(AuthResultEnum.AUTH_ACCEPT_LOC)
997                 || result.equals(AuthResultEnum.AUTH_ACCEPT)) {
998
999             AuthenticatedUser user = activeUsers.get(authentication
1000                     .getPrincipal().toString());
1001
1002             if (user == null) {
1003                 throw new AuthenticationServiceException(
1004                         "Authentication Failure");
1005             }
1006
1007             authentication = new UsernamePasswordAuthenticationToken(
1008                     authentication.getPrincipal(),
1009                     authentication.getCredentials(),
1010                     user.getGrantedAuthorities(getUserLevel(authentication
1011                             .getName())));
1012             return authentication;
1013
1014         } else
1015             throw new BadCredentialsException(
1016                     "Username or credentials did not match");
1017
1018     }
1019
1020     // following are setters for use in unit testing
1021     void setLocalUserConfigList(ConcurrentMap<String, UserConfig> ucl) {
1022         if (ucl != null) {
1023             this.localUserConfigList = ucl;
1024         }
1025     }
1026
1027     void setRemoteServerConfigList(ConcurrentMap<String, ServerConfig> scl) {
1028         if (scl != null) {
1029             this.remoteServerConfigList = scl;
1030         }
1031     }
1032
1033     void setAuthorizationConfList(ConcurrentMap<String, AuthorizationConfig> acl) {
1034         if (acl != null) {
1035             this.authorizationConfList = acl;
1036         }
1037     }
1038
1039     void setActiveUsers(ConcurrentMap<String, AuthenticatedUser> au) {
1040         if (au != null) {
1041             this.activeUsers = au;
1042         }
1043     }
1044
1045     void setAuthProviders(ConcurrentMap<String, IAAAProvider> ap) {
1046         if (ap != null) {
1047             this.authProviders = ap;
1048         }
1049     }
1050
1051     @Override
1052     public ISessionManager getSessionManager() {
1053         return this.sessionMgr;
1054     }
1055
1056     public void setSessionMgr(ISessionManager sessionMgr) {
1057         this.sessionMgr = sessionMgr;
1058     }
1059
1060     public String getPassword(String username) {
1061         return localUserConfigList.get(username).getPassword();
1062     }
1063 }