fix(api): store and refresh Resource.name on every scan (#11476)

Co-authored-by: Josema Camacho <josema@prowler.com>
This commit is contained in:
Pedro Martín
2026-06-10 10:55:31 +02:00
committed by GitHub
parent a21cb64a94
commit 4a5a49b5bb
3 changed files with 83 additions and 0 deletions
+1
View File
@@ -17,6 +17,7 @@ All notable changes to the **Prowler API** are documented in this file.
### 🐞 Fixed
- Workers now shut down gracefully on deploy or restart, finishing or re-queueing in-flight tasks instead of being force-killed and leaving them stuck [(#11416)](https://github.com/prowler-cloud/prowler/pull/11416)
- Resource `name` is now stored and refreshed on every scan, so resources no longer keep an empty name [(#11476)](https://github.com/prowler-cloud/prowler/pull/11476)
### 🔐 Security
+9
View File
@@ -269,6 +269,7 @@ def _store_resources(
provider=provider_instance,
uid=finding.resource_uid,
defaults={
"name": finding.resource_name,
"region": finding.region,
"service": finding.service_name,
"type": finding.resource_type,
@@ -276,6 +277,7 @@ def _store_resources(
)
if not created:
resource_instance.name = finding.resource_name
resource_instance.region = finding.region
resource_instance.service = finding.service_name
resource_instance.type = finding.resource_type
@@ -704,6 +706,12 @@ def _process_finding_micro_batch(
if finding.region and resource_instance.region != finding.region:
resource_instance.region = finding.region
updated = True
if (
finding.resource_name
and resource_instance.name != finding.resource_name
):
resource_instance.name = finding.resource_name
updated = True
if resource_instance.service != finding.service_name:
resource_instance.service = finding.service_name
updated = True
@@ -945,6 +953,7 @@ def _process_finding_micro_batch(
Resource.objects.bulk_update(
resources_to_bulk_update,
[
"name",
"metadata",
"details",
"partition",
+73
View File
@@ -315,6 +315,7 @@ class TestPerformScan:
provider=provider_instance,
uid=finding.resource_uid,
defaults={
"name": finding.resource_name,
"region": finding.region,
"service": finding.service_name,
"type": finding.resource_type,
@@ -348,6 +349,7 @@ class TestPerformScan:
resource_instance = MagicMock()
resource_instance.uid = finding.resource_uid
resource_instance.name = "old_name"
resource_instance.region = "us-west-1"
resource_instance.service = "old_service"
resource_instance.type = "old_type"
@@ -366,6 +368,7 @@ class TestPerformScan:
provider=provider_instance,
uid=finding.resource_uid,
defaults={
"name": finding.resource_name,
"region": finding.region,
"service": finding.service_name,
"type": finding.resource_type,
@@ -373,6 +376,7 @@ class TestPerformScan:
)
# Check that resource fields were updated
assert resource_instance.name == finding.resource_name
assert resource_instance.region == finding.region
assert resource_instance.service == finding.service_name
assert resource_instance.type == finding.resource_type
@@ -1565,6 +1569,75 @@ class TestProcessFindingMicroBatch:
assert resource_cache[finding.resource_uid].service == finding.service_name
assert tag_cache.keys() == {("team", "devsec")}
def test_process_finding_micro_batch_refreshes_empty_resource_name(
self, tenants_fixture, scans_fixture
):
tenant = tenants_fixture[0]
scan = scans_fixture[0]
provider = scan.provider
# Old resource stored before names were persisted: empty name.
existing_resource = Resource.objects.create(
tenant_id=tenant.id,
provider=provider,
uid="arn:aws:s3:::my-bucket",
name="",
region="us-east-1",
service="s3",
type="bucket",
)
finding = FakeFinding(
uid="finding-empty-name",
status=StatusChoices.PASS,
status_extended="passing",
severity=Severity.low,
check_id="s3_bucket_public_access",
resource_uid=existing_resource.uid,
resource_name="my-bucket",
region="us-east-1",
service_name="s3",
resource_type="bucket",
partition="aws",
raw={"status": "PASS"},
metadata={"source": "prowler"},
)
resource_cache = {existing_resource.uid: existing_resource}
tag_cache = {}
last_status_cache = {}
resource_failed_findings_cache = {existing_resource.uid: 0}
unique_resources: set[tuple[str, str]] = set()
scan_resource_cache: set[tuple[str, str, str, str]] = set()
mute_rules_cache = {}
scan_categories_cache: dict[tuple[str, str], dict[str, int]] = {}
scan_resource_groups_cache: dict[tuple[str, str], dict[str, int]] = {}
group_resources_cache: dict[str, set] = {}
with (
patch("tasks.jobs.scan.rls_transaction", new=noop_rls_transaction),
patch("api.db_utils.rls_transaction", new=noop_rls_transaction),
):
_process_finding_micro_batch(
str(tenant.id),
[finding],
scan,
provider,
resource_cache,
tag_cache,
last_status_cache,
resource_failed_findings_cache,
unique_resources,
scan_resource_cache,
mute_rules_cache,
scan_categories_cache,
scan_resource_groups_cache,
group_resources_cache,
)
existing_resource.refresh_from_db()
assert existing_resource.name == finding.resource_name
def test_process_finding_micro_batch_skips_long_uid(
self, tenants_fixture, scans_fixture
):