Add audit API client
- cleanup - generate PCAP API
This commit is contained in:
parent
bb46b7f58a
commit
15106dbfd6
13 changed files with 151 additions and 58 deletions
73
src/INetMock.Client/Audit/Client/AuditApiClient.cs
Normal file
73
src/INetMock.Client/Audit/Client/AuditApiClient.cs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Grpc.Core;
|
||||||
|
using Grpc.Net.Client;
|
||||||
|
using INetMock.Client.Audit.Serialization;
|
||||||
|
using INetMock.Client.Rpc;
|
||||||
|
|
||||||
|
namespace INetMock.Client.Audit.Client
|
||||||
|
{
|
||||||
|
public class AuditApiClient : IAuditApiClient
|
||||||
|
{
|
||||||
|
private readonly Rpc.Audit.AuditClient _auditClient;
|
||||||
|
|
||||||
|
public AuditApiClient(string address, GrpcChannelOptions? options = null) : this(new Uri(address), options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuditApiClient(Uri address, GrpcChannelOptions? options = null) : this(
|
||||||
|
GrpcChannel.ForAddress(address, options ?? new GrpcChannelOptions()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuditApiClient(ChannelBase channel)
|
||||||
|
{
|
||||||
|
_auditClient = new Rpc.Audit.AuditClient(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<string>> ListSinksAsync(CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var sinks = await _auditClient.ListSinksAsync(new ListSinksRequest(), Metadata.Empty, null, token);
|
||||||
|
return sinks.Sinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> RegisterFileSinkAsync(string targetPath, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var resp = await _auditClient.RegisterFileSinkAsync(
|
||||||
|
new RegisterFileSinkRequest {TargetPath = targetPath},
|
||||||
|
Metadata.Empty,
|
||||||
|
null,
|
||||||
|
token
|
||||||
|
);
|
||||||
|
|
||||||
|
return resp.ResolvedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> RemoveFileSinkAsync(string targetPath, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var resp = await _auditClient.RemoveFileSinkAsync(new RemoveFileSinkRequest
|
||||||
|
{
|
||||||
|
TargetPath = targetPath
|
||||||
|
},
|
||||||
|
Metadata.Empty,
|
||||||
|
null,
|
||||||
|
token
|
||||||
|
);
|
||||||
|
|
||||||
|
return resp.SinkGotRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProtoEventReader EventStreamAsync(string watcherName, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var stream = _auditClient.WatchEvents(
|
||||||
|
new WatchEventsRequest {WatcherName = watcherName},
|
||||||
|
Metadata.Empty,
|
||||||
|
null,
|
||||||
|
token
|
||||||
|
);
|
||||||
|
return new EventServerStreamReader(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using Google.Protobuf.WellKnownTypes;
|
using Google.Protobuf.WellKnownTypes;
|
||||||
|
@ -9,11 +8,13 @@ using INetMock.Client.Audit.Details;
|
||||||
namespace INetMock.Client.Audit
|
namespace INetMock.Client.Audit
|
||||||
{
|
{
|
||||||
public abstract record EventDetails;
|
public abstract record EventDetails;
|
||||||
|
|
||||||
public record EmptyDetails : EventDetails;
|
public record EmptyDetails : EventDetails;
|
||||||
|
|
||||||
public record GenericDetails : EventDetails
|
public record GenericDetails : EventDetails
|
||||||
{
|
{
|
||||||
private readonly Any? _detailsAny;
|
private readonly Any? _detailsAny;
|
||||||
|
|
||||||
public GenericDetails()
|
public GenericDetails()
|
||||||
{
|
{
|
||||||
_detailsAny = null;
|
_detailsAny = null;
|
||||||
|
@ -27,14 +28,16 @@ namespace INetMock.Client.Audit
|
||||||
public static implicit operator HttpDetails(GenericDetails gd)
|
public static implicit operator HttpDetails(GenericDetails gd)
|
||||||
{
|
{
|
||||||
if (gd._detailsAny == null || gd._detailsAny.Value == null) return new();
|
if (gd._detailsAny == null || gd._detailsAny.Value == null) return new();
|
||||||
if(!gd._detailsAny.TypeUrl.EndsWith(HTTPDetailsEntity.Descriptor.FullName)) throw new InvalidOperationException();
|
if (!gd._detailsAny.TypeUrl.EndsWith(HTTPDetailsEntity.Descriptor.FullName))
|
||||||
|
throw new InvalidOperationException();
|
||||||
return new HttpDetails(gd._detailsAny);
|
return new HttpDetails(gd._detailsAny);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator DnsDetails(GenericDetails gd)
|
public static implicit operator DnsDetails(GenericDetails gd)
|
||||||
{
|
{
|
||||||
if (gd._detailsAny == null || gd._detailsAny.Value == null) return new();
|
if (gd._detailsAny == null || gd._detailsAny.Value == null) return new();
|
||||||
if(!gd._detailsAny.TypeUrl.EndsWith(HTTPDetailsEntity.Descriptor.FullName)) throw new InvalidOperationException();
|
if (!gd._detailsAny.TypeUrl.EndsWith(HTTPDetailsEntity.Descriptor.FullName))
|
||||||
|
throw new InvalidOperationException();
|
||||||
return new DnsDetails(gd._detailsAny);
|
return new DnsDetails(gd._detailsAny);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +46,6 @@ namespace INetMock.Client.Audit
|
||||||
{
|
{
|
||||||
public HttpDetails()
|
public HttpDetails()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpDetails(Any? any)
|
public HttpDetails(Any? any)
|
||||||
|
@ -70,7 +72,6 @@ namespace INetMock.Client.Audit
|
||||||
{
|
{
|
||||||
public DnsDetails()
|
public DnsDetails()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DNSOpCode OpCode { get; init; }
|
public DNSOpCode OpCode { get; init; }
|
||||||
|
|
|
@ -7,7 +7,6 @@ namespace INetMock.Client.Audit
|
||||||
{
|
{
|
||||||
public Event()
|
public Event()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Event(EventEntity entity)
|
public Event(EventEntity entity)
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Grpc.Core;
|
|
||||||
|
|
||||||
namespace INetMock.Client.Audit
|
|
||||||
{
|
|
||||||
public sealed class EventServerStreamReader : IProtoEventReader
|
|
||||||
{
|
|
||||||
private readonly IAsyncStreamReader<EventEntity> _asyncEventStream;
|
|
||||||
|
|
||||||
public EventServerStreamReader(IAsyncStreamReader<EventEntity> asyncEventStream)
|
|
||||||
{
|
|
||||||
_asyncEventStream = asyncEventStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<EventEntity?> ReadAsync(CancellationToken token = default)
|
|
||||||
{
|
|
||||||
if (!await _asyncEventStream.MoveNext(token)) return null;
|
|
||||||
return _asyncEventStream.Current;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
|
||||||
}
|
|
||||||
}
|
|
14
src/INetMock.Client/Audit/IAuditApiClient.cs
Normal file
14
src/INetMock.Client/Audit/IAuditApiClient.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace INetMock.Client.Audit
|
||||||
|
{
|
||||||
|
public interface IAuditApiClient
|
||||||
|
{
|
||||||
|
IProtoEventReader EventStreamAsync(string watcherName, CancellationToken token = default);
|
||||||
|
Task<IEnumerable<string>> ListSinksAsync(CancellationToken token = default);
|
||||||
|
Task<string> RegisterFileSinkAsync(string targetPath, CancellationToken token = default);
|
||||||
|
Task<bool> RemoveFileSinkAsync(string targetPath, CancellationToken token = default);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Grpc.Core;
|
||||||
|
|
||||||
|
namespace INetMock.Client.Audit.Serialization
|
||||||
|
{
|
||||||
|
public sealed class EventServerStreamReader : IProtoEventReader
|
||||||
|
{
|
||||||
|
private readonly AsyncServerStreamingCall<EventEntity> _asyncEventStream;
|
||||||
|
|
||||||
|
public EventServerStreamReader(AsyncServerStreamingCall<EventEntity> asyncEventStream)
|
||||||
|
{
|
||||||
|
_asyncEventStream = asyncEventStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EventEntity?> ReadAsync(CancellationToken token = default)
|
||||||
|
{
|
||||||
|
if (!await _asyncEventStream.ResponseStream.MoveNext(token)) return null;
|
||||||
|
return _asyncEventStream.ResponseStream.Current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() => _asyncEventStream.Dispose();
|
||||||
|
|
||||||
|
public ValueTask DisposeAsync()
|
||||||
|
{
|
||||||
|
_asyncEventStream.Dispose();
|
||||||
|
return ValueTask.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace INetMock.Client.Audit
|
namespace INetMock.Client.Audit.Serialization
|
||||||
{
|
{
|
||||||
public sealed class GenericReader : IEventReader<GenericDetails>
|
public sealed class GenericReader : IEventReader<GenericDetails>
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,8 @@ namespace INetMock.Client.Audit
|
||||||
_reader = reader;
|
_reader = reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async IAsyncEnumerable<Event<GenericDetails>> ReadAllAsync([EnumeratorCancellation] CancellationToken token = default)
|
public async IAsyncEnumerable<Event<GenericDetails>> ReadAllAsync(
|
||||||
|
[EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
|
@ -5,7 +5,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
|
||||||
namespace INetMock.Client.Audit
|
namespace INetMock.Client.Audit.Serialization
|
||||||
{
|
{
|
||||||
public sealed class ProtoReader : IProtoEventReader
|
public sealed class ProtoReader : IProtoEventReader
|
||||||
{
|
{
|
|
@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace INetMock.Client.Audit
|
namespace INetMock.Client.Audit.Serialization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Configures how the TypedReader proceeds with mismatching entities.
|
/// Configures how the TypedReader proceeds with mismatching entities.
|
|
@ -19,5 +19,6 @@
|
||||||
<Protobuf Include="proto/audit/details/http_details.proto" GrpcServices="Client" AdditionalImportDirs="./proto/" />
|
<Protobuf Include="proto/audit/details/http_details.proto" GrpcServices="Client" AdditionalImportDirs="./proto/" />
|
||||||
<Protobuf Include="proto/rpc/audit.proto" GrpcServices="Client" AdditionalImportDirs="./proto/" />
|
<Protobuf Include="proto/rpc/audit.proto" GrpcServices="Client" AdditionalImportDirs="./proto/" />
|
||||||
<Protobuf Include="proto/rpc/health.proto" GrpcServices="Client" AdditionalImportDirs="./proto/" />
|
<Protobuf Include="proto/rpc/health.proto" GrpcServices="Client" AdditionalImportDirs="./proto/" />
|
||||||
|
<Protobuf Include="proto/rpc/pcap.proto" GrpcServices="Client" AdditionalImportDirs="./proto/" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using INetMock.Client.Audit;
|
using INetMock.Client.Audit;
|
||||||
|
using INetMock.Client.Audit.Serialization;
|
||||||
using INetMock.Client.Test.Hex;
|
using INetMock.Client.Test.Hex;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace INetMock.Client.Test.Audit
|
namespace INetMock.Client.Test.Audit.Serialization
|
||||||
{
|
{
|
||||||
public class GenericReaderTest
|
public class GenericReaderTest
|
||||||
{
|
{
|
||||||
|
@ -23,7 +24,7 @@ namespace INetMock.Client.Test.Audit
|
||||||
public async void TestRead_HttpEvent_Success()
|
public async void TestRead_HttpEvent_Success()
|
||||||
{
|
{
|
||||||
await using var protoReader = new ProtoReader(new MemoryStream(_httpEventPayloadBytes));
|
await using var protoReader = new ProtoReader(new MemoryStream(_httpEventPayloadBytes));
|
||||||
await using var reader = new GenericReader(protoReader);
|
await using IEventReader<GenericDetails> reader = new GenericReader(protoReader);
|
||||||
await foreach (var ev in reader.ReadAllAsync())
|
await foreach (var ev in reader.ReadAllAsync())
|
||||||
{
|
{
|
||||||
Assert.NotNull(ev);
|
Assert.NotNull(ev);
|
||||||
|
@ -44,7 +45,7 @@ namespace INetMock.Client.Test.Audit
|
||||||
{
|
{
|
||||||
await using var memStream = new MemoryStream(_dnsEventPayloadBytes);
|
await using var memStream = new MemoryStream(_dnsEventPayloadBytes);
|
||||||
await using var protoReader = new ProtoReader(new MemoryStream(_dnsEventPayloadBytes));
|
await using var protoReader = new ProtoReader(new MemoryStream(_dnsEventPayloadBytes));
|
||||||
await using var reader = new GenericReader(protoReader);
|
await using IEventReader<GenericDetails> reader = new GenericReader(protoReader);
|
||||||
await foreach (var ev in reader.ReadAllAsync())
|
await foreach (var ev in reader.ReadAllAsync())
|
||||||
{
|
{
|
||||||
Assert.NotNull(ev);
|
Assert.NotNull(ev);
|
|
@ -1,9 +1,10 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using INetMock.Client.Audit;
|
using INetMock.Client.Audit;
|
||||||
|
using INetMock.Client.Audit.Serialization;
|
||||||
using INetMock.Client.Test.Hex;
|
using INetMock.Client.Test.Hex;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace INetMock.Client.Test.Audit
|
namespace INetMock.Client.Test.Audit.Serialization
|
||||||
{
|
{
|
||||||
public class TypedReaderTest
|
public class TypedReaderTest
|
||||||
{
|
{
|
||||||
|
@ -23,7 +24,7 @@ namespace INetMock.Client.Test.Audit
|
||||||
public async void TestRead_HttpEvent_Success()
|
public async void TestRead_HttpEvent_Success()
|
||||||
{
|
{
|
||||||
await using var protoReader = new ProtoReader(new MemoryStream(_httpEventPayloadBytes));
|
await using var protoReader = new ProtoReader(new MemoryStream(_httpEventPayloadBytes));
|
||||||
await using var reader = new TypedReader<HttpDetails>(protoReader, DropMode.DropEntity);
|
await using IEventReader<HttpDetails> reader = new TypedReader<HttpDetails>(protoReader, DropMode.DropEntity);
|
||||||
await foreach (var ev in reader.ReadAllAsync())
|
await foreach (var ev in reader.ReadAllAsync())
|
||||||
{
|
{
|
||||||
Assert.NotNull(ev);
|
Assert.NotNull(ev);
|
||||||
|
@ -34,7 +35,7 @@ namespace INetMock.Client.Test.Audit
|
||||||
public async void TestRead_DnsEvent_Success()
|
public async void TestRead_DnsEvent_Success()
|
||||||
{
|
{
|
||||||
await using var protoReader = new ProtoReader(new MemoryStream(_dnsEventPayloadBytes));
|
await using var protoReader = new ProtoReader(new MemoryStream(_dnsEventPayloadBytes));
|
||||||
await using var reader = new TypedReader<DnsDetails>(protoReader, DropMode.DropEntity);
|
await using IEventReader<DnsDetails> reader = new TypedReader<DnsDetails>(protoReader, DropMode.DropEntity);
|
||||||
await foreach (var ev in reader.ReadAllAsync())
|
await foreach (var ev in reader.ReadAllAsync())
|
||||||
{
|
{
|
||||||
Assert.NotNull(ev);
|
Assert.NotNull(ev);
|
Loading…
Reference in a new issue