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