mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-11-02 01:15:31 +00:00
feat: add SDK contract for dynamic provider construction args
- Add get_scan_arguments/get_connection_arguments to the provider contract - Route non-built-in providers through the contract; built-ins unchanged - Cover the external dynamic path in tests
This commit is contained in:
1 parent
cd15ed07eb
commit
51581c35ec
3 files changed
+106
-5
No files matched your search
@@ -164,6 +164,7 @@ class TestInitializeProwlerProvider:
|
||||
@patch("api.utils.return_prowler_provider")
|
||||
def test_initialize_prowler_provider(self, mock_return_prowler_provider):
|
||||
provider = MagicMock()
|
||||
provider.provider = "aws"
|
||||
provider.secret.secret = {"key": "value"}
|
||||
mock_return_prowler_provider.return_value = MagicMock()
|
||||
|
||||
@@ -175,6 +176,7 @@ class TestInitializeProwlerProvider:
|
||||
self, mock_return_prowler_provider
|
||||
):
|
||||
provider = MagicMock()
|
||||
provider.provider = "aws"
|
||||
provider.secret.secret = {"key": "value"}
|
||||
mutelist_processor = MagicMock()
|
||||
mutelist_processor.configuration = {"Mutelist": {"key": "value"}}
|
||||
@@ -190,6 +192,7 @@ class TestProwlerProviderConnectionTest:
|
||||
@patch("api.utils.return_prowler_provider")
|
||||
def test_prowler_provider_connection_test(self, mock_return_prowler_provider):
|
||||
provider = MagicMock()
|
||||
provider.provider = "aws"
|
||||
provider.uid = "1234567890"
|
||||
provider.secret.secret = {"key": "value"}
|
||||
mock_return_prowler_provider.return_value = MagicMock()
|
||||
@@ -199,6 +202,29 @@ class TestProwlerProviderConnectionTest:
|
||||
key="value", provider_id="1234567890", raise_on_exception=False
|
||||
)
|
||||
|
||||
@patch("api.utils.return_prowler_provider")
|
||||
def test_prowler_provider_connection_test_external_uses_contract(
|
||||
self, mock_return_prowler_provider
|
||||
):
|
||||
"""External providers build connection kwargs through the SDK contract
|
||||
(get_connection_arguments), with no provider_id forced by the API."""
|
||||
provider = MagicMock()
|
||||
provider.provider = "external-template"
|
||||
provider.uid = "acme-1"
|
||||
provider.secret.secret = {"api_key": "k"}
|
||||
mock_return_prowler_provider.return_value.get_connection_arguments.return_value = {
|
||||
"api_key": "k"
|
||||
}
|
||||
|
||||
prowler_provider_connection_test(provider)
|
||||
|
||||
mock_return_prowler_provider.return_value.get_connection_arguments.assert_called_once_with(
|
||||
"acme-1", {"api_key": "k"}
|
||||
)
|
||||
mock_return_prowler_provider.return_value.test_connection.assert_called_once_with(
|
||||
api_key="k", raise_on_exception=False
|
||||
)
|
||||
|
||||
@pytest.mark.django_db
|
||||
@patch("api.utils.return_prowler_provider")
|
||||
def test_prowler_provider_connection_test_without_secret(
|
||||
@@ -573,7 +599,8 @@ class TestGetProwlerProviderKwargs:
|
||||
assert result == expected_result
|
||||
|
||||
def test_get_prowler_provider_kwargs_unsupported_provider(self):
|
||||
# Setup
|
||||
# A non-built-in provider is resolved dynamically; one that is neither a
|
||||
# built-in nor an installed entry-point provider cannot be resolved.
|
||||
provider_uid = "provider_uid"
|
||||
secret_dict = {"key": "value"}
|
||||
secret_mock = MagicMock()
|
||||
@@ -584,10 +611,30 @@ class TestGetProwlerProviderKwargs:
|
||||
provider.secret = secret_mock
|
||||
provider.uid = provider_uid
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
get_prowler_provider_kwargs(provider)
|
||||
|
||||
@patch("api.utils.return_prowler_provider")
|
||||
def test_get_prowler_provider_kwargs_external_uses_contract(
|
||||
self, mock_return_prowler_provider
|
||||
):
|
||||
"""External providers build constructor kwargs through the SDK contract
|
||||
(get_scan_arguments), not a hardcoded branch in the API."""
|
||||
provider = MagicMock()
|
||||
provider.provider = "external-template"
|
||||
provider.uid = "acme-1"
|
||||
provider.secret.secret = {"api_key": "k"}
|
||||
mock_return_prowler_provider.return_value.get_scan_arguments.return_value = {
|
||||
"api_key": "k",
|
||||
"custom": "acme-1",
|
||||
}
|
||||
|
||||
result = get_prowler_provider_kwargs(provider)
|
||||
|
||||
expected_result = secret_dict.copy()
|
||||
assert result == expected_result
|
||||
mock_return_prowler_provider.return_value.get_scan_arguments.assert_called_once_with(
|
||||
"acme-1", {"api_key": "k"}, None
|
||||
)
|
||||
assert result == {"api_key": "k", "custom": "acme-1"}
|
||||
|
||||
def test_get_prowler_provider_kwargs_no_secret(self):
|
||||
# Setup
|
||||
|
||||
@@ -89,6 +89,18 @@ def get_prowler_provider_kwargs(
|
||||
Returns:
|
||||
dict: The provider kwargs for the corresponding provider class.
|
||||
"""
|
||||
# External providers declare their own uid/secret -> kwargs mapping through
|
||||
# the SDK contract; built-in providers keep the explicit mapping below.
|
||||
if not SDKProvider.is_builtin(provider.provider):
|
||||
mutelist_content = (
|
||||
mutelist_processor.configuration.get("Mutelist", {})
|
||||
if mutelist_processor
|
||||
else None
|
||||
)
|
||||
return return_prowler_provider(provider).get_scan_arguments(
|
||||
provider.uid, provider.secret.secret, mutelist_content
|
||||
)
|
||||
|
||||
prowler_provider_kwargs = provider.secret.secret
|
||||
if provider.provider == Provider.ProviderChoices.AZURE.value:
|
||||
prowler_provider_kwargs = {
|
||||
@@ -205,6 +217,16 @@ def prowler_provider_connection_test(provider: Provider) -> Connection:
|
||||
except Provider.secret.RelatedObjectDoesNotExist as secret_error:
|
||||
return Connection(is_connected=False, error=secret_error)
|
||||
|
||||
# External providers declare their own connection kwargs through the SDK
|
||||
# contract; built-in providers keep the explicit mapping below.
|
||||
if not SDKProvider.is_builtin(provider.provider):
|
||||
return prowler_provider.test_connection(
|
||||
**prowler_provider.get_connection_arguments(
|
||||
provider.uid, prowler_provider_kwargs
|
||||
),
|
||||
raise_on_exception=False,
|
||||
)
|
||||
|
||||
# For IaC provider, construct the kwargs properly for test_connection
|
||||
if provider.provider == Provider.ProviderChoices.IAC.value:
|
||||
# Don't pass repository_url from secret, use scan_repository_url with the UID
|
||||
|
||||
Reference in new issue
Block a user