Add audit API client

- cleanup
- generate PCAP API
This commit is contained in:
Peter 2021-02-20 15:18:08 +01:00
parent bb46b7f58a
commit 15106dbfd6
Signed by: prskr
GPG key ID: C1DB5D2E8DB512F9
13 changed files with 151 additions and 58 deletions

View 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);
}
}
}

View file

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using Google.Protobuf.WellKnownTypes;
@ -9,11 +8,13 @@ using INetMock.Client.Audit.Details;
namespace INetMock.Client.Audit
{
public abstract record EventDetails;
public record EmptyDetails : EventDetails;
public record GenericDetails : EventDetails
{
private readonly Any? _detailsAny;
public GenericDetails()
{
_detailsAny = null;
@ -27,14 +28,16 @@ namespace INetMock.Client.Audit
public static implicit operator HttpDetails(GenericDetails gd)
{
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);
}
public static implicit operator DnsDetails(GenericDetails gd)
{
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);
}
}
@ -43,7 +46,6 @@ namespace INetMock.Client.Audit
{
public HttpDetails()
{
}
public HttpDetails(Any? any)
@ -70,7 +72,6 @@ namespace INetMock.Client.Audit
{
public DnsDetails()
{
}
public DNSOpCode OpCode { get; init; }
@ -79,7 +80,7 @@ namespace INetMock.Client.Audit
public DnsDetails(Any? any)
{
if(any == null || any.Value == null) return;
if (any == null || any.Value == null) return;
var entity = DNSDetailsEntity.Parser.ParseFrom(any.Value);
OpCode = entity.Opcode;

View file

@ -7,7 +7,6 @@ namespace INetMock.Client.Audit
{
public Event()
{
}
public Event(EventEntity entity)

View file

@ -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;
}
}

View 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);
}
}

View file

@ -5,7 +5,7 @@ using System.Threading.Tasks;
namespace INetMock.Client.Audit
{
public interface IEventReader<T>: IDisposable, IAsyncDisposable where T : EventDetails, new()
public interface IEventReader<T> : IDisposable, IAsyncDisposable where T : EventDetails, new()
{
IAsyncEnumerable<Event<T>> ReadAllAsync(CancellationToken token = default);

View file

@ -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;
}
}
}

View file

@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace INetMock.Client.Audit
namespace INetMock.Client.Audit.Serialization
{
public sealed class GenericReader : IEventReader<GenericDetails>
{
@ -14,7 +14,8 @@ namespace INetMock.Client.Audit
_reader = reader;
}
public async IAsyncEnumerable<Event<GenericDetails>> ReadAllAsync([EnumeratorCancellation] CancellationToken token = default)
public async IAsyncEnumerable<Event<GenericDetails>> ReadAllAsync(
[EnumeratorCancellation] CancellationToken token = default)
{
while (true)
{

View file

@ -5,7 +5,7 @@ using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
namespace INetMock.Client.Audit
namespace INetMock.Client.Audit.Serialization
{
public sealed class ProtoReader : IProtoEventReader
{

View file

@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace INetMock.Client.Audit
namespace INetMock.Client.Audit.Serialization
{
/// <summary>
/// Configures how the TypedReader proceeds with mismatching entities.

View file

@ -19,5 +19,6 @@
<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/health.proto" GrpcServices="Client" AdditionalImportDirs="./proto/" />
<Protobuf Include="proto/rpc/pcap.proto" GrpcServices="Client" AdditionalImportDirs="./proto/" />
</ItemGroup>
</Project>

View file

@ -1,9 +1,10 @@
using System.IO;
using INetMock.Client.Audit;
using INetMock.Client.Audit.Serialization;
using INetMock.Client.Test.Hex;
using Xunit;
namespace INetMock.Client.Test.Audit
namespace INetMock.Client.Test.Audit.Serialization
{
public class GenericReaderTest
{
@ -23,7 +24,7 @@ namespace INetMock.Client.Test.Audit
public async void TestRead_HttpEvent_Success()
{
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())
{
Assert.NotNull(ev);
@ -44,7 +45,7 @@ namespace INetMock.Client.Test.Audit
{
await using var memStream = 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())
{
Assert.NotNull(ev);

View file

@ -1,9 +1,10 @@
using System.IO;
using INetMock.Client.Audit;
using INetMock.Client.Audit.Serialization;
using INetMock.Client.Test.Hex;
using Xunit;
namespace INetMock.Client.Test.Audit
namespace INetMock.Client.Test.Audit.Serialization
{
public class TypedReaderTest
{
@ -23,7 +24,7 @@ namespace INetMock.Client.Test.Audit
public async void TestRead_HttpEvent_Success()
{
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())
{
Assert.NotNull(ev);
@ -34,7 +35,7 @@ namespace INetMock.Client.Test.Audit
public async void TestRead_DnsEvent_Success()
{
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())
{
Assert.NotNull(ev);