mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 11:52:28 +01:00
Improve console access security with random generated hash key
This commit is contained in:
parent
a0e4b927f0
commit
0653d6d7f6
@ -57,7 +57,10 @@ public interface ConfigurationDao extends GenericDao<ConfigurationVO, String> {
|
||||
* Gets the value for the specified configuration name
|
||||
* @return value
|
||||
*/
|
||||
public String getValue(String name);
|
||||
public String getValue(String name);
|
||||
|
||||
public String getValueAndInitIfNotExist(String name, String initValue);
|
||||
|
||||
|
||||
/**
|
||||
* returns whether or not this is a premium configuration
|
||||
@ -65,5 +68,5 @@ public interface ConfigurationDao extends GenericDao<ConfigurationVO, String> {
|
||||
*/
|
||||
boolean isPremium();
|
||||
|
||||
ConfigurationVO findByName(String name);
|
||||
ConfigurationVO findByName(String name);
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
package com.cloud.configuration.dao;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -29,10 +30,12 @@ import javax.naming.ConfigurationException;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.configuration.ConfigurationVO;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Local(value={ConfigurationDao.class})
|
||||
public class ConfigurationDaoImpl extends GenericDaoBase<ConfigurationVO, String> implements ConfigurationDao {
|
||||
@ -144,7 +147,36 @@ public class ConfigurationDaoImpl extends GenericDaoBase<ConfigurationVO, String
|
||||
ConfigurationVO config = configurations.get(0);
|
||||
String value = config.getValue();
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public String getValueAndInitIfNotExist(String name, String initValue) {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
PreparedStatement stmt = null;
|
||||
PreparedStatement stmtInsert = null;
|
||||
String returnValue = initValue;
|
||||
try {
|
||||
txn.start();
|
||||
stmt = txn.prepareAutoCloseStatement("SELECT value FROM configuration WHERE name=?");
|
||||
stmt.setString(1, name);
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
if(rs != null && rs.next()) {
|
||||
returnValue = rs.getString(1);
|
||||
} else {
|
||||
stmtInsert = txn.prepareAutoCloseStatement("INSERT INTO configuration(instance, name, value, description) VALUES('DEFAULT', ?, ?, '')");
|
||||
stmtInsert.setString(1, name);
|
||||
stmtInsert.setString(2, initValue);
|
||||
if(stmtInsert.executeUpdate() < 1) {
|
||||
throw new CloudRuntimeException("Unable to init configuration variable: " + name);
|
||||
}
|
||||
}
|
||||
txn.commit();
|
||||
return returnValue;
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Unable to update Configuration Value", e);
|
||||
throw new CloudRuntimeException("Unable to init configuration variable: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -191,8 +191,9 @@ public enum Config {
|
||||
CreatePoolsInPod("Hidden", ManagementServer.class, Boolean.class, "xen.create.pools.in.pod", "false", "Should we automatically add XenServers into pools that are inside a Pod", null),
|
||||
CloudIdentifier("Hidden", ManagementServer.class, String.class, "cloud.identifier", null, "A unique identifier for the cloud.", null),
|
||||
SSOKey("Hidden", ManagementServer.class, String.class, "security.singlesignon.key", null, "A Single Sign-On key used for logging into the cloud", null),
|
||||
SSOAuthTolerance("Advanced", ManagementServer.class, Long.class, "security.singlesignon.tolerance.millis", "300000", "The allowable clock difference in milliseconds between when an SSO login request is made and when it is received.", null);
|
||||
|
||||
SSOAuthTolerance("Advanced", ManagementServer.class, Long.class, "security.singlesignon.tolerance.millis", "300000", "The allowable clock difference in milliseconds between when an SSO login request is made and when it is received.", null),
|
||||
HashKey("Hidden", ManagementServer.class, String.class, "security.hash.key", null, "for generic key-ed hash", null);
|
||||
|
||||
private final String _category;
|
||||
private final Class<?> _componentClass;
|
||||
private final Class<?> _type;
|
||||
|
||||
@ -1299,8 +1299,14 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach
|
||||
|
||||
String ticket = ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId());
|
||||
if(!ticket.startsWith(ticketInUrl)) {
|
||||
s_logger.error("Access ticket expired or has been modified. vmId: " + cmd.getVmId());
|
||||
return new ConsoleAccessAuthenticationAnswer(cmd, false);
|
||||
Date now = new Date();
|
||||
// considering of minute round-up
|
||||
String minuteEarlyTicket = ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId(),
|
||||
new Date(now.getTime() - 60*1000));
|
||||
if(!minuteEarlyTicket.startsWith(ticketInUrl)) {
|
||||
s_logger.error("Access ticket expired or has been modified. vmId: " + cmd.getVmId());
|
||||
return new ConsoleAccessAuthenticationAnswer(cmd, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) {
|
||||
|
||||
@ -1047,4 +1047,5 @@ public interface ManagementServer {
|
||||
public List<RemoteAccessVpnVO> searchForRemoteAccessVpns(ListRemoteAccessVpnsCmd cmd);
|
||||
|
||||
public List<VpnUserVO> searchForVpnUsers(ListVpnUsersCmd cmd);
|
||||
public String getHashKey();
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -400,6 +401,7 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
private boolean _networkGroupsEnabled = false;
|
||||
|
||||
private boolean _isHypervisorSnapshotCapable = false;
|
||||
private String _hashKey = null;
|
||||
|
||||
protected ManagementServerImpl() {
|
||||
ComponentLocator locator = ComponentLocator.getLocator(Name);
|
||||
@ -5765,4 +5767,14 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
|
||||
return _vpnUsersDao.search(sc, searchFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHashKey() {
|
||||
// although we may have race conditioning here, database transaction serialization should
|
||||
// give us the same key
|
||||
if(_hashKey == null) {
|
||||
_hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), UUID.randomUUID().toString());
|
||||
}
|
||||
return _hashKey;
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ public class ConsoleProxyServlet extends HttpServlet {
|
||||
private static final int DEFAULT_THUMBNAIL_WIDTH = 144;
|
||||
private static final int DEFAULT_THUMBNAIL_HEIGHT = 110;
|
||||
|
||||
private final ManagementServer _ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name);
|
||||
private final static ManagementServer _ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name);
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
|
||||
@ -298,14 +298,18 @@ public class ConsoleProxyServlet extends HttpServlet {
|
||||
}
|
||||
|
||||
public static String genAccessTicket(String host, String port, String sid, String tag) {
|
||||
return genAccessTicket(host, port, sid, tag, new Date());
|
||||
}
|
||||
|
||||
public static String genAccessTicket(String host, String port, String sid, String tag, Date normalizedHashTime) {
|
||||
String params = "host=" + host + "&port=" + port + "&sid=" + sid + "&tag=" + tag;
|
||||
|
||||
try {
|
||||
Mac mac = Mac.getInstance("HmacSHA1");
|
||||
|
||||
long ts = (new Date()).getTime();
|
||||
long ts = normalizedHashTime.getTime();
|
||||
ts = ts/60000; // round up to 1 minute
|
||||
String secretKey = "cloud.com";
|
||||
String secretKey = _ms.getHashKey();
|
||||
|
||||
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
|
||||
mac.init(keySpec);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user