mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 13:01:56 +00:00
feat(azure/vm): add new check vm_backup_enabled (#8182)
Co-authored-by: Sergio Garcia <hello@mistercloudsec.com>
This commit is contained in:
committed by
GitHub
parent
c0c736bffe
commit
4c50f4d811
Generated
+40
-2
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "about-time"
|
||||
@@ -666,6 +666,42 @@ azure-common = ">=1.1,<2.0"
|
||||
azure-mgmt-core = ">=1.3.0,<2.0.0"
|
||||
msrest = ">=0.6.21"
|
||||
|
||||
[[package]]
|
||||
name = "azure-mgmt-recoveryservices"
|
||||
version = "3.1.0"
|
||||
description = "Microsoft Azure Recovery Services Client Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "azure_mgmt_recoveryservices-3.1.0-py3-none-any.whl", hash = "sha256:21c58afdf4ae66806783e95f8cd17e3bec31be7178c48784db21f0b05de7fa66"},
|
||||
{file = "azure_mgmt_recoveryservices-3.1.0.tar.gz", hash = "sha256:7f2db98401708cf145322f50bc491caf7967bec4af3bf7b0984b9f07d3092687"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
azure-common = ">=1.1"
|
||||
azure-mgmt-core = ">=1.5.0"
|
||||
isodate = ">=0.6.1"
|
||||
typing-extensions = ">=4.6.0"
|
||||
|
||||
[[package]]
|
||||
name = "azure-mgmt-recoveryservicesbackup"
|
||||
version = "9.2.0"
|
||||
description = "Microsoft Azure Recovery Services Backup Management Client Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "azure_mgmt_recoveryservicesbackup-9.2.0-py3-none-any.whl", hash = "sha256:c0002858d0166b6a10189a1fd580a49c83dc31b111e98010a5b2ea0f767dfff1"},
|
||||
{file = "azure_mgmt_recoveryservicesbackup-9.2.0.tar.gz", hash = "sha256:c402b3e22a6c3879df56bc37e0063142c3352c5102599ff102d19824f1b32b29"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
azure-common = ">=1.1"
|
||||
azure-mgmt-core = ">=1.3.2"
|
||||
isodate = ">=0.6.1"
|
||||
typing-extensions = ">=4.6.0"
|
||||
|
||||
[[package]]
|
||||
name = "azure-mgmt-resource"
|
||||
version = "23.3.0"
|
||||
@@ -2678,6 +2714,8 @@ python-versions = "*"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "jsonpath-ng-1.7.0.tar.gz", hash = "sha256:f6f5f7fd4e5ff79c785f1573b394043b39849fb2bb47bcead935d12b00beab3c"},
|
||||
{file = "jsonpath_ng-1.7.0-py2-none-any.whl", hash = "sha256:898c93fc173f0c336784a3fa63d7434297544b7198124a68f9a3ef9597b0ae6e"},
|
||||
{file = "jsonpath_ng-1.7.0-py3-none-any.whl", hash = "sha256:f3d7f9e848cba1b6da28c55b1c26ff915dc9e0b1ba7e752a53d6da8d5cbd00b6"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -6622,4 +6660,4 @@ type = ["pytest-mypy"]
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">3.9.1,<3.13"
|
||||
content-hash = "c442552635c8e904d1c7a50f4787c8e90ec90787960ee1867f2235a7aa2205f0"
|
||||
content-hash = "a0c3e917dcedf073426ae47c942c1db1e04e14ea1ab1a81d7fb91f2873daf1cb"
|
||||
|
||||
@@ -6,9 +6,9 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
|
||||
### Added
|
||||
- `storage_smb_channel_encryption_with_secure_algorithm` check for Azure provider [(#8123)](https://github.com/prowler-cloud/prowler/pull/8123)
|
||||
- `vm_backup_enabled` check for Azure provider [(#8182)](https://github.com/prowler-cloud/prowler/pull/8182)
|
||||
- `vm_linux_enforce_ssh_authentication` check for Azure provider [(#8149)](https://github.com/prowler-cloud/prowler/pull/8149)
|
||||
- `vm_ensure_using_approved_images` check for Azure provider [(#8168)](https://github.com/prowler-cloud/prowler/pull/8168)
|
||||
|
||||
- `vm_scaleset_associated_load_balancer` check for Azure provider [(#8181)](https://github.com/prowler-cloud/prowler/pull/8181)
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
from prowler.providers.azure.services.recovery.recovery_service import Recovery
|
||||
from prowler.providers.common.provider import Provider
|
||||
|
||||
recovery_client = Recovery(Provider.get_global_provider())
|
||||
@@ -0,0 +1,101 @@
|
||||
from typing import Optional
|
||||
|
||||
from azure.mgmt.recoveryservices import RecoveryServicesClient
|
||||
from azure.mgmt.recoveryservicesbackup import RecoveryServicesBackupClient
|
||||
from azure.mgmt.recoveryservicesbackup.activestamp.models import DataSourceType
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.providers.azure.azure_provider import AzureProvider
|
||||
from prowler.providers.azure.lib.service.service import AzureService
|
||||
|
||||
|
||||
class BackupItem(BaseModel):
|
||||
"""Minimal BackupItem: only essential identifying and descriptive fields."""
|
||||
|
||||
id: str
|
||||
name: str
|
||||
workload_type: Optional[DataSourceType]
|
||||
|
||||
|
||||
class BackupVault(BaseModel):
|
||||
"""Minimal BackupVault: only essential identifying fields and its backup items."""
|
||||
|
||||
id: str
|
||||
name: str
|
||||
location: str
|
||||
backup_protected_items: dict[str, BackupItem] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class Recovery(AzureService):
|
||||
def __init__(self, provider: AzureProvider):
|
||||
super().__init__(RecoveryServicesClient, provider)
|
||||
self.vaults: dict[str, dict[str, BackupVault]] = self._get_vaults()
|
||||
RecoveryBackup(provider, self.vaults)
|
||||
|
||||
def _get_vaults(self) -> dict[str, dict[str, BackupVault]]:
|
||||
"""
|
||||
Retrieve all Recovery Services vaults for each subscription.
|
||||
|
||||
Returns:
|
||||
Nested dictionary of vaults by subscription.
|
||||
"""
|
||||
logger.info("Recovery - Getting Recovery Services vaults...")
|
||||
vaults_dict: dict[str, dict[str, BackupVault]] = {}
|
||||
try:
|
||||
vaults_dict: dict[str, dict[str, BackupVault]] = {}
|
||||
for subscription_name, client in self.clients.items():
|
||||
vaults = client.vaults.list_by_subscription_id()
|
||||
vaults_dict[subscription_name] = {}
|
||||
for vault in vaults:
|
||||
vault_obj = BackupVault(
|
||||
id=vault.id,
|
||||
name=vault.name,
|
||||
location=vault.location,
|
||||
)
|
||||
vaults_dict[subscription_name][vault_obj.id] = vault_obj
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"Subscription name: {subscription_name} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return vaults_dict
|
||||
|
||||
|
||||
class RecoveryBackup(AzureService):
|
||||
def __init__(
|
||||
self, provider: AzureProvider, vaults: dict[str, dict[str, BackupVault]]
|
||||
):
|
||||
super().__init__(RecoveryServicesBackupClient, provider)
|
||||
for subscription_name, vaults in vaults.items():
|
||||
for vault in vaults.values():
|
||||
vault.backup_protected_items = self._get_backup_protected_items(
|
||||
subscription_name=subscription_name, vault=vault
|
||||
)
|
||||
|
||||
def _get_backup_protected_items(
|
||||
self, subscription_name: str, vault: BackupVault
|
||||
) -> dict[str, BackupItem]:
|
||||
"""
|
||||
Retrieve all backup protected items for a given vault.
|
||||
"""
|
||||
logger.info("Recovery - Getting backup protected items...")
|
||||
backup_protected_items_dict: dict[str, BackupItem] = {}
|
||||
try:
|
||||
backup_protected_items = self.clients[
|
||||
subscription_name
|
||||
].backup_protected_items.list(
|
||||
vault_name=vault.name,
|
||||
resource_group_name=vault.id.split("/")[4],
|
||||
)
|
||||
for item in backup_protected_items:
|
||||
item_properties = getattr(item, "properties", None)
|
||||
backup_protected_items_dict[item.id] = BackupItem(
|
||||
id=item.id,
|
||||
name=item.name,
|
||||
workload_type=(
|
||||
item_properties.workload_type if item_properties else None
|
||||
),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Recovery - Error getting backup protected items: {e}")
|
||||
return backup_protected_items_dict
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "vm_backup_enabled",
|
||||
"CheckTitle": "Ensure Backups are enabled for Azure Virtual Machines",
|
||||
"CheckType": [],
|
||||
"ServiceName": "vm",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "Microsoft.Compute/virtualMachines",
|
||||
"Description": "Ensure that Microsoft Azure Backup service is in use for your Azure virtual machines (VMs) to protect against accidental deletion or corruption.",
|
||||
"Risk": "Without Azure Backup enabled, VMs are at risk of data loss due to accidental deletion, corruption, or other failures, and recovery options are limited.",
|
||||
"RelatedUrl": "https://docs.microsoft.com/en-us/azure/backup/backup-overview",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az backup protection enable-for-vm --resource-group <resource-group> --vm <vm-name> --vault-name <vault-name> --policy-name DefaultPolicy",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://learn.microsoft.com/en-us/azure/backup/quick-backup-vm-portal",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable Azure Backup for each VM by associating it with a Recovery Services vault and a backup policy.",
|
||||
"Url": "https://docs.microsoft.com/en-us/azure/backup/quick-backup-vm-portal"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
from azure.mgmt.recoveryservicesbackup.activestamp.models import DataSourceType
|
||||
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.recovery.recovery_client import recovery_client
|
||||
from prowler.providers.azure.services.vm.vm_client import vm_client
|
||||
|
||||
|
||||
class vm_backup_enabled(Check):
|
||||
"""
|
||||
Ensure that Microsoft Azure Backup service is in use for your Azure virtual machines (VMs).
|
||||
|
||||
This check evaluates whether each Azure VM in the subscription is protected by Azure Backup.
|
||||
|
||||
- PASS: The VM is protected by Azure Backup (present in a Recovery Services vault).
|
||||
- FAIL: The VM is not protected by Azure Backup (not present in any Recovery Services vault).
|
||||
"""
|
||||
|
||||
def execute(self) -> list[Check_Report_Azure]:
|
||||
"""Execute Azure VM backup enabled check.
|
||||
|
||||
Returns:
|
||||
A list of reports containing the result of the check.
|
||||
"""
|
||||
findings = []
|
||||
for subscription_name, vms in vm_client.virtual_machines.items():
|
||||
vaults = recovery_client.vaults.get(subscription_name, {})
|
||||
for vm in vms.values():
|
||||
found = False
|
||||
found_vault_name = None
|
||||
for vault in vaults.values():
|
||||
for backup_item in vault.backup_protected_items.values():
|
||||
if (
|
||||
backup_item.workload_type == DataSourceType.VM
|
||||
and backup_item.name.split(";")[-1] == vm.resource_name
|
||||
):
|
||||
found = True
|
||||
found_vault_name = vault.name
|
||||
break
|
||||
if found:
|
||||
break
|
||||
report = Check_Report_Azure(metadata=self.metadata(), resource=vm)
|
||||
report.subscription = subscription_name
|
||||
if found:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"VM {vm.resource_name} in subscription {subscription_name} is protected by Azure Backup (vault: {found_vault_name})."
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"VM {vm.resource_name} in subscription {subscription_name} is not protected by Azure Backup."
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -26,6 +26,8 @@ dependencies = [
|
||||
"azure-mgmt-monitor==6.0.2",
|
||||
"azure-mgmt-network==28.1.0",
|
||||
"azure-mgmt-rdbms==10.1.0",
|
||||
"azure-mgmt-recoveryservices==3.1.0",
|
||||
"azure-mgmt-recoveryservicesbackup==9.2.0",
|
||||
"azure-mgmt-resource==23.3.0",
|
||||
"azure-mgmt-search==9.1.0",
|
||||
"azure-mgmt-security==7.0.0",
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from tests.providers.azure.azure_fixtures import (
|
||||
AZURE_SUBSCRIPTION_ID,
|
||||
set_mocked_azure_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_vm_backup_enabled:
|
||||
def test_vm_backup_enabled_no_subscriptions(self):
|
||||
vm_client = mock.MagicMock
|
||||
recovery_client = mock.MagicMock
|
||||
|
||||
vm_client.virtual_machines = {}
|
||||
recovery_client.vaults = {}
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled.vm_client",
|
||||
new=vm_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled.recovery_client",
|
||||
new=recovery_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled import (
|
||||
vm_backup_enabled,
|
||||
)
|
||||
|
||||
check = vm_backup_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_no_vms(self):
|
||||
mock_vm_client = mock.MagicMock()
|
||||
mock_vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {}}
|
||||
mock_recovery_client = mock.MagicMock()
|
||||
mock_recovery_client.vaults = {AZURE_SUBSCRIPTION_ID: {}}
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled.vm_client",
|
||||
new=mock_vm_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled.recovery_client",
|
||||
new=mock_recovery_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled import (
|
||||
vm_backup_enabled,
|
||||
)
|
||||
|
||||
check = vm_backup_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_vm_protected_by_backup(self):
|
||||
vm_id = str(uuid4())
|
||||
vm_name = "VMTest"
|
||||
vault_id = str(uuid4())
|
||||
vault_name = "vault1"
|
||||
mock_vm_client = mock.MagicMock()
|
||||
mock_recovery_client = mock.MagicMock()
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled.vm_client",
|
||||
new=mock_vm_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled.recovery_client",
|
||||
new=mock_recovery_client,
|
||||
),
|
||||
):
|
||||
from azure.mgmt.recoveryservicesbackup.activestamp.models import (
|
||||
DataSourceType,
|
||||
)
|
||||
|
||||
from prowler.providers.azure.services.recovery.recovery_service import (
|
||||
BackupItem,
|
||||
BackupVault,
|
||||
)
|
||||
from prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled import (
|
||||
vm_backup_enabled,
|
||||
)
|
||||
from prowler.providers.azure.services.vm.vm_service import (
|
||||
ManagedDiskParameters,
|
||||
OSDisk,
|
||||
StorageProfile,
|
||||
VirtualMachine,
|
||||
)
|
||||
|
||||
vm = VirtualMachine(
|
||||
resource_id=vm_id,
|
||||
resource_name=vm_name,
|
||||
location="eastus",
|
||||
security_profile=None,
|
||||
extensions=[],
|
||||
storage_profile=StorageProfile(
|
||||
os_disk=OSDisk(
|
||||
name="os_disk_name",
|
||||
operating_system_type="Linux",
|
||||
managed_disk=ManagedDiskParameters(id="managed_disk_id"),
|
||||
),
|
||||
data_disks=[],
|
||||
),
|
||||
)
|
||||
backup_item = BackupItem(
|
||||
id=str(uuid4()),
|
||||
name=f"someprefix;{vm_name}",
|
||||
workload_type=DataSourceType.VM,
|
||||
)
|
||||
vault = BackupVault(
|
||||
id=vault_id,
|
||||
name=vault_name,
|
||||
location="eastus",
|
||||
backup_protected_items={backup_item.id: backup_item},
|
||||
)
|
||||
mock_vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {vm_id: vm}}
|
||||
mock_recovery_client.vaults = {AZURE_SUBSCRIPTION_ID: {vault_id: vault}}
|
||||
check = vm_backup_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION_ID
|
||||
assert result[0].resource_name == vm_name
|
||||
assert result[0].resource_id == vm_id
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"VM {vm_name} in subscription {AZURE_SUBSCRIPTION_ID} is protected by Azure Backup (vault: {vault_name})."
|
||||
)
|
||||
|
||||
def test_vm_not_protected_by_backup(self):
|
||||
vm_id = str(uuid4())
|
||||
vm_name = "VMTest"
|
||||
vault_id = str(uuid4())
|
||||
vault_name = "vault1"
|
||||
mock_vm_client = mock.MagicMock()
|
||||
mock_recovery_client = mock.MagicMock()
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled.vm_client",
|
||||
new=mock_vm_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled.recovery_client",
|
||||
new=mock_recovery_client,
|
||||
),
|
||||
):
|
||||
from azure.mgmt.recoveryservicesbackup.activestamp.models import (
|
||||
DataSourceType,
|
||||
)
|
||||
|
||||
from prowler.providers.azure.services.recovery.recovery_service import (
|
||||
BackupItem,
|
||||
BackupVault,
|
||||
)
|
||||
from prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled import (
|
||||
vm_backup_enabled,
|
||||
)
|
||||
from prowler.providers.azure.services.vm.vm_service import (
|
||||
ManagedDiskParameters,
|
||||
OSDisk,
|
||||
StorageProfile,
|
||||
VirtualMachine,
|
||||
)
|
||||
|
||||
vm = VirtualMachine(
|
||||
resource_id=vm_id,
|
||||
resource_name=vm_name,
|
||||
location="eastus",
|
||||
security_profile=None,
|
||||
extensions=[],
|
||||
storage_profile=StorageProfile(
|
||||
os_disk=OSDisk(
|
||||
name="os_disk_name",
|
||||
operating_system_type="Linux",
|
||||
managed_disk=ManagedDiskParameters(id="managed_disk_id"),
|
||||
),
|
||||
data_disks=[],
|
||||
),
|
||||
)
|
||||
backup_item = BackupItem(
|
||||
id=str(uuid4()),
|
||||
name="someprefix;OtherVM",
|
||||
workload_type=DataSourceType.VM,
|
||||
)
|
||||
vault = BackupVault(
|
||||
id=vault_id,
|
||||
name=vault_name,
|
||||
location="eastus",
|
||||
backup_protected_items={backup_item.id: backup_item},
|
||||
)
|
||||
mock_vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {vm_id: vm}}
|
||||
mock_recovery_client.vaults = {AZURE_SUBSCRIPTION_ID: {vault_id: vault}}
|
||||
check = vm_backup_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION_ID
|
||||
assert result[0].resource_name == vm_name
|
||||
assert result[0].resource_id == vm_id
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"VM {vm_name} in subscription {AZURE_SUBSCRIPTION_ID} is not protected by Azure Backup."
|
||||
)
|
||||
|
||||
def test_vm_protected_by_backup_non_vm_workload(self):
|
||||
vm_id = str(uuid4())
|
||||
vm_name = "VMTest"
|
||||
vault_id = str(uuid4())
|
||||
vault_name = "vault1"
|
||||
mock_vm_client = mock.MagicMock()
|
||||
mock_recovery_client = mock.MagicMock()
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled.vm_client",
|
||||
new=mock_vm_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled.recovery_client",
|
||||
new=mock_recovery_client,
|
||||
),
|
||||
):
|
||||
from azure.mgmt.recoveryservicesbackup.activestamp.models import (
|
||||
DataSourceType,
|
||||
)
|
||||
|
||||
from prowler.providers.azure.services.recovery.recovery_service import (
|
||||
BackupItem,
|
||||
BackupVault,
|
||||
)
|
||||
from prowler.providers.azure.services.vm.vm_backup_enabled.vm_backup_enabled import (
|
||||
vm_backup_enabled,
|
||||
)
|
||||
from prowler.providers.azure.services.vm.vm_service import (
|
||||
ManagedDiskParameters,
|
||||
OSDisk,
|
||||
StorageProfile,
|
||||
VirtualMachine,
|
||||
)
|
||||
|
||||
vm = VirtualMachine(
|
||||
resource_id=vm_id,
|
||||
resource_name=vm_name,
|
||||
location="eastus",
|
||||
security_profile=None,
|
||||
extensions=[],
|
||||
storage_profile=StorageProfile(
|
||||
os_disk=OSDisk(
|
||||
name="os_disk_name",
|
||||
operating_system_type="Linux",
|
||||
managed_disk=ManagedDiskParameters(id="managed_disk_id"),
|
||||
),
|
||||
data_disks=[],
|
||||
),
|
||||
)
|
||||
backup_item = BackupItem(
|
||||
id=str(uuid4()),
|
||||
name=f"someprefix;{vm_name}",
|
||||
workload_type=DataSourceType.FILE_FOLDER,
|
||||
)
|
||||
vault = BackupVault(
|
||||
id=vault_id,
|
||||
name=vault_name,
|
||||
location="eastus",
|
||||
backup_protected_items={backup_item.id: backup_item},
|
||||
)
|
||||
mock_vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {vm_id: vm}}
|
||||
mock_recovery_client.vaults = {AZURE_SUBSCRIPTION_ID: {vault_id: vault}}
|
||||
check = vm_backup_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION_ID
|
||||
assert result[0].resource_name == vm_name
|
||||
assert result[0].resource_id == vm_id
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"VM {vm_name} in subscription {AZURE_SUBSCRIPTION_ID} is not protected by Azure Backup."
|
||||
)
|
||||
Reference in New Issue
Block a user