
If you want to send data from NodeJS application to Log Analytics/Sentinel you can do it by using the HTTP Log Collector API.

Note: If your app is in Azure PaaS solution, you should check out AppInsights first before going to this route 🙂
Writing module for the Log Collector API
There we’re some existing examples to do this, but I couldn’t get them to work in quick breeze. Due to this I did my own implementation with some key differences:
Signature generation part is done in two phases to improve readability
- Basically I separated the creation of buffer shared key to base64 into an separate variable (var)
Function is bit different with callbacks and try catch logic added
Request Module will handle the Body Payload as non stringified
I did find, that If I sent the body payload stringified, it wouldnt match with the signature. To get the signature to match with the body payload, I added the request option json:true, and sent the non-stringified JSON payload.
The module to be imported
//https://nodejs.org/api/crypto.html //https://docs.microsoft.com/en-us/azure/azure-monitor/platform/data-collector-api //https://stackoverflow.com/questions/44532530/encoding-encrypting-the-azure-log-analytics-authorization-header-in-node-js const rq = require('request') const crypto = require('crypto') const util = require('util') function PushToAzureLogs (content,{id,key,rfc1123date,LogType}, callback) { console.log(id) try { //Checking if the data can be parsed as JSON if ( JSON.parse(JSON.stringify(content)) ) { var length = Buffer.byteLength(JSON.stringify(content),'utf8') var binaryKey = Buffer.from(key,'base64') var stringToSign = 'POST\n' + length + '\napplication/json\nx-ms-date:' + rfc1123date + '\n/api/logs'; //console.log(stringToSign) var hash = crypto.createHmac('sha256',binaryKey) .update(stringToSign,'utf8') .digest('base64') var authorization = "SharedKey "+id +":"+hash var options= { json:true, headers:{ "content-type": "application/json", "authorization":authorization, "Log-Type":LogType, "x-ms-date":rfc1123date, "time-generated-field":"DateValue" }, body:content } var uri = "https://"+ id + ".ods.opinsights.azure.com/api/logs?api-version=2016-04-01" rq.post(uri,options,(err,Response) => { //return if error inside try catch block if (err) { return callback(("Not data sent to LA: " + err)) } callback(("Data sent to LA " +util.inspect(content) + "with status code " + Response.statusCode)) }) } //Catch error if data cant be parsed as JSON } catch (err) { callback(("Not data sent to LA: " + err)) } } module.exports={PushToAzureLogs}
Example from ExpressJS
//Add your other dependencies before this const logs = require('./SRC/laws') //define workspace details const laws = { id:'yourID', key:'yourKey', rfc1123date:(new Date).toUTCString(), LogType:'yourLogType' } app.get('/graph', (request,response) => { //not related to LA, this the data I am sending to LA var token = mods.readToken('rt').access_token mods.apiCall(token,'https://graph.microsoft.com/v1.0/me?$select=displayName,givenName,onPremisesSamAccountName', (data) => { console.log('reading graph', data) //LA object jsonObject = { WAFCaller:request.hostname, identity:data.displayName, datasource:request.ip } console.log(jsonObject) //send data to LA logs.PushToAzureLogs(jsonObject,laws,(data)=> { console.log(data) }) //return original response response.send(data) }) })
Once the data is sent, it will take about 5-10 minutes, for the first entries to be popping up


If /when you attach the Log Analytics workspace to Sentinel, you can then use it create your own hunting queries, and combine the data you have with TI-feeds etc

Happy hunting!
0 comments on “NodeJS Logging integration with Azure Log Analytics/Sentinel”