2026-01-25 18:01:48 +01:00

6.4 KiB

Security Model & Best Practices

Credential Management

CRITICAL: Never Store Plaintext Passwords

All SSH credentials must be handled securely:

User provides SSH credentials at push time:

// Frontend
const response = await fetch('/api/v1/configurations/123/push', {
  method: 'POST',
  body: JSON.stringify({
    configuration_id: 123,
    device_id: 456,
    ssh_username: 'admin',
    ssh_password: 'SecurePass123',  // ONLY sent at push time
    confirmed: true,
    dry_run: false
  })
})

Backend receives credentials in request, uses immediately, discards after execution.

Option 2: Encrypted Storage (Advanced)

If storing credentials (not recommended without vault):

# Backend
from app.core.security import encrypt_credential, decrypt_credential

# Encrypt before storing
encrypted = encrypt_credential("plaintext_password")
device.ssh_password_encrypted = encrypted

# Decrypt only when pushing
plaintext = decrypt_credential(device.ssh_password_encrypted)
executor = SSHExecutor(..., password=plaintext)
# Use immediately
plaintext = None  # Clear from memory

⚠️ Never use hardcoded encryption keys. Use:

  • AWS KMS
  • HashiCorp Vault
  • Azure Key Vault
  • Environment variables (CI/CD only)

Access Control

User Isolation

  • Each user owns their projects
  • Projects contain devices & configs
  • API enforces project.owner_id == current_user.id
# Backend example
def get_project(project_id: int, current_user: User):
    project = db.query(Project).filter(Project.id == project_id).first()
    if project.owner_id != current_user.id:
        raise HTTPException(status_code=403, detail="Forbidden")
    return project

Token-Based Authentication

  • JWT tokens expire after 30 minutes
  • Refresh token pattern (future: V1)
  • Token contains only user email (no sensitive data)
# core/security.py
def create_access_token(data: dict):
    to_encode = data.copy()
    expire = datetime.utcnow() + timedelta(minutes=30)
    to_encode.update({"exp": expire})
    
    encoded_jwt = jwt.encode(
        to_encode,
        settings.secret_key,
        algorithm=settings.algorithm
    )
    return encoded_jwt

SSH Security

Pre-Push Validation

  1. Dry-run mode (generate only, no execution)
  2. CLI preview (user sees exact commands)
  3. Confirmation modal (explicit yes/no)
  4. Backup running-config before push

Connection Security

  • SSH only (no Telnet)
  • Device authentication via username/password or SSH keys (future)
  • 30-second timeout (prevent hanging)
  • Error handling without exposing internals
# ssh/__init__.py
def connect(self):
    try:
        device = {
            "device_type": "cisco_ios",
            "host": self.ip_address,
            "username": self.username,
            "password": self.password,
            "port": self.ssh_port,
            "timeout": self.timeout,  # 30s timeout
        }
        self.connection = ConnectHandler(**device)
    except NetmikoAuthenticationException as e:
        raise SSHConnectionError(f"Auth failed")  # No password leak
    except NetmikoTimeoutException as e:
        raise SSHConnectionError(f"Timeout")  # Generic error

Audit Logging

All SSH operations logged to push_logs table:

-- What was pushed
- device_id
- configuration_id
- commands_sent (plain text)
- device_output (verbatim)

-- When & by whom
- created_at
- pushed_by (username)

-- Safety
- pre_push_backup (running-config before)
- was_rolled_back (if reverted)
- rollback_reason

Example query to review push history:

SELECT id, device_id, created_at, pushed_by, status
FROM push_logs
WHERE device_id = 456
ORDER BY created_at DESC
LIMIT 10;

Network Security

HTTPS in Production

# main.py production config
if not settings.debug:
    # Redirect HTTP to HTTPS
    app.add_middleware(HTTPSRedirectMiddleware)
    # Add HSTS header
    app.add_middleware(HSTSMiddleware, max_age=31536000)

CORS Configuration

# main.py
app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://your-domain.com"],  # NOT *
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["Authorization", "Content-Type"],
)

API Rate Limiting (TODO: V1)

# Prevent brute force / DoS
# 100 requests per minute per IP
# 1000 requests per hour per user

Database Security

SQL Injection Prevention

Use SQLAlchemy ORM (parameterized queries):

# ✅ Safe - parameterized
user = db.query(User).filter(User.email == user_email).first()

# ❌ NEVER - raw SQL with string formatting
user = db.execute(f"SELECT * FROM users WHERE email = '{user_email}'")

Sensitive Data

  • Passwords: BCrypt hashed (never plaintext)
  • SSH credentials: Encrypted or runtime-only
  • API keys: Environment variables (never in code)

Disclaimer & User Awareness

In UI

<!-- Frontend -->
<div class="security-disclaimer">
  <p>⚠️ <strong>WARNING</strong></p>
  <p>This tool executes commands on live network devices.</p>
  <p>Review all configurations before pushing.</p>
  <p>Test in lab environment first.</p>
  <p>Backup devices before any changes.</p>
  <p>All operations are logged for audit.</p>
</div>

In API

# main.py
@app.get("/api/v1/docs")
def docs():
    """
    Include security warning in OpenAPI docs
    """
    return {
        "warning": "This API modifies network device configurations via SSH. Use with caution.",
        "docs": "...",
    }

Deployment Checklist

  • Secrets: Use environment variables (AWS Secrets Manager, etc.)
  • SSL/TLS: Enforce HTTPS only
  • CORS: Lock down to your domain
  • Database: PostgreSQL with strong credentials, encrypted connection
  • SSH Keys: Support SSH key auth (not just passwords)
  • Logging: Centralized logging (ELK, Datadog, etc.)
  • Monitoring: Alert on failed pushes, timeout errors
  • Backup: Database backups daily
  • Compliance: Log retention policy (min 90 days)
  • Testing: Penetration test before launch

Future: V1 Features

  • SSH key authentication (instead of passwords)
  • OAuth 2.0 / SSO integration
  • Role-based access control (RBAC)
  • Encryption at rest (database)
  • Multi-factor authentication (MFA)
  • Webhook integration for audit events
  • Compliance reporting (PCI-DSS, SOC2)