143 lines
3.7 KiB
Python
Executable File
143 lines
3.7 KiB
Python
Executable File
"""
|
|
Security configuration for Remote Access API.
|
|
"""
|
|
|
|
import os
|
|
from typing import Any, Dict, Tuple
|
|
|
|
from core.models import UserRole
|
|
from core.ssrf_protection import ssrf_protection
|
|
|
|
|
|
class SecurityConfig:
|
|
"""Security configuration for the system."""
|
|
|
|
MAX_TTL_MINUTES = int(os.getenv("MAX_TTL_MINUTES", "480"))
|
|
|
|
MAX_CONNECTIONS_PER_USER = int(os.getenv("MAX_CONNECTIONS_PER_USER", "5"))
|
|
|
|
BLOCKED_HOSTS = {
|
|
"127.0.0.1",
|
|
"localhost",
|
|
"0.0.0.0",
|
|
"::1",
|
|
"169.254.169.254",
|
|
"metadata.google.internal",
|
|
}
|
|
|
|
BLOCKED_NETWORKS = [
|
|
"127.0.0.0/8",
|
|
"169.254.0.0/16",
|
|
"224.0.0.0/4",
|
|
"240.0.0.0/4",
|
|
"172.17.0.0/16",
|
|
"172.18.0.0/16",
|
|
"172.19.0.0/16",
|
|
"172.20.0.0/16",
|
|
"172.21.0.0/16",
|
|
"172.22.0.0/16",
|
|
"172.23.0.0/16",
|
|
"172.24.0.0/16",
|
|
"172.25.0.0/16",
|
|
"172.26.0.0/16",
|
|
"172.27.0.0/16",
|
|
"172.28.0.0/16",
|
|
"172.29.0.0/16",
|
|
"172.30.0.0/16",
|
|
"172.31.0.0/16",
|
|
]
|
|
|
|
ROLE_ALLOWED_NETWORKS = {
|
|
UserRole.GUEST: [],
|
|
UserRole.USER: [
|
|
"10.0.0.0/8",
|
|
"172.16.0.0/16",
|
|
"192.168.1.0/24",
|
|
],
|
|
UserRole.ADMIN: [
|
|
"10.0.0.0/8",
|
|
"172.16.0.0/16",
|
|
"192.168.0.0/16",
|
|
"203.0.113.0/24",
|
|
],
|
|
UserRole.SUPER_ADMIN: [
|
|
"0.0.0.0/0",
|
|
],
|
|
}
|
|
|
|
@classmethod
|
|
def is_host_allowed(
|
|
cls, hostname: str, user_role: UserRole
|
|
) -> Tuple[bool, str]:
|
|
"""
|
|
Check if host is allowed for the given role with enhanced SSRF protection.
|
|
|
|
Args:
|
|
hostname: IP address or hostname.
|
|
user_role: User role.
|
|
|
|
Returns:
|
|
Tuple (allowed: bool, reason: str).
|
|
"""
|
|
return ssrf_protection.validate_host(hostname, user_role.value)
|
|
|
|
@classmethod
|
|
def validate_ttl(cls, ttl_minutes: int) -> Tuple[bool, str]:
|
|
"""
|
|
Validate connection TTL.
|
|
|
|
Args:
|
|
ttl_minutes: Requested time-to-live in minutes.
|
|
|
|
Returns:
|
|
Tuple (valid: bool, reason: str).
|
|
"""
|
|
if ttl_minutes <= 0:
|
|
return False, "TTL must be positive"
|
|
|
|
if ttl_minutes > cls.MAX_TTL_MINUTES:
|
|
return False, f"TTL cannot exceed {cls.MAX_TTL_MINUTES} minutes"
|
|
|
|
return True, "TTL is valid"
|
|
|
|
@classmethod
|
|
def get_role_limits(cls, user_role: UserRole) -> Dict[str, Any]:
|
|
"""
|
|
Get limits for a role.
|
|
|
|
Args:
|
|
user_role: User role.
|
|
|
|
Returns:
|
|
Dictionary with limits.
|
|
"""
|
|
base_limits = {
|
|
"max_ttl_minutes": cls.MAX_TTL_MINUTES,
|
|
"max_connections": cls.MAX_CONNECTIONS_PER_USER,
|
|
"allowed_networks": cls.ROLE_ALLOWED_NETWORKS.get(user_role, []),
|
|
"can_create_connections": user_role != UserRole.GUEST,
|
|
}
|
|
|
|
if user_role == UserRole.GUEST:
|
|
base_limits.update(
|
|
{
|
|
"max_connections": 0,
|
|
"max_ttl_minutes": 0,
|
|
}
|
|
)
|
|
elif user_role == UserRole.USER:
|
|
base_limits.update(
|
|
{
|
|
"max_connections": 3,
|
|
"max_ttl_minutes": 240,
|
|
}
|
|
)
|
|
elif user_role == UserRole.ADMIN:
|
|
base_limits.update(
|
|
{
|
|
"max_connections": 10,
|
|
"max_ttl_minutes": 480,
|
|
}
|
|
)
|
|
|
|
return base_limits |