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