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