2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.usermanager.internal;
12 import java.io.FileInputStream;
13 import java.io.FileNotFoundException;
14 import java.io.IOException;
15 import java.io.ObjectInputStream;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.EnumSet;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.List;
24 import java.util.concurrent.ConcurrentHashMap;
25 import java.util.concurrent.ConcurrentMap;
27 import org.apache.commons.lang3.StringUtils;
28 import org.eclipse.osgi.framework.console.CommandInterpreter;
29 import org.eclipse.osgi.framework.console.CommandProvider;
30 import org.opendaylight.controller.clustering.services.CacheConfigException;
31 import org.opendaylight.controller.clustering.services.CacheExistException;
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.AuthenticatedUser;
47 import org.opendaylight.controller.usermanager.AuthorizationConfig;
48 import org.opendaylight.controller.usermanager.IAAAProvider;
49 import org.opendaylight.controller.usermanager.ISessionManager;
50 import org.opendaylight.controller.usermanager.IUserManager;
51 import org.opendaylight.controller.usermanager.ServerConfig;
52 import org.opendaylight.controller.usermanager.UserConfig;
53 import org.opendaylight.controller.usermanager.security.SessionManager;
54 import org.opendaylight.controller.usermanager.security.UserSecurityContextRepository;
56 import org.osgi.framework.BundleContext;
57 import org.osgi.framework.FrameworkUtil;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60 import org.springframework.security.authentication.AuthenticationProvider;
61 import org.springframework.security.authentication.AuthenticationServiceException;
62 import org.springframework.security.authentication.BadCredentialsException;
63 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
64 import org.springframework.security.core.Authentication;
65 import org.springframework.security.core.AuthenticationException;
66 import org.springframework.security.core.userdetails.User;
67 import org.springframework.security.core.userdetails.UserDetails;
68 import org.springframework.security.core.userdetails.UsernameNotFoundException;
69 import org.springframework.security.web.context.SecurityContextRepository;
72 * The internal implementation of the User Manager.
74 public class UserManager implements IUserManager, IObjectReader,
75 IConfigurationAware, CommandProvider, AuthenticationProvider {
76 private static final Logger logger = LoggerFactory.getLogger(UserManager.class);
77 private static final String DEFAULT_ADMIN = "admin";
78 private static final String DEFAULT_ADMIN_PASSWORD = "admin";
79 private static final String DEFAULT_ADMIN_ROLE = UserLevel.NETWORKADMIN.toString();
80 private static final String ROOT = GlobalConstants.STARTUPHOME.toString();
81 private static final String USERS_FILE_NAME = ROOT + "users.conf";
82 private static final String SERVERS_FILE_NAME = ROOT + "servers.conf";
83 private static final String AUTH_FILE_NAME = ROOT + "authorization.conf";
84 private static final String RECOVERY_FILE = ROOT + "NETWORK_ADMIN_PASSWORD_RECOVERY";
85 private ConcurrentMap<String, UserConfig> localUserConfigList;
86 private ConcurrentMap<String, ServerConfig> remoteServerConfigList;
87 // local authorization info for remotely authenticated users
88 private ConcurrentMap<String, AuthorizationConfig> authorizationConfList;
89 private ConcurrentMap<String, AuthenticatedUser> activeUsers;
90 private ConcurrentMap<String, IAAAProvider> authProviders;
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 protected enum Command {
98 MODIFY("modify", "modified"),
99 REMOVE("remove", "removed");
100 private String action;
101 private String postAction;
102 private Command(String action, String postAction) {
103 this.action = action;
104 this.postAction = postAction;
107 public String getAction() {
111 public String getPostAction() {
116 public boolean addAAAProvider(IAAAProvider provider) {
117 if (provider == null || provider.getName() == null
118 || provider.getName().trim().isEmpty()) {
121 if (authProviders.get(provider.getName()) != null) {
125 authProviders.put(provider.getName(), provider);
129 public void removeAAAProvider(IAAAProvider provider) {
130 authProviders.remove(provider.getName());
133 public IAAAProvider getAAAProvider(String name) {
134 return authProviders.get(name);
138 public Set<String> getAAAProviderNames() {
139 return authProviders.keySet();
142 private void allocateCaches() {
143 this.applicationAuthorizationClients = Collections.synchronizedSet(new HashSet<IResourceAuthorization>());
144 if (clusterGlobalService == null) {
145 logger.error("un-initialized clusterGlobalService, can't create cache");
150 clusterGlobalService.createCache("usermanager.localUserConfigList",
151 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
153 clusterGlobalService.createCache(
154 "usermanager.remoteServerConfigList",
155 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
157 clusterGlobalService.createCache(
158 "usermanager.authorizationConfList",
159 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
161 clusterGlobalService.createCache("usermanager.activeUsers",
162 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
163 } catch (CacheConfigException cce) {
164 logger.error("Cache configuration invalid - check cache mode");
165 } catch (CacheExistException ce) {
166 logger.debug("Skipping cache creation as already present");
170 @SuppressWarnings({ "unchecked" })
171 private void retrieveCaches() {
172 if (clusterGlobalService == null) {
173 logger.error("un-initialized clusterService, can't retrieve cache");
177 activeUsers = (ConcurrentMap<String, AuthenticatedUser>) clusterGlobalService
178 .getCache("usermanager.activeUsers");
179 if (activeUsers == null) {
180 logger.error("Failed to get cache for activeUsers");
183 localUserConfigList = (ConcurrentMap<String, UserConfig>) clusterGlobalService
184 .getCache("usermanager.localUserConfigList");
185 if (localUserConfigList == null) {
186 logger.error("Failed to get cache for localUserConfigList");
189 remoteServerConfigList = (ConcurrentMap<String, ServerConfig>) clusterGlobalService
190 .getCache("usermanager.remoteServerConfigList");
191 if (remoteServerConfigList == null) {
192 logger.error("Failed to get cache for remoteServerConfigList");
195 authorizationConfList = (ConcurrentMap<String, AuthorizationConfig>) clusterGlobalService
196 .getCache("usermanager.authorizationConfList");
197 if (authorizationConfList == null) {
198 logger.error("Failed to get cache for authorizationConfList");
202 private void loadConfigurations() {
203 // To encode and decode user and server configuration objects
207 * Do not load local startup file if we already got the configurations
208 * synced from another cluster node
210 if (localUserConfigList.isEmpty()) {
213 if (remoteServerConfigList.isEmpty()) {
216 if (authorizationConfList.isEmpty()) {
221 private void loadSecurityKeys() {
225 private void checkDefaultNetworkAdmin() {
227 * If startup config is not there, it's old or it was deleted or if a
228 * password recovery was run, need to add Default Network Admin User
230 if (!localUserConfigList.containsKey(DEFAULT_ADMIN)) {
231 List<String> roles = new ArrayList<String>(1);
232 roles.add(DEFAULT_ADMIN_ROLE);
233 // Need to skip the strong password check for the default admin
234 UserConfig defaultAdmin = UserConfig.getUncheckedUserConfig(UserManager.DEFAULT_ADMIN,
235 UserManager.DEFAULT_ADMIN_PASSWORD, roles);
236 localUserConfigList.put(UserManager.DEFAULT_ADMIN, defaultAdmin);
240 private void checkPasswordRecovery() {
241 final String fileDescription = "Default Network Administrator password recovery file";
243 FileInputStream fis = new FileInputStream(UserManager.RECOVERY_FILE);
245 * Recovery file detected, remove current default network
246 * administrator entry from local users configuration list.
247 * Warn user and delete recovery file.
249 this.localUserConfigList.remove(UserManager.DEFAULT_ADMIN);
250 logger.info("Default Network Administrator password has been reset to factory default.");
251 logger.info("Please change the default Network Administrator password as soon as possible");
252 File filePointer = new File(UserManager.RECOVERY_FILE);
253 boolean status = filePointer.delete();
255 logger.warn("Failed to delete {}", fileDescription);
257 logger.trace("{} deleted", fileDescription);
260 } catch (FileNotFoundException fnf) {
261 logger.trace("{} not present", fileDescription);
262 } catch (IOException e) {
263 logger.warn("Failed to close file stream for {}", fileDescription);
268 public AuthResultEnum authenticate(String userName, String password) {
269 IAAAProvider aaaClient;
270 AuthResponse rcResponse = null;
271 AuthenticatedUser result;
272 boolean remotelyAuthenticated = false;
273 boolean authorizationInfoIsPresent = false;
274 boolean authorized = false;
277 * Attempt remote authentication first if server is configured
279 for (ServerConfig aaaServer : remoteServerConfigList.values()) {
280 String protocol = aaaServer.getProtocol();
281 aaaClient = this.getAAAProvider(protocol);
282 if (aaaClient != null) {
283 rcResponse = aaaClient.authService(userName, password,
284 aaaServer.getAddress(), aaaServer.getSecret());
285 if (rcResponse.getStatus() == AuthResultEnum.AUTH_ACCEPT) {
287 "Remote Authentication Succeeded for User: \"{}\", by Server: {}",
288 userName, aaaServer.getAddress());
289 remotelyAuthenticated = true;
291 } else if (rcResponse.getStatus() == AuthResultEnum.AUTH_REJECT) {
293 "Remote Authentication Rejected User: \"{}\", from Server: {}, Reason:{}",
294 new Object[] { userName, aaaServer.getAddress(),
295 rcResponse.getStatus().toString() });
298 "Remote Authentication Failed for User: \"{}\", from Server: {}, Reason:{}",
299 new Object[] { userName, aaaServer.getAddress(),
300 rcResponse.getStatus().toString() });
305 if (!remotelyAuthenticated) {
306 UserConfig localUser = this.localUserConfigList.get(userName);
307 if (localUser == null) {
309 "Local Authentication Failed for User:\"{}\", Reason: "
310 + "user not found in Local Database", userName);
311 return (AuthResultEnum.AUTH_INVALID_LOC_USER);
313 rcResponse = localUser.authenticate(password);
314 if (rcResponse.getStatus() != AuthResultEnum.AUTH_ACCEPT_LOC) {
316 "Local Authentication Failed for User: \"{}\", Reason: {}",
317 userName, rcResponse.getStatus().toString());
319 return (rcResponse.getStatus());
321 logger.info("Local Authentication Succeeded for User: \"{}\"",
326 * Authentication succeeded
328 result = new AuthenticatedUser(userName);
331 * Extract attributes from response All the information we are
332 * interested in is in the first Cisco VSA (vendor specific attribute).
333 * Just process the first VSA and return
335 String attributes = (rcResponse.getData() != null && !rcResponse
336 .getData().isEmpty()) ? rcResponse.getData().get(0) : null;
339 * Check if the authorization information is present
341 authorizationInfoIsPresent = checkAuthorizationInfo(attributes);
344 * The AAA server was only used to perform the authentication Look for
345 * locally stored authorization info for this user If found, add the
346 * data to the rcResponse
348 if (remotelyAuthenticated && !authorizationInfoIsPresent) {
350 "No Remote Authorization Info provided by Server for User: \"{}\"",
353 "Looking for Local Authorization Info for User: \"{}\"",
356 AuthorizationConfig resource = authorizationConfList.get(userName);
357 if (resource != null) {
358 logger.info("Found Local Authorization Info for User: \"{}\"",
360 attributes = resource.getRolesString();
363 authorizationInfoIsPresent = checkAuthorizationInfo(attributes);
367 * Common response parsing for local & remote authenticated user Looking
368 * for authorized resources, detecting attributes' validity
370 if (authorizationInfoIsPresent) {
371 // Identifying the administrative role
372 result.setRoleList(attributes.split(" "));
375 logger.info("Not able to find Authorization Info for User: \"{}\"",
380 * Add profile for authenticated user
382 putUserInActiveList(userName, result);
384 logger.info("User \"{}\" authorized for the following role(s): {}",
385 userName, result.getUserRoles());
387 logger.info("User \"{}\" Not Authorized for any role ", userName);
390 return rcResponse.getStatus();
393 // Check in the attributes string whether or not authorization information
395 private boolean checkAuthorizationInfo(String attributes) {
396 return (attributes != null && !attributes.isEmpty());
399 private void putUserInActiveList(String user, AuthenticatedUser result) {
400 activeUsers.put(user, result);
403 private void removeUserFromActiveList(String user) {
404 if (!activeUsers.containsKey(user)) {
405 // as cookie persists in cache, we can get logout for unexisting
409 activeUsers.remove(user);
413 public Status saveLocalUserList() {
414 return saveLocalUserListInternal();
417 private Status saveLocalUserListInternal() {
418 ObjectWriter objWriter = new ObjectWriter();
419 return objWriter.write(new ConcurrentHashMap<String, UserConfig>(
420 localUserConfigList), USERS_FILE_NAME);
424 public Status saveAAAServerList() {
425 return saveAAAServerListInternal();
428 private Status saveAAAServerListInternal() {
429 ObjectWriter objWriter = new ObjectWriter();
430 return objWriter.write(new ConcurrentHashMap<String, ServerConfig>(
431 remoteServerConfigList), SERVERS_FILE_NAME);
435 public Status saveAuthorizationList() {
436 return saveAuthorizationListInternal();
439 private Status saveAuthorizationListInternal() {
440 ObjectWriter objWriter = new ObjectWriter();
441 return objWriter.write(
442 new ConcurrentHashMap<String, AuthorizationConfig>(
443 authorizationConfList), AUTH_FILE_NAME);
447 public Object readObject(ObjectInputStream ois)
448 throws FileNotFoundException, IOException, ClassNotFoundException {
449 // Perform the class deserialization locally, from inside the package
450 // where the class is defined
451 return ois.readObject();
454 @SuppressWarnings("unchecked")
455 private void loadUserConfig() {
456 ObjectReader objReader = new ObjectReader();
457 ConcurrentMap<String, UserConfig> confList = (ConcurrentMap<String, UserConfig>) objReader
458 .read(this, USERS_FILE_NAME);
460 if (confList == null) {
464 for (UserConfig conf : confList.values()) {
465 addRemoveLocalUserInternal(conf, false);
469 @SuppressWarnings("unchecked")
470 private void loadServerConfig() {
471 ObjectReader objReader = new ObjectReader();
472 ConcurrentMap<String, ServerConfig> confList = (ConcurrentMap<String, ServerConfig>) objReader
473 .read(this, SERVERS_FILE_NAME);
475 if (confList == null) {
479 for (ServerConfig conf : confList.values()) {
484 @SuppressWarnings("unchecked")
485 private void loadAuthConfig() {
486 ObjectReader objReader = new ObjectReader();
487 ConcurrentMap<String, AuthorizationConfig> confList = (ConcurrentMap<String, AuthorizationConfig>) objReader
488 .read(this, AUTH_FILE_NAME);
490 if (confList == null) {
494 for (AuthorizationConfig conf : confList.values()) {
500 * Interaction with GUI START
502 private Status changeLocalUser(UserConfig AAAconf, Command command) {
503 // UserConfig Validation check
504 Status validCheck = AAAconf.validate();
505 if (!validCheck.isSuccess()) {
509 String user = AAAconf.getUser();
511 // Check default admin user
512 if (user.equals(UserManager.DEFAULT_ADMIN)) {
513 String msg = String.format("Invalid Request: Default Network Admin User cannot be %s", command.getPostAction());
515 return new Status(StatusCode.NOTALLOWED, msg);
518 // Check user presence/conflict
519 UserConfig currentAAAconf = localUserConfigList.get(user);
520 StatusCode statusCode = null;
521 String reason = null;
524 if (currentAAAconf != null) {
525 reason = "already present";
526 statusCode = StatusCode.CONFLICT;
531 if (currentAAAconf == null) {
532 reason = "not found";
533 statusCode = StatusCode.NOTFOUND;
540 if (statusCode != null) {
541 String action = String.format("Failed to %s user %s: ", command.getAction(), user);
542 String msg = String.format("User %s %s in configuration database", user, reason);
543 logger.debug(action + msg);
544 return new Status(statusCode, msg);
549 return addRemoveLocalUserInternal(AAAconf, false);
551 addRemoveLocalUserInternal(currentAAAconf, true);
552 return addRemoveLocalUserInternal(AAAconf, false);
554 return addRemoveLocalUserInternal(AAAconf, true);
556 return new Status(StatusCode.INTERNALERROR, "Unknown action");
560 private Status addRemoveLocalUserInternal(UserConfig AAAconf, boolean delete) {
561 // Update Config database
563 localUserConfigList.remove(AAAconf.getUser());
565 * A user account has been removed form local database, we assume
566 * admin does not want this user to stay connected, in case he has
567 * an open session. So we clean the active list as well.
569 removeUserFromActiveList(AAAconf.getUser());
571 localUserConfigList.put(AAAconf.getUser(), AAAconf);
574 return new Status(StatusCode.SUCCESS);
577 private Status addRemoveAAAServer(ServerConfig AAAconf, boolean delete) {
579 if (!AAAconf.isValid()) {
580 String msg = "Invalid Server configuration";
582 return new Status(StatusCode.BADREQUEST, msg);
585 // Update configuration database
587 remoteServerConfigList.remove(AAAconf.getAddress());
589 remoteServerConfigList.put(AAAconf.getAddress(), AAAconf);
592 return new Status(StatusCode.SUCCESS);
595 private Status addRemoveAuthInfo(AuthorizationConfig AAAconf, boolean delete) {
596 Status configCheck = AAAconf.validate();
597 if (!configCheck.isSuccess()) {
598 String msg = "Invalid Authorization configuration: "
599 + configCheck.getDescription();
601 return new Status(StatusCode.BADREQUEST, msg);
604 // Update configuration database
606 authorizationConfList.remove(AAAconf.getUser());
608 authorizationConfList.put(AAAconf.getUser(), AAAconf);
611 return new Status(StatusCode.SUCCESS);
615 public Status addLocalUser(UserConfig AAAconf) {
616 return changeLocalUser(AAAconf, Command.ADD);
620 public Status modifyLocalUser(UserConfig AAAconf) {
621 return changeLocalUser(AAAconf, Command.MODIFY);
625 public Status removeLocalUser(UserConfig AAAconf) {
626 return changeLocalUser(AAAconf, Command.REMOVE);
630 public Status removeLocalUser(String userName) {
631 if (userName == null || userName.trim().isEmpty()) {
632 return new Status(StatusCode.BADREQUEST, "Invalid user name");
635 if (!localUserConfigList.containsKey(userName)) {
636 return new Status(StatusCode.NOTFOUND, "User does not exist");
639 return changeLocalUser(localUserConfigList.get(userName), Command.REMOVE);
643 public Status addAAAServer(ServerConfig AAAconf) {
644 return addRemoveAAAServer(AAAconf, false);
648 public Status removeAAAServer(ServerConfig AAAconf) {
649 return addRemoveAAAServer(AAAconf, true);
653 public Status addAuthInfo(AuthorizationConfig AAAconf) {
654 return addRemoveAuthInfo(AAAconf, false);
658 public Status removeAuthInfo(AuthorizationConfig AAAconf) {
659 return addRemoveAuthInfo(AAAconf, true);
663 public List<UserConfig> getLocalUserList() {
664 return new ArrayList<UserConfig>(localUserConfigList.values());
668 public List<ServerConfig> getAAAServerList() {
669 return new ArrayList<ServerConfig>(remoteServerConfigList.values());
673 public List<AuthorizationConfig> getAuthorizationList() {
674 return new ArrayList<AuthorizationConfig>(
675 authorizationConfList.values());
679 public Status changeLocalUserPassword(String user, String curPassword, String newPassword) {
680 UserConfig targetConfigEntry = null;
682 // update configuration entry
683 targetConfigEntry = localUserConfigList.get(user);
684 if (targetConfigEntry == null) {
685 return new Status(StatusCode.NOTFOUND, "User not found");
687 Status status = targetConfigEntry.update(curPassword, newPassword, null);
688 if (!status.isSuccess()) {
691 // Trigger cluster update
692 localUserConfigList.put(user, targetConfigEntry);
694 logger.info("Password changed for User \"{}\"", user);
700 public void userLogout(String userName) {
701 // TODO: if user was authenticated through AAA server, send
702 // Acct-Status-Type=stop message to server with logout as reason
703 removeUserFromActiveList(userName);
704 logger.info("User \"{}\" logged out", userName);
708 * This function will get called by http session mgr when session times out
711 public void userTimedOut(String userName) {
712 // TODO: if user was authenticated through AAA server, send
713 // Acct-Status-Type=stop message to server with timeout as reason
714 removeUserFromActiveList(userName);
715 logger.info("User \"{}\" timed out", userName);
719 public String getAccessDate(String user) {
720 return this.activeUsers.get(user).getAccessDate();
724 public synchronized Map<String, List<String>> getUserLoggedIn() {
725 Map<String, List<String>> loggedInList = new HashMap<String, List<String>>();
726 for (Map.Entry<String, AuthenticatedUser> user : activeUsers.entrySet()) {
727 String userNameShow = user.getKey();
728 loggedInList.put(userNameShow, user.getValue().getUserRoles());
733 public void _umAddUser(CommandInterpreter ci) {
734 String userName = ci.nextArgument();
735 String password = ci.nextArgument();
736 String role = ci.nextArgument();
738 List<String> roles = new ArrayList<String>();
739 while (role != null) {
740 if (!role.trim().isEmpty()) {
743 role = ci.nextArgument();
746 if (userName == null || userName.trim().isEmpty() || password == null || password.trim().isEmpty()
747 || roles.isEmpty()) {
748 ci.println("Invalid Arguments");
749 ci.println("umAddUser <user_name> <password> <user_role>");
752 ci.print(this.addLocalUser(new UserConfig(userName, password, roles)));
755 public void _umRemUser(CommandInterpreter ci) {
756 String userName = ci.nextArgument();
758 if (userName == null || userName.trim().isEmpty()) {
759 ci.println("Invalid Arguments");
760 ci.println("umRemUser <user_name>");
763 UserConfig target = localUserConfigList.get(userName);
764 if (target == null) {
765 ci.println("User not found");
768 ci.println(this.removeLocalUser(target));
771 public void _umGetUsers(CommandInterpreter ci) {
772 for (UserConfig conf : this.getLocalUserList()) {
773 ci.println(conf.getUser() + " " + conf.getRoles());
777 public void _addAAAServer(CommandInterpreter ci) {
778 String server = ci.nextArgument();
779 String secret = ci.nextArgument();
780 String protocol = ci.nextArgument();
782 if (server == null || secret == null || protocol == null) {
783 ci.println("Usage : addAAAServer <server> <secret> <protocol>");
786 ServerConfig s = new ServerConfig(server, secret, protocol);
790 public void _removeAAAServer(CommandInterpreter ci) {
791 String server = ci.nextArgument();
792 String secret = ci.nextArgument();
793 String protocol = ci.nextArgument();
795 if (server == null || secret == null || protocol == null) {
796 ci.println("Usage : addAAAServer <server> <secret> <protocol>");
799 ServerConfig s = new ServerConfig(server, secret, protocol);
803 public void _printAAAServers(CommandInterpreter ci) {
804 for (ServerConfig aaaServer : remoteServerConfigList.values()) {
805 ci.println(aaaServer.getAddress() + "-" + aaaServer.getProtocol());
810 public String getHelp() {
811 StringBuffer help = new StringBuffer();
812 return help.toString();
815 void setClusterGlobalService(IClusterGlobalServices s) {
816 logger.debug("Cluster Service Global set");
817 this.clusterGlobalService = s;
820 void unsetClusterGlobalService(IClusterGlobalServices s) {
821 if (this.clusterGlobalService == s) {
822 logger.debug("Cluster Service Global removed!");
823 this.clusterGlobalService = null;
827 void unsetContainerAuthClient(IContainerAuthorization s) {
828 if (this.containerAuthorizationClient == s) {
829 this.containerAuthorizationClient = null;
833 void setContainerAuthClient(IContainerAuthorization s) {
834 this.containerAuthorizationClient = s;
837 void setAppAuthClient(IResourceAuthorization s) {
838 this.applicationAuthorizationClients.add(s);
841 void unsetAppAuthClient(IResourceAuthorization s) {
842 this.applicationAuthorizationClients.remove(s);
846 * Function called by the dependency manager when all the required
847 * dependencies are satisfied
854 * Function called by the dependency manager when at least one dependency
855 * become unsatisfied or when the component is shutting down because for
856 * example bundle is being stopped.
863 * Function called by dependency manager after "init ()" is called and after
864 * the services provided by the class are registered in the service registry
868 authProviders = new ConcurrentHashMap<String, IAAAProvider>();
869 // Instantiate cluster synced variables
873 // Read startup configuration and populate databases
874 loadConfigurations();
876 // Check if a password recovery was triggered for default network admin user
877 checkPasswordRecovery();
879 // Make sure default Network Admin account is there
880 checkDefaultNetworkAdmin();
882 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
883 bundleContext.registerService(CommandProvider.class.getName(), this, null);
887 * Function called by the dependency manager before the services exported by
888 * the component are unregistered, this will be followed by a "destroy ()"
896 public List<String> getUserRoles(String userName) {
897 List<String> roles = null;
898 if (userName != null) {
900 * First look in active users then in local configured users,
901 * finally in local authorized users
903 if (activeUsers.containsKey(userName)) {
904 roles = activeUsers.get(userName).getUserRoles();
905 } else if (localUserConfigList.containsKey(userName)) {
906 roles = localUserConfigList.get(userName).getRoles();
907 } else if (authorizationConfList.containsKey(userName)) {
908 roles = authorizationConfList.get(userName).getRoles();
911 return (roles == null) ? new ArrayList<String>(0) : roles;
915 public UserLevel getUserLevel(String username) {
916 // Returns the highest controller user level for the passed user
917 List<String> rolesNames = getUserRoles(username);
919 if (rolesNames.isEmpty()) {
920 return UserLevel.NOUSER;
923 // Check against the well known controller roles first
924 if (rolesNames.contains(UserLevel.SYSTEMADMIN.toString())) {
925 return UserLevel.SYSTEMADMIN;
927 if (rolesNames.contains(UserLevel.NETWORKADMIN.toString())) {
928 return UserLevel.NETWORKADMIN;
930 if (rolesNames.contains(UserLevel.NETWORKOPERATOR.toString())) {
931 return UserLevel.NETWORKOPERATOR;
933 // Check if container user now
934 if (containerAuthorizationClient != null) {
935 for (String roleName : rolesNames) {
936 if (containerAuthorizationClient.isApplicationRole(roleName)) {
937 return UserLevel.CONTAINERUSER;
941 // Finally check if application user
942 if (applicationAuthorizationClients != null) {
943 for (String roleName : rolesNames) {
944 for (IResourceAuthorization client : this.applicationAuthorizationClients) {
945 if (client.isApplicationRole(roleName)) {
946 return UserLevel.APPUSER;
951 return UserLevel.NOUSER;
956 public List<UserLevel> getUserLevels(String username) {
957 // Returns the controller user levels for the passed user
958 List<String> rolesNames = getUserRoles(username);
959 List<UserLevel> levels = new ArrayList<UserLevel>();
961 if (rolesNames.isEmpty()) {
965 // Check against the well known controller roles first
966 if (rolesNames.contains(UserLevel.SYSTEMADMIN.toString())) {
967 levels.add(UserLevel.SYSTEMADMIN);
969 if (rolesNames.contains(UserLevel.NETWORKADMIN.toString())) {
970 levels.add(UserLevel.NETWORKADMIN);
972 if (rolesNames.contains(UserLevel.NETWORKOPERATOR.toString())) {
973 levels.add(UserLevel.NETWORKOPERATOR);
975 // Check if container user now
976 if (containerAuthorizationClient != null) {
977 for (String roleName : rolesNames) {
978 if (containerAuthorizationClient.isApplicationRole(roleName)) {
979 levels.add(UserLevel.CONTAINERUSER);
984 // Finally check if application user
985 if (applicationAuthorizationClients != null) {
986 for (String roleName : rolesNames) {
987 for (IResourceAuthorization client : this.applicationAuthorizationClients) {
988 if (client.isApplicationRole(roleName)) {
989 levels.add(UserLevel.APPUSER);
999 public Status saveConfiguration() {
1000 boolean success = true;
1001 Status ret = saveLocalUserList();
1002 if (!ret.isSuccess()) {
1005 ret = saveAAAServerList();
1006 if (!ret.isSuccess()) {
1009 ret = saveAuthorizationList();
1010 if (!ret.isSuccess()) {
1015 return new Status(StatusCode.SUCCESS);
1018 return new Status(StatusCode.INTERNALERROR, "Failed to save user configurations");
1022 public UserDetails loadUserByUsername(String username)
1023 throws UsernameNotFoundException {
1024 AuthenticatedUser user = activeUsers.get(username);
1027 boolean enabled = true;
1028 boolean accountNonExpired = true;
1029 boolean credentialsNonExpired = true;
1030 boolean accountNonLocked = true;
1032 return new User(username, localUserConfigList.get(username)
1033 .getPassword(), enabled, accountNonExpired,
1034 credentialsNonExpired, accountNonLocked,
1035 user.getGrantedAuthorities(getUserLevel(username)));
1037 throw new UsernameNotFoundException("User not found " + username);
1042 public boolean supports(Class<?> authentication) {
1043 return UsernamePasswordAuthenticationToken.class
1044 .isAssignableFrom(authentication);
1049 public SecurityContextRepository getSecurityContextRepo() {
1050 return securityContextRepo;
1053 public void setSecurityContextRepo(
1054 SecurityContextRepository securityContextRepo) {
1055 this.securityContextRepo = securityContextRepo;
1059 public Authentication authenticate(Authentication authentication)
1060 throws AuthenticationException {
1062 if (StringUtils.isBlank((String) authentication.getCredentials())
1063 || StringUtils.isBlank((String) authentication.getPrincipal())) {
1064 throw new BadCredentialsException(
1065 "Username or credentials did not match");
1068 AuthResultEnum result = authenticate(
1069 (String) authentication.getPrincipal(),
1070 (String) authentication.getCredentials());
1071 if (result.equals(AuthResultEnum.AUTHOR_PASS)
1072 || result.equals(AuthResultEnum.AUTH_ACCEPT_LOC)
1073 || result.equals(AuthResultEnum.AUTH_ACCEPT)) {
1075 AuthenticatedUser user = activeUsers.get(authentication
1076 .getPrincipal().toString());
1079 throw new AuthenticationServiceException(
1080 "Authentication Failure");
1083 authentication = new UsernamePasswordAuthenticationToken(
1084 authentication.getPrincipal(),
1085 authentication.getCredentials(),
1086 user.getGrantedAuthorities(getUserLevel(authentication
1088 return authentication;
1091 throw new BadCredentialsException(
1092 "Username or credentials did not match");
1097 // Following are setters for use in unit testing
1098 void setLocalUserConfigList(ConcurrentMap<String, UserConfig> ucl) {
1100 this.localUserConfigList = ucl;
1104 void setRemoteServerConfigList(ConcurrentMap<String, ServerConfig> scl) {
1106 this.remoteServerConfigList = scl;
1110 void setAuthorizationConfList(ConcurrentMap<String, AuthorizationConfig> acl) {
1112 this.authorizationConfList = acl;
1116 void setActiveUsers(ConcurrentMap<String, AuthenticatedUser> au) {
1118 this.activeUsers = au;
1122 void setAuthProviders(ConcurrentMap<String, IAAAProvider> ap) {
1124 this.authProviders = ap;
1129 public ISessionManager getSessionManager() {
1130 return this.sessionMgr;
1133 public void setSessionMgr(ISessionManager sessionMgr) {
1134 this.sessionMgr = sessionMgr;
1138 public String getPassword(String username) {
1139 return localUserConfigList.get(username).getPassword();
1143 public boolean isRoleInUse(String role) {
1144 if (role == null || role.isEmpty()) {
1147 // Check against controller roles
1148 if (role.equals(UserLevel.SYSTEMADMIN.toString())
1149 || role.equals(UserLevel.NETWORKADMIN.toString())
1150 || role.equals(UserLevel.NETWORKOPERATOR.toString())) {
1153 // Check if container roles
1154 if (containerAuthorizationClient != null) {
1155 if (containerAuthorizationClient.isApplicationRole(role)) {
1159 // Finally if application role
1160 if (applicationAuthorizationClients != null) {
1161 for (IResourceAuthorization client : this.applicationAuthorizationClients) {
1162 if (client.isApplicationRole(role)) {