mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-30 07:14:20 +00:00
feat(scan, schedule): add next_scan_at field to scans and POST /schedules/daily (#5978)
This commit is contained in:
1 parent
ff80a47123
commit
ffaa267b5e
11 files changed
+306
-30
No files matched your search
@@ -1,7 +1,8 @@
|
||||
import json
|
||||
|
||||
from django.utils import timezone
|
||||
from django_celery_beat.models import PeriodicTask, IntervalSchedule
|
||||
from django_celery_beat.models import IntervalSchedule, PeriodicTask
|
||||
from rest_framework_json_api.serializers import ValidationError
|
||||
from tasks.tasks import perform_scheduled_scan_task
|
||||
|
||||
from api.models import Provider
|
||||
|
||||
@@ -16,7 +17,7 @@ def schedule_provider_scan(provider_instance: Provider):
|
||||
task_name = f"scan-perform-scheduled-{provider_instance.id}"
|
||||
|
||||
# Schedule the task
|
||||
PeriodicTask.objects.create(
|
||||
_, created = PeriodicTask.objects.get_or_create(
|
||||
interval=schedule,
|
||||
name=task_name,
|
||||
task="scan-perform-scheduled",
|
||||
@@ -26,6 +27,23 @@ def schedule_provider_scan(provider_instance: Provider):
|
||||
"provider_id": str(provider_instance.id),
|
||||
}
|
||||
),
|
||||
start_time=provider_instance.inserted_at + timezone.timedelta(hours=24),
|
||||
one_off=False,
|
||||
)
|
||||
if not created:
|
||||
raise ValidationError(
|
||||
[
|
||||
{
|
||||
"detail": "There is already a scheduled scan for this provider.",
|
||||
"status": 400,
|
||||
"source": {"pointer": "/data/attributes/provider_id"},
|
||||
"code": "invalid",
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
return perform_scheduled_scan_task.apply_async(
|
||||
kwargs={
|
||||
"tenant_id": str(provider_instance.tenant_id),
|
||||
"provider_id": str(provider_instance.id),
|
||||
},
|
||||
)
|
||||
@@ -1,5 +1,8 @@
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from celery import shared_task
|
||||
from config.celery import RLSTask
|
||||
from django_celery_beat.models import PeriodicTask
|
||||
from tasks.jobs.connection import check_provider_connection
|
||||
from tasks.jobs.deletion import delete_provider
|
||||
from tasks.jobs.scan import aggregate_findings, perform_prowler_scan
|
||||
@@ -98,20 +101,34 @@ def perform_scheduled_scan_task(self, tenant_id: str, provider_id: str):
|
||||
|
||||
with tenant_transaction(tenant_id):
|
||||
provider_instance = Provider.objects.get(pk=provider_id)
|
||||
periodic_task_instance = PeriodicTask.objects.get(
|
||||
name=f"scan-perform-scheduled-{provider_id}"
|
||||
)
|
||||
next_scan_date = datetime.combine(
|
||||
datetime.now(timezone.utc), periodic_task_instance.date_changed.time()
|
||||
) + timedelta(hours=24)
|
||||
|
||||
scan_instance = Scan.objects.create(
|
||||
tenant_id=tenant_id,
|
||||
name="Daily scheduled scan",
|
||||
provider=provider_instance,
|
||||
trigger=Scan.TriggerChoices.SCHEDULED,
|
||||
next_scan_at=next_scan_date,
|
||||
task_id=task_id,
|
||||
)
|
||||
|
||||
return perform_prowler_scan(
|
||||
result = perform_prowler_scan(
|
||||
tenant_id=tenant_id,
|
||||
scan_id=str(scan_instance.id),
|
||||
provider_id=provider_id,
|
||||
)
|
||||
perform_scan_summary_task.apply_async(
|
||||
kwargs={
|
||||
"tenant_id": tenant_id,
|
||||
"scan_id": str(scan_instance.id),
|
||||
}
|
||||
),
|
||||
return result
|
||||
|
||||
|
||||
@shared_task(name="scan-summary")
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from django_celery_beat.models import IntervalSchedule, PeriodicTask
|
||||
from rest_framework_json_api.serializers import ValidationError
|
||||
from tasks.beat import schedule_provider_scan
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestScheduleProviderScan:
|
||||
def test_schedule_provider_scan_success(self, providers_fixture):
|
||||
provider_instance, *_ = providers_fixture
|
||||
|
||||
with patch(
|
||||
"tasks.tasks.perform_scheduled_scan_task.apply_async"
|
||||
) as mock_apply_async:
|
||||
result = schedule_provider_scan(provider_instance)
|
||||
|
||||
assert result is not None
|
||||
|
||||
mock_apply_async.assert_called_once_with(
|
||||
kwargs={
|
||||
"tenant_id": str(provider_instance.tenant_id),
|
||||
"provider_id": str(provider_instance.id),
|
||||
},
|
||||
)
|
||||
|
||||
task_name = f"scan-perform-scheduled-{provider_instance.id}"
|
||||
periodic_task = PeriodicTask.objects.get(name=task_name)
|
||||
assert periodic_task is not None
|
||||
assert periodic_task.interval.every == 24
|
||||
assert periodic_task.interval.period == IntervalSchedule.HOURS
|
||||
assert periodic_task.task == "scan-perform-scheduled"
|
||||
assert json.loads(periodic_task.kwargs) == {
|
||||
"tenant_id": str(provider_instance.tenant_id),
|
||||
"provider_id": str(provider_instance.id),
|
||||
}
|
||||
|
||||
def test_schedule_provider_scan_already_exists(self, providers_fixture):
|
||||
provider_instance, *_ = providers_fixture
|
||||
|
||||
# First, schedule the scan
|
||||
with patch("tasks.tasks.perform_scheduled_scan_task.apply_async"):
|
||||
schedule_provider_scan(provider_instance)
|
||||
|
||||
# Now, try scheduling again, should raise ValidationError
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
schedule_provider_scan(provider_instance)
|
||||
|
||||
assert "There is already a scheduled scan for this provider." in str(
|
||||
exc_info.value
|
||||
)
|
||||
Reference in new issue
Block a user