diff --git a/build/build-cloud.xml b/build/build-cloud.xml
index a40f26126a6..b11abe57254 100755
--- a/build/build-cloud.xml
+++ b/build/build-cloud.xml
@@ -252,25 +252,45 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/com/cloud/storage/VolumeVO.java b/core/src/com/cloud/storage/VolumeVO.java
index 812b6509687..e80a02a6d1d 100755
--- a/core/src/com/cloud/storage/VolumeVO.java
+++ b/core/src/com/cloud/storage/VolumeVO.java
@@ -41,7 +41,7 @@ import com.google.gson.annotations.Expose;
public class VolumeVO implements Volume {
@Id
@TableGenerator(name="volume_sq", table="sequence", pkColumnName="name", valueColumnName="value", pkColumnValue="volume_seq", allocationSize=1)
- @GeneratedValue(strategy=GenerationType.SEQUENCE)
+ @GeneratedValue(strategy=GenerationType.TABLE)
@Column(name="id")
long id;
diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java
index 361aea1d464..18bba6c7603 100644
--- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java
+++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java
@@ -19,7 +19,15 @@
package com.cloud.servlet;
import java.io.IOException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -32,7 +40,10 @@ import com.cloud.host.HostVO;
import com.cloud.server.ManagementServer;
import com.cloud.user.Account;
import com.cloud.user.User;
+import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentLocator;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.encoding.Base64;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
@@ -57,16 +68,29 @@ public class ConsoleProxyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
try {
+ String userId = null;
+ String account = null;
+ Account accountObj = null;
+
+ Map params = new HashMap();
+ params.putAll(req.getParameterMap());
+
HttpSession session = req.getSession(false);
if(session == null) {
- s_logger.info("Invalid web session, reject console/thumbnail access");
- sendResponse(resp, "Access denied. You haven't logged in or your web session has timed out");
- return;
+ if(verifyRequest(params)) {
+ userId = (String)params.get(BaseCmd.Properties.USER_ID.getName())[0];
+ account = (String)params.get(BaseCmd.Properties.ACCOUNT.getName())[0];
+ accountObj = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName())[0];
+ } else {
+ s_logger.info("Invalid web session or API key in request, reject console/thumbnail access");
+ sendResponse(resp, "Access denied. Invalid web session or API key in request");
+ return;
+ }
+ } else {
+ userId = (String)session.getAttribute(BaseCmd.Properties.USER_ID.getName());
+ account = (String)session.getAttribute(BaseCmd.Properties.ACCOUNT.getName());
+ accountObj = (Account)session.getAttribute(BaseCmd.Properties.ACCOUNT_OBJ.getName());
}
-
- String userId = (String)session.getAttribute(BaseCmd.Properties.USER_ID.getName());
- String account = (String)session.getAttribute(BaseCmd.Properties.ACCOUNT.getName());
- Account accountObj = (Account)session.getAttribute(BaseCmd.Properties.ACCOUNT_OBJ.getName());
// Do a sanity check here to make sure the user hasn't already been deleted
if ((userId == null) || (account == null) || (accountObj == null) || !verifyUser(Long.valueOf(userId))) {
@@ -92,7 +116,7 @@ public class ConsoleProxyServlet extends HttpServlet {
return;
}
- if(!checkSessionPermision(req, vmId)) {
+ if(!checkSessionPermision(req, vmId, accountObj)) {
sendResponse(resp, "Permission denied");
return;
}
@@ -106,7 +130,7 @@ public class ConsoleProxyServlet extends HttpServlet {
} catch (Throwable e) {
s_logger.error("Unexepected exception in ConsoleProxyServlet", e);
- sendResponse(resp, "");
+ sendResponse(resp, "Server Internal Error");
}
}
@@ -265,11 +289,8 @@ public class ConsoleProxyServlet extends HttpServlet {
}
}
- private boolean checkSessionPermision(HttpServletRequest req, long vmId) {
+ private boolean checkSessionPermision(HttpServletRequest req, long vmId, Account accountObj) {
- HttpSession session = req.getSession(false);
- Account accountObj = (Account)session.getAttribute("accountobj");
-
VMInstanceVO vm = _ms.findVMInstanceById(vmId);
UserVmVO userVm;
switch(vm.getType())
@@ -321,4 +342,106 @@ public class ConsoleProxyServlet extends HttpServlet {
}
return true;
}
+
+ // copied and modified from ApiServer.java.
+ // TODO need to replace the whole servlet with a API command
+ private boolean verifyRequest(Map requestParameters) {
+ try {
+ String apiKey = null;
+ String secretKey = null;
+ String signature = null;
+ String unsignedRequest = null;
+
+ // - build a request string with sorted params, make sure it's all lowercase
+ // - sign the request, verify the signature is the same
+ List parameterNames = new ArrayList();
+
+ for (Object paramNameObj : requestParameters.keySet()) {
+ parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
+ }
+
+ Collections.sort(parameterNames);
+
+ for (String paramName : parameterNames) {
+ // parameters come as name/value pairs in the form String/String[]
+ String paramValue = ((String[])requestParameters.get(paramName))[0];
+
+ if ("signature".equalsIgnoreCase(paramName)) {
+ signature = paramValue;
+ } else {
+ if ("apikey".equalsIgnoreCase(paramName)) {
+ apiKey = paramValue;
+ }
+
+ if (unsignedRequest == null) {
+ unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
+ } else {
+ unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
+ }
+ }
+ }
+
+
+ // if api/secret key are passed to the parameters
+ if ((signature == null) || (apiKey == null)) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.info("expired session, missing signature, or missing apiKey -- ignoring request...sig: " + signature + ", apiKey: " + apiKey);
+ }
+ return false; // no signature, bad request
+ }
+
+ Transaction txn = Transaction.open(Transaction.CLOUD_DB);
+ txn.close();
+ User user = null;
+ // verify there is a user with this api key
+ Pair userAcctPair = _ms.findUserByApiKey(apiKey);
+ if (userAcctPair == null) {
+ s_logger.info("apiKey does not map to a valid user -- ignoring request, apiKey: " + apiKey);
+ return false;
+ }
+
+ user = userAcctPair.first();
+ Account account = userAcctPair.second();
+
+ if (!user.getState().equals(Account.ACCOUNT_STATE_ENABLED) || !account.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
+ s_logger.info("disabled or locked user accessing the api, userid = " + user.getId() + "; name = " + user.getUsername() + "; state: " + user.getState() + "; accountState: " + account.getState());
+ return false;
+ }
+
+ if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) {
+ requestParameters.put(BaseCmd.Properties.USER_ID.getName(), new String[] { user.getId().toString() });
+ requestParameters.put(BaseCmd.Properties.ACCOUNT.getName(), new String[] { account.getAccountName() });
+ requestParameters.put(BaseCmd.Properties.DOMAIN_ID.getName(), new String[] { account.getDomainId().toString() });
+ requestParameters.put(BaseCmd.Properties.ACCOUNT_OBJ.getName(), new Object[] { account });
+ } else {
+ requestParameters.put(BaseCmd.Properties.USER_ID.getName(), new String[] { user.getId().toString() });
+ requestParameters.put(BaseCmd.Properties.ACCOUNT.getName(), new String[] { account.getAccountName() });
+ requestParameters.put(BaseCmd.Properties.ACCOUNT_OBJ.getName(), new Object[] { account });
+ }
+
+ // verify secret key exists
+ secretKey = user.getSecretKey();
+ if (secretKey == null) {
+ s_logger.info("User does not have a secret key associated with the account -- ignoring request, username: " + user.getUsername());
+ return false;
+ }
+
+ unsignedRequest = unsignedRequest.toLowerCase();
+
+ Mac mac = Mac.getInstance("HmacSHA1");
+ SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
+ mac.init(keySpec);
+ mac.update(unsignedRequest.getBytes());
+ byte[] encryptedBytes = mac.doFinal();
+ String computedSignature = Base64.encodeBytes(encryptedBytes);
+ boolean equalSig = signature.equals(computedSignature);
+ if (!equalSig) {
+ s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
+ }
+ return equalSig;
+ } catch (Exception ex) {
+ s_logger.error("unable to verifty request signature", ex);
+ }
+ return false;
+ }
}
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index c7bab1530fa..beeee83728b 100644
--- a/server/src/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/com/cloud/user/AccountManagerImpl.java
@@ -52,7 +52,7 @@ public class AccountManagerImpl implements AccountManager {
@Inject private VMTemplateDao _templateDao;
@Inject private ResourceLimitDao _resourceLimitDao;
@Inject private ResourceCountDao _resourceCountDao;
- @Inject private final GlobalLock m_resourceCountLock = GlobalLock.getInternLock("resource.count");
+ private final GlobalLock m_resourceCountLock = GlobalLock.getInternLock("resource.count");
AccountVO _systemAccount;
diff --git a/server/src/com/cloud/vm/MauriceMoss.java b/server/src/com/cloud/vm/MauriceMoss.java
index eafefe160d7..2b54c1b90cd 100644
--- a/server/src/com/cloud/vm/MauriceMoss.java
+++ b/server/src/com/cloud/vm/MauriceMoss.java
@@ -36,9 +36,14 @@ public class MauriceMoss implements VmManager {
@Inject private NetworkManager _networkMgr;
@Override
- public VMInstanceVO allocate(VMInstanceVO vm, ServiceOfferingVO serviceOffering, List networkOfferings, List diskOffering, DataCenterVO dc, AccountVO account) {
- _storageMgr.allocateTemplatedVm(vm, template, rootOffering, dataOffering, size, dc, account)
- return null;
+ public VMInstanceVO allocate(VMInstanceVO vm,
+ ServiceOfferingVO serviceOffering,
+ NetworkOfferingVO[] networkOfferings,
+ DiskOfferingVO[] diskOffering,
+ DataCenterVO dc,
+ AccountVO account) {
+
+ return null;
}
@Override