Skip to content

Commit

Permalink
Send logs to syslog server
Browse files Browse the repository at this point in the history
  • Loading branch information
KonstantinYan committed Feb 9, 2021
1 parent 5de70ad commit a937425
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 32 deletions.
2 changes: 2 additions & 0 deletions MultiFactor.Radius.Adapter.sln
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{44F0F077-514B-4997-BA81-333D04E18299}"
ProjectSection(SolutionItems) = preProject
LICENSE.md = LICENSE.md
LICENSE.ru.md = LICENSE.ru.md
README.md = README.md
README.ru.md = README.ru.md
EndProjectSection
EndProject
Global
Expand Down
2 changes: 1 addition & 1 deletion MultiFactor.Radius.Adapter/AdapterService.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions MultiFactor.Radius.Adapter/AdapterService.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using MultiFactor.Radius.Adapter.Core;
using MultiFactor.Radius.Adapter.Server;
using Serilog;
using System;
using System.ServiceProcess;
using System.Threading.Tasks;

namespace MultiFactor.Radius.Adapter
{
Expand All @@ -25,6 +27,8 @@ public void StartServer()
public void StopServer()
{
_radiusServer.Stop();
//2 sec delay to flush logs
Task.WaitAny(Task.Delay(TimeSpan.FromSeconds(2)));
}

protected override void OnStart(string[] args)
Expand Down
22 changes: 16 additions & 6 deletions MultiFactor.Radius.Adapter/App.config
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="RadiusReply" type="MultiFactor.Radius.Adapter.RadiusReplyAttributesSection, MultiFactor.Radius.Adapter" />
<section name="RadiusReply" type="MultiFactor.Radius.Adapter.RadiusReplyAttributesSection, MultiFactor.Radius.Adapter"/>
</configSections>

<appSettings>
<!--this service radius server endpoint -->
<!--this service radius server endpoint (0.0.0.0 - listen all interfaces) -->
<add key="adapter-server-endpoint" value="192.168.0.1:1812"/>
<!-- shared secret between this service and radius client -->
<add key="radius-shared-secret" value="0000000000"/>
Expand Down Expand Up @@ -36,9 +36,6 @@

<!--remote radius server endpoint, must not be 127.0.0.1 -->
<!--<add key="nps-server-endpoint" value="192.168.0.1:1812"/>-->

<!-- Bypass second factor within specified minutes period for same client-machine/user-name -->
<!--<add key="bypass-second-factor-period" value="30"/>-->

<!--Multifactor API -->
<add key="multifactor-api-url" value="https://api.multifactor.ru"/>
Expand All @@ -52,6 +49,19 @@

<!-- minimal log level: 'Debug', 'Info', 'Warn', 'Error' -->
<add key="logging-level" value="Debug"/>


<!--Syslog server-->
<!--add key="syslog-server" value="udp://syslog-server:514"/-->

<!--Syslog format: RFC3164 or RFC5424-->
<!--add key="syslog-format" value="RFC5424"/-->

<!--add key="syslog-facility" value="Auth"/-->
<!--add key="syslog-app-name" value="multifactor-radius"/-->

<!--Windows Service settings -->
<add key="service-unit-name" value="MFRadiusAdapter"/>
<add key="service-display-name" value="MultiFactor Radius Adapter"/>
</appSettings>

</configuration>
35 changes: 35 additions & 0 deletions MultiFactor.Radius.Adapter/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ public bool CheckMembership

#endregion

#region API settings

/// <summary>
/// Multifactor API URL
/// </summary>
Expand All @@ -124,6 +126,9 @@ public bool CheckMembership
/// RADIUS Shared Secret
/// </summary>
public string MultiFactorSharedSecret { get; set; }

#endregion

/// <summary>
/// Logging level
/// </summary>
Expand All @@ -134,6 +139,8 @@ public bool CheckMembership
/// </summary>
public IDictionary<string, List<RadiusReplyAttributeValue>> RadiusReplyAttributes { get; set; }

#region load config section

/// <summary>
/// Read and load settings from appSettings configuration section
/// </summary>
Expand Down Expand Up @@ -385,6 +392,34 @@ private static bool TryParseIPEndPoint(string text, out IPEndPoint ipEndPoint)

throw new FormatException($"Failed to parse {text} to IPEndPoint");
}

#endregion

#region static members

/// <summary>
/// Windows service unit name
/// </summary>
public static string ServiceUnitName
{
get
{
return ConfigurationManager.AppSettings["service-unit-name"] ?? "MFRadiusAdapter";
}
}

/// <summary>
/// Windows service display name
/// </summary>
public static string ServiceDisplayName
{
get
{
return ConfigurationManager.AppSettings["service-display-name"] ?? "MultiFactor Radius Adapter";
}
}

#endregion
}

public enum AuthenticationSource
Expand Down
14 changes: 10 additions & 4 deletions MultiFactor.Radius.Adapter/MultiFactor.Radius.Adapter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<OutputType>Exe</OutputType>
<RootNamespace>MultiFactor.Radius.Adapter</RootNamespace>
<AssemblyName>MultiFactor.Radius.Adapter</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
Expand Down Expand Up @@ -72,16 +72,19 @@
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Serilog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.2.9.0\lib\net45\Serilog.dll</HintPath>
<HintPath>..\packages\Serilog.2.10.0\lib\net45\Serilog.dll</HintPath>
</Reference>
<Reference Include="Serilog.Sinks.Console, Version=3.1.1.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.Sinks.Console.3.1.1\lib\net45\Serilog.Sinks.Console.dll</HintPath>
</Reference>
<Reference Include="Serilog.Sinks.File, Version=2.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.Sinks.File.4.1.0\lib\net45\Serilog.Sinks.File.dll</HintPath>
</Reference>
<Reference Include="Serilog.Sinks.RollingFile, Version=2.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.Sinks.RollingFile.3.3.0\lib\net45\Serilog.Sinks.RollingFile.dll</HintPath>
<Reference Include="Serilog.Sinks.PeriodicBatching, Version=2.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.Sinks.PeriodicBatching.2.3.0\lib\net45\Serilog.Sinks.PeriodicBatching.dll</HintPath>
</Reference>
<Reference Include="Serilog.Sinks.Syslog, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.Sinks.SyslogMessages.2.0.1\lib\net462\Serilog.Sinks.Syslog.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
Expand All @@ -91,6 +94,9 @@
<Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.DirectoryServices.Protocols" />
<Reference Include="System.Management" />
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Web.Extensions" />
Expand Down
122 changes: 115 additions & 7 deletions MultiFactor.Radius.Adapter/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@
using Serilog;
using Serilog.Core;
using Serilog.Events;
using Serilog.Sinks.Syslog;
using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.ServiceProcess;
using System.Threading;

namespace MultiFactor.Radius.Adapter
{
Expand All @@ -29,6 +35,8 @@ static void Main(string[] args)
.WriteTo.Console(LogEventLevel.Debug)
.WriteTo.File($"{path}Logs{Path.DirectorySeparatorChar}log-.txt", rollingInterval: RollingInterval.Day);

ConfigureSyslog(loggerConfiguration, out var syslogInfoMessage);

Log.Logger = loggerConfiguration.CreateLogger();

if (args.Length > 0)
Expand Down Expand Up @@ -57,7 +65,10 @@ static void Main(string[] args)
var configuration = Configuration.Load(dictionary);

SetLogLevel(configuration.LogLevel, levelSwitch);

if (syslogInfoMessage != null)
{
Log.Logger.Information(syslogInfoMessage);
}

var adapterService = new AdapterService(configuration, dictionary, Log.Logger);

Expand All @@ -67,11 +78,20 @@ static void Main(string[] args)
Log.Logger.Information("Console mode");
Log.Logger.Information("Press CTRL+C to exit");

Console.CancelKeyPress += delegate { adapterService.StopServer(); };
Serilog.Debugging.SelfLog.Enable(Console.Error);

var cts = new CancellationTokenSource();

Console.CancelKeyPress += (sender, eventArgs) =>
{
adapterService.StopServer();
eventArgs.Cancel = true;
cts.Cancel();
};

adapterService.StartServer();

Console.ReadLine();
cts.Token.WaitHandle.WaitOne();
}
else
{
Expand All @@ -93,17 +113,17 @@ static void Main(string[] args)

private static void InstallService()
{
Log.Logger.Information("Installing service MFRadiusAdapter");
Log.Logger.Information($"Installing service {Configuration.ServiceUnitName}");
System.Configuration.Install.ManagedInstallerClass.InstallHelper(new string[] { "/i", Assembly.GetExecutingAssembly().Location });
Log.Logger.Information("Service installed");
Log.Logger.Information("Use 'net start MFRadiusAdapter' to run");
Log.Logger.Information($"Use 'net start {Configuration.ServiceUnitName}' to run");
Log.Logger.Information("Press any key to exit");
Console.ReadKey();
}

public static void UnInstallService()
{
Log.Logger.Information("UnInstalling service MFRadiusAdapter");
Log.Logger.Information($"UnInstalling service {Configuration.ServiceUnitName}");
System.Configuration.Install.ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
Log.Logger.Information("Service uninstalled");
Log.Logger.Information("Press any key to exit");
Expand All @@ -130,5 +150,93 @@ private static void SetLogLevel(string level, LoggingLevelSwitch levelSwitch)

Log.Logger.Information($"Logging level: {levelSwitch.MinimumLevel}");
}

private static void ConfigureSyslog(LoggerConfiguration loggerConfiguration, out string logMessage)
{
logMessage = null;

var appSettings = ConfigurationManager.AppSettings;
var sysLogServer = appSettings["syslog-server"];
var sysLogFormatSetting = appSettings["syslog-format"];
var sysLogFramerSetting = appSettings["syslog-framer"];
var sysLogFacilitySetting = appSettings["syslog-facility"];
var sysLogAppName = appSettings["syslog-app-name"] ?? "multifactor-radius";

var facility = ParseSettingOrDefault(sysLogFacilitySetting, Facility.Auth);
var format = ParseSettingOrDefault(sysLogFormatSetting, SyslogFormat.RFC5424);
var framer = ParseSettingOrDefault(sysLogFramerSetting, FramingType.OCTET_COUNTING);

ISyslogFormatter formatter;
switch (format)
{
case SyslogFormat.RFC5424:
formatter = new Rfc5424Formatter(facility: facility, applicationName: sysLogAppName);
break;
case SyslogFormat.RFC3164:
formatter = new Rfc3164Formatter(facility: facility, applicationName: sysLogAppName);
break;
default:
throw new NotImplementedException($"Unknown syslog format {format}");
}

if (sysLogServer != null)
{
var uri = new Uri(sysLogServer);

if (uri.Port == -1)
{
throw new ConfigurationErrorsException($"Invalid port number for syslog-server {sysLogServer}");
}

switch (uri.Scheme)
{
case "udp":
var serverIp = ResolveIP(uri.Host);
loggerConfiguration
.WriteTo
.UdpSyslog(serverIp, port: uri.Port, format: format, appName: sysLogAppName, facility: facility);
logMessage = $"Using syslog server: {sysLogServer}, format: {format}, facility: {facility}, appName: {sysLogAppName}";
break;
case "tcp":
var tcpConfig = new SyslogTcpConfig
{
Host = uri.Host,
Port = uri.Port,
Framer = new MessageFramer(framer),
Formatter = formatter,
};
loggerConfiguration
.WriteTo
.TcpSyslog(tcpConfig);
logMessage = $"Using syslog server {sysLogServer}, format: {format}, framing: {framer}, facility: {facility}, appName: {sysLogAppName}";
break;
default:
throw new NotImplementedException($"Unknown scheme {uri.Scheme} for syslog-server {sysLogServer}. Expected udp or tcp");
}
}
}

private static TEnum ParseSettingOrDefault<TEnum>(string setting, TEnum defaultValue) where TEnum : struct
{
if (Enum.TryParse<TEnum>(setting, out var val))
{
return val;
}

return defaultValue;
}

private static string ResolveIP(string host)
{
if (!IPAddress.TryParse(host, out var addr))
{
addr = Dns.GetHostAddresses(host)
.First(x => x.AddressFamily == AddressFamily.InterNetwork); //only ipv4

return addr.ToString();
}

return host;
}
}
}
}
3 changes: 0 additions & 3 deletions MultiFactor.Radius.Adapter/Server/RadiusServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,6 @@ private void RouterRequestProcessed(object sender, PendingRequest request)
}

Send(responsePacket, request.RemoteEndpoint);

//request processed, clear all
GC.Collect();
}

/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions MultiFactor.Radius.Adapter/ServiceInstaller.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a937425

Please sign in to comment.