Block storage snapshots reference existing volumes
OpenStack block storage snapshots are evaluated to verify they reference existing volumes. Orphaned snapshots (whose source volumes have been deleted) may contain stale data, incur unnecessary storage costs, and can be overlooked during security reviews. They may also contain sensitive data from deleted volumes that is no longer being managed.
Risk
Orphaned snapshots may contain sensitive data from deleted volumes that is no longer actively managed or monitored. These snapshots continue to consume storage resources and may be restored by unauthorized users to access old data. They can be overlooked during security audits and compliance reviews.
Run this check with Prowler
Run in Prowler Cloudprowler openstack --checks blockstorage_snapshot_not_orphanedRecommendation
Review orphaned snapshots regularly and delete those no longer needed. Before deleting a volume, review and clean up associated snapshots. Implement snapshot lifecycle policies to prevent accumulation of orphaned snapshots. Tag snapshots with ownership and purpose metadata.
Remediation
CLI
openstack volume snapshot list
openstack volume snapshot delete <snapshot_id>Other
Check Code
from typing import List
from prowler.lib.check.models import Check, CheckReportOpenStack
from prowler.providers.openstack.services.blockstorage.blockstorage_client import (
blockstorage_client,
)
class blockstorage_snapshot_not_orphaned(Check):
"""Ensure block storage snapshots reference existing volumes."""
def execute(self) -> List[CheckReportOpenStack]:
findings: List[CheckReportOpenStack] = []
# Build set of existing volume IDs
existing_volume_ids = {volume.id for volume in blockstorage_client.volumes}
for snapshot in blockstorage_client.snapshots:
report = CheckReportOpenStack(metadata=self.metadata(), resource=snapshot)
if snapshot.volume_id in existing_volume_ids:
report.status = "PASS"
report.status_extended = f"Snapshot {snapshot.name} ({snapshot.id}) references existing volume {snapshot.volume_id}."
else:
report.status = "FAIL"
report.status_extended = (
f"Snapshot {snapshot.name} ({snapshot.id}) references non-existent volume "
f"{snapshot.volume_id} and may be orphaned."
)
findings.append(report)
return findings