Odoo Güvenliği Güçlendirme: Kimlik Doğrulama, Erişim Hakları ve Şifreleme
Kurumsal ERP sistemleri siber saldırılar için yüksek değerli hedeflerdir. Müşteri kişisel bilgileri, mali kayıtlar, tedarikçi sözleşmeleri ve çalışan verilerini içeren bir Odoo örneği, kasıtlı, katmanlı güvenlik kontrolleri gerektiren önemli bir saldırı yüzeyini temsil eder.
Bu kılavuz, Odoo 19 Enterprise için güvenlik güçlendirme sürecinin tamamını kapsar: kimlik doğrulama güçlendirme ve erişim hakları tasarımından ağ güçlendirme, şifreleme, denetim günlüğü ve olay müdahale hazırlığına kadar.
Önemli Çıkarımlar
- Varsayılan Odoo konfigürasyonları güvenlik açısından üretime hazır değil
- Hassas erişime sahip tüm kullanıcılar için iki faktörlü kimlik doğrulama (2FA) zorunlu olmalıdır
- Erişim hakları en az ayrıcalık ilkesine uygundur; kullanıcılar yalnızca ihtiyaç duydukları şeyi alırlar
- Kayıt kuralları, veri izolasyonunu zorlamak için satır düzeyinde güvenlik sağlar
- Tüm servisler arası iletişim TLS kullanmalıdır; üretimde hiçbir zaman HTTP
- Veritabanı kimlik bilgileri düzenli olarak değiştirilmeli ve hiçbir zaman sabit kodlanmamalıdır
- Denetim günlükleri kurcalamaya karşı dayanıklı olmalı ve uyumluluk gereksinimleri için saklanmalıdır
- Güvenlik yamaları Odoo SA duyurularından sonraki 48 saat içinde uygulanmalıdır
Kimlik Doğrulama Sağlamlaştırma
Şifre Politikası
Odoo 19, Ayarlar → Kullanıcılar ve Şirketler → Parola Sıfırlama Politikası altında yapılandırılabilir parola politikalarını destekler.
Önerilen ayarlar:
- Minimum uzunluk: 12 karakter
- Büyük harf, küçük harf, rakam ve özel karakterler kullanılmasını zorunlu kılın
- Şifrenin geçerlilik süresi: 90 gün
- Son 12 şifrenin tekrar kullanılmasını önleyin
- 5 başarısız denemeden sonra hesabın kilitlenmesi (15 dakikalık kilitleme)
# 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.")
İki Faktörlü Kimlik Doğrulama (2FA)
Ayarlar → İzinler → İki Faktörlü Kimlik Doğrulama altında 2FA'yı etkinleştirin.
Yapılandırma seçenekleri:
- İsteğe bağlı: Kullanıcılar 2FA'yı etkinleştirip etkinleştirmemeyi seçer
- Belirli gruplar için gereklidir: Yöneticilere ve muhasebecilere uygulayın
- Tüm kullanıcılar için gereklidir: Maksimum güvenlik
Kurumsal dağıtımlar için aşağıdakiler için 2FA'yı zorunlu tutun:
- Yönetici hesapları (
base.group_system) - Finans kullanıcıları (
account.group_account_manager) - Bordro erişimine sahip İK yöneticileri
- API anahtarı erişimine sahip tüm kullanıcılar
OAuth ve SSO Entegrasyonu
Mevcut kimlik sağlayıcıları olan kuruluşlar için Odoo'yu SAML 2.0 veya OAuth 2.0 kullanacak şekilde yapılandırın:
# 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',
}
]
Bu, kimlik sağlayıcınızda kimlik doğrulamayı merkezileştirerek tek oturum açma, merkezi MFA ve çalışanlar ayrıldığında otomatik hesap yetkilendirmesi gibi özellikleri etkinleştirir.
API Anahtar Güvenliği
# 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>
Bir politikayı zorunlu kılın: API anahtarlarının geçerliliği 90 gün sonra sona erer, minimum izinlere sahip özel hizmet hesaplarına bağlanır ve herhangi bir şüpheli güvenlik ihlali durumunda dönüşümlü olarak kullanılır.
Erişim Hakları Mimarisi
Grup Hiyerarşi Tasarımı
Odoo'nun erişim kontrolü gruplara dayalıdır. Organizasyon yapınızı yansıtan bir grup hiyerarşisi tasarlayın:
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)
En az ayrıcalık ilkesi: Her kullanıcı, işini gerçekleştirmek için gereken minimum erişime sahip olmalıdır. Bu, ele geçirilen hesapların patlama yarıçapını sınırlar.
Erişim Kontrol Listeleri (ACL)
ir.model.access içindeki ACL girişleri model düzeyinde CRUD izinlerini tanımlar:
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
Kayıt Kuralları (Satır Düzeyinde Güvenlik)
Kullanıcının bir model içinde görebildiği kayıt kuralları filtresi:
<!-- 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>
Performans uyarısı: Birçok search() veya child_of işleci içeren karmaşık kayıt kuralları, liste görünümlerini önemli ölçüde yavaşlatabilir. Üretime dağıtmadan önce tüm kayıt kurallarını büyük veri kümelerine karşı test edin.
Ağ Güvenliği
TLS/HTTPS Yaptırımı
Odoo'yu üretimde hiçbir zaman düz HTTP üzerinden çalıştırmayın. Tüm trafiğin şifrelenmesi gerekir.
Nginx TLS yapılandırması:
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;
}
Güvenlik Duvarı Yapılandırması
# 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
Hız Sınırlama
Kaba kuvvet saldırılarını önlemek için Nginx'te hız sınırlamasını yapılandırın:
# 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;
}
}
Veri Şifreleme
Veritabanı Düzeyinde Şifreleme
Son derece hassas veriler için Odoo alanları kullanımda değilken şifrelenebilir:
# 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
Ortam Değişkeni Güvenliği
Gizli bilgileri asla odoo.conf içinde düz metin olarak saklamayın. Ortam değişkenlerini kullanın:
# /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}
Denetim Günlüğü
Odoo'nun yerleşik denetim günlüğü tüm model değişikliklerini izler. Hassas modeller için etkinleştirin:
# 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()
Denetlenecek uyumluluk açısından kritik modeller:
res.users(kullanıcı oluşturma, izin değişiklikleri)account.move(fatura değişiklikleri)hr.payslip(maaş bordrosu değişiklikleri)res.partner(müşteri/satıcı PII değişiklikleri)ir.model.access,ir.rule(izin değişiklikleri)ir.config_parameter(sistem yapılandırma değişiklikleri)
Güvenlik Yaması Yönetimi
Odoo güvenlik tavsiyelerine abone olun:
Odoo SA, https://github.com/odoo/odoo/security/advisories adresinde güvenlik önerileri yayınlamaktadır. Bu depo için GitHub bildirimlerine abone olun.
Yama başvuru süreci:
# 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
Hedef: Kritik veya Yüksek önem derecesine sahip bir uyarıdan sonra 48 saat içinde yama yapın. Orta şiddet: 1 hafta içinde. Düşük önem derecesi: bir sonraki planlı bakım penceresi.
Sıkça Sorulan Sorular
Odoo'da bir kaydı kimin sildiğini nasıl denetleyeceğim?
Odoo varsayılan olarak silme işlemlerini günlüğe kaydetmez. Odoo Community Association'dan (OCA) auditlog modülünü yükleyin veya hassas modellerinize özel bir unlink() geçersiz kılma uygulayın. OCA denetim günlüğü modülü, kullanıcı, zaman damgası ve alan düzeyinde değişiklik takibi ile oluşturma, yazma ve bağlantıyı kaldırma işlemlerini auditlog.log modeline kaydeder.
Odoo erişimini IP adresine göre kısıtlayabilir miyim?
Yerel olarak Odoo'da değil. Nginx veya güvenlik duvarı düzeyinde IP izin verilenler listesine eklemeyi uygulayın. Yönetici erişimi için önkoşul olarak VPN bağlantısı gerekir. Odoo'nun ir.config_parameter'si web.base.url kısıtlamasını destekler, ancak gerçek IP tabanlı erişim kontrolü ağ katmanına aittir.
Erişim hakları (ACL) ile kayıt kuralları arasındaki fark nedir?
Erişim hakları (ACL, ir.model.access'da depolanır), bir kullanıcı grubunun bir modelin herhangi bir kaydını okuyup yazamayacağını, yazabileceğini, oluşturabileceğini veya silebileceğini kontrol eder; bu, model düzeyinde kontroldür. Kayıt kuralları, bir kullanıcının etki alanı ifadelerini kullanarak bir model içinde hangi belirli kayıtlara erişebileceğini filtreler; bu, satır düzeyinde kontroldür. Her ikisi de birlikte çalışır: Bir kullanıcının bir kaydı görebilmesi için ACL okuma iznine ihtiyacı vardır VE kayıt kuralı etki alanı filtresini geçmesi gerekir.
Odoo ana şifresini (admin_passwd) nasıl kullanmalıyım?
Odoo.conf dosyasındaki admin_passwd, /web/database/manager adresindeki veritabanı yönetimi arayüzüne erişimi kontrol eder. Üretimde: bunu uzun, rastgele bir dizeye (32+ karakter) ayarlayın, bir parola yöneticisinde saklayın, hiçbir zaman paylaşmayın ve veritabanını doğrudan PostgreSQL erişimi yoluyla yönetiyorsanız, veritabanı yöneticisini odoo.conf'taki list_db = False ile tamamen devre dışı bırakmayı düşünün.
Odoo'yu root olarak çalıştırmalı mıyım?
Asla. Kabuk erişimi olmayan ve sınırlı dosya sistemi izinlerine sahip, özel bir odoo sistem kullanıcısı oluşturun. Odoo kullanıcısının Odoo kod tabanına okuma erişimine ve yalnızca dosya deposu ve günlük dizinlerine yazma erişimine ihtiyacı vardır. Systemd hizmetini bu kullanıcı olarak çalıştırın. Kök olarak çalıştırmak, en az ayrıcalık ilkesini ihlal eder ve herhangi bir kod yürütme güvenlik açığından kaynaklanan zararı en üst düzeye çıkarır.
Sonraki Adımlar
Güvenliğin güçlendirilmesi tek seferlik bir görev değildir; devam eden bir uygulamadır. Yeni güvenlik açıkları ortaya çıkıyor, kullanıcı erişim gereksinimleri değişiyor ve uyumluluk çerçeveleri gelişiyor. Güvenli bir Odoo dağıtımı, düzenli güvenlik incelemeleri, yama yönetimi disiplini ve erişim hakları denetimleri gerektirir.
ECOSIRE, yanlış yapılandırmaları, aşırı izinleri, eksik kontrolleri ve uyumluluk boşluklarını tespit eden Odoo güvenliğini güçlendirme değerlendirmeleri sağlar. Güvenlik ekibimiz Odoo ortamlarında ISO 27001, SOC 2 ve GDPR gereklilikleri konusunda deneyime sahiptir.
ECOSIRE'den Odoo Güvenlik Değerlendirmesi isteyin →
Mevcut yapılandırmanızı endüstri standartlarına göre inceleyeceğiz ve uygulama desteğiyle birlikte öncelikli bir iyileştirme planı sunacağız.
Yazan
ECOSIRE Research and Development Team
ECOSIRE'da kurumsal düzeyde dijital ürünler geliştiriyor. Odoo entegrasyonları, e-ticaret otomasyonu ve yapay zeka destekli iş çözümleri hakkında içgörüler paylaşıyor.
İlgili Makaleler
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%.