Skip to main content

Security Deployment Guide

Comprehensive guide for deploying Aragora securely in production environments.

Table of Contents


Security Headers

Required Headers

Apply these headers to all responses in your reverse proxy (nginx, Cloudflare, etc.):

# nginx.conf

# Prevent MIME type sniffing
add_header X-Content-Type-Options "nosniff" always;

# Prevent clickjacking
add_header X-Frame-Options "DENY" always;

# Enable XSS filter (legacy browsers)
add_header X-XSS-Protection "1; mode=block" always;

# Enforce HTTPS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# Control referrer information
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# Restrict browser features
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()" always;

Content Security Policy

Configure CSP based on your deployment:

# Production CSP - strict
add_header Content-Security-Policy "
default-src 'self';
script-src 'self' 'unsafe-inline' https://js.stripe.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self';
connect-src 'self' wss://your-domain.com https://api.stripe.com;
frame-src https://js.stripe.com;
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
upgrade-insecure-requests;
" always;

CORS Headers

Configure CORS in your application or reverse proxy:

# Environment variable
ARAGORA_ALLOWED_ORIGINS=https://app.yourdomain.com,https://yourdomain.com
# nginx.conf
location /api/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '$http_origin';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Request-ID';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' '86400';
add_header 'Content-Length' '0';
return 204;
}
}

WAF Configuration

Cloudflare WAF

Recommended Cloudflare WAF rules for Aragora:

1. Rate Limiting Rules

Rule: API Rate Limit
Expression: (http.request.uri.path contains "/api/")
Action: Challenge
Rate: 100 requests per 10 seconds per IP
Rule: Auth Endpoint Protection
Expression: (http.request.uri.path contains "/api/auth/login" or http.request.uri.path contains "/api/auth/register")
Action: Challenge
Rate: 5 requests per minute per IP

2. SQL Injection Protection

Rule: SQL Injection Block
Expression: (
http.request.uri.query contains "UNION" or
http.request.uri.query contains "SELECT" or
http.request.uri.query contains "INSERT" or
http.request.uri.query contains "UPDATE" or
http.request.uri.query contains "DELETE" or
http.request.uri.query contains "--" or
http.request.uri.query contains "'" and http.request.uri.query contains "OR"
)
Action: Block

3. XSS Protection

Rule: XSS Block
Expression: (
http.request.uri.query contains "<script" or
http.request.uri.query contains "javascript:" or
http.request.uri.query contains "onerror=" or
http.request.uri.query contains "onload="
)
Action: Block

4. Path Traversal Protection

Rule: Path Traversal Block
Expression: (
http.request.uri.path contains ".." or
http.request.uri.path contains "..%2f" or
http.request.uri.path contains "%2e%2e"
)
Action: Block

5. Bot Protection

Rule: Known Bad Bots
Expression: (
cf.client.bot or
http.user_agent contains "sqlmap" or
http.user_agent contains "nikto" or
http.user_agent contains "nmap"
)
Action: Challenge

AWS WAF Rules

For AWS deployments, use these WAF rule sets:

# AWS WAF Web ACL
Resources:
AragoraWAF:
Type: AWS::WAFv2::WebACL
Properties:
Name: aragora-waf
Scope: REGIONAL
DefaultAction:
Allow: {}
Rules:
# AWS Managed Rule Sets
- Name: AWSManagedRulesCommonRuleSet
Priority: 1
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesCommonRuleSet
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: CommonRuleSet

- Name: AWSManagedRulesKnownBadInputsRuleSet
Priority: 2
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesKnownBadInputsRuleSet
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: KnownBadInputsRuleSet

- Name: AWSManagedRulesSQLiRuleSet
Priority: 3
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesSQLiRuleSet
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: SQLiRuleSet

# Custom Rate Limiting
- Name: RateLimitRule
Priority: 4
Statement:
RateBasedStatement:
Limit: 2000
AggregateKeyType: IP
Action:
Block: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: RateLimitRule

nginx ModSecurity

For self-hosted deployments with nginx:

# /etc/nginx/modsecurity/aragora.conf

# Enable ModSecurity
SecRuleEngine On

# SQL Injection
SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_BODY|REQUEST_HEADERS|XML:/*|XML://@* "@detectSQLi" \
"id:1,\
phase:2,\
block,\
capture,\
t:none,t:urlDecodeUni,\
msg:'SQL Injection Attack',\
logdata:'Matched Data: %{TX.0} found within %\{MATCHED_VAR_NAME\}',\
tag:'attack-sqli'"

# XSS
SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_BODY|REQUEST_HEADERS|XML:/*|XML://@* "@detectXSS" \
"id:2,\
phase:2,\
block,\
capture,\
t:none,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,\
msg:'XSS Attack',\
logdata:'Matched Data: %{TX.0} found within %\{MATCHED_VAR_NAME\}',\
tag:'attack-xss'"

# Path Traversal
SecRule REQUEST_URI "@contains .." \
"id:3,\
phase:1,\
block,\
msg:'Path Traversal Attempt',\
tag:'attack-lfi'"

# Rate Limiting (use with nginx limit_req)
# See nginx rate limiting below

TLS Configuration

nginx TLS Configuration

# /etc/nginx/conf.d/ssl.conf

# TLS 1.2 and 1.3 only
ssl_protocols TLSv1.2 TLSv1.3;

# Strong cipher suites
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;

# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# SSL session caching
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

# DH parameters (generate with: openssl dhparam -out /etc/nginx/dhparam.pem 2048)
ssl_dhparam /etc/nginx/dhparam.pem;

Certificate Requirements

  • Use certificates from trusted CAs (Let's Encrypt, DigiCert, etc.)
  • Enable automatic renewal
  • Monitor certificate expiration
# Let's Encrypt with certbot
certbot certonly --nginx -d api.yourdomain.com -d app.yourdomain.com

# Auto-renewal cron
0 0 * * * certbot renew --quiet --post-hook "systemctl reload nginx"

Network Security

Firewall Rules

# Allow HTTPS only
ufw allow 443/tcp

# Allow SSH from specific IPs
ufw allow from <admin-ip> to any port 22

# Block everything else
ufw default deny incoming
ufw enable

Internal Network Isolation

# kubernetes/network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: aragora-network-policy
namespace: aragora
spec:
podSelector:
matchLabels:
app: aragora
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: nginx-ingress
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: redis
ports:
- protocol: TCP
port: 6379
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
# Allow external HTTPS for LLM APIs
- to:
- ipBlock:
cidr: 0.0.0.0/0
ports:
- protocol: TCP
port: 443

Secrets Management

Environment Variables

Never commit secrets to version control.

# Production secrets (set in deployment platform)
ARAGORA_JWT_SECRET=<random-256-bit-key>
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...

# Database credentials
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_KEY=eyJ...

Kubernetes Secrets

# secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: aragora-secrets
namespace: aragora
type: Opaque
stringData:
aragora-jwt-secret: $\{ARAGORA_JWT_SECRET\}
stripe-secret-key: $\{STRIPE_SECRET_KEY\}
anthropic-api-key: $\{ANTHROPIC_API_KEY\}

HashiCorp Vault

For advanced secret management:

# Example Vault integration
import hvac

client = hvac.Client(url='https://vault.internal:8200')
client.auth.kubernetes.login(role='aragora')

secrets = client.secrets.kv.read_secret_version(path='aragora/production')
ARAGORA_JWT_SECRET = secrets['data']['data']['aragora_jwt_secret']

Monitoring and Alerting

Security Alerts

Configure alerts for:

  1. Authentication Failures

    • 5 failed logins per user per hour

    • 20 failed logins per IP per hour

  2. Rate Limiting

    • 100 requests blocked per minute

  3. WAF Blocks

    • Any SQL injection attempt
    • Any XSS attempt
    • Path traversal attempts
  4. Certificate Expiration

    • Alert at 30 days before expiry
    • Critical at 7 days before expiry

Prometheus Alerts

# prometheus/alerts.yaml
groups:
- name: security
rules:
- alert: HighFailedLogins
expr: sum(rate(aragora_auth_failures_total[5m])) > 10
for: 5m
labels:
severity: warning
annotations:
summary: High rate of failed login attempts

- alert: WAFBlocksSpike
expr: sum(rate(aragora_waf_blocks_total[5m])) > 50
for: 2m
labels:
severity: critical
annotations:
summary: High rate of WAF blocks - possible attack

- alert: CertificateExpiringSoon
expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 7
for: 1h
labels:
severity: critical
annotations:
summary: TLS certificate expires in less than 7 days

Audit Logging

Enable comprehensive audit logging:

# Environment variable
ARAGORA_AUDIT_ENABLED=true
ARAGORA_AUDIT_RETENTION_DAYS=90

Audit log includes:

  • All authentication events (login, logout, MFA)
  • Authorization failures
  • Admin actions
  • Data access patterns
  • API key usage

Application Security

Aragora includes several application-level security features that are enabled by default.

OIDC Token Validation

Token validation is enforced strictly in production mode:

# Environment variable (default: true in production)
ARAGORA_STRICT_TOKEN_VALIDATION=true

When enabled:

  • ID tokens must have valid signatures (no fallback to userinfo endpoint)
  • Expired tokens are rejected without exception
  • Token claims (iss, aud, exp) are fully validated

Tenant Isolation

Multi-tenant deployments enforce strict resource isolation:

# Shared resources are validated at startup
# Only explicitly allowed resources can be shared across tenants:
ALLOWED_SHARED_RESOURCES = frozenset([
"system_agents", # System-provided agents
"public_templates", # Public workflow templates
])

Key protections:

  • Query filters automatically include tenant_id
  • Cross-tenant data access is logged and audited
  • Shared resources are immutable and defined at startup

RBAC Permission Validation

All route permissions are validated at startup:

# Environment variable (default: false, set to true for strict mode)
ARAGORA_RBAC_STRICT_MODE=true

Features:

  • Route permissions validated against SYSTEM_PERMISSIONS registry
  • Undefined permissions logged as warnings (errors in strict mode)
  • Wildcard permissions (e.g., admin.*) validated against defined permission prefixes
  • O(1) cache invalidation using version-based keys

Rate Limiting

Configure per-client and per-endpoint rate limits:

# Global rate limits
ARAGORA_RATE_LIMIT_REQUESTS=1000
ARAGORA_RATE_LIMIT_WINDOW_SECONDS=60

# Per-tier overrides
ARAGORA_RATE_LIMIT_FREE_TIER=100
ARAGORA_RATE_LIMIT_PRO_TIER=1000
ARAGORA_RATE_LIMIT_ENTERPRISE_TIER=10000

Security Checklist

Pre-Deployment

  • All secrets stored in secure vault/platform secrets
  • TLS certificates configured and valid
  • WAF rules deployed and tested
  • Security headers configured
  • CORS properly restricted
  • Rate limiting configured
  • Network policies applied
  • Audit logging enabled

Post-Deployment

  • Penetration test completed
  • Security monitoring active
  • Alert thresholds configured
  • Incident response plan documented
  • Regular security updates scheduled

Periodic Review

  • Review access logs monthly
  • Rotate secrets quarterly
  • Update dependencies weekly
  • Review WAF rules quarterly
  • Test backup restoration quarterly