X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fusermanager%2Fimplementation%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fusermanager%2Finternal%2FUserManager.java;h=3f6ac4a8c786af11cb88bf16e4ab0c44ae8b3097;hp=5d0cbb62862d6f0e7f61be02a7d72153e0780284;hb=c198e5355b6702b6d96f1174bc4d1477143397cc;hpb=93bfe8bc7d657d3c5ddd7cde508a3c0464724e67 diff --git a/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/UserManager.java b/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/UserManager.java index 5d0cbb6286..3f6ac4a8c7 100644 --- a/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/UserManager.java +++ b/opendaylight/usermanager/implementation/src/main/java/org/opendaylight/controller/usermanager/internal/UserManager.java @@ -8,9 +8,10 @@ package org.opendaylight.controller.usermanager.internal; +import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.IOException; import java.io.ObjectInputStream; import java.util.ArrayList; @@ -31,15 +32,14 @@ import org.opendaylight.controller.clustering.services.CacheConfigException; import org.opendaylight.controller.clustering.services.CacheExistException; import org.opendaylight.controller.clustering.services.IClusterGlobalServices; import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.configuration.ConfigurationObject; import org.opendaylight.controller.configuration.IConfigurationAware; +import org.opendaylight.controller.configuration.IConfigurationService; import org.opendaylight.controller.containermanager.IContainerAuthorization; import org.opendaylight.controller.sal.authorization.AuthResultEnum; import org.opendaylight.controller.sal.authorization.IResourceAuthorization; import org.opendaylight.controller.sal.authorization.UserLevel; -import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.IObjectReader; -import org.opendaylight.controller.sal.utils.ObjectReader; -import org.opendaylight.controller.sal.utils.ObjectWriter; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.usermanager.AuthResponse; @@ -53,6 +53,7 @@ import org.opendaylight.controller.usermanager.UserConfig; import org.opendaylight.controller.usermanager.security.SessionManager; import org.opendaylight.controller.usermanager.security.UserSecurityContextRepository; import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -76,11 +77,12 @@ public class UserManager implements IUserManager, IObjectReader, private static final String DEFAULT_ADMIN = "admin"; private static final String DEFAULT_ADMIN_PASSWORD = "admin"; private static final String DEFAULT_ADMIN_ROLE = UserLevel.NETWORKADMIN.toString(); - private static final String ROOT = GlobalConstants.STARTUPHOME.toString(); - private static final String USERS_FILE_NAME = ROOT + "users.conf"; - private static final String SERVERS_FILE_NAME = ROOT + "servers.conf"; - private static final String AUTH_FILE_NAME = ROOT + "authorization.conf"; - private static final String RECOVERY_FILE = ROOT + "NETWORK_ADMIN_PASSWORD_RECOVERY"; + private static final String USERS_FILE_NAME = "users.conf"; + private static final String SERVERS_FILE_NAME = "servers.conf"; + private static final String AUTH_FILE_NAME = "authorization.conf"; + private static final String RECOVERY_FILE = "NETWORK_ADMIN_PASSWORD_RECOVERY"; + private static final boolean DISALLOW_DEFAULT_ADMIN_PASSWORD = + Boolean.getBoolean("usermanager.disable-default-admin-password"); private ConcurrentMap localUserConfigList; private ConcurrentMap remoteServerConfigList; // local authorization info for remotely authenticated users @@ -88,6 +90,7 @@ public class UserManager implements IUserManager, IObjectReader, private ConcurrentMap activeUsers; private ConcurrentMap authProviders; private IClusterGlobalServices clusterGlobalService = null; + private IConfigurationService configurationService; private SecurityContextRepository securityContextRepo = new UserSecurityContextRepository(); private IContainerAuthorization containerAuthorizationClient; private Set applicationAuthorizationClients; @@ -96,8 +99,8 @@ public class UserManager implements IUserManager, IObjectReader, ADD("add", "added"), MODIFY("modify", "modified"), REMOVE("remove", "removed"); - private String action; - private String postAction; + private final String action; + private final String postAction; private Command(String action, String postAction) { this.action = action; this.postAction = postAction; @@ -204,57 +207,103 @@ public class UserManager implements IUserManager, IObjectReader, /* * Do not load local startup file if we are not the coordinator */ - if ((clusterGlobalService != null) && (clusterGlobalService.amICoordinator())) { - loadUserConfig(); - loadServerConfig(); - loadAuthConfig(); - } + loadUserConfig(); + loadServerConfig(); + loadAuthConfig(); } private void loadSecurityKeys() { } - private void checkDefaultNetworkAdmin() { - /* - * If startup config is not there, it's old or it was deleted or if a - * password recovery was run, need to add Default Network Admin User - */ - if (!localUserConfigList.containsKey(DEFAULT_ADMIN)) { - List roles = new ArrayList(1); - roles.add(DEFAULT_ADMIN_ROLE); - // Need to skip the strong password check for the default admin - UserConfig defaultAdmin = UserConfig.getUncheckedUserConfig(UserManager.DEFAULT_ADMIN, - UserManager.DEFAULT_ADMIN_PASSWORD, roles); - localUserConfigList.put(UserManager.DEFAULT_ADMIN, defaultAdmin); + private void checkDefaultNetworkAdmin(String newPass) { + boolean usingFactoryPassword = false; + // network admin already configured. + if (localUserConfigList.containsKey(DEFAULT_ADMIN)) { + UserConfig uc = localUserConfigList.get(DEFAULT_ADMIN); + if (!uc.isPasswordMatch(DEFAULT_ADMIN_PASSWORD)) { + return; + } else { + usingFactoryPassword = true; + } + } + + List defaultRoles = new ArrayList(1); + defaultRoles.add(DEFAULT_ADMIN_ROLE); + if (newPass == null) { + if (!localUserConfigList.containsKey(DEFAULT_ADMIN)) { + // Need to skip the strong password check for the default admin + UserConfig defaultAdmin = UserConfig.getUncheckedUserConfig( + UserManager.DEFAULT_ADMIN, UserManager.DEFAULT_ADMIN_PASSWORD, + defaultRoles); + localUserConfigList.put(UserManager.DEFAULT_ADMIN, defaultAdmin); + usingFactoryPassword = true; + } + } else { + // use new password for admin + Status status = UserConfig.validateClearTextPassword(newPass); + if (status.isSuccess()) { + localUserConfigList.put(UserManager.DEFAULT_ADMIN, + new UserConfig(UserManager.DEFAULT_ADMIN, newPass, defaultRoles)); + logger.trace("Network Adminstrator password is reset."); + if (newPass.equals(DEFAULT_ADMIN_PASSWORD)) { + usingFactoryPassword = true; + } + } else { + logger.warn("Password is invalid - {}. Network Adminstrator password " + + "cannot be set.", status.getDescription()); + } + } + + if (usingFactoryPassword) { + if (DISALLOW_DEFAULT_ADMIN_PASSWORD) { + logger.warn("Network Administrator factory default password " + + "is disallowed. Please set the password prior to starting " + + "the controller. Shutting down now."); + // shutdown osgi + try { + BundleContext bundleContext = FrameworkUtil.getBundle( + getClass()).getBundleContext(); + bundleContext.getBundle(0).stop(); + } catch (BundleException e) { + logger.warn("Cannot stop framework ", e); + } + } else { + logger.warn("Network Administrator password is set to factory default. " + + "Please change the password as soon as possible."); + } } } - private void checkPasswordRecovery() { + private String checkPasswordRecovery() { final String fileDescription = "Default Network Administrator password recovery file"; + File recoveryFile = new File(UserManager.RECOVERY_FILE); + if (!recoveryFile.exists()) return null; + // read the recovery file + String pwd = null; try { - FileInputStream fis = new FileInputStream(UserManager.RECOVERY_FILE); + BufferedReader reader = new BufferedReader(new FileReader(recoveryFile)); + // read password from recovery file if it has one + pwd = reader.readLine(); + if (pwd != null && pwd.trim().length() == 0) { + pwd = null; + } + reader.close(); /* * Recovery file detected, remove current default network * administrator entry from local users configuration list. * Warn user and delete recovery file. */ this.localUserConfigList.remove(UserManager.DEFAULT_ADMIN); - logger.info("Default Network Administrator password has been reset to factory default."); - logger.info("Please change the default Network Administrator password as soon as possible"); - File filePointer = new File(UserManager.RECOVERY_FILE); - boolean status = filePointer.delete(); - if (!status) { + if (!recoveryFile.delete()) { logger.warn("Failed to delete {}", fileDescription); } else { logger.trace("{} deleted", fileDescription); } - fis.close(); - } catch (FileNotFoundException fnf) { - logger.trace("{} not present", fileDescription); } catch (IOException e) { - logger.warn("Failed to close file stream for {}", fileDescription); + logger.warn("Failed to process file {}", fileDescription); } + return pwd; } @Override @@ -276,18 +325,18 @@ public class UserManager implements IUserManager, IObjectReader, rcResponse = aaaClient.authService(userName, password, aaaServer.getAddress(), aaaServer.getSecret()); if (rcResponse.getStatus() == AuthResultEnum.AUTH_ACCEPT) { - logger.info( + logger.trace( "Remote Authentication Succeeded for User: \"{}\", by Server: {}", userName, aaaServer.getAddress()); remotelyAuthenticated = true; break; } else if (rcResponse.getStatus() == AuthResultEnum.AUTH_REJECT) { - logger.info( + logger.trace( "Remote Authentication Rejected User: \"{}\", from Server: {}, Reason:{}", new Object[] { userName, aaaServer.getAddress(), rcResponse.getStatus().toString() }); } else { - logger.info( + logger.trace( "Remote Authentication Failed for User: \"{}\", from Server: {}, Reason:{}", new Object[] { userName, aaaServer.getAddress(), rcResponse.getStatus().toString() }); @@ -298,20 +347,20 @@ public class UserManager implements IUserManager, IObjectReader, if (!remotelyAuthenticated) { UserConfig localUser = this.localUserConfigList.get(userName); if (localUser == null) { - logger.info( + logger.trace( "Local Authentication Failed for User:\"{}\", Reason: " + "user not found in Local Database", userName); return (AuthResultEnum.AUTH_INVALID_LOC_USER); } rcResponse = localUser.authenticate(password); if (rcResponse.getStatus() != AuthResultEnum.AUTH_ACCEPT_LOC) { - logger.info( + logger.trace( "Local Authentication Failed for User: \"{}\", Reason: {}", userName, rcResponse.getStatus().toString()); return (rcResponse.getStatus()); } - logger.info("Local Authentication Succeeded for User: \"{}\"", + logger.trace("Local Authentication Succeeded for User: \"{}\"", userName); } @@ -339,16 +388,16 @@ public class UserManager implements IUserManager, IObjectReader, * data to the rcResponse */ if (remotelyAuthenticated && !authorizationInfoIsPresent) { - logger.info( + logger.trace( "No Remote Authorization Info provided by Server for User: \"{}\"", userName); - logger.info( + logger.trace( "Looking for Local Authorization Info for User: \"{}\"", userName); AuthorizationConfig resource = authorizationConfList.get(userName); if (resource != null) { - logger.info("Found Local Authorization Info for User: \"{}\"", + logger.trace("Found Local Authorization Info for User: \"{}\"", userName); attributes = resource.getRolesString(); @@ -365,7 +414,7 @@ public class UserManager implements IUserManager, IObjectReader, result.setRoleList(attributes.split(" ")); authorized = true; } else { - logger.info("Not able to find Authorization Info for User: \"{}\"", + logger.trace("Not able to find Authorization Info for User: \"{}\"", userName); } @@ -374,10 +423,10 @@ public class UserManager implements IUserManager, IObjectReader, */ putUserInActiveList(userName, result); if (authorized) { - logger.info("User \"{}\" authorized for the following role(s): {}", + logger.trace("User \"{}\" authorized for the following role(s): {}", userName, result.getUserRoles()); } else { - logger.info("User \"{}\" Not Authorized for any role ", userName); + logger.trace("User \"{}\" Not Authorized for any role ", userName); } return rcResponse.getStatus(); @@ -408,9 +457,8 @@ public class UserManager implements IUserManager, IObjectReader, } private Status saveLocalUserListInternal() { - ObjectWriter objWriter = new ObjectWriter(); - return objWriter.write(new ConcurrentHashMap( - localUserConfigList), USERS_FILE_NAME); + return configurationService.persistConfiguration( + new ArrayList(localUserConfigList.values()), USERS_FILE_NAME); } @Override @@ -419,9 +467,8 @@ public class UserManager implements IUserManager, IObjectReader, } private Status saveAAAServerListInternal() { - ObjectWriter objWriter = new ObjectWriter(); - return objWriter.write(new ConcurrentHashMap( - remoteServerConfigList), SERVERS_FILE_NAME); + return configurationService.persistConfiguration( + new ArrayList(remoteServerConfigList.values()), SERVERS_FILE_NAME); } @Override @@ -430,10 +477,8 @@ public class UserManager implements IUserManager, IObjectReader, } private Status saveAuthorizationListInternal() { - ObjectWriter objWriter = new ObjectWriter(); - return objWriter.write( - new ConcurrentHashMap( - authorizationConfList), AUTH_FILE_NAME); + return configurationService.persistConfiguration( + new ArrayList(authorizationConfList.values()), AUTH_FILE_NAME); } @Override @@ -444,48 +489,21 @@ public class UserManager implements IUserManager, IObjectReader, return ois.readObject(); } - @SuppressWarnings("unchecked") private void loadUserConfig() { - ObjectReader objReader = new ObjectReader(); - ConcurrentMap confList = (ConcurrentMap) objReader - .read(this, USERS_FILE_NAME); - - if (confList == null) { - return; - } - - for (UserConfig conf : confList.values()) { - addRemoveLocalUserInternal(conf, false); + for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, USERS_FILE_NAME)) { + addRemoveLocalUserInternal((UserConfig) conf, false); } } - @SuppressWarnings("unchecked") private void loadServerConfig() { - ObjectReader objReader = new ObjectReader(); - ConcurrentMap confList = (ConcurrentMap) objReader - .read(this, SERVERS_FILE_NAME); - - if (confList == null) { - return; - } - - for (ServerConfig conf : confList.values()) { - addAAAServer(conf); + for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, SERVERS_FILE_NAME)) { + addAAAServer((ServerConfig) conf); } } - @SuppressWarnings("unchecked") private void loadAuthConfig() { - ObjectReader objReader = new ObjectReader(); - ConcurrentMap confList = (ConcurrentMap) objReader - .read(this, AUTH_FILE_NAME); - - if (confList == null) { - return; - } - - for (AuthorizationConfig conf : confList.values()) { - addAuthInfo(conf); + for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, AUTH_FILE_NAME)) { + addAuthInfo((AuthorizationConfig) conf); } } @@ -684,7 +702,7 @@ public class UserManager implements IUserManager, IObjectReader, // Trigger cluster update localUserConfigList.put(user, targetConfigEntry); - logger.info("Password changed for User \"{}\"", user); + logger.trace("Password changed for User \"{}\"", user); return status; } @@ -694,7 +712,7 @@ public class UserManager implements IUserManager, IObjectReader, // TODO: if user was authenticated through AAA server, send // Acct-Status-Type=stop message to server with logout as reason removeUserFromActiveList(userName); - logger.info("User \"{}\" logged out", userName); + logger.trace("User \"{}\" logged out", userName); } /* @@ -705,7 +723,7 @@ public class UserManager implements IUserManager, IObjectReader, // TODO: if user was authenticated through AAA server, send // Acct-Status-Type=stop message to server with timeout as reason removeUserFromActiveList(userName); - logger.info("User \"{}\" timed out", userName); + logger.trace("User \"{}\" timed out", userName); } @Override @@ -817,6 +835,16 @@ public class UserManager implements IUserManager, IObjectReader, } } + public void setConfigurationService(IConfigurationService service) { + logger.trace("Got configuration service set request {}", service); + this.configurationService = service; + } + + public void unsetConfigurationService(IConfigurationService service) { + logger.trace("Got configuration service UNset request"); + this.configurationService = null; + } + void unsetContainerAuthClient(IContainerAuthorization s) { if (this.containerAuthorizationClient == s) { this.containerAuthorizationClient = null; @@ -867,10 +895,10 @@ public class UserManager implements IUserManager, IObjectReader, loadConfigurations(); // Check if a password recovery was triggered for default network admin user - checkPasswordRecovery(); + String pwd = checkPasswordRecovery(); // Make sure default Network Admin account is there - checkDefaultNetworkAdmin(); + checkDefaultNetworkAdmin(pwd); BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext(); bundleContext.registerService(CommandProvider.class.getName(), this, null);