Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Commit f4d2250

Browse files
committed
Merge branch 'main' of https://github.com/microsoft/onefuzz into tevoinea/MoreTruncations
2 parents 68deb5f + 6397803 commit f4d2250

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+781
-247
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ lcov.info
1919
/src/ApiService/ApiService/Properties/PublishProfiles/*
2020
/src/ApiService/ApiService/Properties/ServiceDependencies/*
2121

22-
.vs
22+
.vs
23+
24+
**/__azurite_db_*.json
25+
**/__blobstorage__
26+
**/__queuestorage__

src/ApiService/ApiService/ApiService.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<PackageReference Include="Azure.Data.Tables" Version="12.8.0" />
2929
<PackageReference Include="Azure.ResourceManager.Compute" Version="1.0.0-beta.8" />
3030
<PackageReference Include="Azure.Identity" Version="1.8.2" />
31-
<PackageReference Include="Azure.Messaging.EventGrid" Version="4.10.0" />
31+
<PackageReference Include="Azure.Messaging.EventGrid" Version="4.15.0" />
3232
<PackageReference Include="Azure.ResourceManager" Version="1.3.1" />
3333
<PackageReference Include="Azure.ResourceManager.Network" Version="1.0.0" />
3434
<PackageReference Include="Azure.ResourceManager.Resources" Version="1.3.0" />
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Microsoft.Azure.Functions.Worker;
2+
using Microsoft.Azure.Functions.Worker.Http;
3+
4+
namespace Microsoft.OneFuzz.Service.Functions;
5+
6+
public class EventsFunction {
7+
private readonly ILogTracer _log;
8+
private readonly IEndpointAuthorization _auth;
9+
private readonly IOnefuzzContext _context;
10+
11+
public EventsFunction(ILogTracer log, IEndpointAuthorization auth, IOnefuzzContext context) {
12+
_auth = auth;
13+
_context = context;
14+
_log = log;
15+
}
16+
17+
[Function("Events")]
18+
public Async.Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymous, "GET")] HttpRequestData req)
19+
=> _auth.CallIfUser(req, r => r.Method switch {
20+
"GET" => Get(r),
21+
_ => throw new NotSupportedException(),
22+
});
23+
24+
private async Async.Task<HttpResponseData> Get(HttpRequestData req) {
25+
var request = await RequestHandling.ParseRequest<EventsGet>(req);
26+
if (!request.IsOk) {
27+
return await _context.RequestHandling.NotOk(req, request.ErrorV, "events get");
28+
}
29+
30+
var eventsGet = request.OkV;
31+
32+
var requestedEvent = await _context.Events.GetDownloadableEvent(eventsGet.EventId);
33+
if (!requestedEvent.IsOk) {
34+
return await _context.RequestHandling.NotOk(req, requestedEvent.ErrorV, "events get");
35+
}
36+
37+
return await RequestHandling.Ok(req, new EventGetResponse(requestedEvent.OkV));
38+
}
39+
}

src/ApiService/ApiService/OneFuzzTypes/Enums.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public enum ErrorCode {
3636
ADO_VALIDATION_INVALID_FIELDS = 479,
3737
GITHUB_VALIDATION_INVALID_PAT = 480,
3838
GITHUB_VALIDATION_INVALID_REPOSITORY = 481,
39+
UNEXPECTED_DATA_SHAPE = 482,
40+
UNABLE_TO_SEND = 483,
3941
}
4042

4143
public enum VmState {

src/ApiService/ApiService/OneFuzzTypes/Events.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,30 +50,28 @@ public enum EventType {
5050
}
5151

5252
public abstract record BaseEvent() {
53-
54-
private static readonly IReadOnlyDictionary<Type, EventType> typeToEvent;
55-
private static readonly IReadOnlyDictionary<EventType, Type> eventToType;
53+
private static readonly IReadOnlyDictionary<Type, EventType> _typeToEvent;
54+
private static readonly IReadOnlyDictionary<EventType, Type> _eventToType;
5655

5756
static BaseEvent() {
58-
59-
EventType ExtractEventType(Type type) {
57+
static EventType ExtractEventType(Type type) {
6058
var attr = type.GetCustomAttribute<EventTypeAttribute>();
6159
if (attr is null) {
6260
throw new InvalidOperationException($"Type {type} is missing {nameof(EventTypeAttribute)}");
6361
}
6462
return attr.EventType;
6563
}
6664

67-
typeToEvent =
65+
_typeToEvent =
6866
typeof(BaseEvent).Assembly.GetTypes()
6967
.Where(t => t.IsSubclassOf(typeof(BaseEvent)))
7068
.ToDictionary(x => x, ExtractEventType);
7169

72-
eventToType = typeToEvent.ToDictionary(x => x.Value, x => x.Key);
70+
_eventToType = _typeToEvent.ToDictionary(x => x.Value, x => x.Key);
7371

7472
// check that all event types are accounted for
7573
var allEventTypes = Enum.GetValues<EventType>();
76-
var missingEventTypes = allEventTypes.Except(eventToType.Keys).ToList();
74+
var missingEventTypes = allEventTypes.Except(_eventToType.Keys).ToList();
7775
if (missingEventTypes.Any()) {
7876
throw new InvalidOperationException($"Missing event types: {string.Join(", ", missingEventTypes)}");
7977
}
@@ -82,15 +80,15 @@ EventType ExtractEventType(Type type) {
8280

8381
public EventType GetEventType() {
8482
var type = this.GetType();
85-
if (typeToEvent.TryGetValue(type, out var eventType)) {
83+
if (_typeToEvent.TryGetValue(type, out var eventType)) {
8684
return eventType;
8785
}
8886

8987
throw new NotSupportedException($"Unknown event type: {type.GetType()}");
9088
}
9189

9290
public static Type GetTypeInfo(EventType eventType) {
93-
if (eventToType.TryGetValue(eventType, out var type)) {
91+
if (_eventToType.TryGetValue(eventType, out var type)) {
9492
return type;
9593
}
9694

@@ -350,14 +348,24 @@ public record EventNotificationFailed(
350348
Error? Error
351349
) : BaseEvent();
352350

351+
public record DownloadableEventMessage : EventMessage {
352+
public Uri SasUrl { get; init; }
353+
354+
public DownloadableEventMessage(Guid EventId, EventType EventType, BaseEvent Event, Guid InstanceId, string InstanceName, DateTime CreatedAt, Uri SasUrl)
355+
: base(EventId, EventType, Event, InstanceId, InstanceName, CreatedAt) {
356+
this.SasUrl = SasUrl;
357+
}
358+
}
353359
public record EventMessage(
354360
Guid EventId,
355361
EventType EventType,
356362
[property: TypeDiscrimnatorAttribute("EventType", typeof(EventTypeProvider))]
357363
[property: JsonConverter(typeof(BaseEventConverter))]
358364
BaseEvent Event,
359365
Guid InstanceId,
360-
String InstanceName
366+
String InstanceName,
367+
DateTime CreatedAt,
368+
String Version = "1.0"
361369
);
362370

363371
public class BaseEventConverter : JsonConverter<BaseEvent> {

src/ApiService/ApiService/OneFuzzTypes/Requests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,3 +328,7 @@ public record TemplateValidationPost(
328328
public record JinjaToScribanMigrationPost(
329329
bool DryRun = false
330330
) : BaseRequest;
331+
332+
public record EventsGet(
333+
[property: Required] Guid EventId
334+
) : BaseRequest;

src/ApiService/ApiService/OneFuzzTypes/Responses.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ public record JinjaToScribanMigrationDryRunResponse(
206206
List<Guid> NotificationIdsToUpdate
207207
) : BaseResponse();
208208

209+
public record EventGetResponse(
210+
DownloadableEventMessage Event
211+
) : BaseResponse();
212+
209213
public record NotificationTestResponse(
210214
bool Success,
211215
string? Error = null

src/ApiService/ApiService/OneFuzzTypes/Webhooks.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ public record WebhookMessage(Guid EventId,
1919
BaseEvent Event,
2020
Guid InstanceId,
2121
String InstanceName,
22-
Guid WebhookId) : EventMessage(EventId, EventType, Event, InstanceId, InstanceName);
22+
Guid WebhookId,
23+
DateTime CreatedAt,
24+
Uri SasUrl) : DownloadableEventMessage(EventId, EventType, Event, InstanceId, InstanceName, CreatedAt, SasUrl);
2325

2426

2527
public record WebhookMessageEventGrid(
@@ -30,7 +32,9 @@ public record WebhookMessageEventGrid(
3032
Guid Id,
3133
[property: TypeDiscrimnatorAttribute("EventType", typeof(EventTypeProvider))]
3234
[property: JsonConverter(typeof(BaseEventConverter))]
33-
BaseEvent Data);
35+
BaseEvent Data,
36+
Uri SasUrl,
37+
String Version = "1.0");
3438

3539
public record WebhookMessageLog(
3640
[RowKey] Guid EventId,

src/ApiService/ApiService/TestHooks/EventsTestHooks.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public async Task<HttpResponseData> LogEvent([HttpTrigger(AuthorizationLevel.Ano
2525
_log.Info($"Log event");
2626

2727
var s = await req.ReadAsStringAsync();
28-
var msg = JsonSerializer.Deserialize<EventMessage>(s!, EntityConverter.GetJsonSerializerOptions());
28+
var msg = JsonSerializer.Deserialize<DownloadableEventMessage>(s!, EntityConverter.GetJsonSerializerOptions());
2929
_events.LogEvent(msg!.Event);
3030
var resp = req.CreateResponse(HttpStatusCode.OK);
3131
return resp;
@@ -37,7 +37,7 @@ public async Task<HttpResponseData> SendEvent([HttpTrigger(AuthorizationLevel.An
3737
_log.Info($"Send event");
3838

3939
var s = await req.ReadAsStringAsync();
40-
var msg = JsonSerializer.Deserialize<EventMessage>(s!, EntityConverter.GetJsonSerializerOptions());
40+
var msg = JsonSerializer.Deserialize<DownloadableEventMessage>(s!, EntityConverter.GetJsonSerializerOptions());
4141
await _events.SendEvent(msg!.Event);
4242
var resp = req.CreateResponse(HttpStatusCode.OK);
4343
return resp;

src/ApiService/ApiService/onefuzzlib/Events.cs

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System.Text.Json;
22
using System.Text.Json.Serialization;
33
using Azure;
4+
using System.Threading.Tasks;
5+
using Azure.Storage.Sas;
46
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
57

68
namespace Microsoft.OneFuzz.Service {
@@ -9,16 +11,20 @@ namespace Microsoft.OneFuzz.Service {
911
public record SignalREvent
1012
(
1113
string Target,
12-
List<EventMessage> arguments
14+
List<DownloadableEventMessage> arguments
1315
);
1416

1517

1618
public interface IEvents {
1719
Async.Task SendEvent(BaseEvent anEvent);
1820

19-
Async.Task QueueSignalrEvent(EventMessage message);
21+
Async.Task QueueSignalrEvent(DownloadableEventMessage message);
2022

2123
void LogEvent(BaseEvent anEvent);
24+
25+
Async.Task<OneFuzzResult<EventMessage>> GetEvent(Guid eventId);
26+
Async.Task<OneFuzzResult<DownloadableEventMessage>> GetDownloadableEvent(Guid eventId);
27+
Async.Task<DownloadableEventMessage> MakeDownloadable(EventMessage eventMessage);
2228
}
2329

2430
public class Events : IEvents {
@@ -29,63 +35,119 @@ public class Events : IEvents {
2935
private readonly ICreds _creds;
3036
private readonly JsonSerializerOptions _options;
3137

32-
public Events(IQueue queue, IWebhookOperations webhook, ILogTracer log, IContainers containers, ICreds creds) {
33-
_queue = queue;
34-
_webhook = webhook;
38+
public Events(ILogTracer log, IOnefuzzContext context) {
39+
_queue = context.Queue;
40+
_webhook = context.WebhookOperations;
3541
_log = log;
36-
_containers = containers;
37-
_creds = creds;
42+
_containers = context.Containers;
43+
_creds = context.Creds;
3844
_options = new JsonSerializerOptions(EntityConverter.GetJsonSerializerOptions()) {
3945
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
4046
};
4147
_options.Converters.Add(new RemoveUserInfo());
4248
}
4349

44-
public async Async.Task QueueSignalrEvent(EventMessage message) {
50+
public virtual async Async.Task QueueSignalrEvent(DownloadableEventMessage message) {
4551
var tags = new (string, string)[] {
4652
("event_type", message.EventType.ToString()),
4753
("event_id", message.EventId.ToString())
4854
};
4955
try {
50-
var ev = new SignalREvent("events", new List<EventMessage>() { message });
56+
var ev = new SignalREvent("events", new List<DownloadableEventMessage>() { message });
5157
await _queue.SendMessage("signalr-events", JsonSerializer.Serialize(ev, _options), StorageType.Config);
5258
} catch (RequestFailedException ex) {
5359
if (ex.Message.Contains("The request body is too large") && message.Event is ITruncatable<BaseEvent> truncatableEvent) {
5460
_log.WithTags(tags).Warning($"The EventMessage was too large for Azure Queue. Truncating event data and trying again.");
5561
message = message with {
5662
Event = truncatableEvent.Truncate(1000)
5763
};
58-
var ev = new SignalREvent("events", new List<EventMessage>() { message });
64+
var ev = new SignalREvent("events", new List<DownloadableEventMessage>() { message });
5965
await _queue.SendMessage("signalr-events", JsonSerializer.Serialize(ev, _options), StorageType.Config);
6066
} else {
6167
// Not handled
6268
throw ex;
6369
}
6470
}
65-
6671
}
6772

6873
public async Async.Task SendEvent(BaseEvent anEvent) {
6974
var eventType = anEvent.GetEventType();
7075

7176
var instanceId = await _containers.GetInstanceId();
72-
77+
var creationDate = DateTime.UtcNow;
7378
var eventMessage = new EventMessage(
7479
Guid.NewGuid(),
7580
eventType,
7681
anEvent,
7782
instanceId,
78-
_creds.GetInstanceName()
83+
_creds.GetInstanceName(),
84+
creationDate
7985
);
80-
await QueueSignalrEvent(eventMessage);
81-
await _webhook.SendEvent(eventMessage);
86+
87+
var downloadableEventMessage = await MakeDownloadable(eventMessage);
88+
89+
await QueueSignalrEvent(downloadableEventMessage);
90+
await _webhook.SendEvent(downloadableEventMessage);
8291
LogEvent(anEvent);
8392
}
8493

85-
public void LogEvent(BaseEvent anEvent) {
94+
public virtual void LogEvent(BaseEvent anEvent) {
8695
var serializedEvent = JsonSerializer.Serialize(anEvent, anEvent.GetType(), _options);
8796
_log.Info($"sending event: {anEvent.GetEventType():Tag:EventType} - {serializedEvent}");
8897
}
98+
99+
public async Async.Task<OneFuzzResult<EventMessage>> GetEvent(Guid eventId) {
100+
var blob = await _containers.GetBlob(WellKnownContainers.Events, eventId.ToString(), StorageType.Corpus);
101+
if (blob == null) {
102+
return OneFuzzResult<EventMessage>.Error(ErrorCode.UNABLE_TO_FIND, $"Could not find container for event with id {eventId}");
103+
}
104+
105+
var eventMessage = JsonSerializer.Deserialize<EventMessage>(blob, _options);
106+
if (eventMessage == null) {
107+
return OneFuzzResult<EventMessage>.Error(ErrorCode.UNEXPECTED_DATA_SHAPE, $"Could not deserialize event with id {eventId}");
108+
}
109+
110+
return OneFuzzResult<EventMessage>.Ok(eventMessage);
111+
}
112+
113+
public async Async.Task<OneFuzzResult<DownloadableEventMessage>> GetDownloadableEvent(Guid eventId) {
114+
var eventMessageResult = await GetEvent(eventId);
115+
if (!eventMessageResult.IsOk) {
116+
return eventMessageResult.ErrorV;
117+
}
118+
119+
var sasUrl = await _containers.GetFileSasUrl(WellKnownContainers.Events, eventId.ToString(), StorageType.Corpus, BlobSasPermissions.Read);
120+
if (sasUrl == null) {
121+
return OneFuzzResult<DownloadableEventMessage>.Error(ErrorCode.UNABLE_TO_FIND, $"Could not find container for event with id {eventId}");
122+
}
123+
124+
var eventMessage = eventMessageResult.OkV!;
125+
126+
return OneFuzzResult<DownloadableEventMessage>.Ok(new DownloadableEventMessage(
127+
eventMessage.EventId,
128+
eventMessage.EventType,
129+
eventMessage.Event,
130+
eventMessage.InstanceId,
131+
eventMessage.InstanceName,
132+
eventMessage.CreatedAt,
133+
sasUrl
134+
));
135+
}
136+
137+
public async Task<DownloadableEventMessage> MakeDownloadable(EventMessage eventMessage) {
138+
await _containers.SaveBlob(WellKnownContainers.Events, eventMessage.EventId.ToString(), JsonSerializer.Serialize(eventMessage, _options), StorageType.Corpus);
139+
var sasUrl = await _containers.GetFileSasUrl(WellKnownContainers.Events, eventMessage.EventId.ToString(), StorageType.Corpus, BlobSasPermissions.Read);
140+
141+
return new DownloadableEventMessage(
142+
eventMessage.EventId,
143+
eventMessage.EventType,
144+
eventMessage.Event,
145+
eventMessage.InstanceId,
146+
eventMessage.InstanceName,
147+
eventMessage.CreatedAt,
148+
sasUrl
149+
);
150+
}
89151
}
90152

91153

0 commit comments

Comments
 (0)