Skip to content

Commit

Permalink
#115 chore: traffic drivers as plugins
Browse files Browse the repository at this point in the history
+ implemented json traffic driver
  • Loading branch information
joseantmazonsb committed Mar 30, 2022
1 parent 866bea4 commit f2b776e
Show file tree
Hide file tree
Showing 69 changed files with 1,356 additions and 201 deletions.
1 change: 1 addition & 0 deletions Linguard/Cli/Cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
<ProjectReference Include="..\Json\Json.csproj" />
<ProjectReference Include="..\Yaml\Yaml.csproj" />
</ItemGroup>

Expand Down
3 changes: 2 additions & 1 deletion Linguard/Cli/DefaultYamlConfigurationSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Linguard.Core.Configuration.Serialization;
using Linguard.Core.Drivers.TrafficStorage;
using Linguard.Core.Models.Wireguard;
using Linguard.Json;
using Linguard.Yaml.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using UriTypeConverter = Linguard.Yaml.Serialization.UriTypeConverter;
Expand All @@ -20,7 +21,7 @@ public static class DefaultYamlConfigurationSerializer {
.WithTypeMapping<IWireguardConfiguration, WireguardConfiguration>()
.WithTypeMapping<ILoggingConfiguration, LoggingConfiguration>()
.WithTypeMapping<ITrafficConfiguration, TrafficConfiguration>()
.WithTypeMapping<ITrafficStorageDriver, JsonTrafficStorageDriver>()
.WithTypeMapping<ITrafficStorageDriver, TrafficStorageDriver>()
.WithTypeMapping<ISet<Interface>, HashSet<Interface>>()
.WithTypeMapping<ISet<Client>, HashSet<Client>>()
.WithTypeMapping<ISet<IPAddressCidr>, HashSet<IPAddressCidr>>()
Expand Down
15 changes: 15 additions & 0 deletions Linguard/Core.Test/Mocks/PluginEngineMock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Core.Test.Stubs;
using Linguard.Core.Plugins;
using Moq;

namespace Core.Test.Mocks;

public class PluginEngineMock : Mock<IPluginEngine> {
public PluginEngineMock() {
SetupGet(p => p.Plugins).Returns(new[] {
new TrafficStorageDriverStub(),
new TrafficStorageDriverMock("Mock driver", "This is a mocked driver").Object,
new TrafficStorageDriverMock("Mock driver 2", "This is another mocked driver").Object
});
}
}
15 changes: 15 additions & 0 deletions Linguard/Core.Test/Mocks/TrafficStorageDriverMock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using Linguard.Core.Drivers.TrafficStorage;
using Moq;

namespace Core.Test.Mocks;

public class TrafficStorageDriverMock : Mock<ITrafficStorageDriver> {
public TrafficStorageDriverMock(string name, string description) {
SetupGet(d => d.Name).Returns(name);
SetupGet(d => d.Description).Returns(description);
SetupProperty(d => d.CollectionInterval, TimeSpan.FromHours(1));
SetupProperty(d => d.AdditionalOptions, new Dictionary<string, string>());
}
}
56 changes: 56 additions & 0 deletions Linguard/Core.Test/Stubs/TrafficStorageDriverStub.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using Bogus;
using ByteSizeLib;
using Linguard.Core.Configuration;
using Linguard.Core.Drivers.TrafficStorage;
using Linguard.Core.Managers;
using Linguard.Core.Models;


namespace Core.Test.Stubs;

public class TrafficStorageDriverStub : ITrafficStorageDriver {

public string Name => "Stub driver";
public string Description => "This is a stub driver";
private IConfigurationManager _configurationManager;
private readonly Faker _faker = new();
public void Initialize(IConfigurationManager configurationManager) {
_configurationManager = configurationManager;
}

public TimeSpan CollectionInterval { get; set; } = TimeSpan.FromHours(1);

public IDictionary<string, string> AdditionalOptions { get; set; } = new Dictionary<string, string> {
{ "Fake", "Option" }
};
public void Save(IEnumerable<ITrafficData> data) {
throw new NotImplementedException();
}

public IEnumerable<ITrafficData> Load() {
var interfaces = _configurationManager.Configuration.GetModule<IWireguardConfiguration>()!.Interfaces;
var data = new List<ITrafficData>();
var entries = (int) TimeSpan.FromDays(2).TotalHours;
var timestampBase = DateTime.Now - TimeSpan.FromHours(entries);
foreach (var iface in interfaces) {
for (var i = 0; i < entries; i++) {
data.Add(new TrafficData {
Peer = iface,
ReceivedData = ByteSize.FromBytes(_faker.Random.Number((int) ByteSize.BytesInMegaByte)),
SentData = ByteSize.FromBytes(_faker.Random.Number((int) ByteSize.BytesInMegaByte)),
TimeStamp = timestampBase + TimeSpan.FromHours(i)
});
}
}
return data;
}

public object Clone() {
return new TrafficStorageDriverStub {
CollectionInterval = CollectionInterval,
AdditionalOptions = new Dictionary<string, string>(AdditionalOptions)
};
}
}
36 changes: 33 additions & 3 deletions Linguard/Core.Test/WireguardConfigParserShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Linguard.Core.Models.Wireguard;
using Linguard.Core.OS;
using Linguard.Core.Services;
using Linguard.Core.Utils.Wireguard;
using Xunit;

namespace Core.Test;
Expand All @@ -26,16 +27,45 @@ public WireguardConfigParserShould() {
Configuration.Interfaces.Add(new Interface {
Name = "wg0",
PublicKey = "server-pubkey",
PrivateKey = "server-privkey",
IPv4Address = IPAddressCidr.Parse("10.0.0.1", 24),
Clients = new HashSet<Client>()
Clients = new HashSet<Client> {
new() {
Name = "Michael Scott",
Description = "Scranton branch's manager",
IPv4Address = IPAddressCidr.Parse("10.0.0.2", 24),
PrimaryDns = new Uri("1.1.1.1", UriKind.RelativeOrAbsolute),
PublicKey = "client-pubkey",
PrivateKey = "client-privkey",
AllowedIPs = new HashSet<IPAddressCidr> {
IPAddressCidr.Parse("0.0.0.0", 0),
IPAddressCidr.Parse("::/0")
}
}
},
OnUp = new HashSet<Rule> {
"iptables -A FORWARD -i wg0 -j ACCEPT",
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE"
},
OnDown = new HashSet<Rule> {
"iptables -D FORWARD -i wg0 -j ACCEPT",
"iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE"
}
});
}

public void ParseInterface() {
var iface = Configuration.Interfaces.First();
var config = WireguardUtils.GenerateWireguardConfiguration(iface);
var output = Parser.Parse<Interface>(config);
output.Should().Be(iface);
}

[Fact]
public void ParseClient() {
const string config = @"[Interface]
Address = 10.0.0.2/24
PrivateKey = privkey
PrivateKey = client-privkey
DNS = 1.1.1.1
#Name = Michael Scott
#Description = Scranton branch's manager
Expand All @@ -47,7 +77,7 @@ public void ParseClient() {

var client = Parser.Parse<Client>(config);
client.IPv4Address.Should().Be(IPAddressCidr.Parse("10.0.0.2/24"));
client.PrivateKey.Should().Be("privkey");
client.PrivateKey.Should().Be("client-privkey");
client.PublicKey.Should().NotBeEmpty();
client.PrimaryDns.Should().Be(new Uri("1.1.1.1", UriKind.RelativeOrAbsolute));
client.Name.Should().Be("Michael Scott");
Expand Down
6 changes: 4 additions & 2 deletions Linguard/Core.Test/WireguardDumpParserShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public void ExtractEmptyData() {
wg1 fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds= (none) (none) (none) 0 0 0 off
wg1 jUd41n3XYa3yXBzyBvWqlLhYgRef5RiBD7jwo70U+Rw= (none) (none) 10.7.1.0/24 0 0 0 off";

var data = WireguardDumpParser.GetTrafficData(sampleData, Configuration.Interfaces.First());
var data =
WireguardDumpParser.GetTrafficData(sampleData, Configuration.Interfaces.First());
data.Should().HaveCount(3);
var clients = data.Where(e => e.Peer is Client);
clients.Should().HaveCount(2);
Expand All @@ -71,7 +72,8 @@ public void ExtractDataFromSingleInterface() {
wg1 fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds= (none) 172.19.0.8:51822 10.0.0.2/32 1617235493 3481633 33460136 off
wg1 jUd41n3XYa3yXBzyBvWqlLhYgRef5RiBD7jwo70U+Rw= (none) 172.19.0.7:51823 10.0.0.3/32 1609974495 1403752 19462368 off";

var data = WireguardDumpParser.GetTrafficData(sampleData, Configuration.Interfaces.First());
var data =
WireguardDumpParser.GetTrafficData(sampleData, Configuration.Interfaces.First());
data.Should().HaveCount(3);
var clients = data.Where(e => e.Peer is Client);
clients.Should().HaveCount(2);
Expand Down
15 changes: 15 additions & 0 deletions Linguard/Core/Annotations/Annotations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Linguard.Core.Annotations;

/// <summary>
/// Indicates that a property MAY have value.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class OptionalAttribute : Attribute {
}

/// <summary>
/// Indicates that a property MUST have value.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class MandatoryAttribute : Attribute {
}
4 changes: 2 additions & 2 deletions Linguard/Core/Configuration/ITrafficConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
namespace Linguard.Core.Configuration;

public interface ITrafficConfiguration : IConfigurationModule {
public bool Enabled { get; set; }
public ITrafficStorageDriver StorageDriver { get; set; }
bool Enabled { get; set; }
ITrafficStorageDriver StorageDriver { get; set; }
}
1 change: 1 addition & 0 deletions Linguard/Core/Configuration/IWorkingDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public interface IWorkingDirectory {
DirectoryInfo BaseDirectory { get; set; }
FileInfo GetInterfaceConfigurationFile(Interface @interface);
string CredentialsPath { get; }
DirectoryInfo PluginsDirectory { get; }
}
4 changes: 3 additions & 1 deletion Linguard/Core/Configuration/TrafficConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ public class TrafficConfiguration : ITrafficConfiguration {
public bool Enabled { get; set; }
public ITrafficStorageDriver StorageDriver { get; set; }
public object Clone() {
return MemberwiseClone();
var clone = (ITrafficConfiguration) MemberwiseClone();
clone.StorageDriver = (ITrafficStorageDriver) StorageDriver.Clone();
return clone;
}
}
1 change: 1 addition & 0 deletions Linguard/Core/Configuration/WorkingDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ public FileInfo GetInterfaceConfigurationFile(Interface @interface) =>
WireguardConfigurationFileExtension));

public string CredentialsPath => Path.Combine(BaseDirectory.FullName, $"{AssemblyInfo.Product.ToLower()}.db");
public DirectoryInfo PluginsDirectory => new(Path.Combine(BaseDirectory.FullName, "plugins"));
}
18 changes: 14 additions & 4 deletions Linguard/Core/Drivers/TrafficStorage/ITrafficStorageDriver.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
using Linguard.Core.Models;
using Linguard.Core.Plugins;

namespace Linguard.Core.Drivers.TrafficStorage;

public interface ITrafficStorageDriver {
public string TimestampFormat { get; set; }
public void Save(IEnumerable<ITrafficData> data);
public IEnumerable<ITrafficData> Load();
public interface ITrafficStorageDriver : IPlugin {
TimeSpan CollectionInterval { get; set; }
IDictionary<string, string> AdditionalOptions { get; set; }
/// <summary>
/// Store the given traffic data.
/// </summary>
/// <param name="data"></param>
void Save(IEnumerable<ITrafficData> data);
/// <summary>
/// Load all the stored traffic data.
/// </summary>
/// <returns></returns>
IEnumerable<ITrafficData> Load();
}
15 changes: 0 additions & 15 deletions Linguard/Core/Drivers/TrafficStorage/JsonTrafficStorageDriver.cs

This file was deleted.

19 changes: 19 additions & 0 deletions Linguard/Core/Drivers/TrafficStorage/TrafficStorageDriverBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Linguard.Core.Managers;
using Linguard.Core.Models;

namespace Linguard.Core.Drivers.TrafficStorage;

public abstract class TrafficStorageDriverBase : ITrafficStorageDriver {
public abstract string Name { get; }
public abstract string Description { get; }
public virtual TimeSpan CollectionInterval { get; set; } = TimeSpan.FromHours(1);
public IDictionary<string, string> AdditionalOptions { get; set; } = new Dictionary<string, string>();
protected IConfigurationManager? ConfigurationManager { get; private set; }

public void Initialize(IConfigurationManager configurationManager) {
ConfigurationManager = configurationManager;
}
public abstract void Save(IEnumerable<ITrafficData> data);
public abstract IEnumerable<ITrafficData> Load();
public abstract object Clone();
}
15 changes: 8 additions & 7 deletions Linguard/Core/Managers/ConfigurationManagerBase.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Linguard.Core.Configuration;
using Linguard.Core.Drivers.TrafficStorage;
using Linguard.Core.Models.Wireguard;
using Linguard.Core.OS;
using Linguard.Core.Plugins;
using Linguard.Core.Utils;
using Linguard.Log;
using Microsoft.Extensions.Logging;
Expand All @@ -14,37 +14,38 @@ public abstract class ConfigurationManagerBase : IConfigurationManager {
private readonly ILinguardLogger _logger;

protected ConfigurationManagerBase(IConfiguration configuration, IWorkingDirectory workingDirectory,
ISystemWrapper systemWrapper, ILinguardLogger logger) {
ISystemWrapper systemWrapper, ILinguardLogger logger, IPluginEngine pluginEngine) {
Configuration = configuration;
WorkingDirectory = workingDirectory;
PluginEngine = pluginEngine;
_systemWrapper = systemWrapper;
_logger = logger;
}

public IConfiguration Configuration { get; set; }
public IWorkingDirectory WorkingDirectory { get; set; }
public IPluginEngine PluginEngine { get; set; }

public virtual void LoadDefaults() {
LoadLoggingDefaults();
LoadTrafficDefaults();
LoadWireguardDefaults();
}

private void LoadLoggingDefaults() {
protected virtual void LoadLoggingDefaults() {
var configuration = new LoggingConfiguration {
Level = LogLevel.Information,
DateTimeFormat = _logger.DateTimeFormat
};
Configuration.Modules.Add(configuration);
}
private void LoadTrafficDefaults() {
protected virtual void LoadTrafficDefaults() {
var configuration = new TrafficConfiguration {
Enabled = true,
StorageDriver = new JsonTrafficStorageDriver()
Enabled = false
};
Configuration.Modules.Add(configuration);
}
private void LoadWireguardDefaults() {
protected virtual void LoadWireguardDefaults() {
var configuration = new WireguardConfiguration {
Interfaces = new HashSet<Interface>(),
PrimaryDns = new("8.8.8.8", UriKind.RelativeOrAbsolute),
Expand Down
6 changes: 4 additions & 2 deletions Linguard/Core/Managers/DefaultFileConfigurationManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Linguard.Core.Configuration;
using Linguard.Core.Configuration.Serialization;
using Linguard.Core.OS;
using Linguard.Core.Plugins;
using Linguard.Core.Utils;
using Linguard.Log;

Expand All @@ -9,8 +10,9 @@ namespace Linguard.Core.Managers;
public abstract class DefaultFileConfigurationManager<T> : FileConfigurationManager<T> where T : IConfiguration {

protected DefaultFileConfigurationManager(IConfiguration configuration, IWorkingDirectory workingDirectory,
ISystemWrapper systemWrapper, IConfigurationSerializer serializer, ILinguardLogger logger)
: base(configuration, workingDirectory, systemWrapper, serializer, logger) {
ISystemWrapper systemWrapper, IConfigurationSerializer serializer, ILinguardLogger logger,
IPluginEngine pluginEngine)
: base(configuration, workingDirectory, systemWrapper, serializer, logger, pluginEngine) {
}

private FileInfo? _configurationFile;
Expand Down
Loading

0 comments on commit f2b776e

Please sign in to comment.