Last Updated: 7/5/2021 12:10:13 AM
Sample Code
The samples demonstrate how to interact with SMPI by sending an https request along with authentication headers. Before you use SMPI, you should have applied a pair of Secret Key and Access Token, credentials that will help SMPI recognize you as a valid integrating partner of Trend Micro. For the guide of applying API credential, please refer to Invoking SMPI.
After implementation, you can go to Check if your signature is correct.
Python
smpi_connection.py
import base64
import calendar
import hashlib
import hmac
import httplib
import time
import uuid
class SMPIConnection(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 SMPI
'''
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 SMPI using SMPIConnection. For example, we call GET /SMPI/service/wfbss/api/customers to list all the WFBSS customers.
import json
from smpi_connection import SMPIConnection
ACCESS_TOKEN = "<em>c137ff67-c53d-4c91-9e84-81025a721ca2</em>" # Your access token
SECRET_KEY = "<em>L/HXx2y1RpIE94Zx2EikeCtkO7G+Y6Qibk7uNd5llRU=</em>" # Your secret key
CSPI_SERVER_HOSTNAME = "smpi-nabu.sco.trendmicro.com" # SMPI URL
CSPI_SERVER_PORT = "443"
if __name__ == '__main__':
smpi_conn = SMPIConnection(ACCESS_TOKEN, SECRET_KEY,
SMPI_SERVER_HOSTNAME, SMPI_SERVER_PORT)
# Example to call GET /SMPI/service/wfbss/api/customers
method = "GET"
request_uri = "/SMPI/service/wfbss/api/customers"
res_status, res_data = smpi_conn.send_request(method, request_uri)
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 = "SMPI_URL";
string uri = "/SMPI/service/wfbss/api/customers";
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();
}
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("SMPI_URL")
.setPath("/SMPI/service/wfbss/api/customers");
httpMethod = "GET";
jsonContent = null;
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: /SMPI/service/wfbss/api/customers
Request Body: No request body
POSIX time: 1446422400
The correct x-signature shoule be:
Therefore, the HTTP header will look like: 6mU4SfJzos4ZaEGticXUYnNCwNr85dCyfbpMyLcQGiI=
x-access-token: c137ff67-c53d-4c91-9e84-81025a721ca2
x-posix-time: 1446422400
x-signature: 6mU4SfJzos4ZaEGticXUYnNCwNr85dCyfbpMyLcQGiI=
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
