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