mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-18 12:48:07 +00:00
automatically clean PII after retention period (#1051)
This PR removes PII from Jobs, Tasks, and Repros after 18 months. This PR also removes notifications tied to a container that has not been used in a task for 18 months. This is done due to notifications having arbitrarily complex mechanisms for storing PII (typically the "assignee").
This commit is contained in:
79
src/api-service/__app__/timer_retention/__init__.py
Normal file
79
src/api-service/__app__/timer_retention/__init__.py
Normal file
@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
import azure.functions as func
|
||||
from onefuzztypes.enums import JobState, TaskState
|
||||
|
||||
from ..onefuzzlib.events import get_events
|
||||
from ..onefuzzlib.jobs import Job
|
||||
from ..onefuzzlib.notifications.main import Notification
|
||||
from ..onefuzzlib.repro import Repro
|
||||
from ..onefuzzlib.tasks.main import Task
|
||||
|
||||
RETENTION_POLICY = datetime.timedelta(days=(18 * 30))
|
||||
SEARCH_EXTENT = datetime.timedelta(days=(20 * 30))
|
||||
|
||||
|
||||
def main(mytimer: func.TimerRequest, dashboard: func.Out[str]) -> None: # noqa: F841
|
||||
|
||||
now = datetime.datetime.now(tz=datetime.timezone.utc)
|
||||
|
||||
time_retained_older = now - RETENTION_POLICY
|
||||
time_retained_newer = now - SEARCH_EXTENT
|
||||
|
||||
time_filter = (
|
||||
f"Timestamp lt datetime'{time_retained_older.isoformat()}' "
|
||||
f"and Timestamp gt datetime'{time_retained_newer.isoformat()}'"
|
||||
)
|
||||
time_filter_newer = f"Timestamp gt datetime'{time_retained_older.isoformat()}'"
|
||||
|
||||
# Collecting 'still relevant' task containers.
|
||||
# NOTE: This must be done before potentially modifying tasks otherwise
|
||||
# the task timestamps will not be useful.
|
||||
used_containers = set()
|
||||
for task in Task.search(raw_unchecked_filter=time_filter_newer):
|
||||
task_containers = {x.name for x in task.config.containers}
|
||||
used_containers.update(task_containers)
|
||||
|
||||
for notification in Notification.search(raw_unchecked_filter=time_filter):
|
||||
logging.debug(
|
||||
"checking expired notification for removal: %s",
|
||||
notification.notification_id,
|
||||
)
|
||||
container = notification.container
|
||||
if container not in used_containers:
|
||||
logging.info(
|
||||
"deleting expired notification: %s", notification.notification_id
|
||||
)
|
||||
notification.delete()
|
||||
|
||||
for job in Job.search(
|
||||
query={"state": [JobState.stopped]}, raw_unchecked_filter=time_filter
|
||||
):
|
||||
if job.user_info is not None and job.user_info.upn is not None:
|
||||
logging.info("removing PII from job: %s", job.job_id)
|
||||
job.user_info.upn = None
|
||||
job.save()
|
||||
|
||||
for task in Task.search(
|
||||
query={"state": [TaskState.stopped]}, raw_unchecked_filter=time_filter
|
||||
):
|
||||
if task.user_info is not None and task.user_info.upn is not None:
|
||||
logging.info("removing PII from task: %s", task.task_id)
|
||||
task.user_info.upn = None
|
||||
task.save()
|
||||
|
||||
for repro in Repro.search(raw_unchecked_filter=time_filter):
|
||||
if repro.user_info is not None and repro.user_info.upn is not None:
|
||||
logging.info("removing PII from repro: %s", repro.vm_id)
|
||||
repro.user_info.upn = None
|
||||
repro.save()
|
||||
|
||||
events = get_events()
|
||||
if events:
|
||||
dashboard.set(events)
|
17
src/api-service/__app__/timer_retention/function.json
Normal file
17
src/api-service/__app__/timer_retention/function.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"bindings": [
|
||||
{
|
||||
"direction": "in",
|
||||
"name": "mytimer",
|
||||
"schedule": "20:00:00",
|
||||
"type": "timerTrigger"
|
||||
},
|
||||
{
|
||||
"type": "signalR",
|
||||
"direction": "out",
|
||||
"name": "dashboard",
|
||||
"hubName": "dashboard"
|
||||
}
|
||||
],
|
||||
"scriptFile": "__init__.py"
|
||||
}
|
Reference in New Issue
Block a user