Odoo Security Hardening: Autenticação, Direitos de Acesso e Criptografia
Os sistemas ERP empresariais são alvos de alto valor para ataques cibernéticos. Uma instância Odoo contendo PII de clientes, registros financeiros, contratos de fornecedores e dados de funcionários representa uma superfície de ataque significativa que exige controles de segurança deliberados e em camadas.
Este guia cobre todo o processo de fortalecimento da segurança do Odoo 19 Enterprise: desde o fortalecimento da autenticação e design de direitos de acesso até o fortalecimento da rede, criptografia, registro de auditoria e prontidão para resposta a incidentes.
Principais conclusões
- As configurações padrão do Odoo não estão prontas para produção do ponto de vista da segurança
- Autenticação de dois fatores (2FA) deverá ser obrigatória para todos os usuários com acesso sensível
- Os direitos de acesso seguem o princípio do menor privilégio — os usuários obtêm apenas o que precisam
- As regras de registro fornecem segurança em nível de linha para impor o isolamento de dados
- Todas as comunicações entre serviços devem utilizar TLS; nunca HTTP em produção
- As credenciais do banco de dados devem ser alternadas regularmente e nunca codificadas
- Os registros de auditoria devem ser à prova de falsificação e retidos para atender aos requisitos de conformidade
- Os patches de segurança devem ser aplicados dentro de 48 horas após os anúncios da Odoo SA
Fortalecimento de autenticação
Política de senha
Odoo 19 suporta políticas de senha configuráveis em Configurações → Usuários e Empresas → Política de redefinição de senha.
Configurações recomendadas:
- Comprimento mínimo: 12 caracteres
- Exigir letras maiúsculas, minúsculas, números e caracteres especiais
- Expiração da senha: 90 dias
- Impedir a reutilização das últimas 12 senhas
- Bloqueio de conta após 5 tentativas fracassadas (bloqueio de 15 minutos)
# Custom password validator in a security module
from odoo import api, models
from odoo.exceptions import UserError
import re
class ResUsers(models.Model):
_inherit = 'res.users'
@api.constrains('password')
def _check_password_strength(self):
for user in self:
if user.password:
pwd = user.password
if len(pwd) < 12:
raise UserError("Password must be at least 12 characters.")
if not re.search(r'[A-Z]', pwd):
raise UserError("Password must contain an uppercase letter.")
if not re.search(r'[a-z]', pwd):
raise UserError("Password must contain a lowercase letter.")
if not re.search(r'\d', pwd):
raise UserError("Password must contain a number.")
if not re.search(r'[!@#$%^&*(),.?":{}|<>]', pwd):
raise UserError("Password must contain a special character.")
Autenticação de dois fatores (2FA)
Habilite 2FA em Configurações → Permissões → Autenticação de dois fatores.
Opções de configuração:
- Opcional: os usuários escolhem se desejam ativar o 2FA
- Obrigatório para grupos específicos: Inscreva-se para administradores e contadores
- Obrigatório para todos os usuários: Segurança máxima
Para implantações empresariais, exija 2FA para:
- Contas de administrador (
base.group_system) - Usuários financeiros (
account.group_account_manager) - Gerentes de RH com acesso à folha de pagamento
- Todos os usuários com acesso à chave API
Integração OAuth e SSO
Para organizações com provedores de identidade existentes, configure o Odoo para usar SAML 2.0 ou OAuth 2.0:
# In odoo.conf — configure OAuth
oauth_providers = [
{
'name': 'Your SSO Provider',
'client_id': 'odoo-client-id',
'auth_endpoint': 'https://sso.company.com/auth',
'validation_endpoint': 'https://sso.company.com/userinfo',
'scope': 'openid email profile',
}
]
Isso centraliza a autenticação em seu provedor de identidade, permitindo recursos como logon único, MFA centralizado e desprovisionamento automático de contas quando os funcionários saem.
Segurança da chave de API
# Restrict API key creation to administrators only
# In custom security module:
# ir.rule to prevent non-admin users from creating API keys
<record id="rule_api_key_admin_only" model="ir.rule">
<field name="name">API Keys: Admin Only</field>
<field name="model_id" ref="base.model_auth_api_key"/>
<field name="domain_force">[('create_uid', '=', user.id)]</field>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
<field name="perm_create" eval="False"/>
<field name="perm_unlink" eval="False"/>
</record>
Aplique uma política: as chaves de API expiram após 90 dias, são vinculadas a contas de serviço dedicadas com permissões mínimas e são alternadas em qualquer suspeita de comprometimento.
Arquitetura de direitos de acesso
Design de hierarquia de grupo
O controle de acesso do Odoo é baseado em grupos. Projete uma hierarquia de grupo que reflita sua estrutura organizacional:
base.group_user (Internal User)
├── sales.group_sale_salesman (Salesperson)
│ └── sales.group_sale_manager (Sales Manager)
├── account.group_account_user (Accounting User)
│ └── account.group_account_manager (Accounting Manager)
├── stock.group_stock_user (Inventory User)
│ └── stock.group_stock_manager (Inventory Manager)
└── base.group_system (Administrator)
Princípio do menor privilégio: Todo usuário deve ter o acesso mínimo necessário para realizar seu trabalho. Isso limita o raio de ataque das contas comprometidas.
Listas de controle de acesso (ACL)
As entradas ACL em ir.model.access definem permissões CRUD em nível de modelo:
id,name,model_id,group_id,perm_read,perm_write,perm_create,perm_unlink
# Salesperson: can read/write own orders, cannot delete
access_sale_order_salesman,sale.order.salesman,sale.model_sale_order,sales.group_sale_salesman,1,1,1,0
# Manager: full CRUD
access_sale_order_manager,sale.order.manager,sale.model_sale_order,sales.group_sale_manager,1,1,1,1
# Accounting user: read-only on sales orders
access_sale_order_accountant,sale.order.accountant,sale.model_sale_order,account.group_account_user,1,0,0,0
Regras de registro (segurança em nível de linha)
Filtro de regras de registro que registros um usuário pode ver em um modelo:
<!-- Salesperson sees only their own opportunities -->
<record id="rule_crm_salesman" model="ir.rule">
<field name="name">CRM: Own Leads</field>
<field name="model_id" ref="crm.model_crm_lead"/>
<field name="domain_force">
['|', ('user_id', '=', user.id), ('user_id', '=', False)]
</field>
<field name="groups" eval="[(4, ref('sales.group_sale_salesman'))]"/>
</record>
<!-- Multi-company isolation: users see only their company's records -->
<record id="rule_sale_order_company" model="ir.rule">
<field name="name">Sale Order: Company</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="domain_force">
[('company_id', 'in', company_ids)]
</field>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>
Aviso de desempenho: regras de registro complexas com muitos operadores search() ou child_of podem retardar significativamente as exibições de lista. Teste todas as regras de registro em grandes conjuntos de dados antes de implantar na produção.
Segurança de rede
Aplicação de TLS/HTTPS
Nunca execute o Odoo sobre HTTP simples em produção. Todo o tráfego deve ser criptografado.
Configuração Nginx TLS:
server {
listen 80;
server_name your-odoo.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-odoo.com;
ssl_certificate /etc/ssl/certs/your-odoo.com.pem;
ssl_certificate_key /etc/ssl/private/your-odoo.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
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 off;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
# HSTS: 2 years, include subdomains
add_header Strict-Transport-Security
"max-age=63072000; includeSubDomains; preload" always;
# Security headers
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
add_header Permissions-Policy
"camera=(), microphone=(), geolocation=()" always;
}
Configuração de Firewall
# UFW firewall rules for Odoo server
ufw default deny incoming
ufw default allow outgoing
# Allow SSH from management IP only
ufw allow from 10.0.1.100 to any port 22
# Allow HTTPS from anywhere
ufw allow 443/tcp
# Allow HTTP (for Let's Encrypt renewal)
ufw allow 80/tcp
# Allow PostgreSQL only from Odoo server (if separate DB server)
ufw allow from 10.0.1.10 to any port 5432
# Block direct access to Odoo port (must go through Nginx)
ufw deny 8069/tcp
ufw deny 8072/tcp
ufw enable
Limitação de taxa
Configure a limitação de taxa no Nginx para evitar ataques de força bruta:
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=api:10m rate=60r/m;
server {
# Apply rate limiting to login endpoint
location /web/login {
limit_req zone=login burst=3 nodelay;
limit_req_status 429;
proxy_pass http://odoo;
}
# Apply rate limiting to API
location /web/dataset/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://odoo;
}
}
Criptografia de dados
Criptografia em nível de banco de dados
Para dados altamente confidenciais, os campos Odoo podem ser criptografados em repouso:
# Custom encrypted field using Fernet symmetric encryption
from cryptography.fernet import Fernet
from odoo import api, fields, models
import base64, os
class EncryptedField(models.Model):
_name = 'my.sensitive.model'
_fernet_key = os.environ.get('ODOO_FIELD_ENCRYPTION_KEY')
ssn_encrypted = fields.Char(string='SSN (Encrypted)', groups='hr.group_hr_user')
ssn_display = fields.Char(
string='SSN', compute='_compute_ssn_display',
inverse='_inverse_ssn_display'
)
def _get_fernet(self):
return Fernet(self._fernet_key.encode())
def _compute_ssn_display(self):
f = self._get_fernet()
for record in self:
if record.ssn_encrypted:
decrypted = f.decrypt(record.ssn_encrypted.encode()).decode()
record.ssn_display = f"***-**-{decrypted[-4:]}"
else:
record.ssn_display = False
def _inverse_ssn_display(self):
f = self._get_fernet()
for record in self:
if record.ssn_display:
encrypted = f.encrypt(record.ssn_display.encode()).decode()
record.ssn_encrypted = encrypted
Segurança de variáveis de ambiente
Nunca armazene segredos em odoo.conf em texto simples. Use variáveis de ambiente:
# /etc/systemd/system/odoo.service
[Service]
Environment="ODOO_DB_PASSWORD=your_secure_password"
Environment="ODOO_ADMIN_PASSWD=your_master_password"
Environment="ODOO_FIELD_ENCRYPTION_KEY=your_fernet_key"
EnvironmentFile=/etc/odoo/secrets.env
# odoo.conf — reference env vars
[options]
db_password = ${ODOO_DB_PASSWORD}
admin_passwd = ${ODOO_ADMIN_PASSWD}
Registro de auditoria
O registro de auditoria integrado do Odoo rastreia todas as alterações do modelo. Ative-o para modelos sensíveis:
# Enable audit logging via the Audit Trail module
# Or implement custom logging:
class AuditableMixin(models.AbstractModel):
_name = 'audit.mixin'
def write(self, vals):
# Log what changed before the write
for record in self:
old_vals = {f: record[f] for f in vals if f in record._fields}
self.env['audit.log'].create({
'model_name': self._name,
'record_id': record.id,
'user_id': self.env.uid,
'action': 'write',
'old_values': str(old_vals),
'new_values': str(vals),
'ip_address': self.env.context.get('remote_addr'),
})
return super().write(vals)
def unlink(self):
for record in self:
self.env['audit.log'].create({
'model_name': self._name,
'record_id': record.id,
'user_id': self.env.uid,
'action': 'unlink',
'old_values': str({f: record[f] for f in ['name', 'id']}),
})
return super().unlink()
Modelos críticos de conformidade para auditoria:
res.users(criação de usuário, alterações de permissão)account.move(modificações na fatura)hr.payslip(alterações na folha de pagamento)res.partner(alterações de PII do cliente/fornecedor)ir.model.access,ir.rule(alterações de permissão)ir.config_parameter(alterações na configuração do sistema)
Gerenciamento de patches de segurança
Assine os avisos de segurança do Odoo:
Odoo SA publica avisos de segurança em https://github.com/odoo/odoo/security/advisories. Assine as notificações do GitHub para este repositório.
Processo de aplicação de patch:
# Check current Odoo version
python3 odoo-bin --version
# Pull latest security patches (within a minor version)
cd /opt/odoo
git fetch origin
git log origin/19.0..HEAD --oneline # See what's changed
# Apply patches on staging first
git merge origin/19.0
python3 odoo-bin -d staging_db -u all --stop-after-init
# Test critical workflows on staging
# If all clear, apply to production during maintenance window
Meta: correção dentro de 48 horas após um aviso de gravidade Crítica ou Alta. Gravidade média: dentro de 1 semana. Gravidade baixa: próxima janela de manutenção planejada.
Perguntas frequentes
Como faço para auditar quem excluiu um registro no Odoo?
Odoo não registra exclusões por padrão. Instale o módulo auditlog da Odoo Community Association (OCA) ou implemente uma substituição unlink() personalizada em seus modelos confidenciais. O módulo auditlog do OCA registra operações de criação, gravação e desvinculação de um modelo auditlog.log com usuário, carimbo de data/hora e rastreamento de alterações em nível de campo.
Posso restringir o acesso do Odoo por endereço IP?
Não nativamente em Odoo. Implemente a lista de permissões de IP no nível do Nginx ou do firewall. Para acesso administrativo, exija conexão VPN como pré-requisito. O ir.config_parameter do Odoo suporta uma restrição web.base.url, mas o verdadeiro controle de acesso baseado em IP pertence à camada de rede.
Qual é a diferença entre direitos de acesso (ACL) e regras de registro?
Os direitos de acesso (ACL, armazenados em ir.model.access) controlam se um grupo de usuários pode ler, gravar, criar ou excluir qualquer registro de um modelo — este é o controle em nível de modelo. As regras de registro filtram quais registros específicos um usuário pode acessar dentro de um modelo usando expressões de domínio — este é o controle em nível de linha. Ambos trabalham juntos: um usuário precisa de permissão de leitura da ACL E deve passar pelo filtro de domínio da regra de registro para ver um registro.
Como devo lidar com a senha mestra do Odoo (admin_passwd)?
O admin_passwd em odoo.conf controla o acesso à interface de gerenciamento de banco de dados em /web/database/manager. Na produção: defina-o como uma string aleatória longa (mais de 32 caracteres), armazene-o em um gerenciador de senhas, nunca compartilhe-o e considere desabilitar totalmente o gerenciador de banco de dados com list_db = False em odoo.conf se você gerencia o banco de dados via acesso direto ao PostgreSQL.
Devo executar o Odoo como root?
Nunca. Crie um usuário de sistema odoo dedicado sem acesso shell e permissões limitadas de sistema de arquivos. O usuário odoo precisa de acesso de leitura à base de código Odoo e acesso de gravação apenas ao armazenamento de arquivos e aos diretórios de log. Execute o serviço systemd como este usuário. Executar como root viola o princípio do menor privilégio e maximiza os danos de qualquer vulnerabilidade de execução de código.
Próximas etapas
O fortalecimento da segurança não é uma tarefa única – é uma prática contínua. Surgem novas vulnerabilidades, os requisitos de acesso dos usuários mudam e as estruturas de conformidade evoluem. Uma implantação segura do Odoo requer análises regulares de segurança, disciplina de gerenciamento de patches e auditorias de direitos de acesso.
ECOSIRE fornece avaliações de reforço de segurança Odoo que identificam configurações incorretas, permissões excessivas, controles ausentes e lacunas de conformidade. Nossa equipe de segurança tem experiência com os requisitos ISO 27001, SOC 2 e GDPR em ambientes Odoo.
Solicite uma avaliação de segurança Odoo da ECOSIRE →
Analisaremos sua configuração atual em relação aos padrões do setor e forneceremos um plano de correção priorizado com suporte de implementação.
Escrito por
ECOSIRE Research and Development Team
Construindo produtos digitais de nível empresarial na ECOSIRE. Compartilhando insights sobre integrações Odoo, automação de e-commerce e soluções de negócios com IA.
Artigos Relacionados
Odoo Accounting vs QuickBooks: Detailed Comparison 2026
In-depth 2026 comparison of Odoo Accounting vs QuickBooks covering features, pricing, integrations, scalability, and which platform fits your business needs.
API Rate Limiting: Patterns and Best Practices
Master API rate limiting with token bucket, sliding window, and fixed counter patterns. Protect your backend with NestJS throttler, Redis, and real-world configuration examples.
Case Study: eCommerce Migration to Shopify with Odoo Backend
How a fashion retailer migrated from WooCommerce to Shopify and connected it to Odoo ERP, cutting order fulfillment time by 71% and growing revenue 43%.