Odoo Security Hardening: Authentication, Access Rights, and Encryption

Comprehensive Odoo 19 security hardening guide covering authentication, access rights, record rules, encryption, network security, and audit logging for enterprise deployments.

E
ECOSIRE Research and Development Team
|19 de março de 202610 min de leitura2.1k Palavras|

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.

E

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.

Converse no WhatsApp