fix: address PR review comments for Image provider

- Extract _is_registry_url() into ImageProvider to deduplicate logic
- Restore relative URL handling in _next_page_url for path-only Link headers
- Yield empty findings on generic error in scan_per_image
- Add credential validation to ImageProviderSecret serializer
This commit is contained in:
Andoni A. committed 2026-02-23 08:04:51 +01:00
1 parent f5f91f85d4
commit 18bac5a890
7 files changed
+115 -34

No files matched your search

@@ -2,6 +2,7 @@ import pytest
from rest_framework.exceptions import ValidationError
from api.v1.serializer_utils.integrations import S3ConfigSerializer
from api.v1.serializers import ImageProviderSecret
class TestS3ConfigSerializer:
@@ -98,3 +99,37 @@ class TestS3ConfigSerializer:
serializer = S3ConfigSerializer(data=data)
assert not serializer.is_valid()
assert "output_directory" in serializer.errors
class TestImageProviderSecret:
"""Test cases for ImageProviderSecret validation."""
def test_valid_no_credentials(self):
serializer = ImageProviderSecret(data={})
assert serializer.is_valid()
def test_valid_token_only(self):
serializer = ImageProviderSecret(data={"registry_token": "tok"})
assert serializer.is_valid()
def test_valid_username_and_password(self):
serializer = ImageProviderSecret(
data={"registry_username": "user", "registry_password": "pass"}
)
assert serializer.is_valid()
def test_valid_token_with_username_only(self):
serializer = ImageProviderSecret(
data={"registry_token": "tok", "registry_username": "user"}
)
assert serializer.is_valid()
def test_invalid_username_without_password(self):
serializer = ImageProviderSecret(data={"registry_username": "user"})
assert not serializer.is_valid()
assert "non_field_errors" in serializer.errors
def test_invalid_password_without_username(self):
serializer = ImageProviderSecret(data={"registry_password": "pass"})
assert not serializer.is_valid()
assert "non_field_errors" in serializer.errors
+3 -15
View File
@@ -230,28 +230,16 @@ def get_prowler_provider_kwargs(
elif provider.provider == Provider.ProviderChoices.IMAGE.value:
# Detect whether uid is a registry URL (e.g. "docker.io/andoniaf") or
# a concrete image reference (e.g. "docker.io/andoniaf/myimage:latest").
# Uses the same heuristic as ImageProvider.test_connection.
from prowler.providers.image.image_provider import ImageProvider
image_uid = provider.uid
registry_host = ImageProvider._extract_registry(image_uid)
if registry_host:
repo_and_tag = image_uid[len(registry_host) + 1 :]
else:
repo_and_tag = image_uid
is_registry_url = (
registry_host and "/" not in repo_and_tag and ":" not in repo_and_tag
)
if is_registry_url:
if ImageProvider._is_registry_url(provider.uid):
prowler_provider_kwargs = {
"registry": image_uid,
"registry": provider.uid,
**{k: v for k, v in prowler_provider_kwargs.items() if v},
}
else:
prowler_provider_kwargs = {
"images": [image_uid],
"images": [provider.uid],
**{k: v for k, v in prowler_provider_kwargs.items() if v},
}
+15
View File
@@ -1712,6 +1712,21 @@ class ImageProviderSecret(serializers.Serializer):
class Meta:
resource_name = "provider-secrets"
def validate(self, attrs):
token = attrs.get("registry_token")
username = attrs.get("registry_username")
password = attrs.get("registry_password")
if not token:
if username and not password:
raise serializers.ValidationError(
"registry_password is required when registry_username is provided."
)
if password and not username:
raise serializers.ValidationError(
"registry_username is required when registry_password is provided."
)
return attrs
class AlibabaCloudProviderSecret(serializers.Serializer):
access_key_id = serializers.CharField()