forked from apache/cloudstack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUserCloudAPIExecutor.java
More file actions
188 lines (166 loc) · 7.05 KB
/
UserCloudAPIExecutor.java
File metadata and controls
188 lines (166 loc) · 7.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.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.codec.binary.Base64;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
/**
*
*
*
*
*
*
*
*
*
*/
/**
* 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
*
*
*/
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.encodeBase64String(encryptedBytes), "UTF-8");
} catch (Exception ex) {
System.out.println(ex);
}
return null;
}
}