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;
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.StatusCode;
-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;
import org.opendaylight.controller.usermanager.AuthenticatedUser;
import org.opendaylight.controller.usermanager.AuthorizationConfig;
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;
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<String, UserConfig> localUserConfigList;
private ConcurrentMap<String, ServerConfig> remoteServerConfigList;
// local authorization info for remotely authenticated users
private ConcurrentMap<String, AuthenticatedUser> activeUsers;
private ConcurrentMap<String, IAAAProvider> authProviders;
private IClusterGlobalServices clusterGlobalService = null;
+ private IConfigurationService configurationService;
private SecurityContextRepository securityContextRepo = new UserSecurityContextRepository();
private IContainerAuthorization containerAuthorizationClient;
private Set<IResourceAuthorization> applicationAuthorizationClients;
private ISessionManager sessionMgr = new SessionManager();
+ protected enum Command {
+ ADD("add", "added"),
+ MODIFY("modify", "modified"),
+ REMOVE("remove", "removed");
+ private final String action;
+ private final String postAction;
+ private Command(String action, String postAction) {
+ this.action = action;
+ this.postAction = postAction;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public String getPostAction() {
+ return postAction;
+ }
+ }
public boolean addAAAProvider(IAAAProvider provider) {
if (provider == null || provider.getName() == null
private void loadConfigurations() {
// To encode and decode user and server configuration objects
loadSecurityKeys();
-
/*
- * Do not load local startup file if we already got the configurations
- * synced from another cluster node
+ * Do not load local startup file if we are not the coordinator
*/
- if (localUserConfigList.isEmpty()) {
- loadUserConfig();
- }
- if (remoteServerConfigList.isEmpty()) {
- loadServerConfig();
- }
- if (authorizationConfList.isEmpty()) {
- loadAuthConfig();
- }
+ loadUserConfig();
+ loadServerConfig();
+ loadAuthConfig();
}
private void loadSecurityKeys() {
}
- private void checkDefaultNetworkAdmin() {
- // If startup config is not there, it's old or it was deleted,
- // need to add Default Network Admin User
- if (!localUserConfigList.containsKey(DEFAULT_ADMIN)) {
- List<String> roles = new ArrayList<String>(1);
- roles.add(DEFAULT_ADMIN_ROLE);
- localUserConfigList.put(DEFAULT_ADMIN, new UserConfig(DEFAULT_ADMIN, DEFAULT_ADMIN_PASSWORD, roles));
+ 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<String> defaultRoles = new ArrayList<String>(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
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() });
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);
}
* 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();
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);
}
*/
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();
}
private Status saveLocalUserListInternal() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(new ConcurrentHashMap<String, UserConfig>(
- localUserConfigList), USERS_FILE_NAME);
+ return configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(localUserConfigList.values()), USERS_FILE_NAME);
}
@Override
}
private Status saveAAAServerListInternal() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(new ConcurrentHashMap<String, ServerConfig>(
- remoteServerConfigList), SERVERS_FILE_NAME);
+ return configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(remoteServerConfigList.values()), SERVERS_FILE_NAME);
}
@Override
}
private Status saveAuthorizationListInternal() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(
- new ConcurrentHashMap<String, AuthorizationConfig>(
- authorizationConfList), AUTH_FILE_NAME);
+ return configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(authorizationConfList.values()), AUTH_FILE_NAME);
}
@Override
return ois.readObject();
}
- @SuppressWarnings("unchecked")
private void loadUserConfig() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, UserConfig> confList = (ConcurrentMap<String, UserConfig>) 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<String, ServerConfig> confList = (ConcurrentMap<String, ServerConfig>) 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<String, AuthorizationConfig> confList = (ConcurrentMap<String, AuthorizationConfig>) 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);
}
}
/*
* Interaction with GUI START
*/
- private Status addRemoveLocalUser(UserConfig AAAconf, boolean delete) {
+ private Status changeLocalUser(UserConfig AAAconf, Command command) {
// UserConfig Validation check
Status validCheck = AAAconf.validate();
if (!validCheck.isSuccess()) {
// Check default admin user
if (user.equals(UserManager.DEFAULT_ADMIN)) {
- String msg = "Invalid Request: Default Network Admin User cannot be " + ((delete)? "removed" : "added");
+ String msg = String.format("Invalid Request: Default Network Admin User cannot be %s", command.getPostAction());
logger.debug(msg);
return new Status(StatusCode.NOTALLOWED, msg);
}
// Check user presence/conflict
+ UserConfig currentAAAconf = localUserConfigList.get(user);
StatusCode statusCode = null;
String reason = null;
- if (delete && !localUserConfigList.containsKey(user)) {
- reason = "not found";
- statusCode = StatusCode.NOTFOUND;
- } else if (!delete && localUserConfigList.containsKey(user)) {
- reason = "already present";
- statusCode = StatusCode.CONFLICT;
+ switch (command) {
+ case ADD:
+ if (currentAAAconf != null) {
+ reason = "already present";
+ statusCode = StatusCode.CONFLICT;
+ }
+ break;
+ case MODIFY:
+ case REMOVE:
+ if (currentAAAconf == null) {
+ reason = "not found";
+ statusCode = StatusCode.NOTFOUND;
+ }
+ break;
+ default:
+ break;
+
}
if (statusCode != null) {
+ String action = String.format("Failed to %s user %s: ", command.getAction(), user);
String msg = String.format("User %s %s in configuration database", user, reason);
- logger.debug(msg);
+ logger.debug(action + msg);
return new Status(statusCode, msg);
}
- return addRemoveLocalUserInternal(AAAconf, delete);
+ switch (command) {
+ case ADD:
+ return addRemoveLocalUserInternal(AAAconf, false);
+ case MODIFY:
+ addRemoveLocalUserInternal(currentAAAconf, true);
+ return addRemoveLocalUserInternal(AAAconf, false);
+ case REMOVE:
+ return addRemoveLocalUserInternal(AAAconf, true);
+ default:
+ return new Status(StatusCode.INTERNALERROR, "Unknown action");
+ }
}
private Status addRemoveLocalUserInternal(UserConfig AAAconf, boolean delete) {
@Override
public Status addLocalUser(UserConfig AAAconf) {
- return addRemoveLocalUser(AAAconf, false);
+ return changeLocalUser(AAAconf, Command.ADD);
+ }
+
+ @Override
+ public Status modifyLocalUser(UserConfig AAAconf) {
+ return changeLocalUser(AAAconf, Command.MODIFY);
}
@Override
public Status removeLocalUser(UserConfig AAAconf) {
- return addRemoveLocalUser(AAAconf, true);
+ return changeLocalUser(AAAconf, Command.REMOVE);
}
@Override
return new Status(StatusCode.NOTFOUND, "User does not exist");
}
- return addRemoveLocalUser(localUserConfigList.get(userName), true);
+ return changeLocalUser(localUserConfigList.get(userName), Command.REMOVE);
}
@Override
// Trigger cluster update
localUserConfigList.put(user, targetConfigEntry);
- logger.info("Password changed for User \"{}\"", user);
+ logger.trace("Password changed for User \"{}\"", user);
return status;
}
// 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);
}
/*
// 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
}
}
+ 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;
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);