From 4d423bb3578b71639650af15e2003e847ca3cc12 Mon Sep 17 00:00:00 2001 From: "Hugo P.Brito" Date: Fri, 21 Aug 2026 11:54:56 +0100 Subject: [PATCH] fix(azure): wire certificate authentication flags --- .../azure/lib/arguments/arguments.py | 11 +++++ prowler/providers/common/provider.py | 2 + tests/lib/cli/parser_test.py | 48 +++++++++++++++++++ tests/providers/azure/azure_provider_test.py | 6 +-- 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/prowler/providers/azure/lib/arguments/arguments.py b/prowler/providers/azure/lib/arguments/arguments.py index 87bea948aa..95a0d007db 100644 --- a/prowler/providers/azure/lib/arguments/arguments.py +++ b/prowler/providers/azure/lib/arguments/arguments.py @@ -29,6 +29,17 @@ def init_parser(self): action="store_true", help="Use managed identity authentication to log in against Azure ", ) + azure_auth_modes_group.add_argument( + "--certificate-auth", + action="store_true", + help="Use certificate authentication to log in against Azure", + ) + azure_parser.add_argument( + "--certificate-path", + nargs="?", + default=None, + help="Path to the certificate file to be used with --certificate-auth option", + ) # Subscriptions azure_subscriptions_subparser = azure_parser.add_argument_group("Subscriptions") azure_subscriptions_subparser.add_argument( diff --git a/prowler/providers/common/provider.py b/prowler/providers/common/provider.py index 2e81bad121..5616a5f8c4 100644 --- a/prowler/providers/common/provider.py +++ b/prowler/providers/common/provider.py @@ -404,6 +404,8 @@ class Provider(ABC): sp_env_auth=arguments.sp_env_auth, browser_auth=arguments.browser_auth, managed_identity_auth=arguments.managed_identity_auth, + certificate_auth=arguments.certificate_auth, + certificate_path=arguments.certificate_path, tenant_id=arguments.tenant_id, region=arguments.azure_region, subscription_ids=arguments.subscription_id, diff --git a/tests/lib/cli/parser_test.py b/tests/lib/cli/parser_test.py index da16f437b5..f4bad70b2a 100644 --- a/tests/lib/cli/parser_test.py +++ b/tests/lib/cli/parser_test.py @@ -12,6 +12,7 @@ from prowler.providers.aws.lib.arguments.arguments import ( validate_role_session_name, ) from prowler.providers.azure.lib.arguments.arguments import validate_azure_region +from prowler.providers.common.provider import Provider prowler_command = "prowler" @@ -154,6 +155,53 @@ class Test_Parser: assert not parsed.managed_identity_auth assert not parsed.shodan + def test_azure_certificate_auth_arguments(self): + certificate_path = "/secure/path/prowler-cert.pem" + + parsed = self.parser.parse( + [ + prowler_command, + "azure", + "--certificate-auth", + "--certificate-path", + certificate_path, + ] + ) + + assert parsed.certificate_auth + assert parsed.certificate_path == certificate_path + + def test_azure_certificate_auth_arguments_are_forwarded(self): + certificate_path = "/secure/path/prowler-cert.pem" + parsed = self.parser.parse( + [ + prowler_command, + "azure", + "--certificate-auth", + "--certificate-path", + certificate_path, + ] + ) + captured = {} + + class AzureProviderStub: + def __init__(self, **kwargs): + captured.update(kwargs) + + with ( + patch.object(Provider, "_global", None), + patch.object(Provider, "get_class", return_value=AzureProviderStub), + patch.object(Provider, "is_builtin", return_value=True), + patch( + "prowler.providers.common.provider.load_and_validate_config_file", + return_value={}, + ), + ): + Provider.init_global_provider(parsed) + + assert captured["certificate_auth"] is True + assert captured["certificate_path"] == certificate_path + def test_default_parser_no_arguments_gcp(self): provider = "gcp" command = [prowler_command, provider] diff --git a/tests/providers/azure/azure_provider_test.py b/tests/providers/azure/azure_provider_test.py index 5f4677fba2..45fac3e3c2 100644 --- a/tests/providers/azure/azure_provider_test.py +++ b/tests/providers/azure/azure_provider_test.py @@ -1257,7 +1257,7 @@ class TestAzureProviderCertificateAuth: @staticmethod def _certificate_and_key(): - from datetime import UTC, datetime, timedelta + from datetime import datetime, timedelta, timezone from cryptography import x509 from cryptography.hazmat.primitives import hashes @@ -1272,8 +1272,8 @@ class TestAzureProviderCertificateAuth: .issuer_name(subject) .public_key(private_key.public_key()) .serial_number(x509.random_serial_number()) - .not_valid_before(datetime.now(UTC)) - .not_valid_after(datetime.now(UTC) + timedelta(days=1)) + .not_valid_before(datetime.now(timezone.utc)) + .not_valid_after(datetime.now(timezone.utc) + timedelta(days=1)) .sign(private_key, hashes.SHA256()) ) return certificate, private_key