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