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;
11 import java.io.BufferedReader;
13 import java.io.FileNotFoundException;
14 import java.io.FileReader;
15 import java.io.IOException;
16 import java.io.ObjectInputStream;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.EnumSet;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.ConcurrentMap;
28 import org.apache.commons.lang3.StringUtils;
29 import org.eclipse.osgi.framework.console.CommandInterpreter;
30 import org.eclipse.osgi.framework.console.CommandProvider;
31 import org.opendaylight.controller.clustering.services.CacheConfigException;
32 import org.opendaylight.controller.clustering.services.CacheExistException;
33 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
34 import org.opendaylight.controller.clustering.services.IClusterServices;
35 import org.opendaylight.controller.configuration.ConfigurationObject;
36 import org.opendaylight.controller.configuration.IConfigurationAware;
37 import org.opendaylight.controller.configuration.IConfigurationService;
38 import org.opendaylight.controller.containermanager.IContainerAuthorization;
39 import org.opendaylight.controller.sal.authorization.AuthResultEnum;
40 import org.opendaylight.controller.sal.authorization.IResourceAuthorization;
41 import org.opendaylight.controller.sal.authorization.UserLevel;
42 import org.opendaylight.controller.sal.utils.IObjectReader;
43 import org.opendaylight.controller.sal.utils.Status;
44 import org.opendaylight.controller.sal.utils.StatusCode;
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;
55 import org.osgi.framework.BundleContext;
56 import org.osgi.framework.BundleException;
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 USERS_FILE_NAME = "users.conf";
81 private static final String SERVERS_FILE_NAME = "servers.conf";
82 private static final String AUTH_FILE_NAME = "authorization.conf";
83 private static final String RECOVERY_FILE = "NETWORK_ADMIN_PASSWORD_RECOVERY";
84 private static final boolean DISALLOW_DEFAULT_ADMIN_PASSWORD =
85 Boolean.getBoolean("usermanager.disable-default-admin-password");
86 private ConcurrentMap<String, UserConfig> localUserConfigList;
87 private ConcurrentMap<String, ServerConfig> remoteServerConfigList;
88 // local authorization info for remotely authenticated users
89 private ConcurrentMap<String, AuthorizationConfig> authorizationConfList;
90 private ConcurrentMap<String, AuthenticatedUser> activeUsers;
91 private ConcurrentMap<String, IAAAProvider> authProviders;
92 private IClusterGlobalServices clusterGlobalService = null;
93 private IConfigurationService configurationService;
94 private SecurityContextRepository securityContextRepo = new UserSecurityContextRepository();
95 private IContainerAuthorization containerAuthorizationClient;
96 private Set<IResourceAuthorization> applicationAuthorizationClients;
97 private ISessionManager sessionMgr = new SessionManager();
98 protected enum Command {
100 MODIFY("modify", "modified"),
101 REMOVE("remove", "removed");
102 private final String action;
103 private final String postAction;
104 private Command(String action, String postAction) {
105 this.action = action;
106 this.postAction = postAction;
109 public String getAction() {
113 public String getPostAction() {
118 public boolean addAAAProvider(IAAAProvider provider) {
119 if (provider == null || provider.getName() == null
120 || provider.getName().trim().isEmpty()) {
123 if (authProviders.get(provider.getName()) != null) {
127 authProviders.put(provider.getName(), provider);
131 public void removeAAAProvider(IAAAProvider provider) {
132 authProviders.remove(provider.getName());
135 public IAAAProvider getAAAProvider(String name) {
136 return authProviders.get(name);
140 public Set<String> getAAAProviderNames() {
141 return authProviders.keySet();
144 private void allocateCaches() {
145 this.applicationAuthorizationClients = Collections.synchronizedSet(new HashSet<IResourceAuthorization>());
146 if (clusterGlobalService == null) {
147 logger.error("un-initialized clusterGlobalService, can't create cache");
152 clusterGlobalService.createCache("usermanager.localUserConfigList",
153 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
155 clusterGlobalService.createCache(
156 "usermanager.remoteServerConfigList",
157 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
159 clusterGlobalService.createCache(
160 "usermanager.authorizationConfList",
161 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
163 clusterGlobalService.createCache("usermanager.activeUsers",
164 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
165 } catch (CacheConfigException cce) {
166 logger.error("Cache configuration invalid - check cache mode");
167 } catch (CacheExistException ce) {
168 logger.debug("Skipping cache creation as already present");
172 @SuppressWarnings({ "unchecked" })
173 private void retrieveCaches() {
174 if (clusterGlobalService == null) {
175 logger.error("un-initialized clusterService, can't retrieve cache");
179 activeUsers = (ConcurrentMap<String, AuthenticatedUser>) clusterGlobalService
180 .getCache("usermanager.activeUsers");
181 if (activeUsers == null) {
182 logger.error("Failed to get cache for activeUsers");
185 localUserConfigList = (ConcurrentMap<String, UserConfig>) clusterGlobalService
186 .getCache("usermanager.localUserConfigList");
187 if (localUserConfigList == null) {
188 logger.error("Failed to get cache for localUserConfigList");
191 remoteServerConfigList = (ConcurrentMap<String, ServerConfig>) clusterGlobalService
192 .getCache("usermanager.remoteServerConfigList");
193 if (remoteServerConfigList == null) {
194 logger.error("Failed to get cache for remoteServerConfigList");
197 authorizationConfList = (ConcurrentMap<String, AuthorizationConfig>) clusterGlobalService
198 .getCache("usermanager.authorizationConfList");
199 if (authorizationConfList == null) {
200 logger.error("Failed to get cache for authorizationConfList");
204 private void loadConfigurations() {
205 // To encode and decode user and server configuration objects
208 * Do not load local startup file if we are not the coordinator
215 private void loadSecurityKeys() {
219 private void checkDefaultNetworkAdmin(String newPass) {
220 boolean usingFactoryPassword = false;
221 // network admin already configured.
222 if (localUserConfigList.containsKey(DEFAULT_ADMIN)) {
223 UserConfig uc = localUserConfigList.get(DEFAULT_ADMIN);
224 if (!uc.isPasswordMatch(DEFAULT_ADMIN_PASSWORD)) {
227 usingFactoryPassword = true;
231 List<String> defaultRoles = new ArrayList<String>(1);
232 defaultRoles.add(DEFAULT_ADMIN_ROLE);
233 if (newPass == null) {
234 if (!localUserConfigList.containsKey(DEFAULT_ADMIN)) {
235 // Need to skip the strong password check for the default admin
236 UserConfig defaultAdmin = UserConfig.getUncheckedUserConfig(
237 UserManager.DEFAULT_ADMIN, UserManager.DEFAULT_ADMIN_PASSWORD,
239 localUserConfigList.put(UserManager.DEFAULT_ADMIN, defaultAdmin);
240 usingFactoryPassword = true;
243 // use new password for admin
244 Status status = UserConfig.validateClearTextPassword(newPass);
245 if (status.isSuccess()) {
246 localUserConfigList.put(UserManager.DEFAULT_ADMIN,
247 new UserConfig(UserManager.DEFAULT_ADMIN, newPass, defaultRoles));
248 logger.trace("Network Adminstrator password is reset.");
249 if (newPass.equals(DEFAULT_ADMIN_PASSWORD)) {
250 usingFactoryPassword = true;
253 logger.warn("Password is invalid - {}. Network Adminstrator password " +
254 "cannot be set.", status.getDescription());
258 if (usingFactoryPassword) {
259 if (DISALLOW_DEFAULT_ADMIN_PASSWORD) {
260 logger.warn("Network Administrator factory default password " +
261 "is disallowed. Please set the password prior to starting " +
262 "the controller. Shutting down now.");
265 BundleContext bundleContext = FrameworkUtil.getBundle(
266 getClass()).getBundleContext();
267 bundleContext.getBundle(0).stop();
268 } catch (BundleException e) {
269 logger.warn("Cannot stop framework ", e);
272 logger.warn("Network Administrator password is set to factory default. " +
273 "Please change the password as soon as possible.");
278 private String checkPasswordRecovery() {
279 final String fileDescription = "Default Network Administrator password recovery file";
280 File recoveryFile = new File(UserManager.RECOVERY_FILE);
281 if (!recoveryFile.exists()) {
284 // read the recovery file
287 BufferedReader reader = new BufferedReader(new FileReader(recoveryFile));
288 // read password from recovery file if it has one
289 pwd = reader.readLine();
290 if (pwd != null && pwd.trim().length() == 0) {
295 * Recovery file detected, remove current default network
296 * administrator entry from local users configuration list.
297 * Warn user and delete recovery file.
299 this.localUserConfigList.remove(UserManager.DEFAULT_ADMIN);
300 if (!recoveryFile.delete()) {
301 logger.warn("Failed to delete {}", fileDescription);
303 logger.trace("{} deleted", fileDescription);
305 } catch (IOException e) {
306 logger.warn("Failed to process file {}", fileDescription);
312 public AuthResultEnum authenticate(String userName, String password) {
313 IAAAProvider aaaClient;
314 AuthResponse rcResponse = null;
315 AuthenticatedUser result;
316 boolean remotelyAuthenticated = false;
317 boolean authorizationInfoIsPresent = false;
318 boolean authorized = false;
321 * Attempt remote authentication first if server is configured
323 for (ServerConfig aaaServer : remoteServerConfigList.values()) {
324 String protocol = aaaServer.getProtocol();
325 aaaClient = this.getAAAProvider(protocol);
326 if (aaaClient != null) {
327 rcResponse = aaaClient.authService(userName, password,
328 aaaServer.getAddress(), aaaServer.getSecret());
329 if (rcResponse.getStatus() == AuthResultEnum.AUTH_ACCEPT) {
331 "Remote Authentication Succeeded for User: \"{}\", by Server: {}",
332 userName, aaaServer.getAddress());
333 remotelyAuthenticated = true;
335 } else if (rcResponse.getStatus() == AuthResultEnum.AUTH_REJECT) {
337 "Remote Authentication Rejected User: \"{}\", from Server: {}, Reason:{}",
338 new Object[] { userName, aaaServer.getAddress(),
339 rcResponse.getStatus().toString() });
342 "Remote Authentication Failed for User: \"{}\", from Server: {}, Reason:{}",
343 new Object[] { userName, aaaServer.getAddress(),
344 rcResponse.getStatus().toString() });
349 if (!remotelyAuthenticated) {
350 UserConfig localUser = this.localUserConfigList.get(userName);
351 if (localUser == null) {
353 "Local Authentication Failed for User:\"{}\", Reason: "
354 + "user not found in Local Database", userName);
355 return (AuthResultEnum.AUTH_INVALID_LOC_USER);
357 rcResponse = localUser.authenticate(password);
358 if (rcResponse.getStatus() != AuthResultEnum.AUTH_ACCEPT_LOC) {
360 "Local Authentication Failed for User: \"{}\", Reason: {}",
361 userName, rcResponse.getStatus().toString());
363 return (rcResponse.getStatus());
365 logger.trace("Local Authentication Succeeded for User: \"{}\"",
370 * Authentication succeeded
372 result = new AuthenticatedUser(userName);
375 * Extract attributes from response All the information we are
376 * interested in is in the first Cisco VSA (vendor specific attribute).
377 * Just process the first VSA and return
379 String attributes = (rcResponse.getData() != null && !rcResponse
380 .getData().isEmpty()) ? rcResponse.getData().get(0) : null;
383 * Check if the authorization information is present
385 authorizationInfoIsPresent = checkAuthorizationInfo(attributes);
388 * The AAA server was only used to perform the authentication Look for
389 * locally stored authorization info for this user If found, add the
390 * data to the rcResponse
392 if (remotelyAuthenticated && !authorizationInfoIsPresent) {
394 "No Remote Authorization Info provided by Server for User: \"{}\"",
397 "Looking for Local Authorization Info for User: \"{}\"",
400 AuthorizationConfig resource = authorizationConfList.get(userName);
401 if (resource != null) {
402 logger.trace("Found Local Authorization Info for User: \"{}\"",
404 attributes = resource.getRolesString();
407 authorizationInfoIsPresent = checkAuthorizationInfo(attributes);
411 * Common response parsing for local & remote authenticated user Looking
412 * for authorized resources, detecting attributes' validity
414 if (authorizationInfoIsPresent) {
415 // Identifying the administrative role
416 result.setRoleList(attributes.split(" "));
419 logger.trace("Not able to find Authorization Info for User: \"{}\"",
424 * Add profile for authenticated user
426 putUserInActiveList(userName, result);
428 logger.trace("User \"{}\" authorized for the following role(s): {}",
429 userName, result.getUserRoles());
431 logger.trace("User \"{}\" Not Authorized for any role ", userName);
434 return rcResponse.getStatus();
437 // Check in the attributes string whether or not authorization information
439 private boolean checkAuthorizationInfo(String attributes) {
440 return (attributes != null && !attributes.isEmpty());
443 private void putUserInActiveList(String user, AuthenticatedUser result) {
444 activeUsers.put(user, result);
447 private void removeUserFromActiveList(String user) {
448 if (!activeUsers.containsKey(user)) {
449 // as cookie persists in cache, we can get logout for unexisting
453 activeUsers.remove(user);
457 public Status saveLocalUserList() {
458 return saveLocalUserListInternal();
461 private Status saveLocalUserListInternal() {
462 return configurationService.persistConfiguration(
463 new ArrayList<ConfigurationObject>(localUserConfigList.values()), USERS_FILE_NAME);
467 public Status saveAAAServerList() {
468 return saveAAAServerListInternal();
471 private Status saveAAAServerListInternal() {
472 return configurationService.persistConfiguration(
473 new ArrayList<ConfigurationObject>(remoteServerConfigList.values()), SERVERS_FILE_NAME);
477 public Status saveAuthorizationList() {
478 return saveAuthorizationListInternal();
481 private Status saveAuthorizationListInternal() {
482 return configurationService.persistConfiguration(
483 new ArrayList<ConfigurationObject>(authorizationConfList.values()), AUTH_FILE_NAME);
487 public Object readObject(ObjectInputStream ois)
488 throws FileNotFoundException, IOException, ClassNotFoundException {
489 // Perform the class deserialization locally, from inside the package
490 // where the class is defined
491 return ois.readObject();
494 private void loadUserConfig() {
495 for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, USERS_FILE_NAME)) {
496 addRemoveLocalUserInternal((UserConfig) conf, false);
500 private void loadServerConfig() {
501 for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, SERVERS_FILE_NAME)) {
502 addAAAServer((ServerConfig) conf);
506 private void loadAuthConfig() {
507 for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, AUTH_FILE_NAME)) {
508 addAuthInfo((AuthorizationConfig) conf);
513 * Interaction with GUI START
515 private Status changeLocalUser(UserConfig AAAconf, Command command) {
516 // UserConfig Validation check
517 Status validCheck = AAAconf.validate();
518 if (!validCheck.isSuccess()) {
522 String user = AAAconf.getUser();
524 // Check default admin user
525 if (user.equals(UserManager.DEFAULT_ADMIN)) {
526 String msg = String.format("Invalid Request: Default Network Admin User cannot be %s", command.getPostAction());
528 return new Status(StatusCode.NOTALLOWED, msg);
531 // Check user presence/conflict
532 UserConfig currentAAAconf = localUserConfigList.get(user);
533 StatusCode statusCode = null;
534 String reason = null;
537 if (currentAAAconf != null) {
538 reason = "already present";
539 statusCode = StatusCode.CONFLICT;
544 if (currentAAAconf == null) {
545 reason = "not found";
546 statusCode = StatusCode.NOTFOUND;
553 if (statusCode != null) {
554 String action = String.format("Failed to %s user %s: ", command.getAction(), user);
555 String msg = String.format("User %s %s in configuration database", user, reason);
556 logger.debug(action + msg);
557 return new Status(statusCode, msg);
562 return addRemoveLocalUserInternal(AAAconf, false);
564 addRemoveLocalUserInternal(currentAAAconf, true);
565 return addRemoveLocalUserInternal(AAAconf, false);
567 return addRemoveLocalUserInternal(AAAconf, true);
569 return new Status(StatusCode.INTERNALERROR, "Unknown action");
573 private Status addRemoveLocalUserInternal(UserConfig AAAconf, boolean delete) {
574 // Update Config database
576 localUserConfigList.remove(AAAconf.getUser());
578 * A user account has been removed form local database, we assume
579 * admin does not want this user to stay connected, in case he has
580 * an open session. So we clean the active list as well.
582 removeUserFromActiveList(AAAconf.getUser());
584 localUserConfigList.put(AAAconf.getUser(), AAAconf);
587 return new Status(StatusCode.SUCCESS);
590 private Status addRemoveAAAServer(ServerConfig AAAconf, boolean delete) {
592 if (!AAAconf.isValid()) {
593 String msg = "Invalid Server configuration";
595 return new Status(StatusCode.BADREQUEST, msg);
598 // Update configuration database
600 remoteServerConfigList.remove(AAAconf.getAddress());
602 remoteServerConfigList.put(AAAconf.getAddress(), AAAconf);
605 return new Status(StatusCode.SUCCESS);
608 private Status addRemoveAuthInfo(AuthorizationConfig AAAconf, boolean delete) {
609 Status configCheck = AAAconf.validate();
610 if (!configCheck.isSuccess()) {
611 String msg = "Invalid Authorization configuration: "
612 + configCheck.getDescription();
614 return new Status(StatusCode.BADREQUEST, msg);
617 // Update configuration database
619 authorizationConfList.remove(AAAconf.getUser());
621 authorizationConfList.put(AAAconf.getUser(), AAAconf);
624 return new Status(StatusCode.SUCCESS);
628 public Status addLocalUser(UserConfig AAAconf) {
629 return changeLocalUser(AAAconf, Command.ADD);
633 public Status modifyLocalUser(UserConfig AAAconf) {
634 return changeLocalUser(AAAconf, Command.MODIFY);
638 public Status removeLocalUser(UserConfig AAAconf) {
639 return changeLocalUser(AAAconf, Command.REMOVE);
643 public Status removeLocalUser(String userName) {
644 if (userName == null || userName.trim().isEmpty()) {
645 return new Status(StatusCode.BADREQUEST, "Invalid user name");
648 if (!localUserConfigList.containsKey(userName)) {
649 return new Status(StatusCode.NOTFOUND, "User does not exist");
652 return changeLocalUser(localUserConfigList.get(userName), Command.REMOVE);
656 public Status addAAAServer(ServerConfig AAAconf) {
657 return addRemoveAAAServer(AAAconf, false);
661 public Status removeAAAServer(ServerConfig AAAconf) {
662 return addRemoveAAAServer(AAAconf, true);
666 public Status addAuthInfo(AuthorizationConfig AAAconf) {
667 return addRemoveAuthInfo(AAAconf, false);
671 public Status removeAuthInfo(AuthorizationConfig AAAconf) {
672 return addRemoveAuthInfo(AAAconf, true);
676 public List<UserConfig> getLocalUserList() {
677 return new ArrayList<UserConfig>(localUserConfigList.values());
681 public List<ServerConfig> getAAAServerList() {
682 return new ArrayList<ServerConfig>(remoteServerConfigList.values());
686 public List<AuthorizationConfig> getAuthorizationList() {
687 return new ArrayList<AuthorizationConfig>(
688 authorizationConfList.values());
692 public Status changeLocalUserPassword(String user, String curPassword, String newPassword) {
693 UserConfig targetConfigEntry = null;
695 // update configuration entry
696 targetConfigEntry = localUserConfigList.get(user);
697 if (targetConfigEntry == null) {
698 return new Status(StatusCode.NOTFOUND, "User not found");
700 Status status = targetConfigEntry.update(curPassword, newPassword, null);
701 if (!status.isSuccess()) {
704 // Trigger cluster update
705 localUserConfigList.put(user, targetConfigEntry);
707 logger.trace("Password changed for User \"{}\"", user);
713 public void userLogout(String userName) {
714 // TODO: if user was authenticated through AAA server, send
715 // Acct-Status-Type=stop message to server with logout as reason
716 removeUserFromActiveList(userName);
717 logger.trace("User \"{}\" logged out", userName);
721 * This function will get called by http session mgr when session times out
724 public void userTimedOut(String userName) {
725 // TODO: if user was authenticated through AAA server, send
726 // Acct-Status-Type=stop message to server with timeout as reason
727 removeUserFromActiveList(userName);
728 logger.trace("User \"{}\" timed out", userName);
732 public String getAccessDate(String user) {
733 return this.activeUsers.get(user).getAccessDate();
737 public synchronized Map<String, List<String>> getUserLoggedIn() {
738 Map<String, List<String>> loggedInList = new HashMap<String, List<String>>();
739 for (Map.Entry<String, AuthenticatedUser> user : activeUsers.entrySet()) {
740 String userNameShow = user.getKey();
741 loggedInList.put(userNameShow, user.getValue().getUserRoles());
746 public void _umAddUser(CommandInterpreter ci) {
747 String userName = ci.nextArgument();
748 String password = ci.nextArgument();
749 String role = ci.nextArgument();
751 List<String> roles = new ArrayList<String>();
752 while (role != null) {
753 if (!role.trim().isEmpty()) {
756 role = ci.nextArgument();
759 if (userName == null || userName.trim().isEmpty() || password == null || password.trim().isEmpty()
760 || roles.isEmpty()) {
761 ci.println("Invalid Arguments");
762 ci.println("umAddUser <user_name> <password> <user_role>");
765 ci.print(this.addLocalUser(new UserConfig(userName, password, roles)));
768 public void _umRemUser(CommandInterpreter ci) {
769 String userName = ci.nextArgument();
771 if (userName == null || userName.trim().isEmpty()) {
772 ci.println("Invalid Arguments");
773 ci.println("umRemUser <user_name>");
776 UserConfig target = localUserConfigList.get(userName);
777 if (target == null) {
778 ci.println("User not found");
781 ci.println(this.removeLocalUser(target));
784 public void _umGetUsers(CommandInterpreter ci) {
785 for (UserConfig conf : this.getLocalUserList()) {
786 ci.println(conf.getUser() + " " + conf.getRoles());
790 public void _addAAAServer(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 _removeAAAServer(CommandInterpreter ci) {
804 String server = ci.nextArgument();
805 String secret = ci.nextArgument();
806 String protocol = ci.nextArgument();
808 if (server == null || secret == null || protocol == null) {
809 ci.println("Usage : addAAAServer <server> <secret> <protocol>");
812 ServerConfig s = new ServerConfig(server, secret, protocol);
816 public void _printAAAServers(CommandInterpreter ci) {
817 for (ServerConfig aaaServer : remoteServerConfigList.values()) {
818 ci.println(aaaServer.getAddress() + "-" + aaaServer.getProtocol());
823 public String getHelp() {
824 StringBuffer help = new StringBuffer();
825 return help.toString();
828 void setClusterGlobalService(IClusterGlobalServices s) {
829 logger.debug("Cluster Service Global set");
830 this.clusterGlobalService = s;
833 void unsetClusterGlobalService(IClusterGlobalServices s) {
834 if (this.clusterGlobalService == s) {
835 logger.debug("Cluster Service Global removed!");
836 this.clusterGlobalService = null;
840 public void setConfigurationService(IConfigurationService service) {
841 logger.trace("Got configuration service set request {}", service);
842 this.configurationService = service;
845 public void unsetConfigurationService(IConfigurationService service) {
846 logger.trace("Got configuration service UNset request");
847 this.configurationService = null;
850 void unsetContainerAuthClient(IContainerAuthorization s) {
851 if (this.containerAuthorizationClient == s) {
852 this.containerAuthorizationClient = null;
856 void setContainerAuthClient(IContainerAuthorization s) {
857 this.containerAuthorizationClient = s;
860 void setAppAuthClient(IResourceAuthorization s) {
861 this.applicationAuthorizationClients.add(s);
864 void unsetAppAuthClient(IResourceAuthorization s) {
865 this.applicationAuthorizationClients.remove(s);
869 * Function called by the dependency manager when all the required
870 * dependencies are satisfied
877 * Function called by the dependency manager when at least one dependency
878 * become unsatisfied or when the component is shutting down because for
879 * example bundle is being stopped.
886 * Function called by dependency manager after "init ()" is called and after
887 * the services provided by the class are registered in the service registry
891 authProviders = new ConcurrentHashMap<String, IAAAProvider>();
892 // Instantiate cluster synced variables
896 // Read startup configuration and populate databases
897 loadConfigurations();
899 // Check if a password recovery was triggered for default network admin user
900 String pwd = checkPasswordRecovery();
902 // Make sure default Network Admin account is there
903 checkDefaultNetworkAdmin(pwd);
905 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
906 bundleContext.registerService(CommandProvider.class.getName(), this, null);
910 * Function called by the dependency manager before the services exported by
911 * the component are unregistered, this will be followed by a "destroy ()"
919 public List<String> getUserRoles(String userName) {
920 List<String> roles = null;
921 if (userName != null) {
923 * First look in active users then in local configured users,
924 * finally in local authorized users
926 if (activeUsers.containsKey(userName)) {
927 roles = activeUsers.get(userName).getUserRoles();
928 } else if (localUserConfigList.containsKey(userName)) {
929 roles = localUserConfigList.get(userName).getRoles();
930 } else if (authorizationConfList.containsKey(userName)) {
931 roles = authorizationConfList.get(userName).getRoles();
934 return (roles == null) ? new ArrayList<String>(0) : roles;
938 public UserLevel getUserLevel(String username) {
939 // Returns the highest controller user level for the passed user
940 List<String> rolesNames = getUserRoles(username);
942 if (rolesNames.isEmpty()) {
943 return UserLevel.NOUSER;
946 // Check against the well known controller roles first
947 if (rolesNames.contains(UserLevel.SYSTEMADMIN.toString())) {
948 return UserLevel.SYSTEMADMIN;
950 if (rolesNames.contains(UserLevel.NETWORKADMIN.toString())) {
951 return UserLevel.NETWORKADMIN;
953 if (rolesNames.contains(UserLevel.NETWORKOPERATOR.toString())) {
954 return UserLevel.NETWORKOPERATOR;
956 // Check if container user now
957 if (containerAuthorizationClient != null) {
958 for (String roleName : rolesNames) {
959 if (containerAuthorizationClient.isApplicationRole(roleName)) {
960 return UserLevel.CONTAINERUSER;
964 // Finally check if application user
965 if (applicationAuthorizationClients != null) {
966 for (String roleName : rolesNames) {
967 for (IResourceAuthorization client : this.applicationAuthorizationClients) {
968 if (client.isApplicationRole(roleName)) {
969 return UserLevel.APPUSER;
974 return UserLevel.NOUSER;
979 public List<UserLevel> getUserLevels(String username) {
980 // Returns the controller user levels for the passed user
981 List<String> rolesNames = getUserRoles(username);
982 List<UserLevel> levels = new ArrayList<UserLevel>();
984 if (rolesNames.isEmpty()) {
988 // Check against the well known controller roles first
989 if (rolesNames.contains(UserLevel.SYSTEMADMIN.toString())) {
990 levels.add(UserLevel.SYSTEMADMIN);
992 if (rolesNames.contains(UserLevel.NETWORKADMIN.toString())) {
993 levels.add(UserLevel.NETWORKADMIN);
995 if (rolesNames.contains(UserLevel.NETWORKOPERATOR.toString())) {
996 levels.add(UserLevel.NETWORKOPERATOR);
998 // Check if container user now
999 if (containerAuthorizationClient != null) {
1000 for (String roleName : rolesNames) {
1001 if (containerAuthorizationClient.isApplicationRole(roleName)) {
1002 levels.add(UserLevel.CONTAINERUSER);
1007 // Finally check if application user
1008 if (applicationAuthorizationClients != null) {
1009 for (String roleName : rolesNames) {
1010 for (IResourceAuthorization client : this.applicationAuthorizationClients) {
1011 if (client.isApplicationRole(roleName)) {
1012 levels.add(UserLevel.APPUSER);
1022 public Status saveConfiguration() {
1023 boolean success = true;
1024 Status ret = saveLocalUserList();
1025 if (!ret.isSuccess()) {
1028 ret = saveAAAServerList();
1029 if (!ret.isSuccess()) {
1032 ret = saveAuthorizationList();
1033 if (!ret.isSuccess()) {
1038 return new Status(StatusCode.SUCCESS);
1041 return new Status(StatusCode.INTERNALERROR, "Failed to save user configurations");
1045 public UserDetails loadUserByUsername(String username)
1046 throws UsernameNotFoundException {
1047 AuthenticatedUser user = activeUsers.get(username);
1050 boolean enabled = true;
1051 boolean accountNonExpired = true;
1052 boolean credentialsNonExpired = true;
1053 boolean accountNonLocked = true;
1055 return new User(username, localUserConfigList.get(username)
1056 .getPassword(), enabled, accountNonExpired,
1057 credentialsNonExpired, accountNonLocked,
1058 user.getGrantedAuthorities(getUserLevel(username)));
1060 throw new UsernameNotFoundException("User not found " + username);
1065 public boolean supports(Class<?> authentication) {
1066 return UsernamePasswordAuthenticationToken.class
1067 .isAssignableFrom(authentication);
1072 public SecurityContextRepository getSecurityContextRepo() {
1073 return securityContextRepo;
1076 public void setSecurityContextRepo(
1077 SecurityContextRepository securityContextRepo) {
1078 this.securityContextRepo = securityContextRepo;
1082 public Authentication authenticate(Authentication authentication)
1083 throws AuthenticationException {
1085 if (StringUtils.isBlank((String) authentication.getCredentials())
1086 || StringUtils.isBlank((String) authentication.getPrincipal())) {
1087 throw new BadCredentialsException(
1088 "Username or credentials did not match");
1091 AuthResultEnum result = authenticate(
1092 (String) authentication.getPrincipal(),
1093 (String) authentication.getCredentials());
1094 if (result.equals(AuthResultEnum.AUTHOR_PASS)
1095 || result.equals(AuthResultEnum.AUTH_ACCEPT_LOC)
1096 || result.equals(AuthResultEnum.AUTH_ACCEPT)) {
1098 AuthenticatedUser user = activeUsers.get(authentication
1099 .getPrincipal().toString());
1102 throw new AuthenticationServiceException(
1103 "Authentication Failure");
1106 authentication = new UsernamePasswordAuthenticationToken(
1107 authentication.getPrincipal(),
1108 authentication.getCredentials(),
1109 user.getGrantedAuthorities(getUserLevel(authentication
1111 return authentication;
1114 throw new BadCredentialsException(
1115 "Username or credentials did not match");
1120 // Following are setters for use in unit testing
1121 void setLocalUserConfigList(ConcurrentMap<String, UserConfig> ucl) {
1123 this.localUserConfigList = ucl;
1127 void setRemoteServerConfigList(ConcurrentMap<String, ServerConfig> scl) {
1129 this.remoteServerConfigList = scl;
1133 void setAuthorizationConfList(ConcurrentMap<String, AuthorizationConfig> acl) {
1135 this.authorizationConfList = acl;
1139 void setActiveUsers(ConcurrentMap<String, AuthenticatedUser> au) {
1141 this.activeUsers = au;
1145 void setAuthProviders(ConcurrentMap<String, IAAAProvider> ap) {
1147 this.authProviders = ap;
1152 public ISessionManager getSessionManager() {
1153 return this.sessionMgr;
1156 public void setSessionMgr(ISessionManager sessionMgr) {
1157 this.sessionMgr = sessionMgr;
1161 public String getPassword(String username) {
1162 return localUserConfigList.get(username).getPassword();
1166 public boolean isRoleInUse(String role) {
1167 if (role == null || role.isEmpty()) {
1170 // Check against controller roles
1171 if (role.equals(UserLevel.SYSTEMADMIN.toString())
1172 || role.equals(UserLevel.NETWORKADMIN.toString())
1173 || role.equals(UserLevel.NETWORKOPERATOR.toString())) {
1176 // Check if container roles
1177 if (containerAuthorizationClient != null) {
1178 if (containerAuthorizationClient.isApplicationRole(role)) {
1182 // Finally if application role
1183 if (applicationAuthorizationClients != null) {
1184 for (IResourceAuthorization client : this.applicationAuthorizationClients) {
1185 if (client.isApplicationRole(role)) {