Compare commits

...

1 Commits

Author SHA1 Message Date
Pepe Fagoaga
a317bc3ec9 fix(findings): do not limit UID 2025-05-27 15:32:06 +02:00
8 changed files with 84 additions and 29 deletions

View File

@@ -10,6 +10,9 @@ All notable changes to the **Prowler API** are documented in this file.
### Changed
- Renamed field encrypted_password to password for M365 provider [(#7784)](https://github.com/prowler-cloud/prowler/pull/7784)
### Fixed
- Add support for Finding UID with no lenght limitation [(#XXXX)](https://github.com/prowler-cloud/prowler/pull/XXXX)
---
## [v1.8.2] (Prowler v5.7.2)

View File

@@ -166,7 +166,7 @@ class Command(BaseCommand):
Finding(
tenant_id=tenant_id,
scan=scan,
uid=f"testing-{uid_token}-{i}",
new_uid=f"testing-{uid_token}-{i}",
delta=random.choice(possible_deltas),
check_id=f"check-{check_id}",
status=random.choice(list(StatusChoices)),

View File

@@ -0,0 +1,17 @@
# Generated manually for adding new_uid field to Finding model
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("api", "0026_provider_secret_gcp_service_account"),
]
operations = [
migrations.AddField(
model_name="finding",
name="new_uid",
field=models.TextField(blank=True, null=True),
),
]

View File

@@ -668,6 +668,7 @@ class Finding(PostgresPartitionedModel, RowLevelSecurityProtectedModel):
first_seen_at = models.DateTimeField(editable=False, null=True)
uid = models.CharField(max_length=300)
new_uid = models.TextField(blank=True, null=True)
delta = FindingDeltaEnumField(
choices=DeltaChoices.choices,
blank=True,
@@ -767,6 +768,24 @@ class Finding(PostgresPartitionedModel, RowLevelSecurityProtectedModel):
class JSONAPIMeta:
resource_name = "findings"
@property
def effective_uid(self):
"""
Property to read the uid value. Returns new_uid if uid is null, otherwise returns uid.
This ensures backward compatibility.
"""
if self.uid is None:
return self.new_uid
return self.uid
@effective_uid.setter
def effective_uid(self, value):
"""
Property to set the uid value. Always stores in new_uid field.
This ensures new findings are stored in the new field.
"""
self.new_uid = value
def add_resources(self, resources: list[Resource] | None):
if not resources:
return

View File

@@ -1,6 +1,6 @@
import pytest
from api.models import Resource, ResourceTag
from api.models import Finding, Resource, ResourceTag, StatusChoices
@pytest.mark.django_db
@@ -94,29 +94,29 @@ class TestResourceModel:
assert resource.get_tags(tenant_id=tenant_id) == {}
# @pytest.mark.django_db
# class TestFindingModel:
# def test_add_finding_with_long_uid(
# self, providers_fixture, scans_fixture, resources_fixture
# ):
# provider, *_ = providers_fixture
# tenant_id = provider.tenant_id
@pytest.mark.django_db
class TestFindingModel:
def test_add_finding_with_long_uid(
self, providers_fixture, scans_fixture, resources_fixture
):
provider, *_ = providers_fixture
tenant_id = provider.tenant_id
# long_uid = "1" * 500
# _ = Finding.objects.create(
# tenant_id=tenant_id,
# uid=long_uid,
# delta=Finding.DeltaChoices.NEW,
# check_metadata={},
# status=StatusChoices.PASS,
# status_extended="",
# severity="high",
# impact="high",
# raw_result={},
# check_id="test_check",
# scan=scans_fixture[0],
# first_seen_at=None,
# muted=False,
# compliance={},
# )
# assert Finding.objects.filter(uid=long_uid).exists()
long_uid = "1" * 1000
_ = Finding.objects.create(
tenant_id=tenant_id,
new_uid=long_uid,
delta=Finding.DeltaChoices.NEW,
check_metadata={},
status=StatusChoices.PASS,
status_extended="",
severity="high",
impact="high",
raw_result={},
check_id="test_check",
scan=scans_fixture[0],
first_seen_at=None,
muted=False,
compliance={},
)
assert Finding.objects.filter(uid=long_uid).exists()

View File

@@ -1085,6 +1085,7 @@ class FindingSerializer(RLSSerializer):
"""
resources = serializers.ResourceRelatedField(many=True, read_only=True)
uid = serializers.SerializerMethodField()
class Meta:
model = Finding
@@ -1113,6 +1114,13 @@ class FindingSerializer(RLSSerializer):
"resources": ResourceIncludeSerializer,
}
def get_uid(self, obj):
"""
Custom getter for uid field that uses the effective_uid property.
This ensures backward compatibility.
"""
return obj.effective_uid
# To be removed when the related endpoint is removed as well
class FindingDynamicFilterSerializer(serializers.Serializer):

View File

@@ -631,6 +631,9 @@ def findings_fixture(scans_fixture, resources_fixture):
},
first_seen_at="2024-01-02T00:00:00Z",
)
# Set the uid using the effective_uid property
# finding1.effective_uid = "test_finding_uid_1"
# finding1.save()
finding1.add_resources([resource1])
@@ -658,6 +661,9 @@ def findings_fixture(scans_fixture, resources_fixture):
first_seen_at="2024-01-02T00:00:00Z",
muted=True,
)
# Set the uid using the effective_uid property
# finding2.effective_uid = "test_finding_uid_2"
# finding2.save()
finding2.add_resources([resource2])
@@ -943,7 +949,6 @@ def latest_scan_finding(authenticated_client, providers_fixture, resources_fixtu
)
finding = Finding.objects.create(
tenant_id=tenant_id,
uid="test_finding_uid_1",
scan=scan,
delta="new",
status=Status.FAIL,
@@ -964,6 +969,9 @@ def latest_scan_finding(authenticated_client, providers_fixture, resources_fixtu
},
first_seen_at="2024-01-02T00:00:00Z",
)
# Set the uid using the effective_uid property
finding.effective_uid = "test_finding_uid_1"
# finding.save()
finding.add_resources([resource])
backfill_resource_scan_summaries(tenant_id, str(scan.id))

View File

@@ -271,7 +271,7 @@ def perform_prowler_scan(
# Create the finding
finding_instance = Finding.objects.create(
tenant_id=tenant_id,
uid=finding_uid,
new_uid=finding_uid,
delta=delta,
check_metadata=finding.get_metadata(),
status=status,