> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Arvo-AI/aurora/llms.txt
> Use this file to discover all available pages before exploring further.

# Security Architecture

> Security best practices and architecture for Aurora

## Overview

Aurora implements defense-in-depth security with multiple layers of protection:

* **Authentication & Authorization**: User identity verification and access control
* **Secrets Management**: HashiCorp Vault for sensitive credentials
* **Network Security**: TLS encryption and CORS protection
* **Data Protection**: Row-Level Security and encryption
* **Input Validation**: Protection against injection attacks
* **Rate Limiting**: DDoS and abuse prevention

## Authentication

### Password-Based Authentication

Aurora uses bcrypt for secure password hashing:

```python theme={null}
import bcrypt

# Registration
password_hash = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())

# Login
password_valid = bcrypt.checkpw(
    password.encode('utf-8'), 
    password_hash.encode('utf-8')
)
```

**Security Features:**

* **Minimum 8 characters** password requirement
* **bcrypt hashing** with automatic salt generation
* **Work factor**: Default bcrypt cost parameter (10-12 rounds)
* **Constant-time comparison** to prevent timing attacks
* **No password storage**: Only hashed values stored in database

**Best Practices:**

```python theme={null}
# SECURE: Timing-attack resistant
if bcrypt.checkpw(user_password, stored_hash):
    return True

# INSECURE: Vulnerable to timing attacks
if user_password == stored_password:  # DON'T DO THIS
    return True
```

### Session Management

Flask session cookies with secure configuration:

```python theme={null}
app.config.update(
    SECRET_KEY=os.getenv("FLASK_SECRET_KEY") or secrets.token_hex(24),
    SESSION_TYPE="filesystem",
    SESSION_PERMANENT=False,
    SESSION_FILE_DIR="/tmp/flask_session",
    SESSION_COOKIE_SECURE=True,      # HTTPS only in production
    SESSION_COOKIE_HTTPONLY=True,    # No JavaScript access
    SESSION_COOKIE_SAMESITE="Lax"    # CSRF protection
)
```

**Session Security:**

* **Secure cookies** in production (HTTPS)
* **HttpOnly flag** prevents XSS cookie theft
* **SameSite=Lax** prevents CSRF attacks
* **File-based storage** (not memory-based)
* **Automatic session cleanup**

### OAuth 2.0 Integration

Cloud provider authentication via OAuth:

**GCP OAuth Flow:**

```python theme={null}
# 1. Generate authorization URL
auth_url = get_auth_url(state=user_id)

# 2. User authorizes in browser
# 3. Handle callback with authorization code
token_data = exchange_code_for_token(code)

# 4. Store tokens securely in Vault
store_tokens_in_db(user_id, token_data, "gcp")
```

**OAuth Security:**

* **State parameter** prevents CSRF attacks
* **PKCE (optional)** for public clients
* **Token encryption** before storage
* **Automatic token refresh**
* **Scope limitation** (principle of least privilege)

## Authorization

### Row-Level Security (RLS)

PostgreSQL RLS enforces data isolation:

```sql theme={null}
-- Enable RLS on table
ALTER TABLE chat_sessions ENABLE ROW LEVEL SECURITY;

-- Create user isolation policy
CREATE POLICY user_isolation_policy ON chat_sessions
    USING (user_id = current_setting('myapp.current_user_id', TRUE)::TEXT);
```

**Protected Tables:**

* `chat_sessions`: Users can only access their own chats
* `incidents`: Users can only see their incidents
* `user_tokens`: Users can only access their credentials
* `llm_usage_tracking`: Users can only see their usage
* All Kubernetes and monitoring tables

**Setting User Context:**

```python theme={null}
with db_pool.get_admin_connection() as conn:
    cursor = conn.cursor()
    cursor.execute("SET myapp.current_user_id = %s", (user_id,))
    conn.commit()
    
    # Now queries respect RLS policies
    cursor.execute("SELECT * FROM chat_sessions")
```

### API Authorization

Header-based authentication for API requests:

```python theme={null}
from utils.auth.stateless_auth import get_user_id_from_request

@app.route('/api/resource')
def get_resource():
    user_id = get_user_id_from_request()
    if not user_id:
        return jsonify({'error': 'Unauthorized'}), 401
    
    # User authenticated, proceed with request
    return jsonify({'data': ...})
```

**Authentication Headers:**

```http theme={null}
X-User-ID: user_abc123
Authorization: Bearer <token>  # For kubectl agent
```

## Secrets Management

### HashiCorp Vault

Aurora uses Vault for sensitive credential storage:

**Architecture:**

```
┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│   Aurora    │────▶│  PostgreSQL  │────▶│    Vault    │
│   Server    │     │  (secret_ref)│     │  (secrets)  │
└─────────────┘     └──────────────┘     └─────────────┘
```

**Configuration:**

```bash theme={null}
VAULT_ADDR=http://vault:8200
VAULT_TOKEN=hvs.xxxxxxxxxxxxx
VAULT_KV_MOUNT=aurora
VAULT_KV_BASE_PATH=
```

**Storing Secrets:**

```python theme={null}
from utils.secrets.vault_utils import store_secret_in_vault

# Store OAuth tokens in Vault
secret_ref = store_secret_in_vault(
    user_id=user_id,
    provider="gcp",
    data={
        "access_token": token_data["access_token"],
        "refresh_token": token_data["refresh_token"]
    }
)

# Store reference in database
cursor.execute(
    "UPDATE user_tokens SET secret_ref = %s WHERE user_id = %s AND provider = %s",
    (secret_ref, user_id, "gcp")
)
```

**Retrieving Secrets:**

```python theme={null}
from utils.secrets.vault_utils import get_secret_from_vault

# Get reference from database
cursor.execute(
    "SELECT secret_ref FROM user_tokens WHERE user_id = %s AND provider = %s",
    (user_id, "gcp")
)
secret_ref = cursor.fetchone()[0]

# Retrieve secret from Vault
token_data = get_secret_from_vault(secret_ref)
```

**Secret References:**

```
vault:kv/data/aurora/users/user_abc123/gcp
```

### Redis Caching

Secrets cached in Redis with TTL:

```python theme={null}
from utils.secrets.secret_cache import get_cached_secret, cache_secret

# Check cache first
secret = get_cached_secret(secret_ref)
if not secret:
    # Cache miss, fetch from Vault
    secret = get_secret_from_vault(secret_ref)
    cache_secret(secret_ref, secret, ttl=3600)  # 1 hour TTL
```

**Cache Invalidation:**

```python theme={null}
from utils.secrets.secret_cache import clear_secret_cache

# Clear cache after credential update
clear_secret_cache(secret_ref)
```

## Network Security

### TLS/HTTPS

**Production Configuration:**

```yaml theme={null}
# nginx.conf
server {
    listen 443 ssl http2;
    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    
    location / {
        proxy_pass http://aurora-server:5080;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

### CORS Configuration

Cross-Origin Resource Sharing protection:

```python theme={null}
from flask_cors import CORS

CORS(app, 
    origins=FRONTEND_URL,
    supports_credentials=True,
    methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    allow_headers=[
        "Content-Type",
        "X-Provider",
        "X-User-ID",
        "Authorization"
    ]
)
```

**Security Headers:**

```python theme={null}
@app.after_request
def add_security_headers(response):
    response.headers['X-Content-Type-Options'] = 'nosniff'
    response.headers['X-Frame-Options'] = 'DENY'
    response.headers['X-XSS-Protection'] = '1; mode=block'
    response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
    return response
```

## Input Validation

### SQL Injection Prevention

**Always use parameterized queries:**

```python theme={null}
# SECURE: Parameterized query
cursor.execute(
    "SELECT * FROM users WHERE email = %s",
    (user_email,)
)

# INSECURE: String concatenation (NEVER DO THIS)
cursor.execute(
    f"SELECT * FROM users WHERE email = '{user_email}'"  # SQL INJECTION!
)
```

### XSS Prevention

**Frontend sanitization:**

```typescript theme={null}
import DOMPurify from 'dompurify';

// Sanitize user input before rendering
const cleanHTML = DOMPurify.sanitize(userInput);
```

**Backend validation:**

```python theme={null}
import bleach

# Strip HTML tags from user input
clean_text = bleach.clean(user_input, tags=[], strip=True)
```

### Command Injection Prevention

**Never use shell=True with user input:**

```python theme={null}
import subprocess

# SECURE: List arguments (no shell)
result = subprocess.run(
    ["kubectl", "get", "pods", "-n", namespace],
    capture_output=True,
    check=True
)

# INSECURE: shell=True with user input (COMMAND INJECTION!)
result = subprocess.run(
    f"kubectl get pods -n {namespace}",  # DANGEROUS!
    shell=True,
    capture_output=True
)
```

### Path Traversal Prevention

**Validate file paths:**

```python theme={null}
import os

def safe_read_file(base_dir, filename):
    # Resolve absolute path
    filepath = os.path.abspath(os.path.join(base_dir, filename))
    
    # Ensure path is within base directory
    if not filepath.startswith(os.path.abspath(base_dir)):
        raise ValueError("Path traversal detected")
    
    with open(filepath, 'r') as f:
        return f.read()
```

## Rate Limiting

### API Rate Limiting

Protect against abuse and DDoS:

```python theme={null}
from utils.web.limiter_ext import limiter

# Global rate limit
limiter.init_app(app)

# Per-endpoint limits
@app.route('/api/resource')
@limiter.limit("100/minute")
def get_resource():
    return jsonify({'data': ...})

# Stricter limit for expensive operations
@app.route('/api/deploy')
@limiter.limit("10/minute")
def deploy():
    return jsonify({'status': 'deploying'})
```

**Configuration:**

```python theme={null}
app.config.update(
    RATELIMIT_STORAGE_URL="redis://redis:6379",
    RATELIMIT_STRATEGY="fixed-window",
    RATELIMIT_DEFAULT="100/minute"
)
```

### WebSocket Rate Limiting

Custom rate limiter for WebSocket connections:

```python theme={null}
class RateLimiter:
    def __init__(self, rate, per):
        self.tokens = defaultdict(lambda: rate)
        self.rate = rate
        self.per = per
        self.last_checked = defaultdict(time.time)

    def is_allowed(self, client_id):
        now = time.time()
        elapsed = now - self.last_checked[client_id]
        self.last_checked[client_id] = now

        self.tokens[client_id] += elapsed * (self.rate / self.per)
        if self.tokens[client_id] > self.rate:
            self.tokens[client_id] = self.rate

        if self.tokens[client_id] >= 1:
            self.tokens[client_id] -= 1
            return True
        return False

# 5 messages per 60 seconds
rate_limiter = RateLimiter(rate=5, per=60)
```

## Data Protection

### Encryption at Rest

**Database encryption:**

```yaml theme={null}
# PostgreSQL with encryption
postgres:
  image: postgres:15
  command: postgres -c ssl=on -c ssl_cert_file=/var/lib/postgresql/server.crt
  volumes:
    - ./certs:/var/lib/postgresql
```

**Object storage encryption:**

```python theme={null}
from utils.storage.storage import get_storage_manager

storage = get_storage_manager(
    user_id=user_id,
    encryption=True  # Server-side encryption
)

storage.upload_file("sensitive-data.txt", data)
```

### Encryption in Transit

**All network traffic encrypted:**

* HTTPS for REST API (TLS 1.2+)
* WSS for WebSocket (TLS 1.2+)
* SSL for PostgreSQL connections
* TLS for Redis connections

### Data Retention

**Soft deletes for user data:**

```sql theme={null}
-- Soft delete chat session
UPDATE chat_sessions 
SET is_active = false, updated_at = NOW()
WHERE id = %s AND user_id = %s;

-- Hard delete after retention period (30 days)
DELETE FROM chat_sessions 
WHERE is_active = false 
  AND updated_at < NOW() - INTERVAL '30 days';
```

## Vulnerability Management

### Dependency Scanning

**Python dependencies:**

```bash theme={null}
# Scan for known vulnerabilities
pip-audit

# Update vulnerable packages
pip install --upgrade package-name
```

**npm dependencies:**

```bash theme={null}
# Scan for vulnerabilities
npm audit

# Automatically fix
npm audit fix
```

### Container Security

**Dockerfile best practices:**

```dockerfile theme={null}
# Use specific versions (not :latest)
FROM python:3.11-slim

# Run as non-root user
RUN useradd -m -u 1000 aurora
USER aurora

# Minimal base image
FROM python:3.11-slim AS base

# Multi-stage build
FROM base AS builder
# ... build steps ...

FROM base AS final
COPY --from=builder /app /app
```

**Image scanning:**

```bash theme={null}
# Scan Docker images for vulnerabilities
trivy image aurora-server:latest
```

## Incident Response

### Logging

**Security event logging:**

```python theme={null}
import logging

logger = logging.getLogger(__name__)

# Log authentication events
logger.info(f"User logged in: {user_email}")
logger.warning(f"Failed login attempt: {user_email}")

# Log authorization failures
logger.error(f"Unauthorized access attempt: {user_id} -> {resource}")

# Log security-critical operations
logger.info(f"User {user_id} deleted incident {incident_id}")
```

### Monitoring

**Security metrics:**

* Failed authentication attempts
* Rate limit violations
* Unauthorized access attempts
* Abnormal API usage patterns
* Database connection failures

### Reporting Security Issues

**DO NOT report security vulnerabilities through public GitHub issues.**

Instead, email: **[info@arvoai.ca](mailto:info@arvoai.ca)**

**Include:**

* Type of vulnerability
* Affected source files
* Steps to reproduce
* Proof-of-concept (if possible)
* Impact assessment

## Security Checklist

### Development

* [ ] All passwords hashed with bcrypt
* [ ] Parameterized SQL queries only
* [ ] No shell=True in subprocess calls
* [ ] Input validation on all endpoints
* [ ] Output sanitization for user-generated content
* [ ] Secrets stored in Vault, not environment variables
* [ ] Rate limiting on all public endpoints

### Deployment

* [ ] HTTPS enabled with valid certificates
* [ ] Security headers configured
* [ ] CORS properly restricted
* [ ] Database encryption enabled
* [ ] Redis password configured
* [ ] Vault sealed/unsealed properly
* [ ] Firewall rules configured
* [ ] Container images scanned

### Operations

* [ ] Regular security updates applied
* [ ] Dependency vulnerabilities patched
* [ ] Audit logs reviewed regularly
* [ ] Access logs monitored
* [ ] Incident response plan documented
* [ ] Backup encryption verified
* [ ] Disaster recovery tested

## Additional Resources

* [OWASP Top 10](https://owasp.org/www-project-top-ten/)
* [CWE Top 25](https://cwe.mitre.org/top25/)
* [Docker Security Best Practices](https://docs.docker.com/engine/security/)
* [Kubernetes Security Best Practices](https://kubernetes.io/docs/concepts/security/)
* [PostgreSQL Security](https://www.postgresql.org/docs/current/security.html)
* [HashiCorp Vault Security](https://www.vaultproject.io/docs/internals/security)
