Files
prowler/tests/providers/oraclecloud/oraclecloud_provider_test.py
2026-05-21 16:09:29 +01:00

316 lines
13 KiB
Python

from unittest.mock import MagicMock, patch
import pytest
from prowler.providers.oraclecloud.exceptions.exceptions import (
OCIAuthenticationError,
OCIInvalidConfigError,
)
from prowler.providers.oraclecloud.models import OCIIdentityInfo, OCIRegion, OCISession
from prowler.providers.oraclecloud.oraclecloud_provider import OraclecloudProvider
class TestSetIdentityAuthenticationErrors:
"""Tests for authentication error handling in set_identity()"""
@pytest.fixture
def mock_session(self):
"""Create a mock OCI session."""
session = OCISession(
config={
"tenancy": "ocid1.tenancy.oc1..aaaaaaaexample",
"user": "ocid1.user.oc1..aaaaaaaexample",
"region": "us-ashburn-1",
"fingerprint": "aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99",
},
signer=None,
profile="DEFAULT",
)
return session
def test_authentication_error_401_raises_exception(self, mock_session):
"""Test 401 error raises OCIAuthenticationError."""
with patch("oci.identity.IdentityClient") as mock_identity_client:
mock_client_instance = MagicMock()
mock_client_instance.get_tenancy.side_effect = self._create_service_error(
401, "Authentication failed"
)
mock_identity_client.return_value = mock_client_instance
with pytest.raises(OCIAuthenticationError) as exc_info:
OraclecloudProvider.set_identity(mock_session)
assert "OCI credential validation failed" in str(exc_info.value)
def test_authentication_error_403_raises_exception(self, mock_session):
"""Test 403 error raises OCIAuthenticationError."""
with patch("oci.identity.IdentityClient") as mock_identity_client:
mock_client_instance = MagicMock()
mock_client_instance.get_tenancy.side_effect = self._create_service_error(
403, "Forbidden access"
)
mock_identity_client.return_value = mock_client_instance
with pytest.raises(OCIAuthenticationError) as exc_info:
OraclecloudProvider.set_identity(mock_session)
assert "OCI credential validation failed" in str(exc_info.value)
def test_authentication_error_404_raises_exception(self, mock_session):
"""Test 404 error raises OCIAuthenticationError."""
with patch("oci.identity.IdentityClient") as mock_identity_client:
mock_client_instance = MagicMock()
mock_client_instance.get_tenancy.side_effect = self._create_service_error(
404, "Resource not found"
)
mock_identity_client.return_value = mock_client_instance
with pytest.raises(OCIAuthenticationError) as exc_info:
OraclecloudProvider.set_identity(mock_session)
assert "OCI credential validation failed" in str(exc_info.value)
def test_service_error_500_raises_exception(self, mock_session):
"""Test 500 error raises OCIAuthenticationError (can't validate credentials)."""
with patch("oci.identity.IdentityClient") as mock_identity_client:
mock_client_instance = MagicMock()
mock_client_instance.get_tenancy.side_effect = self._create_service_error(
500, "Internal server error"
)
mock_identity_client.return_value = mock_client_instance
with pytest.raises(OCIAuthenticationError) as exc_info:
OraclecloudProvider.set_identity(mock_session)
assert "OCI credential validation failed" in str(exc_info.value)
def test_invalid_private_key_raises_exception(self, mock_session):
"""Test InvalidPrivateKey exception raises OCIAuthenticationError."""
with patch("oci.identity.IdentityClient") as mock_identity_client:
import oci
mock_client_instance = MagicMock()
mock_client_instance.get_tenancy.side_effect = (
oci.exceptions.InvalidPrivateKey("Invalid private key")
)
mock_identity_client.return_value = mock_client_instance
with pytest.raises(OCIAuthenticationError) as exc_info:
OraclecloudProvider.set_identity(mock_session)
assert "Invalid OCI private key format" in str(exc_info.value)
def test_generic_exception_raises_authentication_error(self, mock_session):
"""Test generic exception raises OCIAuthenticationError."""
with patch("oci.identity.IdentityClient") as mock_identity_client:
mock_client_instance = MagicMock()
mock_client_instance.get_tenancy.side_effect = Exception("Unexpected error")
mock_identity_client.return_value = mock_client_instance
with pytest.raises(OCIAuthenticationError) as exc_info:
OraclecloudProvider.set_identity(mock_session)
assert "Failed to authenticate with OCI" in str(exc_info.value)
def test_successful_authentication(self, mock_session):
"""Test successful authentication returns identity info."""
with patch("oci.identity.IdentityClient") as mock_identity_client:
mock_tenancy = MagicMock()
mock_tenancy.name = "test-tenancy"
mock_response = MagicMock()
mock_response.data = mock_tenancy
mock_client_instance = MagicMock()
mock_client_instance.get_tenancy.return_value = mock_response
mock_identity_client.return_value = mock_client_instance
identity = OraclecloudProvider.set_identity(mock_session)
assert identity.tenancy_name == "test-tenancy"
assert identity.tenancy_id == "ocid1.tenancy.oc1..aaaaaaaexample"
assert identity.user_id == "ocid1.user.oc1..aaaaaaaexample"
assert identity.region == "us-ashburn-1"
@staticmethod
def _create_service_error(status, message):
"""Helper to create an OCI ServiceError."""
import oci
error = oci.exceptions.ServiceError(
status=status,
code="TestError",
headers={},
message=message,
)
return error
class TestTestConnectionKeyValidation:
"""Tests for key_content validation in test_connection()"""
def test_test_connection_invalid_base64_key_raises_error(self):
"""Test invalid base64 key content raises OCIInvalidConfigError."""
with pytest.raises(OCIInvalidConfigError) as exc_info:
OraclecloudProvider.test_connection(
oci_config_file=None,
profile=None,
key_content="not-valid-base64!!!",
user="ocid1.user.oc1..aaaaaaaexample",
fingerprint="aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99",
tenancy="ocid1.tenancy.oc1..aaaaaaaexample",
region="us-ashburn-1",
)
assert "Failed to decode key_content" in str(exc_info.value)
def test_test_connection_valid_key_content_proceeds(self):
"""Test valid base64 key content proceeds to authentication."""
import base64
# The SDK will validate the actual key format during authentication
valid_key = """-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA0Z3VS5JJcds3xfn/ygWyF8n0sMcD/QHWCJ7yGSEtLN2T
...key content...
-----END RSA PRIVATE KEY-----"""
encoded_key = base64.b64encode(valid_key.encode("utf-8")).decode("utf-8")
with (
patch("oci.config.validate_config"),
patch("oci.identity.IdentityClient") as mock_identity_client,
):
mock_tenancy = MagicMock()
mock_tenancy.name = "test-tenancy"
mock_response = MagicMock()
mock_response.data = mock_tenancy
mock_client_instance = MagicMock()
mock_client_instance.get_tenancy.return_value = mock_response
mock_identity_client.return_value = mock_client_instance
connection = OraclecloudProvider.test_connection(
oci_config_file=None,
profile=None,
key_content=encoded_key,
user="ocid1.user.oc1..aaaaaaaexample",
fingerprint="aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99",
tenancy="ocid1.tenancy.oc1..aaaaaaaexample",
region="us-ashburn-1",
raise_on_exception=False,
)
assert connection.is_connected is True
class TestOraclecloudProviderInit:
"""Tests for OraclecloudProvider initialization"""
def test_init_with_region_set_populates_provider_state(self):
mock_session = OCISession(
config={"region": "us-ashburn-1"}, signer=None, profile="DEFAULT"
)
mock_identity = OCIIdentityInfo(
tenancy_id="ocid1.tenancy.oc1..aaaaaaaexample",
tenancy_name="test-tenancy",
user_id="ocid1.user.oc1..aaaaaaaexample",
region="us-ashburn-1",
profile="DEFAULT",
audited_regions=set(),
audited_compartments=[],
)
mock_regions = [
OCIRegion(key="us-phoenix-1", name="us-phoenix-1", is_home_region=False),
OCIRegion(key="us-ashburn-1", name="us-ashburn-1", is_home_region=True),
]
mock_compartments = ["ocid1.compartment.oc1..aaaaaaaexample"]
with (
patch(
"prowler.providers.oraclecloud.oraclecloud_provider.OraclecloudProvider.setup_session",
return_value=mock_session,
) as mock_setup_session,
patch(
"prowler.providers.oraclecloud.oraclecloud_provider.OraclecloudProvider.set_identity",
return_value=mock_identity,
),
patch(
"prowler.providers.oraclecloud.oraclecloud_provider.OraclecloudProvider.get_regions_to_audit",
return_value=mock_regions,
),
patch(
"prowler.providers.oraclecloud.oraclecloud_provider.OraclecloudProvider.get_compartments_to_audit",
return_value=mock_compartments,
),
patch(
"prowler.providers.common.provider.Provider.set_global_provider"
) as mock_set_global,
):
provider = OraclecloudProvider(
region={"us-ashburn-1"},
config_content={"dummy": True},
mutelist_content={"Accounts": {}},
)
assert mock_setup_session.call_args.kwargs["region"] == "us-ashburn-1"
assert provider.session == mock_session
assert provider.identity == mock_identity
assert provider.regions == mock_regions
assert provider.compartments == mock_compartments
assert provider.home_region == "us-ashburn-1"
mock_set_global.assert_called_once_with(provider)
def test_home_region_uses_full_subscription_list_not_region_filter(self):
"""Home region must come from the full subscription list, not the --region filter.
When auditing a single non-home region, the tenancy home region must still be
resolved correctly so tenancy-level APIs (e.g. the Audit configuration) target it.
"""
mock_session = OCISession(
config={"region": "eu-frankfurt-1"}, signer=None, profile="DEFAULT"
)
mock_identity = OCIIdentityInfo(
tenancy_id="ocid1.tenancy.oc1..aaaaaaaexample",
tenancy_name="test-tenancy",
user_id="ocid1.user.oc1..aaaaaaaexample",
region="eu-frankfurt-1",
profile="DEFAULT",
audited_regions=set(),
audited_compartments=[],
)
# The audited set is the non-home region; the full subscription list includes home
audited_regions = [
OCIRegion(
key="eu-frankfurt-1", name="eu-frankfurt-1", is_home_region=False
),
]
all_subscribed_regions = [
OCIRegion(
key="eu-frankfurt-1", name="eu-frankfurt-1", is_home_region=False
),
OCIRegion(key="us-ashburn-1", name="us-ashburn-1", is_home_region=True),
]
with (
patch(
"prowler.providers.oraclecloud.oraclecloud_provider.OraclecloudProvider.setup_session",
return_value=mock_session,
),
patch(
"prowler.providers.oraclecloud.oraclecloud_provider.OraclecloudProvider.set_identity",
return_value=mock_identity,
),
patch(
"prowler.providers.oraclecloud.oraclecloud_provider.OraclecloudProvider.get_regions_to_audit",
side_effect=[audited_regions, all_subscribed_regions],
),
patch(
"prowler.providers.oraclecloud.oraclecloud_provider.OraclecloudProvider.get_compartments_to_audit",
return_value=["ocid1.compartment.oc1..aaaaaaaexample"],
),
patch("prowler.providers.common.provider.Provider.set_global_provider"),
):
provider = OraclecloudProvider(
region={"eu-frankfurt-1"},
config_content={"dummy": True},
mutelist_content={"Accounts": {}},
)
assert provider.regions == audited_regions
assert provider.home_region == "us-ashburn-1"