Calling Azure Log Analytics Log Collector API with SmartApp

I’m trying to call the Azure Log Analytics Log Collector API with a SmartThings Smart App, however I keep on getting a 403/forbidden, and now I’m stuck after battling with this for a week or so. Can anyone see any obvious mistakes I’ve made in the code? Thanks very much in advance… been stuck on this for about 2 weeks and I’m at my wits end…

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import biz.source_code.base64Coder.Base64Coder
import groovyx.net.http.ContentType

//Update customer Id to your OMS workspace ID
def customer_id() {return “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”}
def shared_key() {return “xxxxxxxxxxxxxxxxxxxxxxxxxxx”}
def log_type() {return “SmartThings_test”}
def content_type() {return ‘application/json’}

def GetUTCDateNow() {return new Date().format("MM/dd/yyyy'T'HH:mm:ss.SSS'Z'")}
def rfc1123date() {return new Date().format("E, dd MMM yyyy HH':'mm':'ss 'GMT'")}   

// Build & send request to POST API
def Date getNowUTC(){
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone(“UTC”));
System.out.println(cal.toString());
Date now = cal.getTime();
return now;
}

def hmac_sha256(String secretKey, String data) {
try {
Mac mac = Mac.getInstance(“HmacSHA256”)
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), “HmacSHA256”)
mac.init(secretKeySpec)
byte digest = mac.doFinal(data.getBytes())
return digest
} catch (InvalidKeyException e) {
throw new RuntimeException(“Invalid key exception while converting to HMac SHA256”)
log.debug “Invalid key exception while converting to HMac SHA256”
}
}

def build_signature(customer_id, shared_key, date, content_length, content_type){
def x_headers = “x-ms-date:” + date
def method = “POST”
def escapechar = “\n”
def string_to_hash = method + escapechar + content_length.toString() + escapechar + content_type + escapechar + x_headers + escapechar + “/api/logs”
def bytes_to_hash = string_to_hash.getBytes(“UTF-8”)
def decoded_key = shared_key.decodeBase64()
def hmac = hmac_sha256(decoded_key.toString(), string_to_hash.toString())
def encoded_hash = hmac.encodeBase64()
def authorization = "SharedKey " + customer_id + “:” + encoded_hash
return authorization}

def sendEvent(sensorId, sensorName, sensorType, value) {
def cleanedSensorId= sensorId.replace(" ", “”)
def strBody = “{ sensorId : "${cleanedSensorId}", sensorName : "${sensorName}", sensorType : "${sensorType}", value : "${value}" }”
def content_length = strBody.length()
def signature = build_signature(customer_id(), shared_key(), rfc1123date(), content_length, content_type())
def apiURI = “https://” + customer_id() + “.ods.opinsights.azure.com/api/logs?api-version=2016-04-01”

log.info "uri: " + apiURI
log.info "Body: " + strBody
log.info "content_length: " + content_length
log.info "signature: " + signature

  def params = [
    uri: apiURI,
    contentType: "application/json",
        headers: ["Authorization": signature, 
                "Log-Type": log_type(), 
                "x-ms-date": rfc1123date()],
    body: strBody
]

log.info "Params:: " + params

try {
    httpPost(params) { resp ->
        log.debug "response data: ${resp.data}"
        log.debug "response contentType: ${resp.contentType}"
    }
} catch (e) {
    log.debug "something went wrong: $e"
}

}
sendEvent(‘test’,‘test’,‘test’,1)

Anyone got any ideas?

Did you ever find a solution? I’d love to hook this up as well.

Hi, I don’t know a lot about this, but I did find this gentleman wrote a cool app that takes information from SmartThings and uploads it to an Azure Event Hub Namespace/Event Hub. Then he uses an Azure Function to log it to Cosmos DB to do some neat things with PowerBI. Not sure if that’s helpful at all to you.

Here’s his GitHub for his functions…