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