-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
1,047 additions
and
2 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,19 @@ | ||
# SyslogAzureMonitorBridge | ||
Windows Service of Syslog listener and send the messages to Azure Monitor | ||
# SyslogAzureMonitorBridge | ||
Windows Service of Syslog listener and send the messages to Azure Monitor | ||
|
||
 | ||
|
||
## Development environment | ||
Visual Studio, .NET Framework 4.7.2, Windows Service | ||
|
||
## How to install | ||
|
||
### Register as a Windwos Service | ||
in windows command prompt (cmd.exe administrator mode) | ||
sc create SyslogAzureMonitorBridge binpath=<full path name of the SyslogAzureMonitorBridge.exe> | ||
|
||
### Setup your Azure environment | ||
todo: | ||
|
||
### Start the Service | ||
sc start SyslogAzureMonitorBridge |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<configuration> | ||
<startup> | ||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> | ||
</startup> | ||
</configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Converters; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Net.Http; | ||
using System.Net.Http.Headers; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Tono; | ||
|
||
namespace SyslogAzureMonitorBridge | ||
{ | ||
public class AzureUploader | ||
{ | ||
public string WorkspaceID { get; set; } | ||
public string Key1 { get; set; } | ||
public string LogName { get; set; } = "Syslog"; | ||
public Action<string, bool> Logger { get; set; } | ||
|
||
public Func<Queue<SyslogMessageEventArgs>> Messages { get; set; } | ||
|
||
public async Task PorlingMessagesAsync(CancellationToken cancellationToken) | ||
{ | ||
while (cancellationToken.IsCancellationRequested == false) | ||
{ | ||
await Task.Delay(5000, cancellationToken); | ||
|
||
var queue = Messages?.Invoke(); | ||
List<SyslogMessageEventArgs> chunk; | ||
|
||
lock (queue) | ||
{ | ||
chunk = queue.ToList(); | ||
queue.Clear(); | ||
} | ||
if (chunk.Count < 1) | ||
{ | ||
continue; | ||
} | ||
var recs = new List<LogRecord>(); | ||
foreach (var ev in chunk) | ||
{ | ||
// <189>[INSPECT] LAN2[out][101100] TCP 192.168.20.3:54874 > 172.217.25.193:443 (2020/01/23 14:12:42) | ||
// <190>[NAT(1000):LAN2] Released UDP 172.16.20.3.44249 <-> 192.168.20.254.10708 ==> 172.16.20.1.53 | ||
var rec = new LogRecord(); | ||
var pristr = StrUtil.LeftOn(ev.Message, "^<[0-9]+>"); | ||
if (pristr.Length > 2) | ||
{ | ||
// Priority = facility * 8 + severity level ex. 190 = 23*8+6 | ||
var pri = int.Parse(StrUtil.Mid(pristr, 1, pristr.Length - 2)); | ||
rec.Facility = Facilities.GetValueOrDefault(pri / 8, "n/a"); | ||
rec.SeverityLevel = SeverityLevels.GetValueOrDefault(pri % 8, "n/a"); | ||
} | ||
rec.EventTime = ev.EventUtcTime; | ||
rec.HostIP = ev.Remote.Address.ToString(); | ||
rec.HostName = /* Dns.GetHostEntry(ev.Remote.Address)?.HostName ?? */ ev.Remote.Address.ToString(); // Do not use Dns.GetHostEntry because of block 5 seconds each for local IPs. | ||
rec.Computer = rec.HostName; | ||
rec.SyslogMessage = StrUtil.MidSkip(ev.Message, "^<[0-9]+>").TrimStart(' ', '\t', '\r', '\n', '\b'); | ||
recs.Add(rec); | ||
} | ||
var jsonStr = JsonConvert.SerializeObject(recs, new IsoDateTimeConverter()); | ||
var datestring = DateTime.UtcNow.ToString("r"); | ||
var jsonBytes = Encoding.UTF8.GetBytes(jsonStr); | ||
var stringToHash = "POST\n" + jsonBytes.Length + "\napplication/json\n" + "x-ms-date:" + datestring + "\n/api/logs"; | ||
var hashedString = BuildSignature(stringToHash, Key1); | ||
var signature = "SharedKey " + WorkspaceID + ":" + hashedString; | ||
PostData(signature, datestring, jsonStr); | ||
} | ||
} | ||
|
||
public string BuildSignature(string message, string secret) | ||
{ | ||
var encoding = new ASCIIEncoding(); | ||
var keyByte = Convert.FromBase64String(secret); | ||
var messageBytes = encoding.GetBytes(message); | ||
using (var hmacsha256 = new HMACSHA256(keyByte)) | ||
{ | ||
var hash = hmacsha256.ComputeHash(messageBytes); | ||
return Convert.ToBase64String(hash); | ||
} | ||
} | ||
|
||
public void PostData(string signature, string date, string json) | ||
{ | ||
try | ||
{ | ||
var url = "https://" + WorkspaceID + ".ods.opinsights.azure.com/api/logs?api-version=2016-04-01"; | ||
|
||
var client = new HttpClient(); | ||
client.DefaultRequestHeaders.Add("Accept", "application/json"); | ||
client.DefaultRequestHeaders.Add("Log-Type", LogName); | ||
client.DefaultRequestHeaders.Add("Authorization", signature); | ||
client.DefaultRequestHeaders.Add("x-ms-date", date); | ||
client.DefaultRequestHeaders.Add("time-generated-field", ""); | ||
|
||
var httpContent = new StringContent(json, Encoding.UTF8); | ||
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); | ||
var response = client.PostAsync(new Uri(url), httpContent); | ||
|
||
var responseContent = response.Result.Content; | ||
string result = responseContent.ReadAsStringAsync().Result; | ||
} | ||
catch (Exception excep) | ||
{ | ||
Logger?.Invoke("API Post Exception: " + excep.Message, true); | ||
} | ||
} | ||
|
||
public static readonly Dictionary<int, string> Facilities = new Dictionary<int, string> | ||
{ | ||
[0] = "kern", | ||
[1] = "user", | ||
[2] = "mail", | ||
[3] = "daemon", | ||
[4] = "auth", | ||
[5] = "syslog", | ||
[6] = "lpr", | ||
[7] = "news", | ||
[8] = "uucp", | ||
[9] = "cron", | ||
[10] = "authpriv", | ||
[11] = "ftp", | ||
[12] = "ntp", | ||
[13] = "audit", // log audit | ||
[14] = "alert", // log alert | ||
[15] = "clock", // clock daemon | ||
[16] = "local0", | ||
[17] = "local1", | ||
[18] = "local2", | ||
[19] = "local3", | ||
[20] = "local4", | ||
[21] = "local5", | ||
[22] = "local6", | ||
[23] = "local7", | ||
}; | ||
|
||
public static readonly Dictionary<int, string> SeverityLevels = new Dictionary<int, string> | ||
{ | ||
[0] = "emerg", | ||
[1] = "alert", | ||
[2] = "crit", | ||
[3] = "err", | ||
[4] = "warning", | ||
[5] = "notice", | ||
[6] = "info", | ||
[7] = "debug", | ||
}; | ||
|
||
public class LogRecord | ||
{ | ||
public string Facility { get; set; } | ||
public string SeverityLevel { get; set; } | ||
public DateTime EventTime { get; set; } // 2020-01-21T22:33:33Z | ||
public string Computer { get; set; } | ||
public string HostIP { get; set; } | ||
public string HostName { get; set; } | ||
public string SyslogMessage { get; set; } | ||
|
||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
using System; | ||
using System.Configuration.Install; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.ServiceProcess; | ||
|
||
namespace SyslogAzureMonitorBridge | ||
{ | ||
internal static class Program | ||
{ | ||
/// <summary> | ||
/// Program entry point | ||
/// </summary> | ||
/// <param name="args"> | ||
/// ----- | ||
/// /i : Register this service to Windows Service | ||
/// /u : Uninstall this service to Windows Service | ||
/// ----- | ||
/// /n=MySyslog : $table name. ex.MySyslog --> MySyslog_CL | ||
/// /p=514 : Listening port number of syslog | ||
/// /w=12345678-abcd-ef01-2345-123456789012 : Work Space ID of Azure LogAnalytics | ||
/// /k=99aXaEa1C4OXL/EJVBqDH87qF9fHYE4XfGpKnJO/UCPv3xg/n6pAb7k6wSKFE+i40BSRuE0Apo3oP2W8G9nWXr== : Main key (ARM -> LogAnalytics -> Detail -> Connected Sources -> Windows Servers -> Key1 | ||
/// </param> | ||
private static void Main(string[] args) | ||
{ | ||
var service = new SyslogAzureMonitorBridge(); | ||
|
||
if (Environment.UserInteractive) // Console Version | ||
{ | ||
if (args.Length > 0) | ||
{ | ||
var isServiceExists = ServiceController.GetServices().Any(s => s.ServiceName == service.ServiceName); | ||
var path = Assembly.GetExecutingAssembly().Location; | ||
switch (args[0].ToLower()) | ||
{ | ||
case "/i": | ||
if (isServiceExists) | ||
{ | ||
Console.WriteLine($"The service '{service.ServiceName}' has already registered."); | ||
} | ||
else | ||
{ | ||
ManagedInstallerClass.InstallHelper(new[] { path }); | ||
} | ||
return; | ||
case "/u": | ||
if (isServiceExists) | ||
{ | ||
ManagedInstallerClass.InstallHelper(new[] { "/u", path }); | ||
} | ||
else | ||
{ | ||
Console.WriteLine($"The service '{service.ServiceName}' is not installed yet."); | ||
} | ||
return; | ||
} | ||
} | ||
service.OnStartConsole(args); | ||
service.OnStopConsole(); | ||
} | ||
else | ||
{ | ||
ServiceBase.Run(new ServiceBase[] { service }); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System.ComponentModel; | ||
|
||
namespace SyslogAzureMonitorBridge | ||
{ | ||
[RunInstaller(true)] | ||
public partial class ProjectInstaller : System.Configuration.Install.Installer | ||
{ | ||
public ProjectInstaller() | ||
{ | ||
InitializeComponent(); | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.