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.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;
23 import java.util.concurrent.ConcurrentHashMap;
24 import java.util.concurrent.ConcurrentMap;
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.AuthorizationConfig;
47 import org.opendaylight.controller.usermanager.IAAAProvider;
48 import org.opendaylight.controller.usermanager.ISessionManager;
49 import org.opendaylight.controller.usermanager.IUserManager;
50 import org.opendaylight.controller.usermanager.ServerConfig;
51 import org.opendaylight.controller.usermanager.UserConfig;
52 import org.opendaylight.controller.usermanager.security.SessionManager;
53 import org.opendaylight.controller.usermanager.security.UserSecurityContextRepository;
54 import org.opendaylight.controller.usermanager.internal.AuthenticatedUser;
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 UserManagerImpl implements IUserManager, IObjectReader,
75 IConfigurationAware, ICacheUpdateAware<Long, String>, CommandProvider,
76 AuthenticationProvider {
77 private static final Logger logger = LoggerFactory
78 .getLogger(UserManagerImpl.class);
79 private static final String defaultAdmin = "admin";
80 private static final String defaultAdminPassword = "admin";
81 private static final String defaultAdminRole = UserLevel.NETWORKADMIN
83 private static final String ROOT = GlobalConstants.STARTUPHOME.toString();
84 private static final String SAVE = "save";
85 private static final String usersFileName = ROOT + "users.conf";
86 private static final String serversFileName = ROOT + "servers.conf";
87 private static final String authFileName = ROOT + "authorization.conf";
88 private ConcurrentMap<String, UserConfig> localUserConfigList;
89 private ConcurrentMap<String, ServerConfig> remoteServerConfigList;
90 // local authorization info for remotely authenticated users
91 private ConcurrentMap<String, AuthorizationConfig> authorizationConfList;
92 private ConcurrentMap<String, AuthenticatedUser> activeUsers;
93 private ConcurrentMap<String, IAAAProvider> authProviders;
94 private ConcurrentMap<Long, String> localUserListSaveConfigEvent,
95 remoteServerSaveConfigEvent, authorizationSaveConfigEvent;
96 private IClusterGlobalServices clusterGlobalService = null;
97 private SecurityContextRepository securityContextRepo = new UserSecurityContextRepository();
98 private IContainerAuthorization containerAuthorizationClient;
99 private Set<IResourceAuthorization> applicationAuthorizationClients;
100 private ISessionManager sessionMgr = new SessionManager();
102 public boolean addAAAProvider(IAAAProvider provider) {
103 if (provider == null || provider.getName() == null
104 || provider.getName().trim().isEmpty()) {
107 if (authProviders.get(provider.getName()) != null) {
111 authProviders.put(provider.getName(), provider);
115 public void removeAAAProvider(IAAAProvider provider) {
116 authProviders.remove(provider.getName());
119 public IAAAProvider getAAAProvider(String name) {
120 return authProviders.get(name);
124 public Set<String> getAAAProviderNames() {
125 return authProviders.keySet();
128 @SuppressWarnings("deprecation")
129 private void allocateCaches() {
130 this.applicationAuthorizationClients = Collections
131 .synchronizedSet(new HashSet<IResourceAuthorization>());
132 if (clusterGlobalService == null) {
133 logger.error("un-initialized clusterGlobalService, can't create cache");
138 clusterGlobalService.createCache("usermanager.localUserConfigList",
139 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
141 clusterGlobalService.createCache(
142 "usermanager.remoteServerConfigList",
143 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
145 clusterGlobalService.createCache(
146 "usermanager.authorizationConfList",
147 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
149 clusterGlobalService.createCache("usermanager.activeUsers",
150 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
152 clusterGlobalService.createCache(
153 "usermanager.localUserSaveConfigEvent",
154 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
156 clusterGlobalService.createCache(
157 "usermanager.remoteServerSaveConfigEvent",
158 EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
160 clusterGlobalService.createCache(
161 "usermanager.authorizationSaveConfigEvent",
162 EnumSet.of(IClusterServices.cacheMode.NON_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", "deprecation" })
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");
201 localUserListSaveConfigEvent = (ConcurrentMap<Long, String>) clusterGlobalService
202 .getCache("usermanager.localUserSaveConfigEvent");
203 if (localUserListSaveConfigEvent == null) {
204 logger.error("Failed to get cache for localUserSaveConfigEvent");
207 remoteServerSaveConfigEvent = (ConcurrentMap<Long, String>) clusterGlobalService
208 .getCache("usermanager.remoteServerSaveConfigEvent");
209 if (remoteServerSaveConfigEvent == null) {
210 logger.error("Failed to get cache for remoteServerSaveConfigEvent");
213 authorizationSaveConfigEvent = (ConcurrentMap<Long, String>) clusterGlobalService
214 .getCache("usermanager.authorizationSaveConfigEvent");
215 if (authorizationSaveConfigEvent == null) {
216 logger.error("Failed to get cache for authorizationSaveConfigEvent");
220 private void loadConfigurations() {
221 // To encode and decode user and server configuration objects
225 * Do not load local startup file if we already got the configurations
226 * synced from another cluster node
228 if (localUserConfigList.isEmpty()) {
231 if (remoteServerConfigList.isEmpty()) {
234 if (authorizationConfList.isEmpty()) {
239 private void loadSecurityKeys() {
243 private void checkDefaultNetworkAdmin() {
244 // If startup config is not there, it's old or it was deleted,
245 // need to add Default Admin
246 if (!localUserConfigList.containsKey(defaultAdmin)) {
247 List<String> roles = new ArrayList<String>(1);
248 roles.add(defaultAdminRole);
249 localUserConfigList.put(defaultAdmin, new UserConfig(defaultAdmin,
250 defaultAdminPassword, roles));
255 public AuthResultEnum authenticate(String userName, String password) {
256 IAAAProvider aaaClient;
257 AuthResponse rcResponse = null;
258 AuthenticatedUser result;
259 boolean remotelyAuthenticated = false;
260 boolean authorizationInfoIsPresent = false;
261 boolean authorized = false;
264 * Attempt remote authentication first if server is configured
266 for (ServerConfig aaaServer : remoteServerConfigList.values()) {
267 String protocol = aaaServer.getProtocol();
268 aaaClient = this.getAAAProvider(protocol);
269 if (aaaClient != null) {
270 rcResponse = aaaClient.authService(userName, password,
271 aaaServer.getAddress(), aaaServer.getSecret());
272 if (rcResponse.getStatus() == AuthResultEnum.AUTH_ACCEPT) {
274 "Remote Authentication Succeeded for User: \"{}\", by Server: {}",
275 userName, aaaServer.getAddress());
276 remotelyAuthenticated = true;
278 } else if (rcResponse.getStatus() == AuthResultEnum.AUTH_REJECT) {
280 "Remote Authentication Rejected User: \"{}\", from Server: {}, Reason:{}",
281 new Object[] { userName, aaaServer.getAddress(),
282 rcResponse.getStatus().toString() });
285 "Remote Authentication Failed for User: \"{}\", from Server: {}, Reason:{}",
286 new Object[] { userName, aaaServer.getAddress(),
287 rcResponse.getStatus().toString() });
292 if (!remotelyAuthenticated) {
293 UserConfig localUser = this.localUserConfigList.get(userName);
294 if (localUser == null) {
296 "Local Authentication Failed for User:\"{}\", Reason: "
297 + "user not found in Local Database", userName);
298 return (AuthResultEnum.AUTH_INVALID_LOC_USER);
300 rcResponse = localUser.authenticate(password);
301 if (rcResponse.getStatus() != AuthResultEnum.AUTH_ACCEPT_LOC) {
303 "Local Authentication Failed for User: \"{}\", Reason: {}",
304 userName, rcResponse.getStatus().toString());
306 return (rcResponse.getStatus());
308 logger.info("Local Authentication Succeeded for User: \"{}\"",
313 * Authentication succeeded
315 result = new AuthenticatedUser(userName);
318 * Extract attributes from response All the information we are
319 * interested in is in the first Cisco VSA (vendor specific attribute).
320 * Just process the first VSA and return
322 String attributes = (rcResponse.getData() != null && !rcResponse
323 .getData().isEmpty()) ? rcResponse.getData().get(0) : null;
326 * Check if the authorization information is present
328 authorizationInfoIsPresent = checkAuthorizationInfo(attributes);
331 * The AAA server was only used to perform the authentication Look for
332 * locally stored authorization info for this user If found, add the
333 * data to the rcResponse
335 if (remotelyAuthenticated && !authorizationInfoIsPresent) {
337 "No Remote Authorization Info provided by Server for User: \"{}\"",
340 "Looking for Local Authorization Info for User: \"{}\"",
343 AuthorizationConfig resource = authorizationConfList.get(userName);
344 if (resource != null) {
345 logger.info("Found Local Authorization Info for User: \"{}\"",
347 attributes = resource.getRolesString();
350 authorizationInfoIsPresent = checkAuthorizationInfo(attributes);
354 * Common response parsing for local & remote authenticated user Looking
355 * for authorized resources, detecting attributes' validity
357 if (authorizationInfoIsPresent) {
358 // Identifying the administrative role
359 result.setRoleList(attributes.split(" "));
362 logger.info("Not able to find Authorization Info for User: \"{}\"",
367 * Add profile for authenticated user
369 putUserInActiveList(userName, result);
371 logger.info("User \"{}\" authorized for the following role(s): {}",
372 userName, result.getUserRoles());
374 logger.info("User \"{}\" Not Authorized for any role ", userName);
377 return rcResponse.getStatus();
380 // Check in the attributes string whether or not authorization information
382 private boolean checkAuthorizationInfo(String attributes) {
383 return (attributes != null && !attributes.isEmpty());
386 private void putUserInActiveList(String user, AuthenticatedUser result) {
387 activeUsers.put(user, result);
390 private void removeUserFromActiveList(String user) {
391 if (!activeUsers.containsKey(user)) {
392 // as cookie persists in cache, we can get logout for unexisting
396 activeUsers.remove(user);
400 public Status saveLocalUserList() {
401 // Publish the save config event to the cluster nodes
402 localUserListSaveConfigEvent.put(new Date().getTime(), SAVE);
403 return saveLocalUserListInternal();
406 private Status saveLocalUserListInternal() {
407 ObjectWriter objWriter = new ObjectWriter();
408 return objWriter.write(new ConcurrentHashMap<String, UserConfig>(
409 localUserConfigList), usersFileName);
413 public Status saveAAAServerList() {
414 // Publish the save config event to the cluster nodes
415 remoteServerSaveConfigEvent.put(new Date().getTime(), SAVE);
416 return saveAAAServerListInternal();
419 private Status saveAAAServerListInternal() {
420 ObjectWriter objWriter = new ObjectWriter();
421 return objWriter.write(new ConcurrentHashMap<String, ServerConfig>(
422 remoteServerConfigList), serversFileName);
426 public Status saveAuthorizationList() {
427 // Publish the save config event to the cluster nodes
428 authorizationSaveConfigEvent.put(new Date().getTime(), SAVE);
429 return saveAuthorizationListInternal();
432 private Status saveAuthorizationListInternal() {
433 ObjectWriter objWriter = new ObjectWriter();
434 return objWriter.write(
435 new ConcurrentHashMap<String, AuthorizationConfig>(
436 authorizationConfList), authFileName);
440 public Object readObject(ObjectInputStream ois)
441 throws FileNotFoundException, IOException, ClassNotFoundException {
442 // Perform the class deserialization locally, from inside the package
443 // where the class is defined
444 return ois.readObject();
447 @SuppressWarnings("unchecked")
448 private void loadUserConfig() {
449 ObjectReader objReader = new ObjectReader();
450 ConcurrentMap<String, UserConfig> confList = (ConcurrentMap<String, UserConfig>) objReader
451 .read(this, usersFileName);
453 if (confList == null) {
457 for (UserConfig conf : confList.values()) {
462 @SuppressWarnings("unchecked")
463 private void loadServerConfig() {
464 ObjectReader objReader = new ObjectReader();
465 ConcurrentMap<String, ServerConfig> confList = (ConcurrentMap<String, ServerConfig>) objReader
466 .read(this, serversFileName);
468 if (confList == null) {
472 for (ServerConfig conf : confList.values()) {
477 @SuppressWarnings("unchecked")
478 private void loadAuthConfig() {
479 ObjectReader objReader = new ObjectReader();
480 ConcurrentMap<String, AuthorizationConfig> confList = (ConcurrentMap<String, AuthorizationConfig>) objReader
481 .read(this, authFileName);
483 if (confList == null) {
487 for (AuthorizationConfig conf : confList.values()) {
493 * Interaction with GUI START
495 public Status addRemoveLocalUser(UserConfig AAAconf, boolean delete) {
496 // UserConfig Validation check
497 Status validCheck = AAAconf.validate();
498 if (!validCheck.isSuccess()) {
502 // Update Config database
504 if (AAAconf.getUser().equals(UserManagerImpl.defaultAdmin)) {
505 String msg = "Invalid Request: Default Network Admin User "
506 + "cannot be deleted";
508 return new Status(StatusCode.NOTALLOWED, msg);
510 localUserConfigList.remove(AAAconf.getUser());
512 * A user account has been removed form local database, we assume
513 * admin does not want this user to stay connected, in case he has
514 * an open session. So we clean the active list as well.
516 removeUserFromActiveList(AAAconf.getUser());
518 if (AAAconf.getUser().equals(UserManagerImpl.defaultAdmin)) {
519 String msg = "Invalid Request: Default Network Admin User "
522 return new Status(StatusCode.NOTALLOWED, msg);
524 localUserConfigList.put(AAAconf.getUser(), AAAconf);
527 return new Status(StatusCode.SUCCESS, null);
530 private Status addRemoveAAAServer(ServerConfig AAAconf, boolean delete) {
532 if (!AAAconf.isValid()) {
533 String msg = "Invalid Server configuration";
535 return new Status(StatusCode.BADREQUEST, msg);
538 // Update configuration database
540 remoteServerConfigList.remove(AAAconf.getAddress());
542 remoteServerConfigList.put(AAAconf.getAddress(), AAAconf);
545 return new Status(StatusCode.SUCCESS, null);
548 private Status addRemoveAuthInfo(AuthorizationConfig AAAconf, boolean delete) {
549 Status configCheck = AAAconf.validate();
550 if (!configCheck.isSuccess()) {
551 String msg = "Invalid Authorization configuration: "
552 + configCheck.getDescription();
554 return new Status(StatusCode.BADREQUEST, msg);
557 // Update configuration database
559 authorizationConfList.remove(AAAconf.getUser());
561 authorizationConfList.put(AAAconf.getUser(), AAAconf);
564 return new Status(StatusCode.SUCCESS, null);
568 public Status addLocalUser(UserConfig AAAconf) {
569 return addRemoveLocalUser(AAAconf, false);
573 public Status removeLocalUser(UserConfig AAAconf) {
574 return addRemoveLocalUser(AAAconf, true);
578 public Status removeLocalUser(String userName) {
579 if (userName == null || userName.trim().isEmpty()) {
580 return new Status(StatusCode.BADREQUEST, "Invalid user name");
582 if (!localUserConfigList.containsKey(userName)) {
583 return new Status(StatusCode.NOTFOUND, "User does not exist");
585 return addRemoveLocalUser(localUserConfigList.get(userName), true);
589 public Status addAAAServer(ServerConfig AAAconf) {
590 return addRemoveAAAServer(AAAconf, false);
594 public Status removeAAAServer(ServerConfig AAAconf) {
595 return addRemoveAAAServer(AAAconf, true);
599 public Status addAuthInfo(AuthorizationConfig AAAconf) {
600 return addRemoveAuthInfo(AAAconf, false);
604 public Status removeAuthInfo(AuthorizationConfig AAAconf) {
605 return addRemoveAuthInfo(AAAconf, true);
609 public List<UserConfig> getLocalUserList() {
610 return new ArrayList<UserConfig>(localUserConfigList.values());
614 public List<ServerConfig> getAAAServerList() {
615 return new ArrayList<ServerConfig>(remoteServerConfigList.values());
619 public List<AuthorizationConfig> getAuthorizationList() {
620 return new ArrayList<AuthorizationConfig>(
621 authorizationConfList.values());
625 public Status changeLocalUserPassword(String user, String curPassword,
626 String newPassword) {
627 UserConfig targetConfigEntry = null;
629 // update configuration entry
630 targetConfigEntry = localUserConfigList.get(user);
631 if (targetConfigEntry == null) {
632 return new Status(StatusCode.NOTFOUND, "User not found");
634 Status status = targetConfigEntry
635 .update(curPassword, newPassword, null);
636 if (!status.isSuccess()) {
639 // Trigger cluster update
640 localUserConfigList.put(user, targetConfigEntry);
642 logger.info("Password changed for User \"{}\"", user);
648 public void userLogout(String userName) {
649 // TODO: if user was authenticated through AAA server, send
650 // Acct-Status-Type=stop message to server with logout as reason
651 removeUserFromActiveList(userName);
652 logger.info("User \"{}\" logged out", userName);
656 * This function will get called by http session mgr when session times out
659 public void userTimedOut(String userName) {
660 // TODO: if user was authenticated through AAA server, send
661 // Acct-Status-Type=stop message to server with timeout as reason
662 removeUserFromActiveList(userName);
663 logger.info("User \"{}\" timed out", userName);
667 public String getAccessDate(String user) {
668 return this.activeUsers.get(user).getAccessDate();
672 public synchronized Map<String, List<String>> getUserLoggedIn() {
673 Map<String, List<String>> loggedInList = new HashMap<String, List<String>>();
674 for (Map.Entry<String, AuthenticatedUser> user : activeUsers.entrySet()) {
675 String userNameShow = user.getKey();
676 loggedInList.put(userNameShow, user.getValue().getUserRoles());
682 * Interaction with GUI END
686 * Cluster notifications
690 public void entryCreated(Long key, String cacheName, boolean originLocal) {
691 // don't react on this event
695 public void entryUpdated(Long key, String new_value, String cacheName,
696 boolean originLocal) {
697 if (cacheName.equals("localUserSaveConfigEvent")) {
698 this.saveLocalUserListInternal();
699 } else if (cacheName.equals("remoteServerSaveConfigEvent")) {
700 this.saveAAAServerListInternal();
701 } else if (cacheName.equals("authorizationSaveConfigEvent")) {
702 this.saveAuthorizationListInternal();
707 public void entryDeleted(Long key, String cacheName, boolean originLocal) {
708 // don't react on this event
711 public void _umAddUser(CommandInterpreter ci) {
712 String userName = ci.nextArgument();
713 String password = ci.nextArgument();
714 String role = ci.nextArgument();
716 List<String> roles = new ArrayList<String>();
717 while (role != null) {
718 if (!role.trim().isEmpty()) {
721 role = ci.nextArgument();
724 if (userName == null || userName.trim().isEmpty() || password == null
725 || password.trim().isEmpty() || roles == null
726 || roles.isEmpty()) {
727 ci.println("Invalid Arguments");
728 ci.println("umAddUser <user_name> <password> <user_role>");
731 ci.print(this.addLocalUser(new UserConfig(userName, password, roles)));
734 public void _umRemUser(CommandInterpreter ci) {
735 String userName = ci.nextArgument();
737 if (userName == null || userName.trim().isEmpty()) {
738 ci.println("Invalid Arguments");
739 ci.println("umRemUser <user_name>");
742 UserConfig target = localUserConfigList.get(userName);
743 if (target == null) {
744 ci.println("User not found");
747 ci.println(this.removeLocalUser(target));
750 public void _umGetUsers(CommandInterpreter ci) {
751 for (UserConfig conf : this.getLocalUserList()) {
752 ci.println(conf.getUser() + " " + conf.getRoles());
756 public void _addAAAServer(CommandInterpreter ci) {
757 String server = ci.nextArgument();
758 String secret = ci.nextArgument();
759 String protocol = ci.nextArgument();
761 if (server == null || secret == null || protocol == null) {
762 ci.println("Usage : addAAAServer <server> <secret> <protocol>");
765 ServerConfig s = new ServerConfig(server, secret, protocol);
769 public void _removeAAAServer(CommandInterpreter ci) {
770 String server = ci.nextArgument();
771 String secret = ci.nextArgument();
772 String protocol = ci.nextArgument();
774 if (server == null || secret == null || protocol == null) {
775 ci.println("Usage : addAAAServer <server> <secret> <protocol>");
778 ServerConfig s = new ServerConfig(server, secret, protocol);
782 public void _printAAAServers(CommandInterpreter ci) {
783 for (ServerConfig aaaServer : remoteServerConfigList.values()) {
784 ci.println(aaaServer.getAddress() + "-" + aaaServer.getProtocol());
789 public String getHelp() {
790 StringBuffer help = new StringBuffer();
791 return help.toString();
794 void setClusterGlobalService(IClusterGlobalServices s) {
795 logger.debug("Cluster Service Global set");
796 this.clusterGlobalService = s;
799 void unsetClusterGlobalService(IClusterGlobalServices s) {
800 if (this.clusterGlobalService == s) {
801 logger.debug("Cluster Service Global removed!");
802 this.clusterGlobalService = null;
806 void unsetContainerAuthClient(IContainerAuthorization s) {
807 if (this.containerAuthorizationClient == s) {
808 this.containerAuthorizationClient = null;
812 void setContainerAuthClient(IContainerAuthorization s) {
813 this.containerAuthorizationClient = s;
816 void setAppAuthClient(IResourceAuthorization s) {
817 this.applicationAuthorizationClients.add(s);
820 void unsetAppAuthClient(IResourceAuthorization s) {
821 this.applicationAuthorizationClients.remove(s);
825 * Function called by the dependency manager when all the required
826 * dependencies are satisfied
833 * Function called by the dependency manager when at least one dependency
834 * become unsatisfied or when the component is shutting down because for
835 * example bundle is being stopped.
842 * Function called by dependency manager after "init ()" is called and after
843 * the services provided by the class are registered in the service registry
847 authProviders = new ConcurrentHashMap<String, IAAAProvider>();
848 // Instantiate cluster synced variables
852 // Read startup configuration and populate databases
853 loadConfigurations();
855 // Make sure default Network Admin account is there
856 checkDefaultNetworkAdmin();
857 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
859 bundleContext.registerService(CommandProvider.class.getName(), this,
864 * Function called by the dependency manager before the services exported by
865 * the component are unregistered, this will be followed by a "destroy ()"
873 public List<String> getUserRoles(String userName) {
874 List<String> roles = null;
875 if (userName != null) {
877 * First look in active users then in local configured users,
878 * finally in local authorized users
880 if (activeUsers.containsKey(userName)) {
881 roles = activeUsers.get(userName).getUserRoles();
882 } else if (localUserConfigList.containsKey(userName)) {
883 roles = localUserConfigList.get(userName).getRoles();
884 } else if (authorizationConfList.containsKey(userName)) {
885 roles = authorizationConfList.get(userName).getRoles();
888 return (roles == null) ? new ArrayList<String>(0) : roles;
892 public UserLevel getUserLevel(String username) {
893 // Returns the highest controller user level for the passed user
894 List<String> rolesNames = getUserRoles(username);
896 if (rolesNames.isEmpty()) {
897 return UserLevel.NOUSER;
900 // Check against the well known controller roles first
901 if (rolesNames.contains(UserLevel.SYSTEMADMIN.toString())) {
902 return UserLevel.SYSTEMADMIN;
904 if (rolesNames.contains(UserLevel.NETWORKADMIN.toString())) {
905 return UserLevel.NETWORKADMIN;
907 if (rolesNames.contains(UserLevel.NETWORKOPERATOR.toString())) {
908 return UserLevel.NETWORKOPERATOR;
910 // Check if container user now
911 if (containerAuthorizationClient != null) {
912 for (String roleName : rolesNames) {
913 if (containerAuthorizationClient.isApplicationRole(roleName)) {
914 return UserLevel.CONTAINERUSER;
918 // Finally check if application user
919 if (applicationAuthorizationClients != null) {
920 for (String roleName : rolesNames) {
921 for (IResourceAuthorization client : this.applicationAuthorizationClients) {
922 if (client.isApplicationRole(roleName)) {
923 return UserLevel.APPUSER;
928 return UserLevel.NOUSER;
933 public List<UserLevel> getUserLevels(String username) {
934 // Returns the controller user levels for the passed user
935 List<String> rolesNames = getUserRoles(username);
936 List<UserLevel> levels = new ArrayList<UserLevel>();
938 if (rolesNames.isEmpty()) {
942 // Check against the well known controller roles first
943 if (rolesNames.contains(UserLevel.SYSTEMADMIN.toString())) {
944 levels.add(UserLevel.SYSTEMADMIN);
946 if (rolesNames.contains(UserLevel.NETWORKADMIN.toString())) {
947 levels.add(UserLevel.NETWORKADMIN);
949 if (rolesNames.contains(UserLevel.NETWORKOPERATOR.toString())) {
950 levels.add(UserLevel.NETWORKOPERATOR);
952 // Check if container user now
953 if (containerAuthorizationClient != null) {
954 for (String roleName : rolesNames) {
955 if (containerAuthorizationClient.isApplicationRole(roleName)) {
956 levels.add(UserLevel.CONTAINERUSER);
961 // Finally check if application user
962 if (applicationAuthorizationClients != null) {
963 for (String roleName : rolesNames) {
964 for (IResourceAuthorization client : this.applicationAuthorizationClients) {
965 if (client.isApplicationRole(roleName)) {
966 levels.add(UserLevel.APPUSER);
976 public Status saveConfiguration() {
977 boolean success = true;
978 Status ret = saveLocalUserList();
979 if (!ret.isSuccess()) {
982 ret = saveAAAServerList();
983 if (!ret.isSuccess()) {
986 ret = saveAuthorizationList();
987 if (!ret.isSuccess()) {
992 return new Status(StatusCode.SUCCESS, null);
995 return new Status(StatusCode.INTERNALERROR,
996 "Failed to save user configurations");
1000 public UserDetails loadUserByUsername(String username)
1001 throws UsernameNotFoundException {
1002 AuthenticatedUser user = activeUsers.get(username);
1005 boolean enabled = true;
1006 boolean accountNonExpired = true;
1007 boolean credentialsNonExpired = true;
1008 boolean accountNonLocked = true;
1010 return new User(username, localUserConfigList.get(username)
1011 .getPassword(), enabled, accountNonExpired,
1012 credentialsNonExpired, accountNonLocked,
1013 user.getGrantedAuthorities(getUserLevel(username)));
1015 throw new UsernameNotFoundException("User not found " + username);
1020 public boolean supports(Class<?> authentication) {
1021 return UsernamePasswordAuthenticationToken.class
1022 .isAssignableFrom(authentication);
1027 public SecurityContextRepository getSecurityContextRepo() {
1028 return securityContextRepo;
1031 public void setSecurityContextRepo(
1032 SecurityContextRepository securityContextRepo) {
1033 this.securityContextRepo = securityContextRepo;
1037 public Authentication authenticate(Authentication authentication)
1038 throws AuthenticationException {
1040 if (StringUtils.isBlank((String) authentication.getCredentials())
1041 || StringUtils.isBlank((String) authentication.getPrincipal())) {
1042 throw new BadCredentialsException(
1043 "Username or credentials did not match");
1046 AuthResultEnum result = authenticate(
1047 (String) authentication.getPrincipal(),
1048 (String) authentication.getCredentials());
1049 if (result.equals(AuthResultEnum.AUTHOR_PASS)
1050 || result.equals(AuthResultEnum.AUTH_ACCEPT_LOC)
1051 || result.equals(AuthResultEnum.AUTH_ACCEPT)) {
1053 AuthenticatedUser user = activeUsers.get(authentication
1054 .getPrincipal().toString());
1057 throw new AuthenticationServiceException(
1058 "Authentication Failure");
1061 authentication = new UsernamePasswordAuthenticationToken(
1062 authentication.getPrincipal(),
1063 authentication.getCredentials(),
1064 user.getGrantedAuthorities(getUserLevel(authentication
1066 return authentication;
1069 throw new BadCredentialsException(
1070 "Username or credentials did not match");
1075 // Following are setters for use in unit testing
1076 void setLocalUserConfigList(ConcurrentMap<String, UserConfig> ucl) {
1078 this.localUserConfigList = ucl;
1082 void setRemoteServerConfigList(ConcurrentMap<String, ServerConfig> scl) {
1084 this.remoteServerConfigList = scl;
1088 void setAuthorizationConfList(ConcurrentMap<String, AuthorizationConfig> acl) {
1090 this.authorizationConfList = acl;
1094 void setActiveUsers(ConcurrentMap<String, AuthenticatedUser> au) {
1096 this.activeUsers = au;
1100 void setAuthProviders(ConcurrentMap<String, IAAAProvider> ap) {
1102 this.authProviders = ap;
1107 public ISessionManager getSessionManager() {
1108 return this.sessionMgr;
1111 public void setSessionMgr(ISessionManager sessionMgr) {
1112 this.sessionMgr = sessionMgr;
1116 public String getPassword(String username) {
1117 return localUserConfigList.get(username).getPassword();
1121 public boolean isRoleInUse(String role) {
1122 if (role == null || role.isEmpty()) {
1125 // Check against controller roles
1126 if (role.equals(UserLevel.SYSTEMADMIN.toString())
1127 || role.equals(UserLevel.NETWORKADMIN.toString())
1128 || role.equals(UserLevel.NETWORKOPERATOR.toString())) {
1131 // Check if container roles
1132 if (containerAuthorizationClient != null) {
1133 if (containerAuthorizationClient.isApplicationRole(role)) {
1137 // Finally if application role
1138 if (applicationAuthorizationClients != null) {
1139 for (IResourceAuthorization client : this.applicationAuthorizationClients) {
1140 if (client.isApplicationRole(role)) {