mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-16 03:48:09 +00:00
121
src/ApiService/ApiService/TimerRetention.cs
Normal file
121
src/ApiService/ApiService/TimerRetention.cs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
using Microsoft.Azure.Functions.Worker;
|
||||||
|
|
||||||
|
namespace Microsoft.OneFuzz.Service;
|
||||||
|
|
||||||
|
public class TimerRetention
|
||||||
|
{
|
||||||
|
private readonly TimeSpan RETENTION_POLICY = TimeSpan.FromDays(18 * 30);
|
||||||
|
private readonly TimeSpan SEARCH_EXTENT = TimeSpan.FromDays(20 * 30);
|
||||||
|
|
||||||
|
private readonly ILogTracer _log;
|
||||||
|
private readonly ITaskOperations _taskOps;
|
||||||
|
private readonly INotificationOperations _notificaitonOps;
|
||||||
|
private readonly IJobOperations _jobOps;
|
||||||
|
private readonly IReproOperations _reproOps;
|
||||||
|
|
||||||
|
public TimerRetention(
|
||||||
|
ILogTracer log,
|
||||||
|
ITaskOperations taskOps,
|
||||||
|
INotificationOperations notificaitonOps,
|
||||||
|
IJobOperations jobOps,
|
||||||
|
IReproOperations reproOps)
|
||||||
|
{
|
||||||
|
_log = log;
|
||||||
|
_taskOps = taskOps;
|
||||||
|
_notificaitonOps = notificaitonOps;
|
||||||
|
_jobOps = jobOps;
|
||||||
|
_reproOps = reproOps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Async.Task Run([TimerTrigger("20:00:00")] TimerInfo t)
|
||||||
|
{
|
||||||
|
var now = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
|
var timeRetainedOlder = now - RETENTION_POLICY;
|
||||||
|
var timeRetainedNewer = now + SEARCH_EXTENT;
|
||||||
|
|
||||||
|
var timeFilter = $"Timestamp lt datetime'{timeRetainedOlder.ToString("o")}' and Timestamp gt datetime'{timeRetainedNewer.ToString("o")}'";
|
||||||
|
var timeFilterNewer = $"Timestamp gt datetime '{timeRetainedOlder.ToString("o")}'";
|
||||||
|
|
||||||
|
// Collecting 'still relevant' task containers.
|
||||||
|
// NOTE: This must be done before potentially modifying tasks otherwise
|
||||||
|
// the task timestamps will not be useful.\
|
||||||
|
|
||||||
|
var usedContainers = new HashSet<Container>();
|
||||||
|
|
||||||
|
await foreach (var task in _taskOps.QueryAsync(timeFilter))
|
||||||
|
{
|
||||||
|
var containerNames =
|
||||||
|
from container in task.Config.Containers
|
||||||
|
select container.Name;
|
||||||
|
|
||||||
|
foreach (var c in containerNames)
|
||||||
|
{
|
||||||
|
usedContainers.Add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await foreach (var notification in _notificaitonOps.QueryAsync(timeFilter))
|
||||||
|
{
|
||||||
|
_log.Verbose($"checking expired notification for removal: {notification.NotificationId}");
|
||||||
|
var container = notification.Container;
|
||||||
|
|
||||||
|
if (!usedContainers.Contains(container))
|
||||||
|
{
|
||||||
|
_log.Info($"deleting expired notification: {notification.NotificationId}");
|
||||||
|
var r = await _notificaitonOps.Delete(notification);
|
||||||
|
if (!r.IsOk)
|
||||||
|
{
|
||||||
|
_log.Error($"failed to delete notification with id {notification.NotificationId} due to [{r.ErrorV.Item1}] {r.ErrorV.Item2}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await foreach (var job in _jobOps.QueryAsync($"{timeFilter} and state eq '{JobState.Enabled}'"))
|
||||||
|
{
|
||||||
|
if (job.UserInfo is not null && job.UserInfo.Upn is not null)
|
||||||
|
{
|
||||||
|
_log.Info($"removing PII from job {job.JobId}");
|
||||||
|
var userInfo = job.UserInfo with { Upn = null };
|
||||||
|
var updatedJob = job with { UserInfo = userInfo };
|
||||||
|
var r = await _jobOps.Replace(updatedJob);
|
||||||
|
if (!r.IsOk)
|
||||||
|
{
|
||||||
|
_log.Error($"Failed to save job {updatedJob.JobId} due to [{r.ErrorV.Item1}] {r.ErrorV.Item2}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await foreach (var task in _taskOps.QueryAsync($"{timeFilter} and state eq '{TaskState.Stopped}'"))
|
||||||
|
{
|
||||||
|
if (task.UserInfo is not null && task.UserInfo.Upn is not null)
|
||||||
|
{
|
||||||
|
_log.Info($"removing PII from task {task.TaskId}");
|
||||||
|
var userInfo = task.UserInfo with { Upn = null };
|
||||||
|
var updatedTask = task with { UserInfo = userInfo };
|
||||||
|
var r = await _taskOps.Replace(updatedTask);
|
||||||
|
if (!r.IsOk)
|
||||||
|
{
|
||||||
|
_log.Error($"Failed to save task {updatedTask.TaskId} due to [{r.ErrorV.Item1}] {r.ErrorV.Item2}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await foreach (var repro in _reproOps.QueryAsync(timeFilter))
|
||||||
|
{
|
||||||
|
if (repro.UserInfo is not null && repro.UserInfo.Upn is not null)
|
||||||
|
{
|
||||||
|
_log.Info($"removing PII from repro: {repro.VmId}");
|
||||||
|
var userInfo = repro.UserInfo with { Upn = null };
|
||||||
|
var updatedRepro = repro with { UserInfo = userInfo };
|
||||||
|
var r = await _reproOps.Replace(updatedRepro);
|
||||||
|
if (!r.IsOk)
|
||||||
|
{
|
||||||
|
_log.Error($"Failed to save repro {updatedRepro.VmId} due to [{r.ErrorV.Item1}] {r.ErrorV.Item2}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -117,9 +117,6 @@ public class Containers : IContainers
|
|||||||
var SAS_START_TIME_DELTA = TimeSpan.FromHours(6);
|
var SAS_START_TIME_DELTA = TimeSpan.FromHours(6);
|
||||||
var SAS_END_TIME_DELTA = TimeSpan.FromMinutes(6);
|
var SAS_END_TIME_DELTA = TimeSpan.FromMinutes(6);
|
||||||
|
|
||||||
// SAS_START_TIME_DELTA = datetime.timedelta(hours = 6)
|
|
||||||
//SAS_END_TIME_DELTA = datetime.timedelta(minutes = 15)
|
|
||||||
|
|
||||||
var now = DateTimeOffset.UtcNow;
|
var now = DateTimeOffset.UtcNow;
|
||||||
var start = now - SAS_START_TIME_DELTA;
|
var start = now - SAS_START_TIME_DELTA;
|
||||||
var expiry = now + timeSpan + SAS_END_TIME_DELTA;
|
var expiry = now + timeSpan + SAS_END_TIME_DELTA;
|
||||||
|
@ -4,7 +4,7 @@ using Azure.Storage.Sas;
|
|||||||
|
|
||||||
namespace Microsoft.OneFuzz.Service;
|
namespace Microsoft.OneFuzz.Service;
|
||||||
|
|
||||||
public interface INotificationOperations
|
public interface INotificationOperations : IOrm<Notification>
|
||||||
{
|
{
|
||||||
Async.Task NewFiles(Container container, string filename, bool failTaskOnTransientError);
|
Async.Task NewFiles(Container container, string filename, bool failTaskOnTransientError);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ using ApiService.OneFuzzLib.Orm;
|
|||||||
|
|
||||||
namespace Microsoft.OneFuzz.Service;
|
namespace Microsoft.OneFuzz.Service;
|
||||||
|
|
||||||
public interface IReproOperations
|
public interface IReproOperations : IStatefulOrm<Repro, VmState>
|
||||||
{
|
{
|
||||||
public IAsyncEnumerable<Repro?> SearchExpired();
|
public IAsyncEnumerable<Repro?> SearchExpired();
|
||||||
}
|
}
|
||||||
|
@ -872,6 +872,13 @@ namespace Tests
|
|||||||
return Test(e);
|
return Test(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Property]
|
||||||
|
public bool Job(Job e)
|
||||||
|
{
|
||||||
|
return Test(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
//Sample function on how repro a failing test run, using Replay
|
//Sample function on how repro a failing test run, using Replay
|
||||||
//functionality of FsCheck. Feel free to
|
//functionality of FsCheck. Feel free to
|
||||||
|
Reference in New Issue
Block a user