mirror of https://github.com/apache/cloudstack.git
150 lines
4.3 KiB
Java
150 lines
4.3 KiB
Java
/*
|
|
* Copyright (C) 2011 Citrix Systems, Inc. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package com.cloud.stack;
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
import java.net.URLEncoder;
|
|
import java.security.SignatureException;
|
|
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 org.apache.commons.codec.binary.Base64;
|
|
|
|
/**
|
|
* CloudStackCommand wraps command properties that are being sent to CloudStack
|
|
*
|
|
* @author Kelven Yang
|
|
*/
|
|
public class CloudStackCommand {
|
|
Map<String, String> _params = new HashMap<String, String>();
|
|
|
|
public CloudStackCommand(String cmdName) {
|
|
this(cmdName, "json");
|
|
}
|
|
|
|
public CloudStackCommand(String cmdName, String responseType) {
|
|
_params.put("command", cmdName);
|
|
if(responseType != null)
|
|
_params.put("response", responseType);
|
|
}
|
|
|
|
public CloudStackCommand setParam(String paramName, String paramValue) {
|
|
assert(paramName != null);
|
|
assert(paramValue != null);
|
|
|
|
_params.put(paramName, paramValue);
|
|
return this;
|
|
}
|
|
|
|
public String signCommand(String apiKey, String secretKey) throws SignatureException {
|
|
assert(_params.get("command") != null);
|
|
|
|
List<String> paramNames = new ArrayList<String>();
|
|
for(String paramName : _params.keySet())
|
|
paramNames.add(paramName);
|
|
|
|
paramNames.add("apikey");
|
|
Collections.sort(paramNames);
|
|
|
|
StringBuffer sb = new StringBuffer();
|
|
for(String name : paramNames) {
|
|
String value;
|
|
if("apikey".equals(name))
|
|
value = apiKey;
|
|
else
|
|
value = _params.get(name);
|
|
|
|
assert(value != null);
|
|
|
|
value = urlSafe(value);
|
|
|
|
if(sb.length() == 0) {
|
|
sb.append(name).append("=").append(value);
|
|
} else {
|
|
sb.append("&").append(name).append("=").append(value);
|
|
}
|
|
}
|
|
|
|
String signature = calculateRFC2104HMAC(sb.toString().toLowerCase(), secretKey);
|
|
return composeQueryString(apiKey, signature);
|
|
}
|
|
|
|
private String composeQueryString(String apiKey, String signature) {
|
|
StringBuffer sb = new StringBuffer();
|
|
String name;
|
|
String value;
|
|
|
|
// treat command specially (although not really necessary )
|
|
name = "command";
|
|
value = _params.get(name);
|
|
if(value != null) {
|
|
value = urlSafe(value);
|
|
sb.append(name).append("=").append(value);
|
|
}
|
|
|
|
for(Map.Entry<String, String> entry : _params.entrySet()) {
|
|
name = entry.getKey();
|
|
|
|
if(!"command".equals(name)) {
|
|
value = urlSafe(entry.getValue());
|
|
|
|
if(sb.length() == 0)
|
|
sb.append(name).append("=").append(value);
|
|
else
|
|
sb.append("&").append(name).append("=").append(value);
|
|
}
|
|
}
|
|
|
|
sb.append("&apikey=").append(urlSafe(apiKey));
|
|
sb.append("&signature=").append(urlSafe(signature));
|
|
|
|
return sb.toString();
|
|
}
|
|
|
|
private String calculateRFC2104HMAC( String signIt, String secretKey ) throws SignatureException {
|
|
String result = null;
|
|
try {
|
|
SecretKeySpec key = new SecretKeySpec( secretKey.getBytes(), "HmacSHA1" );
|
|
Mac hmacSha1 = Mac.getInstance( "HmacSHA1" );
|
|
hmacSha1.init( key );
|
|
byte [] rawHmac = hmacSha1.doFinal( signIt.getBytes());
|
|
result = new String( Base64.encodeBase64( rawHmac ));
|
|
} catch( Exception e ) {
|
|
throw new SignatureException( "Failed to generate keyed HMAC on soap request: " + e.getMessage());
|
|
}
|
|
return result.trim();
|
|
}
|
|
|
|
private String urlSafe(String value) {
|
|
try {
|
|
if (value != null)
|
|
return URLEncoder.encode(value, "UTF-8").replaceAll("\\+", "%20");
|
|
else
|
|
return null;
|
|
} catch (UnsupportedEncodingException e) {
|
|
assert(false);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
}
|