mirror of https://github.com/apache/cloudstack.git
195 lines
7.8 KiB
Java
195 lines
7.8 KiB
Java
package com.cloud.sample;
|
|
|
|
import java.io.FileInputStream;
|
|
import java.net.URLEncoder;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.Properties;
|
|
import java.util.StringTokenizer;
|
|
|
|
import javax.crypto.Mac;
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
|
|
import org.apache.commons.httpclient.HttpClient;
|
|
import org.apache.commons.httpclient.HttpMethod;
|
|
import org.apache.commons.httpclient.methods.GetMethod;
|
|
|
|
import com.cloud.utils.encoding.Base64;
|
|
|
|
/**
|
|
* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
|
*
|
|
*
|
|
* This software is licensed under the GNU General Public License v3 or later.
|
|
*
|
|
* It is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or any later version.
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*
|
|
* This software is licensed under the GNU General Public License v3 or later.
|
|
*
|
|
* It is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or any later version.
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see .
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* Sample CloudStack Management User API Executor.
|
|
*
|
|
* Prerequisites: - Edit usercloud.properties to include your host, apiUrl, apiKey, and secretKey - Use ./executeUserAPI.sh to
|
|
* execute this test class
|
|
*
|
|
* @author will
|
|
*
|
|
*/
|
|
public class UserCloudAPIExecutor {
|
|
public static void main(String[] args) {
|
|
// Host
|
|
String host = null;
|
|
|
|
// Fully qualified URL with http(s)://host:port
|
|
String apiUrl = null;
|
|
|
|
// ApiKey and secretKey as given by your CloudStack vendor
|
|
String apiKey = null;
|
|
String secretKey = null;
|
|
|
|
try {
|
|
Properties prop = new Properties();
|
|
prop.load(new FileInputStream("usercloud.properties"));
|
|
|
|
// host
|
|
host = prop.getProperty("host");
|
|
if (host == null) {
|
|
System.out.println("Please specify a valid host in the format of http(s)://:/client/api in your usercloud.properties file.");
|
|
}
|
|
|
|
// apiUrl
|
|
apiUrl = prop.getProperty("apiUrl");
|
|
if (apiUrl == null) {
|
|
System.out.println("Please specify a valid API URL in the format of command=¶m1=¶m2=... in your usercloud.properties file.");
|
|
}
|
|
|
|
// apiKey
|
|
apiKey = prop.getProperty("apiKey");
|
|
if (apiKey == null) {
|
|
System.out.println("Please specify your API Key as provided by your CloudStack vendor in your usercloud.properties file.");
|
|
}
|
|
|
|
// secretKey
|
|
secretKey = prop.getProperty("secretKey");
|
|
if (secretKey == null) {
|
|
System.out.println("Please specify your secret Key as provided by your CloudStack vendor in your usercloud.properties file.");
|
|
}
|
|
|
|
if (apiUrl == null || apiKey == null || secretKey == null) {
|
|
return;
|
|
}
|
|
|
|
System.out.println("Constructing API call to host = '" + host + "' with API command = '" + apiUrl + "' using apiKey = '" + apiKey + "' and secretKey = '" + secretKey + "'");
|
|
|
|
// Step 1: Make sure your APIKey is URL encoded
|
|
String encodedApiKey = URLEncoder.encode(apiKey, "UTF-8");
|
|
|
|
// Step 2: URL encode each parameter value, then sort the parameters and apiKey in
|
|
// alphabetical order, and then toLowerCase all the parameters, parameter values and apiKey.
|
|
// Please note that if any parameters with a '&' as a value will cause this test client to fail since we are using
|
|
// '&' to delimit
|
|
// the string
|
|
List<String> sortedParams = new ArrayList<String>();
|
|
sortedParams.add("apikey=" + encodedApiKey.toLowerCase());
|
|
StringTokenizer st = new StringTokenizer(apiUrl, "&");
|
|
String url = null;
|
|
boolean first = true;
|
|
while (st.hasMoreTokens()) {
|
|
String paramValue = st.nextToken();
|
|
String param = paramValue.substring(0, paramValue.indexOf("="));
|
|
String value = URLEncoder.encode(paramValue.substring(paramValue.indexOf("=") + 1, paramValue.length()), "UTF-8");
|
|
if (first) {
|
|
url = param + "=" + value;
|
|
first = false;
|
|
} else {
|
|
url = url + "&" + param + "=" + value;
|
|
}
|
|
sortedParams.add(param.toLowerCase() + "=" + value.toLowerCase());
|
|
}
|
|
Collections.sort(sortedParams);
|
|
|
|
System.out.println("Sorted Parameters: " + sortedParams);
|
|
|
|
// Step 3: Construct the sorted URL and sign and URL encode the sorted URL with your secret key
|
|
String sortedUrl = null;
|
|
first = true;
|
|
for (String param : sortedParams) {
|
|
if (first) {
|
|
sortedUrl = param;
|
|
first = false;
|
|
} else {
|
|
sortedUrl = sortedUrl + "&" + param;
|
|
}
|
|
}
|
|
System.out.println("sorted URL : " + sortedUrl);
|
|
String encodedSignature = signRequest(sortedUrl, secretKey);
|
|
|
|
// Step 4: Construct the final URL we want to send to the CloudStack Management Server
|
|
// Final result should look like:
|
|
// http(s)://://client/api?&apiKey=&signature=
|
|
String finalUrl = host + "?" + url + "&apiKey=" + apiKey + "&signature=" + encodedSignature;
|
|
System.out.println("final URL : " + finalUrl);
|
|
|
|
// Step 5: Perform a HTTP GET on this URL to execute the command
|
|
HttpClient client = new HttpClient();
|
|
HttpMethod method = new GetMethod(finalUrl);
|
|
int responseCode = client.executeMethod(method);
|
|
if (responseCode == 200) {
|
|
// SUCCESS!
|
|
System.out.println("Successfully executed command");
|
|
} else {
|
|
// FAILED!
|
|
System.out.println("Unable to execute command with response code: " + responseCode);
|
|
}
|
|
|
|
} catch (Throwable t) {
|
|
System.out.println(t);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. Signs a string with a secret key using SHA-1 2. Base64 encode the result 3. URL encode the final result
|
|
*
|
|
* @param request
|
|
* @param key
|
|
* @return
|
|
*/
|
|
public static String signRequest(String request, String key) {
|
|
try {
|
|
Mac mac = Mac.getInstance("HmacSHA1");
|
|
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
|
|
mac.init(keySpec);
|
|
mac.update(request.getBytes());
|
|
byte[] encryptedBytes = mac.doFinal();
|
|
return URLEncoder.encode(Base64.encodeBytes(encryptedBytes), "UTF-8");
|
|
} catch (Exception ex) {
|
|
System.out.println(ex);
|
|
}
|
|
return null;
|
|
}
|
|
}
|