Last Updated: 7/7/2021 6:41:10 PM
Sample Code
The samples demonstrate how to interact with CSPI by sending an HTTP request along
with
authentication headers. Before you use CSPI, you should have received a pair of Secret
Key and
Access Token, credentials that will help CSPI recognize you as a valid integrating
partner of
Trend Micro.
After implementation, you can go to Check if your
x-signature is correct.
Python
cspi_connection.py
import base64
import calendar
import hashlib
import hmac
import httplib
import time
import uuid
class CSPIConnection(object):
def __init__(self, access_token, secret_key, hostname, port, timeout=30):
self.access_token = access_token
self.secret_key = secret_key
self.hostname = hostname
self.port = port
self.timeout = timeout
self.connect()
def __del__(self):
self.close()
def connect(self):
if int(self.port) == 443:
self.conn = httplib.HTTPSConnection(self.hostname, self.port,
timeout=self.timeout)
else:
self.conn = httplib.HTTPConnection(self.hostname, self.port,
timeout=self.timeout)
def send_request(self, http_method, request_uri, body=None):
'''
Send request to access CSPI
'''
headers = get_auth_headers(self.access_token, self.secret_key,
http_method, request_uri, body)
self.conn.request(http_method, request_uri, body, headers)
resp = self.conn.getresponse()
return (resp.status, resp.read())
def close(self):
self.conn.close()
def get_auth_headers(access_token, secret_key, method, request_uri, body):
'''
Generate authentication herders
'''
posix_time = calendar.timegm(time.gmtime())
headers = {}
headers["content-type"] = "application/json"
headers["x-access-token"] = access_token
headers["x-signature"] = \
gen_x_signature(secret_key, str(posix_time),
method, request_uri, body)
headers["x-posix-time"] = posix_time
headers["x-traceid"] = str(uuid.uuid4())
return headers
def gen_x_signature(secret_key, x_posix_time, request_method, request_uri,
body):
'''
Generate x-signature
'''
payload = x_posix_time + request_method.upper() + request_uri
if body:
payload += get_content_md5(body)
hm = hmac.new(secret_key.encode("utf8"),
payload.encode("utf8"), hashlib.sha256)
digest = hm.digest()
digest = base64.b64encode(digest)
return digest
def get_content_md5(content):
'''
Get hashed content
'''
m = hashlib.md5()
m.update(content)
digest = m.digest()
digest = base64.b64encode(digest)
return digest
The following code shows you how to access CSPI using CSPIConnection. For example,
we call Me
:: Service Plans :: list to list all your configured service plans.
import json
from cspi_connection import CSPIConnection
ACCESS_TOKEN = "c137ff67-c53d-4c91-9e84-81025a721ca2" # Your access token
SECRET_KEY = "L/HXx2y1RpIE94Zx2EikeCtkO7G+Y6Qibk7uNd5llRU=" # Your secret key
CSPI_SERVER_HOSTNAME = "cspi.trendmicro.com"
CSPI_SERVER_PORT = "443"
if __name__ == '__main__':
cspi_conn = CSPIConnection(ACCESS_TOKEN, SECRET_KEY,
CSPI_SERVER_HOSTNAME, CSPI_SERVER_PORT)
# Example to call GET /LMPI/v2/me/serviceplans
method = "GET"
request_uri = "/LMPI/v2/me/serviceplans"
res_status, res_data = cspi_conn.send_request(method, request_uri)
print "Response status: \n%s", res_status
print "Response data: \n%s", res_data
# Example to call PUT /SMPI/v2/service/wfbss/api/global_settings?cids=640FE47F-5118-4D79-8221-A35D0DE2EE2C
method = "PUT"
request_uri = "/SMPI/v2/service/wfbss/api/global_settings?cids=640FE47F-5118-4D79-8221-A35D0DE2EE2C"
content = {
"replicate_from": {
"cid": "A9CC5A34-3CAD-480D-A9ED-87656316D3B9"
}
}
body = json.dumps(content)
res_status, res_data = cspi_conn.send_request(method, request_uri, body=body)
print "Response status: \n%s", res_status
print "Response data: \n%s", res_data
C#
cspi_auth-headers.cs
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
public static string ACCESS_TOKEN = "c137ff67-c53d-4c91-9e84-81025a721ca2";
public static string SECRET_KEY = "L/HXx2y1RpIE94Zx2EikeCtkO7G+Y6Qibk7uNd5llRU=";
static void Main(string[] args)
{
string scheme = "https";
string host = "Path.To.LMPI";
string uri = "/LMPI/v2/me/serviceplans";
long posixTime = GetPosixTime();
string httpMethod = "GET";
string jsonContent = "";
//Get Test(Care the different of payload with other HTTPMethod)
SendRequest(scheme, host, uri, posixTime, httpMethod, jsonContent);
Console.ReadLine();
uri = "/LMPI/v2/me/users/69f07401-1ccc-4c77-9607-043956a73f1c";
posixTime = GetPosixTime();
httpMethod = "PUT";
jsonContent = "{\"address\":\"865 Green Street\"}";
//Other Test
SendRequest(scheme, host, uri, posixTime, httpMethod, jsonContent);
Console.ReadLine();
}
public static void SendRequest(string scheme, string host, string uri, long posixTime, string httpMethod, string jsonContent)
{
byte[] contentBytes = null;
bool isGet = string.Equals(httpMethod, "GET", StringComparison.OrdinalIgnoreCase);
if (isGet == false)
{
contentBytes = Encoding.UTF8.GetBytes(jsonContent);
}
string signature = GenerateSignature(SECRET_KEY, posixTime, httpMethod, uri, contentBytes);
// Create the web request and headers.
var request = (HttpWebRequest)WebRequest.Create(scheme + "://" + host + uri);
request.ContentType = "application/json; charset=utf-8";
request.Method = httpMethod;
request.Headers.Add("x-access-token", ACCESS_TOKEN);
request.Headers.Add("x-posix-time", posixTime.ToString());
request.Headers.Add("x-signature", signature);
request.Headers.Add("x-traceid", Guid.NewGuid().ToString());
// Set the content length in the request headers
request.ContentLength = isGet ? 0 : contentBytes.Length;
// Write data
if (isGet == false)
{
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(contentBytes, 0, contentBytes.Length);
}
}
// Get response
try
{
using (var response = (HttpWebResponse)request.GetResponse())
{
// Get the response stream
var reader = new StreamReader(response.GetResponseStream());
// Console application output
Console.WriteLine("HTTP " + (int)response.StatusCode + " " + response.StatusCode);
Console.WriteLine("\nResponse Content:");
var responseContent = reader.ReadToEnd();
Console.WriteLine(responseContent);
}
}
catch (WebException we)
{
Console.WriteLine(we);
// Get the error response stream
HttpWebResponse webResponse = (HttpWebResponse)we.Response;
var reader = new StreamReader(webResponse.GetResponseStream());
// Console application output
Console.WriteLine("HTTP " + (int)webResponse.StatusCode + " " + webResponse.StatusCode);
Console.WriteLine("\nResponse Content:");
var responseContent = reader.ReadToEnd();
Console.WriteLine(responseContent);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static long GetPosixTime()
{
return ((long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
}
///
/// Generate a x-signature header value that's required to invoke LMPI api interface
///
///The secrect key used to hash
///Number of secods after 1970-01-01 til now
///HTTP method used to invoke LMPI
///
/// the requiesting Uri without server host. The request uri should be precent-encoded
///
///http request content in binary. Pass in null if no content is to be sent to server
///a hexstring of HMAC-SHA256 hashed value will be assigned to this parameter
///Base64 string encoded x-signature
public static string GenerateSignature(string secret, long unixTimestamp, string method, string requestUri, byte[] content)
{
var posix = unixTimestamp.ToString();
var payload = posix + method.ToUpper() + requestUri + ((content == null) ? "" : CalculateMD5Hash(content));
HMAC hash = new HMACSHA256();
hash.Initialize();
hash.Key = Encoding.UTF8.GetBytes(secret);
var byteArr = hash.ComputeHash(Encoding.UTF8.GetBytes(payload));
return Convert.ToBase64String(byteArr);
}
///
/// Calculates MD5 Hash of a binary and return it as a base64 string.
///
///binary to be calculated
/// MD5 hashed string result in Base64
public static string CalculateMD5Hash(byte[] input)
{
// step 1, calculate MD5 hash from input
MD5 md5 = MD5.Create();
byte[] hash = md5.ComputeHash(input);
return Convert.ToBase64String(hash);
}
}
}
Java
APITest.java
import java.io.*;
import java.net.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
/**
* This example uses Apache HttpClient 4.x library to invoke REST API call. Please refer to:
* http://hc.apache.org/httpcomponents-client-ga/index.html
*
*/
public class APITest
{
// use the access_token and secret_key that's been assigned to you
public static String ACCESS_TOKEN = "c137ff67-c53d-4c91-9e84-81025a721ca2";
public static String SECRET_KEY = "L/HXx2y1RpIE94Zx2EikeCtkO7G+Y6Qibk7uNd5llRU=";
/**
* @param args
*/
public static void main(String[] args) {
long posix;
URIBuilder builder = new URIBuilder();
String httpMethod;
String jsonContent;
try{
//Get
posix = getPosixTime();
builder.setScheme("https")
.setHost("Path.To.LMPI")
.setPath("/LMPI/v2/me/serviceplans");
httpMethod = "GET";
jsonContent = null;
requestAPI(posix, builder, httpMethod, jsonContent);
//Put
posix = getPosixTime();
builder.setScheme("https")
.setHost("Path.To.LMPI")
.setPath("/LMPI/v2/me/users/69f07401-1ccc-4c77-9607-043956a73f1c");
httpMethod = "PUT";
jsonContent = "{\"address\":\"865 Green Street\"}";
requestAPI(posix, builder, httpMethod, jsonContent);
}catch(URISyntaxException e1){
System.out.println(e1.toString());
}catch(UnsupportedEncodingException e2){
System.out.println(e2.toString());
}
}
private static long getPosixTime() {
return new Date().getTime() / 1000L;
}
/**
* Generate a x-signature header value that is required to invoke LMPI
* @param secret The secret key assigned by Trend Micro
* @param unixTimestamp The x-posix-time attribute specified in header, it is suppose to the request time in unix timestamp format.
* @param method The HTTP method that is used to invoke LMPI
* @param uri The absolute uri being requested. The url should url-encoded that is similar to something like:
* /customers?name=some%20customer%20name
* @param content The HTTP content that is to be hashed, pass null if there's no content to be hashed.
* @return a SHA-256 hashed digest in Base64 string.
*/
public static String GenerateSignature(String secret, long unixTimestamp,
String method, String uri, byte[] content)
{
MessageDigest md = null;
String posix = String.valueOf(unixTimestamp);
String payload = posix + method.toUpperCase() + uri;
String contentBase64 = "";
// Create a MD5 hash of content if not null.
if(content != null){
try {
md = MessageDigest.getInstance("MD5");
md.update(content);
contentBase64 = Base64.encodeBase64String(md.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
payload += contentBase64;
}
try{
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256");
hmac.init(secret_key);
byte[] hashed = hmac.doFinal(payload.getBytes("UTF-8"));
return new Base64().encodeAsString(hashed);
}catch(Exception ex){
System.out.println("unable to create message hash." + ex.toString());
}
return null;
}
public static void requestAPI(long posix, URIBuilder builder, String httpMethod, String jsonContent)
throws URISyntaxException, UnsupportedEncodingException
{
HttpClient httpClient = HttpClientBuilder.create().build();
// build requesting URI
URI uri = builder.build();
// prepare HTTP Post object
HttpRequestBase op;
if (httpMethod == null) throw new NullPointerException("HttpMethod cna't be null");
httpMethod = httpMethod.toUpperCase();
if (httpMethod.equals("GET")) {
op = new HttpGet(uri);
} else if (httpMethod.equals("DELETE")) {
op = new HttpDelete(uri);
} else {
HttpEntityEnclosingRequestBase requestBase = null;
if (httpMethod.equals("PUT")) {
requestBase = new HttpPut(uri);
} else if (httpMethod.equals("POST")) {
requestBase = new HttpPost(uri);
} else {
throw new UnsupportedOperationException("HttpMethod must be GET, POST, POST or DELETE");
}
// prepare content
StringEntity entity = new StringEntity(jsonContent);
requestBase.setEntity(entity);
op = requestBase;
}
op.addHeader("x-access-token", ACCESS_TOKEN);
op.addHeader("x-signature",
GenerateSignature(SECRET_KEY, posix, httpMethod, uri.getPath(), jsonContent == null ? null : jsonContent.getBytes("UTF-8")));
op.addHeader("x-posix-time", String.valueOf(posix));
op.addHeader("x-traceid", UUID.randomUUID().toString());
op.addHeader("content-type", "application/json;charset=UTF-8");
// Receive response
try{
HttpResponse response = httpClient.execute(op);
String responseContent = EntityUtils.toString(response.getEntity());
System.out.println("Response status: " + response.getStatusLine());
System.out.println("Response content: " + responseContent);
} catch (ClientProtocolException e) {
System.out.println(e.toString());
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
Check if your x-signature is correct.
1.
Access token: c137ff67-c53d-4c91-9e84-81025a721ca2
Secert key: L/HXx2y1RpIE94Zx2EikeCtkO7G+Y6Qibk7uNd5llRU=
Request Method: GET
Request Path: /LMPI/v2/me/serviceplans
Request Body: No request body
POSIX time: 1446422400
The correct x-signature shoule be: CXhBs89svBoyWh7QPns+7vjbGlH1a4h8gi35ePW/adc=
Therefore, the HTTP header will look like:
x-access-token: c137ff67-c53d-4c91-9e84-81025a721ca2
x-posix-time: 1446422400
x-signature: CXhBs89svBoyWh7QPns+7vjbGlH1a4h8gi35ePW/adc=
x-traceid: 975f9ce9-f509-4842-8c2e-9f0b1f27e1b3
content-type: application/json
2.
Request Method: PUT
Request Path: /SMPI/v2/service/wfbss/api/global_settings?cids=640FE47F-5118-4D79-8221-A35D0DE2EE2C
Request Body:
{
"replicate_from": {
"cid": "A9CC5A34-3CAD-480D-A9ED-87656316D3B9"
}
}
POSIX time: 1446422400
The correct x-signature shoule be: Tmy4RlR65zN9UPvTdZncN23R2EZqMgmE3Ry3FFrDDsg=
Therefore, the HTTP header will look like:
x-access-token: c137ff67-c53d-4c91-9e84-81025a721ca2
x-posix-time: 1446422400
x-signature: Tmy4RlR65zN9UPvTdZncN23R2EZqMgmE3Ry3FFrDDsg=
x-traceid: 975f9ce9-f509-4842-8c2e-9f0b1f27e1b3
content-type: application/json
