addons-cm/docs/openspec/changes/security-audit-hardening/specs/infra-hardening/spec.md
2026-08-07 16:46:33 +02:00

2.9 KiB

ADDED Requirements

Requirement: Hardened Odoo configuration

Production odoo.conf SHALL set a strong admin_passwd (not the default admin), list_db = False, a dbfilter scoping databases per host, proxy_mode = True, workers > 0, request/time limits, without_demo = True, and a strong database password (not the literal odoo). The database manager SHALL NOT be reachable publicly.

Scenario: Database manager not exposed

  • WHEN an anonymous client requests /web/database/manager on production
  • THEN it is not served (blocked at the proxy and/or list_db=False)

Scenario: Real client IP reaches Odoo logs

  • WHEN a login fails behind the reverse proxy
  • THEN with proxy_mode=True the Odoo log records the real client IP (from X-Forwarded-For), not the proxy IP

Requirement: Reverse proxy enforces TLS, rate limiting and security headers

The nginx/traefik layer SHALL terminate TLS with strong protocols/ciphers, apply limit_req to /web/login, /web/session/authenticate, /jsonrpc and /xmlrpc, and set security headers (HSTS, X-Frame-Options/CSP, X-Content-Type-Options, Referrer-Policy). The session_id cookie SHALL be Secure, HttpOnly and SameSite.

Scenario: Login rate limited

  • WHEN a client exceeds the configured request rate on /web/login
  • THEN the proxy returns 429 and further attempts are throttled

Scenario: Security headers present

  • WHEN a response is returned from production
  • THEN it includes HSTS, anti-clickjacking and content-type-options headers, and the session cookie carries Secure/HttpOnly/SameSite

Requirement: Brute-force sources banned on web and API

fail2ban SHALL ban source IPs that exceed a failed-authentication threshold, covering both the web login route and the API authentication routes (/web/session/authenticate, /xmlrpc/2/common), using the real client IP.

Scenario: Repeated web login failures banned

  • WHEN a source exceeds the failed-login threshold on /web/login
  • THEN fail2ban bans that IP for the configured duration

Scenario: API auth brute force banned

  • WHEN a source brute-forces /web/session/authenticate or /xmlrpc/2/common
  • THEN the same fail2ban jail bans it (attacks via API do not bypass protection)

Requirement: Secrets and database access hardened

Database and master secrets SHALL be strong and SHALL NOT be committed in plaintext in versioned files. The PostgreSQL port SHALL NOT be reachable from outside the host/network (firewalled), and the database user SHALL have least privilege.

Scenario: DB port not externally reachable

  • WHEN an external client attempts to connect to PostgreSQL (5432) on production
  • THEN the connection is refused/filtered by the firewall

Scenario: No plaintext secrets in repo

  • WHEN the repository is inspected
  • THEN production database/master passwords are not present in plaintext in versioned files