CloudManager¶
The CloudManager class manages detection of IP addresses from major cloud providers. It uses a singleton pattern to ensure only one instance exists throughout the application.
Class Definition¶
class CloudManager:
_instance = None
ip_ranges: dict[str, set[ipaddress.IPv4Network | ipaddress.IPv6Network]]
redis_handler: Any = None
agent_handler: Any = None
logger: logging.Logger
last_updated: dict[str, datetime | None]
def __new__(cls: type["CloudManager"]) -> "CloudManager":
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.ip_ranges = {
"AWS": set(),
"GCP": set(),
"Azure": set(),
}
cls._instance.last_updated = {
"AWS": None, "GCP": None, "Azure": None,
}
cls._instance.redis_handler = None
cls._instance.agent_handler = None
cls._instance.logger = logging.getLogger("fastapi_guard.handlers.cloud")
return cls._instance
Redis Integration¶
When Redis is enabled, CloudManager automatically:
- Caches cloud IP ranges in Redis with configurable TTL (default: 1 hour, set via
cloud_ip_refresh_interval) - Uses cached ranges if available
- Synchronizes ranges across instances
Methods¶
refresh¶
def refresh(self, providers: set[str] = _ALL_PROVIDERS):
"""
Synchronous refresh of IP ranges from cloud providers.
Only available when Redis is not enabled.
"""
refresh_async¶
async def refresh_async(
self,
providers: set[str] = _ALL_PROVIDERS,
ttl: int = 3600
):
"""
Async refresh of IP ranges with Redis caching.
Args:
providers: Set of provider names to refresh
ttl: Redis cache TTL in seconds (default: 3600)
"""
initialize_redis¶
async def initialize_redis(
self,
redis_handler: Any,
providers: set[str] = _ALL_PROVIDERS,
ttl: int = 3600
):
"""
Initialize Redis integration and load IP ranges.
Args:
redis_handler: Redis handler instance
providers: Set of provider names to load
ttl: Redis cache TTL in seconds (default: 3600)
"""
_log_range_changes¶
def _log_range_changes(
self,
provider: str,
old_ranges: set[ipaddress.IPv4Network | ipaddress.IPv6Network],
new_ranges: set[ipaddress.IPv4Network | ipaddress.IPv6Network],
) -> None:
"""
Log additions and removals when IP ranges change for a provider.
Called automatically during refresh operations.
"""
is_cloud_ip¶
def is_cloud_ip(
self,
ip: str,
providers: set[str]
) -> bool:
"""
Check if an IP belongs to specified cloud providers.
Args:
ip: IP address to check
providers: Set of provider names ('AWS', 'GCP', 'Azure')
"""
Usage Example¶
from guard.handlers.cloud_handler import cloud_handler
# The singleton instance is already created
# Check if IP is from AWS
is_aws = cloud_handler.is_cloud_ip("54.239.28.85", {"AWS"})
# Check multiple providers
is_cloud = cloud_handler.is_cloud_ip(
"35.186.224.25",
{"AWS", "GCP", "Azure"}
)
# Refresh IP ranges manually if needed
cloud_handler.refresh() # Synchronous refresh
await cloud_handler.refresh_async() # Asynchronous with Redis
# Check when a provider was last refreshed
aws_updated = cloud_handler.last_updated["AWS"]
if aws_updated:
print(f"AWS ranges last refreshed: {aws_updated.isoformat()}")