- Introduction
- Deployment
- Configuration
- OS Support
- Integration
- 42. Amazon Web Services (AWS)
- 43. Apache HTTP Server
- 44. Apache Tomcat
- 45. APC Automatic Transfer Switch
- 46. Apple macOS kernel
- 47. ArcSight Common Event Format (CEF)
- 48. Box
- 49. Brocade Switches
- 50. Browser History Logs
- 51. Check Point
- 52. Cisco ACS
- 53. Cisco ASA
- 54. Cisco FireSIGHT
- 55. Cisco IPS
- 56. Cloud Instance Metadata
- 57. Common Event Expression (CEE)
- 58. Dell EqualLogic
- 59. Dell iDRAC
- 60. Dell PowerVault MD Series
- 61. Devo
- 62. DHCP logs
- 63. DNS Monitoring
- 64. Docker
- 65. Elasticsearch and Kibana
- 66. F5 BIG-IP
- 67. File Integrity Monitoring
- 68. FreeRADIUS
- 69. Graylog
- 70. HP ProCurve
- 71. IBM QRadar SIEM
- 72. Industrial Control Systems
- 73. Linux Audit System
- 74. Linux system logs
- 75. Log Event Extended Format (LEEF)
- 76. McAfee Enterprise Security Manager (ESM)
- 77. McAfee ePolicy Orchestrator
- 78. Microsoft Active Directory Domain Controller
- 79. Microsoft Azure
- 80. Microsoft Azure Event Hubs
- 81. Microsoft Azure Sentinel
- 82. Microsoft Exchange
- 83. Microsoft IIS
- 84. Microsoft SharePoint
- 85. Microsoft SQL Server
- 86. Microsoft System Center Endpoint Protection
- 87. Microsoft System Center Configuration Manager
- 88. Microsoft System Center Operations Manager
- 89. MongoDB
- 90. Nagios Log Server
- 91. Nessus Vulnerability Scanner
- 92. NetApp
- 93. .NET application logs
- 94. Nginx
- 95. Okta
- 96. Osquery
- 97. Postfix
- 98. Promise
- 99. Rapid7 InsightIDR SIEM
- 100. RSA NetWitness
- 101. SafeNet KeySecure
- 102. Salesforce
- 103. Snare
- 104. Snort
- 105. Solarwinds Loggly
- 106. Splunk
- 107. Sumo Logic
- 108. Symantec Endpoint Protection
- 109. Synology DiskStation
- 110. Syslog
- 111. Sysmon
- 112. Ubiquiti UniFi
- 113. VMware vCenter
- 114. Windows AppLocker
- 115. Windows Command Line Auditing
- 116. Windows Event Log
- 117. Windows Firewall
- 118. Windows Group Policy
- 119. Windows Management Instrumentation (WMI)
- 120. Windows PowerShell
- 121. Microsoft Windows Update
- 122. Windows USB auditing
- 123. Zeek (formerly Bro) Network Security Monitor
- Troubleshooting
- Enterprise Edition Reference Manual
- NXLog Manager
- NXLog Add-Ons
81. Microsoft Azure Sentinel
Azure Sentinel is Microsoft’s security information event management (SIEM), which is offered as service within Azure. Because of its presence within Azure and close integration with other Azure services, Microsoft refers to Azure Sentinel as "a scalable, cloud-native, and security orchestration automated response (SOAR) solution." NXLog can be configured as an agent for Azure Sentinel, collecting and forwarding logs to its Azure Log Analytics workspaces. For more information about Azure Sentinel, see Microsoft’s Azure Sentinel documentation.
81.1. Sending custom logs to Azure Sentinel
81.1.1. Prerequisites
In order to send any type of logs to Azure Sentinel from NXLog, a few prerequisites need to be met.
-
A subscription to Microsoft Azure
-
A Azure Log Analytics workspace in the Azure portal
-
Contributor permissions to the subscription in which the Azure Sentinel workspace resides
-
Enabling Azure Sentinel if it is not already activated
-
For Linux-based agents, the NXLog Perl package needs to be loaded.
Note
|
Failure to install the NXLog Perl package for Debian/Ubuntu will result in the following error message:
See the Packages in a Debian/Ubuntu Archive table for details about installing individual packages. |
81.1.2. Creating the HTTP POST request
The first step in preparing to send log events from NXLog via the REST API is retrieving the Workspace ID and either the Primary key or the Secondary key (referred to as the shared key in most of the code examples in the Authorization section of the HTTP Data Collector API). These keys can be found by navigating in the Azure portal to Log Analytics workspace > Settings > Agents management. The same set of keys can be viewed under either the Windows servers or Linux servers tab.

Since the Azure Monitor authentication system does not use static tokens, a dynamically-generated, hashed string that can only be generated programmatically with cryptographic libraries is required for each HTTP request. As such, the following Perl script has been developed for use with the Perl (xm_perl) module which needs to be located relative to the agent’s NXLog installation directory as follows:
- Linux
-
%INSTALLDIR%/lib/nxlog/modules/extension/perl/sentinelauth.pl
#!/usr/bin/perl
use strict;
use warnings;
use Log::Nxlog;
use MIME::Base64;
use Digest::SHA qw(hmac_sha256);
BEGIN {
# Statements to be executed when NXLog starts
}
# This subroutine is invoked in nxlog.conf as follows:
#
# Exec {instance_name}->call("genauth");
#
# where {instance_name} is the actual intance name defined for
# the xm_perl module, e.g.: perl->call("genauth");
#
sub genauth {
my ($event) = @_;
my $contentLength = Log::Nxlog::get_field($event,'ContentLength');
my $x_ms_date = Log::Nxlog::get_field($event,'x_ms_date');
my $workspace = Log::Nxlog::get_field($event,'Workspace');
my $sharedKey = Log::Nxlog::get_field($event,'SharedKey');
my $contentType = 'application/json';
my $resource = '/api/logs';
my $stringToSign = "POST\n"
. $contentLength ."\n"
. $contentType ."\n"
. 'x-ms-date:'.$x_ms_date ."\n"
. $resource;
my $decodedSharedKey = decode_base64($sharedKey);
my $hashedString = hmac_sha256($stringToSign,$decodedSharedKey);
my $hashedStringBase64 = encode_base64($hashedString,"");
my $authorization = "SharedKey $workspace:$hashedStringBase64";
my $logMessage =
"Generated from Shared Key and hashed signing string based on:
ContentLength: $contentLength
x-ms-date: $x_ms_date
Authorization: $authorization";
Log::Nxlog::set_field_string($event,'Authorization',$authorization);
Log::Nxlog::log_info($logMessage);
}
- Windows
-
%INSTALLDIR%\modules\extension\perl\sentinelauth.pl
use lib 'c:\Program Files\nxlog\data';
use strict;
use warnings;
use Log::Nxlog;
use MIME::Base64;
use Digest::SHA qw(hmac_sha256);
BEGIN {
# Statements to be executed when NXLog starts
}
# This subroutine is invoked in nxlog.conf as follows:
#
# Exec {instance_name}->call("genauth");
#
# where {instance_name} is the actual intance name defined for
# the xm_perl module, e.g.: perl->call("genauth");
#
sub genauth {
my ($event) = @_;
my $contentLength = Log::Nxlog::get_field($event,'ContentLength');
my $x_ms_date = Log::Nxlog::get_field($event,'x_ms_date');
my $workspace = Log::Nxlog::get_field($event,'Workspace');
my $sharedKey = Log::Nxlog::get_field($event,'SharedKey');
my $contentType = 'application/json';
my $resource = '/api/logs';
my $stringToSign = "POST\n"
. $contentLength ."\n"
. $contentType ."\n"
. 'x-ms-date:'.$x_ms_date ."\n"
. $resource;
my $decodedSharedKey = decode_base64($sharedKey);
my $hashedString = hmac_sha256($stringToSign,$decodedSharedKey);
my $hashedStringBase64 = encode_base64($hashedString,"");
my $authorization = "SharedKey $workspace:$hashedStringBase64";
my $logMessage =
"Generated from Shared Key and hashed signing string based on:
ContentLength: $contentLength
x-ms-date: $x_ms_date
Authorization: $authorization";
Log::Nxlog::set_field_string($event,'Authorization',$authorization);
Log::Nxlog::log_info($logMessage);
}
Note
|
The line in the script which defines
|
From this script it is readily apparent that the hashed part of the authorization string will vary according to the following:
-
Timestamp when the input string is hashed:
$x_ms_date
-
Payload size of the JSON data being transmitted:
$contentLength
The keys needed by the hashing algorithm are passed to the sentinelauth.pl
Perl script via the NXLog configuration as demonstrated in the
following example.
In this example, the NXLog Linux Audit System im_linuxaudit module is used as the event source. However, basically any event source that has been captured and converted to JSON format can be forwarded to Azure Sentinel once the correct keys have been defined in a configuration similar to the one featured below.
Please note that the first (opening) line of the Input
block defines the name
of this instance as LinuxAudit
. This is the name that will be used for the
Azure Sentinel table where these events will be collected.
The xm_resolver module is needed for the ResolveValues
directive in the audit
input instance, where it is used for resolving some of
the numeric values to human readable string values.
The first five define
directives establish the constants needed for
constructing
the REST API’s URL, resource, and the keys needed for authorization.
The define SIZELIMIT 65000
directive sets the maximum payload size in bytes
to the HTTP(s) (om_http) module limit. This enables batch forwarding of multiple
events to minimize the number of HTTP connections needed for forwarding events
to Azure Sentinel.
The xm_perl plxm
instance provides access to the requisite hashing
algorithm for generating the Authorization
header string.
The om_http
module contructs the HTTP request and uses three
add_http_header() procedure calls to set the custom headers.
The second add_http_header() procedure call defines the table,
$SourceModuleName
, to which the events will be forwarded within Azure
Sentinel’s set of Custom Tables. In this case, the input instance’s name is
LinuxAudit
. Azure automatically appends _CL
to all Custom Tables thus the
table will appear as LinuxAudit_CL
in the list of Custom Tables.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<Extension _json>
Module xm_json
</Extension>
<Extension _resolver>
Module xm_resolver
</Extension>
<Input LinuxAudit>
Module im_linuxaudit
FlowControl FALSE
LoadRule "src/docs/topics/high-availability/snippets/im_linuxaudit.rules"
ResolveValues TRUE
Exec to_json();
</Input>
define WORKSPACE 18fb21ab-d8d4-4448-bdf6-3748c9c03135
define SHAREDKEY VfIQqBoz6fxmnI/E4PKVPza2clH/YAdJ20RnCDwzHCqCMnobYdM1/dD1+KJ6cI6AkR4xPJlTIWI/jfwPU6QHmw==
define SUBDOMAIN ods.opinsights.azure.com
define RESOURCE api/logs
define APIVER api-version=2016-04-01
define SIZELIMIT 65000
<Extension plxm>
Module xm_perl
PerlCode %INSTALLDIR%/lib/nxlog/modules/extension/perl/sentinelauth.pl
</Extension>
<Output AzureHTTP>
Module om_http
URL https://%WORKSPACE%.%SUBDOMAIN%/%RESOURCE%?%APIVER%
ContentType application/json
HTTPSAllowUntrusted TRUE
HTTPSCAFile /etc/ssl/certs/ca-certificates.crt
<Exec>
create_stat('ec', 'COUNT');
create_stat('bc', 'COUNT');
create_var('batch');
create_var('nextbatch');
add_stat('ec',1);
#---BEGIN--- the enrichment of this event with any new fields:
$BatchNumber = get_stat('bc');
$EventNumber = get_stat('ec');
to_json();
#---END--- the enrichment of this event
if (size(get_var('batch')) + size($raw_event) + 3) > %SIZELIMIT%
# Flush this batch of events
{
set_var('nextbatch', $raw_event);
$raw_event = '[' + get_var('batch') + ']';
add_stat('bc',1);
set_var('batch',get_var('nextbatch'));
$Workspace = "%WORKSPACE%";
$SharedKey = "%SHAREDKEY%";
$ContentLength = string(size($raw_event));
$dts = strftime(now(),'YYYY-MM-DDThh:mm:ssUTC');
$dts_no_tz = replace($dts,'Z','');
$parsedate_utc_false = parsedate($dts_no_tz,FALSE);
$x_ms_date = strftime($parsedate_utc_false, '%a, %d %b %Y %T GMT');
plxm->call("genauth");
add_http_header('Authorization',$authorization);
add_http_header('Log-Type',$SourceModuleName);
add_http_header('x-ms-date',$x_ms_date);
}
else
{
$delimiter = get_stat('ec') == 1 ? '' : ",\n";
set_var('batch', get_var('batch') + $delimiter + $raw_event);
drop();
}
</Exec>
</Output>
The following JSON event was triggered and captured according to a Linux Audit
rule. In this instance, a rules file is defined by the
LoadRule directive in the audit
input
instance shown above.
{
"type": "PATH",
"time": "2020-09-09T01:44:47.783000+00:00",
"seq": 40649,
"item": 1,
"name": "/etc/bind/zones/db.example.com",
"inode": 528911,
"dev": "fc:02",
"mode": "file,644",
"ouid": "root",
"ogid": "bind",
"rdev": "00:00",
"nametype": "CREATE",
"cap_fp": "0",
"cap_fi": "0",
"cap_fe": "0",
"cap_fver": "0",
"cap_frootid": "0",
"EventReceivedTime": "2020-09-09T01:44:47.797048+00:00",
"SourceModuleName": "LinuxAudit",
"SourceModuleType": "im_linuxaudit"
}
Upon successful receipt in the Log Analytics workspace by Azure Monitor, events are further processed and finally ingested by Azure Sentinel where they can be viewed via user-defined queries.

After expanding the following event to reveal its columns and their values, it can be verified against the JSON formatted event above that was sent via the REST API:

In this example, NXLog collects DNS logs via ETW from the
Microsoft-Windows-DNSServer
provider using the Event Tracing for Windows (im_etw) module. The
collected logs are converted to JSON so that Azure Sentinel can parse and
ingest them.
As illustrated in the previous example, basically any log source that has
been captured and converted to JSON format can be forwarded to Azure Sentinel
once the correct keys have been defined in a configuration similar to the one
featured below.
Please note that the first (opening) line of the Input
block defines the name
of this instance as DNS_Logs
. This is the name that will be used for the
Azure Sentinel table where these events will be collected.
The first five define
directives establish the constants needed for
constructing the REST API’s URL, resource, and the keys needed for
authorization.
The define SIZELIMIT 65000
directive sets the maximum payload size in bytes
to the HTTP(s) (om_http) module limit. This enables batch forwarding of multiple
events to minimize the number of HTTP connections needed for forwarding events
to Azure Sentinel.
The xm_perl plxm
instance provides access to the requisite hashing
algorithm for generating the Authorization
header string.
The om_http
module contructs the HTTP request and uses three
add_http_header() procedure calls to set the custom headers.
The second add_http_header() procedure call defines the table,
$SourceModuleName
, to which the events will be forwarded within Azure
Sentinel’s set of Custom Tables. In this case, the input instance’s name is
DNS_Logs
. Azure automatically appends _CL
to all Custom Tables thus the
table will appear as DNS_Logs_CL
in the list of Custom Tables.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<Extension _json>
Module xm_json
</Extension>
<Input DNS_Logs>
Module im_etw
Provider Microsoft-Windows-DNSServer
Exec to_json();
</Input>
define WORKSPACE 18fb21ab-d8d4-4448-bdf6-3748c9c03135
define SHAREDKEY VfIQqBoz6fxmnI/E4PKVPza2clH/YAdJ20RnCDwzHCqCMnobYdM1/dD1+KJ6cI6AkR4xPJlTIWI/jfwPU6QHmw==
define SUBDOMAIN ods.opinsights.azure.com
define RESOURCE api/logs
define APIVER api-version=2016-04-01
define SIZELIMIT 65000
<Extension plxm>
Module xm_perl
PerlCode %INSTALLDIR%\modules\extension\perl\sentinelauth.pl
</Extension>
<Output AzureHTTP>
Module om_http
URL https://%WORKSPACE%.%SUBDOMAIN%/%RESOURCE%?%APIVER%
ContentType application/json
HTTPSAllowUntrusted TRUE
HTTPSCAFile %INSTALLDIR%\cert\ca-certificates.crt
<Exec>
create_stat('ec', 'COUNT');
create_stat('bc', 'COUNT');
create_var('batch');
create_var('nextbatch');
add_stat('ec',1);
#---BEGIN--- the enrichment of this event with any new fields:
$BatchNumber = get_stat('bc');
$EventNumber = get_stat('ec');
to_json();
#---END--- the enrichment of this event
if (size(get_var('batch')) + size($raw_event) + 3) > %SIZELIMIT%
# Flush this batch of events
{
set_var('nextbatch', $raw_event);
$raw_event = '[' + get_var('batch') + ']';
add_stat('bc',1);
set_var('batch',get_var('nextbatch'));
$Workspace = "%WORKSPACE%";
$SharedKey = "%SHAREDKEY%";
$ContentLength = string(size($raw_event));
$dts = strftime(now(),'YYYY-MM-DDThh:mm:ssUTC');
$dts_no_tz = replace($dts,'Z','');
$parsedate_utc_false = parsedate($dts_no_tz,FALSE);
$x_ms_date = strftime($parsedate_utc_false, '%a, %d %b %Y %T GMT');
plxm->call("genauth");
add_http_header('Authorization',$authorization);
add_http_header('Log-Type',$SourceModuleName);
add_http_header('x-ms-date',$x_ms_date);
}
else
{
$delimiter = get_stat('ec') == 1 ? '' : ",\n";
set_var('batch', get_var('batch') + $delimiter + $raw_event);
drop();
}
</Exec>
</Output>
The following event is typical of Windows DNS Server Audit events captured by
the im_etw module. Based on
EventId 516
logged for this particular event, it is evident that a DNS zone record in the
example.com
domain was deleted.
{
"SourceName": "Microsoft-Windows-DNSServer",
"ProviderGuid": "{EB79061A-A566-4698-9119-3ED2807060E7}",
"EventId": 516,
"Version": 0,
"ChannelID": 17,
"OpcodeValue": 0,
"TaskValue": 5,
"Keywords": "4611686018428436480",
"EventTime": "2020-09-09T21:34:21.600556-05:00",
"ExecutionProcessID": 1784,
"ExecutionThreadID": 4056,
"EventType": "INFO",
"SeverityValue": 2,
"Severity": "INFO",
"Domain": "WIN-FFMCPAJ76HP",
"AccountName": "Administrator",
"UserID": "S-1-5-21-1830054504-3820897498-340727717-500",
"AccountType": "User",
"Flags": "EXTENDED_INFO|IS_64_BIT_HEADER|PROCESSOR_INDEX (577)",
"Type": "1",
"NAME": "u18s1.example.com",
"TTL": "0",
"BufferSize": "4",
"RDATA": "0xC0A80119",
"Zone": "example.com",
"ZoneScope": "Default",
"VirtualizationID": ".",
"EventReceivedTime": "2020-09-09T21:34:23.634177-05:00",
"SourceModuleName": "DNS_Logs",
"SourceModuleType": "im_etw"
}
Upon successful receipt in the
Log Analytics workspace
by Azure Monitor,
events are further processed and finally ingested by Azure Sentinel
where they can be viewed via user-defined queries. Querying for events having
a value of 516
for EventId
yields the following list. The second one has
the same NAME
as the example above: u18s1.example.com
.

After expanding the following event to reveal its columns and their values, it can be verified against the JSON formatted event above that was sent via the REST API:


81.2. Supported platforms
Sending custom logs directly to Azure Sentinel is currently supported only on Linux and Microsoft Windows platforms. Support for AIX and macOS will be coming in a future release. In the meantime, it is still possible to forward log events from these non-supported operating systems through another NXLog agent on Linux or Windows that is configured to communicate with Azure Sentinel.
81.2.1. Forwarding BSM audit logs from macOS to Azure Sentinel
NXLog supports capturing kernel audit logs on macOS with the Basic Security Module Auditing (im_bsm) module. The following example illustrates a typical configuration.
This configuration reads BSM audit events directly from the kernel via the
(default) /dev/auditpipe
device. The output instance toAzureHTTPforwarder
sends the events to the remote Linux NXLog agent listening on TCP port
1514 where they will be routed without any additional processing to Azure
Sentinel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Extension _json>
Module xm_json
</Extension>
<Input BSMmacOS>
Module im_bsm
DeviceFile /dev/auditpipe
Exec to_json();
</Input>
<Output toAzureHTTPforwarder>
Module om_tcp
Host mas-relay-1.example.com:1514
</Output>
The following JSON sample illustrates a typical kernel audit event captured using this configuration.
{
"TokenVersion": "11",
"EventType": "AUE_ssauthorize",
"EventName": "SecSrvr AuthEngine",
"EventModifier": "",
"EventTime": "2020-12-16 18:20:15",
"SubjectAuditID": "ruser2",
"SubjectUID": "ruser2",
"SubjectGID": "staff",
"SubjectRealUID": "ruser2",
"SubjectRealGID": "staff",
"SubjectPID": "2793",
"SubjectSID": "100041",
"SubjectTerminal": "",
"SubjectTerminal.Port": "0:5486",
"SubjectTerminal.Host": "0.0.0.0",
"Text": "creator /System/Library/CoreServices/Setup Assistant.app",
"ReturnErrno": "failure: Operation not permitted",
"ReturnRetval": "-60007",
"Identity": "",
"Identity.SignerType": "1",
"Identity.SignerId": "com.apple.authd",
"Identity.SignerIdTruncated": "0",
"Identity.TeamId": "",
"Identity.TeamIdTruncated": "0",
"Identity.CDHash": "0x9120b9dcb969ee1e8fbdb63bd428e263111e9e9c",
"TrailerCount": "305",
"EventReceivedTime": "2020-12-16T18:20:15.360930-08:00",
"SourceModuleName": "BSMmacOS",
"SourceModuleType": "im_bsm"
}
In order for the macOS kernel audit logs to be sent to their own unique Azure
Sentinel table, the SourceModuleName
must be preserved. The value assigned to
SourceModuleName
, i.e. the input module’s instance name,
directly determines the name of the Azure
Sentinel table that will contain the ingested event logs. In this example, the
instance name BSMmacOS
will be used, resulting in BSMmacOS_CL
as the table
name.
The following configuration on the remote Linux host functioning as a log event
forwarder is comprised of the
Linux audit logs to Azure Sentinel configuration
which has been modified and extended to handle not only its own Linux kernel
audit events, but also the macOS kernel audit events it receives. The first
notable change can be seen in lines 9-13 where a new TCP input module instance
fromBSMmacOS
has been defined. This input instance listens for macOS kernel
audit events on TCP port 1514. Since the data being received is already in JSON
format, it is essential that the parse_json()
procedure is executed.
The original output instance (lines 35-80) is generic and could be used to send
both Linux and macOS kernel audit logs to Azure Sentinel were it not for the
self-imposed requirement that each log source should have its own unique Azure
Sentinel table. For this reason, the entire output instance has been duplicated
in lines 82-127. Except for their instance names, LinuxAudit_AzureHTTP
and
BSMmacOS_AzureHTTP
, they are identical.
Finally, the two routes (lines 129-135) ensure that events from each log source remain separate.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<Extension _json>
Module xm_json
</Extension>
<Extension _resolver>
Module xm_resolver
</Extension>
<input fromBSMmacOS>
Module im_tcp
ListenAddr 0.0.0.0:1514
Exec parse_json();
</Input>
<Input LinuxAudit>
Module im_linuxaudit
FlowControl FALSE
LoadRule "src/docs/topics/high-availability/snippets/im_linuxaudit.rules"
ResolveValues TRUE
Exec to_json();
</Input>
define WORKSPACE 18fb21ab-d8d4-4448-bdf6-3748c9c03135
define SHAREDKEY VfIQqBoz6fxmnI/E4PKVPza2clH/YAdJ20RnCDwzHCqCMnobYdM1/dD1+KJ6cI6AkR4xPJlTIWI/jfwPU6QHmw==
define SUBDOMAIN ods.opinsights.azure.com
define RESOURCE api/logs
define APIVER api-version=2016-04-01
define SIZELIMIT 65000
<Extension plxm>
Module xm_perl
PerlCode %INSTALLDIR%/lib/nxlog/modules/extension/perl/sentinelauth.pl
</Extension>
<Output LinuxAudit_AzureHTTP>
Module om_http
URL https://%WORKSPACE%.%SUBDOMAIN%/%RESOURCE%?%APIVER%
ContentType application/json
HTTPSAllowUntrusted TRUE
HTTPSCAFile /etc/ssl/certs/ca-certificates.crt
<Exec>
create_stat('ec', 'COUNT');
create_stat('bc', 'COUNT');
create_var('batch');
create_var('nextbatch');
add_stat('ec',1);
#---BEGIN--- the enrichment of this event with any new fields:
$BatchNumber = get_stat('bc');
$EventNumber = get_stat('ec');
to_json();
#---END--- the enrichment of this event
if (size(get_var('batch')) + size($raw_event) + 3) > %SIZELIMIT%
# Flush this batch of events
{
set_var('nextbatch', $raw_event);
$raw_event = '[' + get_var('batch') + ']';
add_stat('bc',1);
set_var('batch',get_var('nextbatch'));
$Workspace = "%WORKSPACE%";
$SharedKey = "%SHAREDKEY%";
$ContentLength = string(size($raw_event));
$dts = strftime(now(),'YYYY-MM-DDThh:mm:ssUTC');
$dts_no_tz = replace($dts,'Z','');
$parsedate_utc_false = parsedate($dts_no_tz,FALSE);
$x_ms_date = strftime($parsedate_utc_false, '%a, %d %b %Y %T GMT');
plxm->call("genauth");
add_http_header('Authorization',$authorization);
add_http_header('Log-Type',$SourceModuleName);
add_http_header('x-ms-date',$x_ms_date);
}
else
{
$delimiter = get_stat('ec') == 1 ? '' : ",\n";
set_var('batch', get_var('batch') + $delimiter + $raw_event);
drop();
}
</Exec>
</Output>
<Output BSMmacOS_AzureHTTP>
Module om_http
URL https://%WORKSPACE%.%SUBDOMAIN%/%RESOURCE%?%APIVER%
ContentType application/json
HTTPSAllowUntrusted TRUE
HTTPSCAFile /etc/ssl/certs/ca-certificates.crt
<Exec>
create_stat('ec', 'COUNT');
create_stat('bc', 'COUNT');
create_var('batch');
create_var('nextbatch');
add_stat('ec',1);
#---BEGIN--- the enrichment of this event with any new fields:
$BatchNumber = get_stat('bc');
$EventNumber = get_stat('ec');
to_json();
#---END--- the enrichment of this event
if (size(get_var('batch')) + size($raw_event) + 3) > %SIZELIMIT%
# Flush this batch of events
{
set_var('nextbatch', $raw_event);
$raw_event = '[' + get_var('batch') + ']';
add_stat('bc',1);
set_var('batch',get_var('nextbatch'));
$Workspace = "%WORKSPACE%";
$SharedKey = "%SHAREDKEY%";
$ContentLength = string(size($raw_event));
$dts = strftime(now(),'YYYY-MM-DDThh:mm:ssUTC');
$dts_no_tz = replace($dts,'Z','');
$parsedate_utc_false = parsedate($dts_no_tz,FALSE);
$x_ms_date = strftime($parsedate_utc_false, '%a, %d %b %Y %T GMT');
plxm->call("genauth");
add_http_header('Authorization',$authorization);
add_http_header('Log-Type',$SourceModuleName);
add_http_header('x-ms-date',$x_ms_date);
}
else
{
$delimiter = get_stat('ec') == 1 ? '' : ",\n";
set_var('batch', get_var('batch') + $delimiter + $raw_event);
drop();
}
</Exec>
</Output>
<Route BSMmacOS_R>
Path fromBSMmacOS => BSMmacOS_AzureHTTP
</Route>
<Route LinuxAudit_R>
Path LinuxAudit => LinuxAudit_AzureHTTP
</Route>
Upon successful receipt in the Log Analytics workspace by Azure Monitor, macOS kernel audit events are further processed and finally ingested by Azure Sentinel where they can be viewed via user-defined queries.

After expanding the following event to reveal its columns and their values, it can be verified against the JSON formatted event above that was sent via the REST API:

