الأمن السيبراني

Audit trail وامتثال للبيانات الصحية: درس 2026

6 دقائق للقراءة

📍 المقالة الرئيسية للمجموعة: الصحة الرقمية CEDEAO 2026.

القانون الصحي يفرض تتبعاً شاملاً للوصول إلى ملفات المرضى. ARTCI الإيفواري، CDP السنغالي، CDP المغربي قانون 09-08، NESA الإماراتي يطلبون: من اطلع، متى، ماذا، من أين. التخزين 5-10 سنوات حسب البلد. هذا الدرس يفصل تكوين audit trail شامل لـ OpenMRS مع Loki + Grafana للتصور، وتقارير تلقائية للمدققين.

المتطلبات

OpenMRS في الإنتاج. VPS Hetzner CCX13 minimum. Docker + Loki + Grafana. المستوى المتوقع: متقدم. الوقت المقدر: 3-4 ساعات للتكوين الكامل.

الخطوة 1 — تفعيل OpenMRS Audit Module

OpenMRS لديه Audit module مدمج. تفعيله إجباري للإنتاج الصحي:

Admin → Manage Modules → ابحث «auditlog»
# تثبيت إذا غير مثبت
# Status: Started

# تكوين كائنات للتتبع
Admin → Audit Log → Configuration
# تفعيل: Patient, Encounter, Observation, MedicationRequest, User
# Action types: ALL (CREATED, UPDATED, DELETED, VIEWED)

الخطوة 2 — تثبيت Loki

Loki يجمع ويحفظ السجلات. أخف من Elasticsearch، مثالي لـ audit logs. تثبيت عبر Docker:

docker run -d --name loki \
  -p 3100:3100 \
  -v /var/lib/loki:/loki \
  grafana/loki:latest \
  -config.file=/etc/loki/local-config.yaml

تكوين retention 1 سنة hot، 5 سنوات cold storage على Backblaze B2:

# /etc/loki/local-config.yaml
limits_config:
  retention_period: 8760h  # 1 سنة hot
chunk_store_config:
  max_look_back_period: 8760h
table_manager:
  retention_deletes_enabled: true
  retention_period: 43800h  # 5 سنوات

storage_config:
  aws:
    s3: s3://eu-central-003.backblazeb2.com/audit-cold-storage
    bucketnames: audit-cold-storage

الخطوة 3 — تثبيت Promtail (collecteur)

Promtail يقرأ سجلات OpenMRS Audit ويرسلها إلى Loki:

# /etc/promtail/config.yml
server:
  http_listen_port: 9080

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: openmrs-audit
    static_configs:
      - targets: [localhost]
        labels:
          job: openmrs-audit
          __path__: /var/log/openmrs/audit.log
    pipeline_stages:
      - json:
          expressions:
            user: user
            patient: patient
            action: action
            timestamp: timestamp

الخطوة 4 — تثبيت Grafana للتصور

docker run -d --name grafana \
  -p 3000:3000 \
  -v grafana-data:/var/lib/grafana \
  grafana/grafana:latest

تكوين datasource Loki: Settings → Data Sources → Add → Loki → URL http://loki:3100.

الخطوة 5 — لوحات Grafana للـ Audit

إنشاء dashboards مفيدة للـ DPO (Data Protection Officer):

  1. Dashboard «Patient Access»: من فتح ملف المريض X في 30 يوماً.
  2. Dashboard «After Hours Access»: الوصول خارج ساعات العمل (موقع شك).
  3. Dashboard «Failed Logins»: محاولات اقتحام.
  4. Dashboard «Bulk Exports»: تصدير > 100 ملف (تسرب محتمل).
  5. Dashboard «Modifications par utilisateur»: الأطباء النشطون.

كل لوحة بـ LogQL queries:

# مثال: الوصول إلى ملف مريض محدد
{job="openmrs-audit"} | json | patient="UUID-DIALLO"

# الوصول خارج ساعات العمل (22h-6h)
{job="openmrs-audit"} | json | __error__="" | hour(timestamp) >= 22 or hour(timestamp) <= 6

# تصديرات ضخمة
{job="openmrs-audit"} | json | action="EXPORT" | count > 100

الخطوة 6 — تنبيهات في الوقت الفعلي

Grafana Alerting يولد تنبيهات على أحداث حساسة. webhook إلى Mattermost قناة #security:

# Alert rule: Bulk export
expr: count_over_time({job="openmrs-audit"} | json | action="EXPORT" [5m]) > 50
for: 1m
labels:
  severity: critical
annotations:
  summary: "Suspicious bulk export by {{ $labels.user }}"
  
# Webhook إلى Mattermost
url: https://chat.votre-hopital.com/hooks/abc123
body: |
  {
    "text": "🚨 ALERT: {{ .Annotations.summary }}",
    "channel": "security"
  }

الخطوة 7 — تقرير سنوي للمدقق

سكربت Python يولد تقرير PDF للتدقيق السنوي ARTCI/CDP:

import requests
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas

def generate_audit_report(year):
    # استفسار Loki للسنة
    queries = {
        'total_accesses': f'count_over_time({{job="openmrs-audit"}}[1y])',
        'unique_users': f'count(count by (user) ({{job="openmrs-audit"}}))',
        'bulk_exports': f'count_over_time({{job="openmrs-audit"}} | json | action="EXPORT"[1y])',
        'after_hours': f'count_over_time({{job="openmrs-audit"}} | json | hour > 22 or hour < 6 [1y])',
    }
    
    results = {}
    for key, query in queries.items():
        r = requests.get('http://loki:3100/loki/api/v1/query', 
                         params={'query': query, 'time': f'{year}-12-31T23:59:59Z'})
        results[key] = r.json()['data']['result'][0]['value'][1]
    
    # توليد PDF
    pdf = canvas.Canvas(f"audit-report-{year}.pdf", pagesize=A4)
    pdf.drawString(100, 800, f"تقرير التدقيق السنوي {year}")
    pdf.drawString(100, 750, f"إجمالي الوصول: {results['total_accesses']}")
    pdf.drawString(100, 700, f"المستخدمون الفريدون: {results['unique_users']}")
    pdf.drawString(100, 650, f"تصديرات ضخمة: {results['bulk_exports']}")
    pdf.save()

الخطوة 8 — حماية ضد التلاعب

Audit logs يجب ألا تكون قابلة للتعديل (write-once). استراتيجيات:

  • Object Lock على Backblaze B2: ملفات غير قابلة للحذف لـ 5 سنوات.
  • HMAC-SHA256 signature على كل log entry.
  • Replication إلى MinIO ثانوي offsite.
# Backblaze B2 Object Lock
b2 update-bucket --fileLockEnabled audit-cold-storage allPrivate
b2 update-bucket --defaultRetention compliance --period "5 years" audit-cold-storage

الخطوة 9 — Anonymization للأبحاث

للدراسات الإحصائية، تصدير anonymized يحترم RGPD/CEDEAO:

def anonymize_patient(patient):
    # احذف معرفات مباشرة
    del patient['name'], patient['phone'], patient['email']
    # هاش NIN
    patient['nin_hash'] = hashlib.sha256(patient['nin'].encode()).hexdigest()
    del patient['nin']
    # تعميم تاريخ الميلاد إلى عام
    patient['birth_year'] = patient['birth_date'][:4]
    del patient['birth_date']
    return patient

الخطوة 10 — DPO Dashboard

Dashboard موحد للـ DPO يعرض:

  • نظرة عامة 30 يوم: عدد الوصول، المستخدمون النشطون، الإيقافات.
  • تنبيهات حالية (الأحداث المشبوهة).
  • تقرير شهري قابل للتصدير.
  • إجراء «حذف بيانات مريض» (Right to Erasure GDPR/CDP).
  • إجراء «تصدير بيانات مريض» (Data Portability).

الأخطاء الشائعة

الخطأ السبب الحل
Loki disk full retention مفقود config retention_period
Promtail لا يقرأ logs permissions chmod 644 audit.log + adduser promtail adm
Audit logs مفقودة module غير مفعَّل Admin Modules → Start auditlog
تنبيهات مغرقة thresholds منخفضة tuner alert rules
تقرير PDF فارغ queries خاطئة اختبر LogQL في Grafana Explore
Cold storage بطيء B2 Eu-Central-003 موصى به اختر datacenter قريب

التكيف مع السياق

أربع توضيحات. القوانين المحلية. ARTCI كوت ديفوار (قانون 2013-450)، CDP السنغال (قانون 2008-12)، CDP المغرب (09-08)، NESA الإمارات. كلها تطلب audit trail لكن متطلبات الاحتفاظ تختلف (5-10 سنوات). التدقيقات السنوية. ARTCI تطلب تقريراً سنوياً في الـ DPA report. صدِّر مباشرة من Grafana. Right to Erasure. GDPR/CDP يفرضون حذف البيانات عند الطلب. لكن للبيانات الصحية، استثناءات قانونية (الأرشفة الطبية الإلزامية 20 سنة في فرنسا/المغرب). DPO يقرر. Cross-border data flow. CEDEAO Cross Border Act 2025 يتطلب موافقة قبل نقل البيانات خارج CEDEAO. Hetzner ألمانيا = adequacy decision EU، مقبول لكن وثِّق.

دروس الإخوة

الأسئلة المتكررة

كم تكلفة Loki + Grafana؟ Hetzner CX23 (3.99 يورو/شهر) يستضيف الاثنان لـ < 50 GB logs/شهر.

retention 5 سنوات تكلفة؟ 5 GB/سنة × 5 سنوات × 6 USD/TB Backblaze = 0.15 USD/سنة. ضئيل.

HIPAA-compliant؟ AWS لديه «HIPAA-compliant» eligible services. Hetzner ألمانيا يخضع لـ GDPR، يكفي للقواعد الإفريقية.

التدقيقات في الوقت الفعلي؟ Grafana Alerting + webhook Mattermost = response في 30 ثانية على event مشبوه.

للاستزادة

Où héberger votre projet web ?

Hostinger propose des plans dimensionnés pour les freelances et PME. Lien d'affiliation — pas de surcoût pour vous.

Comparer les plans →

Lien d affiliation. Si vous achetez via ce lien, le blog reçoit une petite commission sans surcoût pour vous.

مقالات ذات صلة

مشاركة
Service ITSkillsCenter

Application mobile Android et iOS

Création d'application mobile Android et iOS. À partir de 350 000 FCFA.

Démarrer mon projet
Publicité