/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.embedded.ssh.internal;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import de.rcenvironment.core.configuration.ConfigurationException;
import de.rcenvironment.core.configuration.ConfigurationSegment;
import de.rcenvironment.core.embedded.ssh.api.SshAccount;
/**
* Configuration class for the ssh console.
*
* @author Sebastian Holtappels
* @author Robert Mischke
*/
public class SshConfiguration {
protected static final int DEFAULT_PORT = 31005;
protected static final String DEFAULT_HOST = "127.0.0.1"; // conservative default: bind to localhost, not 0.0.0.0
private boolean enabled = false;
private String host;
private int port;
private List<SshAccountImpl> accounts = new ArrayList<>();
private final List<SshAccountRole> roles;
public SshConfiguration() {
host = DEFAULT_HOST;
port = DEFAULT_PORT;
// Create predefined roles
roles = createPredefinedRoles();
}
public SshConfiguration(ConfigurationSegment configurationSegment) throws ConfigurationException, IOException {
// Create predefined roles
roles = createPredefinedRoles();
enabled = configurationSegment.getBoolean("enabled", false);
String oldHostSetting = configurationSegment.getString("host"); // deprecated alias
String newHostSetting = configurationSegment.getString("ip");
if (oldHostSetting != null) {
LogFactory.getLog(getClass()).warn("Deprecated SSH server configuration parameter \"host\" used - use \"ip\" instead");
host = oldHostSetting;
}
if (newHostSetting != null) {
if (oldHostSetting != null) {
LogFactory.getLog(getClass()).error(
"Both \"host\" and \"ip\" settings of SSH server used; ignoring deprecated \"host\" setting");
}
host = newHostSetting;
}
if (host == null) {
host = DEFAULT_HOST;
}
port = configurationSegment.getInteger("port", DEFAULT_PORT);
for (Entry<String, ConfigurationSegment> entry : configurationSegment.listElements("accounts").entrySet()) {
try {
SshAccountImpl account = entry.getValue().mapToObject(SshAccountImpl.class);
account.setLoginName(entry.getKey());
accounts.add(account);
} catch (IOException e) {
throw new ConfigurationException("Error parsing the configuration for account \"" + entry.getKey()
+ "\". The embedded SSH server will not be started.");
}
}
// Check if deprecated "roles" configuration was used.
if (configurationSegment.getSubSegment("roles").isPresentInCurrentConfiguration()) {
LogFactory.getLog(getClass()).warn("Deprecated \"roles\" configuration used. The roles will not be applied. Only "
+ "predefined roles can be used. A list of available roles can be found in the configuration reference or the user guide.");
}
}
private List<SshAccountRole> createPredefinedRoles() {
List<SshAccountRole> predefRoles = new ArrayList<SshAccountRole>();
for (String roleName : SshConstants.PREDEFINED_ROLE_NAMES) {
predefRoles.add(new SshAccountRole(roleName));
}
return predefRoles;
}
/**
* Validates the Configuration-Object. To ensure the server is able to start and there are no security issues like users without a
* password or without a role (if there is no default role).
*
* @param logger - the logger to be used to log
*
* @return true if valid else false
*/
public boolean validateConfiguration(Log logger) {
boolean isValid = true;
// List<SshAccountRole> valRoles = new ArrayList<SshAccountRole>();
List<SshAccountImpl> valUsers = new ArrayList<SshAccountImpl>();
if (host == null || host.isEmpty()) {
logger.warn("SSH server host can not be empty");
}
// sshContactPoint valid
if (port < SshConstants.MIN_PORT_NUMBER || port > SshConstants.MAX_PORT_NUMBER) {
logger.warn("sshContactPoint must be between " + SshConstants.MIN_PORT_NUMBER + " and "
+ SshConstants.MAX_PORT_NUMBER);
isValid = false;
}
/*
* Validation of roles currently not needed, only predefined roles are used. // roles not null if (roles != null &&
* !roles.isEmpty()) { for (SshAccountRole role : roles) { // validate single role isValid = role.validateRole(logger) && isValid;
*
* // distinct role names if (valRoles.contains(role)) { logger.warn("Role names must be distinct. found two roles with name: " +
* role.getRoleName()); isValid = false; } else { valRoles.add(role); } } } else { if (roles == null) { roles = new
* ArrayList<SshAccountRole>(); } List<String> defaultPrivileges = new ArrayList<String>();
* defaultPrivileges.add(SshConstants.DEFAULT_ROLE_PRIVILEGES);
* logger.warn("Warning: Configuration did not include roles. Creating default role with all privileges"); roles.add(new
* SshAccountRole("", new ArrayList<String>())); }
*/
// users not null
if (accounts != null && !accounts.isEmpty()) {
for (SshAccountImpl user : accounts) {
// validate single user
isValid = user.validate(roles, logger) && isValid;
// distinct user names (no empty string values)
if (valUsers.contains(user)) {
logger.warn("User names must be distinct. Found two users with name: " + user.getLoginName());
isValid = false;
} else {
valUsers.add(user);
}
}
} else {
logger.warn("Configuration did not include user definitions. At least one user must be defined.");
isValid = false;
}
if (!isValid) {
logger.error("Embedded SSH server will not be started due to an error in the configuration.");
}
return isValid;
}
// Special Getter and Setter - START
/**
*
* Get a user for a user name.
*
* @param loginName - the name of the user
* @param allowDisabled true if disabled accounts should be returned as well; if false, null is returned for disabled accounts
* @return - the account object for the given name, if matched
*/
public SshAccount getAccountByName(String loginName, boolean allowDisabled) {
SshAccount curUser = null;
for (SshAccount user : accounts) {
if (user.getLoginName().equals(loginName) && (allowDisabled || user.isEnabled())) {
if (curUser != null) {
LogFactory.getLog(getClass()).error(
"Invalid state: more than one SSH account matched for login name '" + loginName + "'! Returning 'null' for safety");
return null;
}
curUser = user;
break;
}
}
return curUser;
}
/**
*
* Get a role for a role name.
*
* @param roleName - the name of the role
* @return - the role for the given name
*/
public SshAccountRole getRoleByName(String roleName) {
SshAccountRole curRole = null;
for (SshAccountRole role : roles) {
if (role.getRoleName().equals(roleName)) {
curRole = role;
break;
}
}
if (curRole == null) {
curRole = getRoleByName(SshConstants.ROLE_NAME_DEFAULT);
}
return curRole;
}
// Special Getter - END
// Getter and Setter - START
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean startSshConsole) {
this.enabled = startSshConsole;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public void setPort(int sshContactPoint) {
this.port = sshContactPoint;
}
public List<SshAccountImpl> getAccounts() {
return accounts;
}
public void setAccounts(List<SshAccountImpl> users) {
this.accounts = users;
}
public List<SshAccountRole> getRoles() {
return roles;
}
// Getter and Setter - END
}