211 lines
5.5 KiB
C#
211 lines
5.5 KiB
C#
namespace LibNftables.Tests;
|
|
|
|
public sealed class NftablesClientIntegrationTests
|
|
{
|
|
[Fact]
|
|
public void Validate_InvalidRuleset_ReturnsInvalidResult()
|
|
{
|
|
if (!CanCreateClient())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var client = new NftablesClient();
|
|
var request = NftApplyRequest.FromText("this is not valid nft syntax");
|
|
|
|
NftValidationResult result = client.Validate(request);
|
|
|
|
Assert.False(result.IsValid);
|
|
Assert.False(string.IsNullOrWhiteSpace(result.Diagnostics));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ValidateAsync_InvalidRuleset_ReturnsInvalidResult()
|
|
{
|
|
if (!CanCreateClient())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var client = new NftablesClient();
|
|
var request = NftApplyRequest.FromText("this is not valid nft syntax");
|
|
|
|
NftValidationResult result = await client.ValidateAsync(request);
|
|
|
|
Assert.False(result.IsValid);
|
|
Assert.False(string.IsNullOrWhiteSpace(result.Diagnostics));
|
|
}
|
|
|
|
[Fact]
|
|
public void Apply_InvalidRuleset_ThrowsValidationException()
|
|
{
|
|
if (!CanCreateClient())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var client = new NftablesClient();
|
|
var request = NftApplyRequest.FromText("this is not valid nft syntax");
|
|
|
|
Assert.Throws<NftValidationException>(() => client.Apply(request));
|
|
}
|
|
|
|
[Fact]
|
|
public void Snapshot_WithInsufficientPrivileges_ThrowsPermissionOrReturnsRuleset()
|
|
{
|
|
if (!CanCreateClient())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var client = new NftablesClient();
|
|
|
|
try
|
|
{
|
|
NftSnapshot snapshot = client.Snapshot();
|
|
Assert.False(string.IsNullOrWhiteSpace(snapshot.RulesetText));
|
|
}
|
|
catch (NftPermissionException)
|
|
{
|
|
// Expected in unprivileged environments.
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Category", "Privileged")]
|
|
public void Snapshot_WithPrivilegedLane_ReturnsRuleset()
|
|
{
|
|
if (!CanCreateClient())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!NativeTestSupport.ShouldRunPrivilegedTests())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var client = new NftablesClient();
|
|
|
|
NftSnapshot snapshot = client.Snapshot();
|
|
|
|
Assert.False(string.IsNullOrWhiteSpace(snapshot.RulesetText));
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidateRuleset_WithTypedSetDefinition_ReturnsValidResult()
|
|
{
|
|
if (!CanCreateClient())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var client = new NftablesClient();
|
|
var ruleset = new NftRuleset();
|
|
var table = new NftTable
|
|
{
|
|
Family = NftFamily.Inet,
|
|
Name = "typed_validation",
|
|
};
|
|
var set = new NftSet
|
|
{
|
|
Name = "blocked_ipv4",
|
|
Type = NftSetType.Ipv4Address,
|
|
};
|
|
set.Elements.Add(NftValue.Address(System.Net.IPAddress.Parse("10.0.0.1")));
|
|
set.Elements.Add(NftValue.Address(System.Net.IPAddress.Parse("10.0.0.2")));
|
|
table.Sets.Add(set);
|
|
|
|
var chain = new NftChain
|
|
{
|
|
Name = "input",
|
|
Type = NftChainType.Filter,
|
|
Hook = NftHook.Input,
|
|
Priority = 0,
|
|
Policy = NftChainPolicy.Drop,
|
|
};
|
|
chain.Rules.Add(new NftRule
|
|
{
|
|
SourceAddressSetName = "blocked_ipv4",
|
|
TransportProtocol = NftTransportProtocol.Tcp,
|
|
DestinationPort = NftValue.Port(22),
|
|
Verdict = NftVerdict.Accept,
|
|
});
|
|
table.Chains.Add(chain);
|
|
|
|
ruleset.Tables.Add(table);
|
|
|
|
NftValidationResult result = client.ValidateRuleset(ruleset);
|
|
|
|
Assert.True(result.IsValid);
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidateAndRenderRuleset_WithTypedMapAndRule_ReturnsValidResult()
|
|
{
|
|
if (!CanCreateClient())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var client = new NftablesClient();
|
|
var ruleset = new NftRuleset();
|
|
var table = new NftTable
|
|
{
|
|
Family = NftFamily.Inet,
|
|
Name = "typed_preview",
|
|
};
|
|
var set = new NftSet
|
|
{
|
|
Name = "blocked_ipv4",
|
|
Type = NftSetType.Ipv4Address,
|
|
};
|
|
set.Elements.Add(NftValue.Address(System.Net.IPAddress.Parse("10.0.0.1")));
|
|
table.Sets.Add(set);
|
|
|
|
var map = new NftMap
|
|
{
|
|
Name = "service_policy",
|
|
KeyType = NftMapType.InetService,
|
|
ValueType = NftMapType.Verdict,
|
|
};
|
|
map.Add(NftValue.Port(80), NftValue.Verdict(NftVerdict.Accept));
|
|
table.Maps.Add(map);
|
|
|
|
var chain = new NftChain
|
|
{
|
|
Name = "input",
|
|
Type = NftChainType.Filter,
|
|
Hook = NftHook.Input,
|
|
Priority = 0,
|
|
};
|
|
chain.Rules.Add(new NftRule
|
|
{
|
|
SourceAddressSetName = "blocked_ipv4",
|
|
TransportProtocol = NftTransportProtocol.Tcp,
|
|
DestinationPort = NftValue.Port(22),
|
|
Verdict = NftVerdict.Accept,
|
|
});
|
|
table.Chains.Add(chain);
|
|
ruleset.Tables.Add(table);
|
|
|
|
NftRenderedValidationResult result = client.ValidateAndRenderRuleset(ruleset);
|
|
|
|
Assert.True(result.ValidationResult.IsValid);
|
|
Assert.Contains("add map inet typed_preview service_policy", result.RenderedRulesetText, StringComparison.Ordinal);
|
|
}
|
|
|
|
private static bool CanCreateClient()
|
|
{
|
|
try
|
|
{
|
|
_ = new NftablesClient();
|
|
return true;
|
|
}
|
|
catch (NftException)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|