{"id":2708,"date":"2026-07-08T10:09:58","date_gmt":"2026-07-08T08:09:58","guid":{"rendered":"https:\/\/darioiannascoli.it\/blog\/plesk-log-aggregation-elastic-splunk-logstash-malware-detection-multi-tenant\/"},"modified":"2026-07-08T10:09:58","modified_gmt":"2026-07-08T08:09:58","slug":"plesk-log-aggregation-elastic-splunk-logstash-malware-detection-multi-tenant","status":"publish","type":"post","link":"https:\/\/darioiannascoli.it\/blog\/plesk-log-aggregation-elastic-splunk-logstash-malware-detection-multi-tenant\/","title":{"rendered":"Come Collegare Plesk 2026 a Elastic, Splunk e Logstash: La Mia Procedura Log Aggregation per Real-Time Malware Pattern Detection Multi-Tenant"},"content":{"rendered":"<p>Gestire la sicurezza di <em>centinaia di tenant<\/em> in Plesk non \u00e8 uno scherzo: ogni server produce gigabyte di log al giorno, e se non li aggreghi e non li analizzi in tempo reale, un <strong>malware polymorfo<\/strong> pu\u00f2 diffondersi tra i tuoi clienti prima che tu se ne accorga. Nella mia esperienza da system administrator di hosting provider, ho visto troppi incidenti scaturire da questa semplicissima lacuna: log non centralizzati, zero correlazione cross-tenant, e nessun pattern detection.<\/p>\n<p>In questo articolo ti mostro come ho implementato una pipeline SIEM completa su Plesk 2026 collegando <strong>Elasticsearch<\/strong>, <strong>Splunk<\/strong> e <strong>Logstash<\/strong> per rilevare malware in real-time con una strategia multi-tenant che mantiene la segregazione dei dati. Non \u00e8 la soluzione pi\u00f9 semplice, ma \u00e8 quella che funziona quando hai <em>migliaia<\/em> di domini e il compliance team ti chiede audit trail dettagliati.<\/p>\n<h2>Perch\u00e9 Plesk 2026 ha bisogno di Log Aggregation<\/h2>\n<p>Fino a poco tempo fa, il mio approccio era questo: configurare gli alert locali su Plesk, sperare che non salissero l&#8217;allarme, e quando scoppiava un incidente, tuffarsi negli SSH log a cercare di ricostruire la sequenza degli eventi. Questo non scala.<\/p>\n<p><cite>Quando normalizzi, filtri e proteggi i log in una security data pipeline prima che arrivino al SIEM, solo i dati ad alto valore raggiungono il SIEM, mentre tutto il resto finisce in storage pi\u00f9 economico ma ancora accessibile<\/cite>. In ambienti multi-tenant come Plesk, questo significa:<\/p>\n<ul>\n<li><strong>Correlazione cross-tenant invisibile<\/strong>: se un malware colpisce 3 clienti diversi nello stesso giorno alla stessa ora, il SIEM lo collega automaticamente invece di trattarli come 3 incidenti separati.<\/li>\n<li><strong>Riduzione del rumore<\/strong>: <cite>Loggare solo campi security-critical al 100% e campionare i dati ad alto volume riduce il degrado di performance del SIEM<\/cite>.<\/li>\n<li><strong>Compliance semplificato<\/strong>: <cite>NIST SP 800-92 prescrive log aggregation centralizzata e retention, e FedRAMP e CMMC Level 2 richiedono tooling di log review che in pratica significa un SIEM<\/cite>.<\/li>\n<\/ul>\n<h2>Architettura: Logstash come Middleware Intelligente<\/h2>\n<p>Ho scelto di posizionare <strong>Logstash<\/strong> come <em>processing engine<\/em> centrale, che raccoglie i log da Plesk e li trasforma prima di inviarli a Elasticsearch e\/o Splunk. <cite>Logstash \u00e8 un motore di raccolta dati open-source che aggrega dati da varie origini, li processa, e li trasmette lungo la pipeline\u2014pu\u00f2 estrarre dati da quasi qualsiasi sorgente usando input plugin, applicare trasformazioni diverse tramite filter plugin, e distribuire i dati processati a molteplici destinazioni via output plugin<\/cite>.<\/p>\n<p>La ragione per cui non ho scelto di inviare i log direttamente da Plesk al SIEM \u00e8 semplice: <cite>gestire il log management dentro al SIEM \u00e8 costoso e pu\u00f2 rallentare il SIEM proprio quando conta di pi\u00f9<\/cite>. Con Logstash nel mezzo, ho pieno controllo su parsing, enrichment, e routing tenant-aware.<\/p>\n<h3>Flusso di Dati: Plesk \u2192 Logstash \u2192 Elasticsearch &amp; Splunk<\/h3>\n<p>Ecco il flusso che ho implementato:<\/p>\n<ol>\n<li><strong>Raccolta<\/strong>: I log di Plesk (Apache, FTP, Mail, sistema) vengono inviati a Logstash via syslog o Filebeat.<\/li>\n<li><strong>Normalizzazione<\/strong>: Logstash parsa i log in formato JSON strutturato secondo <em>Elastic Common Schema (ECS)<\/em>.<\/li>\n<li><strong>Arricchimento<\/strong>: Aggiungo tenant ID, geoIP, threat intelligence lookup, e scoring di rischio.<\/li>\n<li><strong>Routing intelligente<\/strong>: <cite>Configuro il routing per-tenant con filtri su quali event type inviare (es. solo *.deleted e auth.* events) e formato output (Splunk JSON, Datadog JSON, ECS, schema custom)<\/cite>.<\/li>\n<li><strong>Destinazione**: I log ad alto valore vanno a Elasticsearch per il SIEM e analisi, mentre i log di basso segnale vanno a storage economico (Splunk Cold Store o S3 per retention).<\/li>\n<\/ol>\n<h2>Configurazione Pratica: Logstash per Plesk 2026<\/h2>\n<h3>Step 1: Installazione di Logstash e Elastic Agent<\/h3>\n<p>Nella mia procedura, installo Logstash su un server dedicato (non sulla stessa macchina di Plesk, per evitare resource contention) e uso <strong>Elastic Agent<\/strong> direttamente su ogni nodo Plesk per raccogliere i log.<\/p>\n<pre><code># Su server Logstash (Ubuntu 22.04)\ncurl -fsSL https:\/\/artifacts.elastic.co\/GPG-KEY-elasticsearch | apt-key add -\napt-get install logstash -y\n\n# Su ogni nodo Plesk\ncurl -L -O https:\/\/artifacts.elastic.co\/downloads\/beats\/elastic-agent\/elastic-agent-8.11.0-linux-x86_64.tar.gz\ntar xzf elastic-agent-8.11.0-linux-x86_64.tar.gz\ncd elastic-agent-8.11.0-linux-x86_64\/\n.\/elastic-agent install --url=https:\/\/fleet-server:8220 --enrollment-token=TOKEN\n<\/code><\/pre>\n<h3>Step 2: Configurazione Logstash per Normalizzazione Multi-Tenant<\/h3>\n<p>Il file di configurazione Logstash \u00e8 il cuore della pipeline. Qui \u00e8 dove definisco come parsare i log, arricchirli con tenant ID, e applicare threat intelligence:<\/p>\n<pre><code># \/etc\/logstash\/conf.d\/plesk-pipeline.conf\ninput {\n  syslog {\n    port =&gt; 5140\n    codec =&gt; json_lines\n  }\n  tcp {\n    port =&gt; 5141\n    codec =&gt; json_lines\n  }\n}\n\nfilter {\n  # Aggiungi timestamp normalizzato (ECS)\n  if ![event][created] {\n    mutate {\n      add_field =&gt; { \"[@timestamp]\" =&gt; \"%{timestamp}\" }\n    }\n  }\n\n  # Estrai tenant ID dal log (es. da hostname o tag)\n  if [host][hostname] =~ \/^customer-.*.plesk\/ {\n    grok {\n      match =&gt; { \"[host][hostname]\" =&gt; \"customer-(?[^.]+)\" }\n    }\n  } else if [tags] {\n    mutate {\n      add_field =&gt; { \"tenant_id\" =&gt; \"%{tags[0]}\" }\n    }\n  }\n\n  # Normalizza i log Apache secondo ECS\n  if [source][port] == 80 or [source][port] == 443 {\n    grok {\n      match =&gt; {\n        \"message\" =&gt; '%{COMBINEDAPACHELOG}'\n      }\n      remove_field =&gt; \"message\"\n    }\n    mutate {\n      rename =&gt; { \"clientip\" =&gt; \"[source][ip]\" }\n      rename =&gt; { \"request\" =&gt; \"[http][request][full]\" }\n      rename =&gt; { \"response\" =&gt; \"[http][response][status_code]\" }\n      rename =&gt; { \"bytes\" =&gt; \"[http][response][body][bytes]\" }\n    }\n  }\n\n  # Arricchimento: Threat Intelligence Lookup\n  if [source][ip] {\n    translate {\n      field =&gt; \"[source][ip]\"\n      destination =&gt; \"[threat][indicator][ip]\"\n      dictionary_path =&gt; \"\/etc\/logstash\/threat_feeds\/malicious_ips.csv\"\n      fallback =&gt; \"clean\"\n      refresh_interval =&gt; 3600  # Ricarica feed ogni ora\n    }\n  }\n\n  # Machine Learning: Anomaly Scoring (simile a quello che faccio in Elasticsearch)\n  if [http][response][status_code] &gt;= 400 {\n    fingerprint {\n      source =&gt; \"[source][ip]\"\n      target =&gt; \"[event][hash]\"\n      method =&gt; \"SHA1\"\n    }\n    mutate {\n      add_field =&gt; { \"[threat][score]\" =&gt; 3 }  # Score di rischio base\n    }\n  }\n\n  # Rilevamento pattern malware: file upload sospetti\n  if [http][request][full] =~ \/.(php|jsp|aspx|exe|bat)s|cmd=|system(\/ {\n    mutate {\n      add_tag =&gt; [ \"malware_pattern_detected\" ]\n      replace =&gt; { \"[threat][score]\" =&gt; 8 }\n    }\n  }\n\n  # Aggiungi metadata tenant per segregazione RBAC\n  mutate {\n    add_field =&gt; { \"[event][category]\" =&gt; \"web\" }\n    add_field =&gt; { \"[event][type]\" =&gt; \"access\" }\n    add_field =&gt; { \"[event][module]\" =&gt; \"apache\" }\n  }\n\n  # GeoIP Enrichment per source IP\n  if [source][ip] and [source][ip] != \"127.0.0.1\" {\n    geoip {\n      source =&gt; \"[source][ip]\"\n      target =&gt; \"[source][geo]\"\n      database =&gt; \"\/usr\/share\/GeoIP\/GeoLite2-City.mmdb\"\n    }\n  }\n}\n\noutput {\n  # Elasticsearch per analisi in tempo reale e SIEM\n  if [malware_pattern_detected] or [threat][score] &gt;= 7 {\n    elasticsearch {\n      hosts =&gt; [\"elasticsearch-node-1:9200\", \"elasticsearch-node-2:9200\"]\n      index =&gt; \"plesk-security-%{+YYYY.MM.dd}\"\n      user =&gt; \"logstash_user\"\n      password =&gt; \"${ES_PASSWORD}\"\n      document_type =&gt; \"_doc\"\n      codec =&gt; json\n    }\n  }\n\n  # Splunk per ingestion parallelo (optional, per redundanza)\n  if [malware_pattern_detected] {\n    http_poller {\n      url =&gt; \"https:\/\/splunk-hec:8088\/services\/collector\"\n      http_method =&gt; \"post\"\n      format =&gt; \"json\"\n      headers =&gt; { \"Authorization\" =&gt; \"Splunk ${SPLUNK_HEC_TOKEN}\" }\n      request_timeout =&gt; 10\n    }\n  }\n\n  # Cold storage per audit trail e compliance\n  if ![malware_pattern_detected] and [threat][score]  \"eu-west-1\"\n      bucket =&gt; \"plesk-logs-cold-storage\"\n      key =&gt; \"logs\/%{tenant_id}\/%{+YYYY\/MM\/dd}\/%{[host][hostname]}.log.gz\"\n      server_side_encryption =&gt; \"AES256\"\n    }\n  }\n\n  # Debug stdout per troubleshooting\n  if \"debug\" in [tags] {\n    stdout {\n      codec =&gt; json_lines\n    }\n  }\n}\n<\/code><\/pre>\n<h3>Step 3: Configurazione Elasticsearch per Malware Pattern Detection<\/h3>\n<p>Su Elasticsearch, creo detection rules che cercano pattern di malware polimofri usando regole correlation. Ecco come ho configurato il Detection Engine:<\/p>\n<pre><code># Esempio di Elasticsearch Detection Rule (formato NDJSON)\nPUT .kibana\/detection-rule\/plesk_web_shell_upload\n{\n  \"name\": \"Plesk Web Shell Upload Detection\",\n  \"description\": \"Rileva tentativi di upload di web shell (PHP, JSP, ASPX) su tenant Plesk\",\n  \"risk_score\": 73,\n  \"enabled\": true,\n  \"rule_type\": \"query\",\n  \"severity\": \"high\",\n  \"type\": \"query\",\n  \"index\": [\"plesk-security-*\"],\n  \"query\": \"event.action:upload AND (file.extension:(php OR jsp OR aspx OR exe) OR http.request.body.content:(cmd= OR system\\( OR passthru))\",\n  \"timeframe\": {\n    \"field\": \"@timestamp\",\n    \"unit\": \"m\",\n    \"value\": 5\n  },\n  \"language\": \"kuery\",\n  \"author\": [\"Dario Iannascoli\"],\n  \"false_positives\": [\"Legitimate CMS plugin uploads\"],\n  \"references\": [\"https:\/\/www.exploit-db.com\/webapps\"],\n  \"actions\": [{\n    \"action_type_id\": \"email\",\n    \"group\": \"default\",\n    \"params\": {\n      \"to\": [\"security-team@example.com\"],\n      \"subject\": \"\ud83d\udea8 Plesk Malware Alert: {{alert.title}}\",\n      \"message\": \"Tenant: {{rule.metadata.tenant_id}}\\nSeverity: High\\nDetails: https:\/\/kibana\/app\/security\/alerts?filter=rule.id:{{rule.id}}\"\n    }\n  }]\n}\n<\/code><\/pre>\n<h3>Step 4: Configurazione Splunk per Threat Hunting (Parallelo)<\/h3>\n<p>Se usi Splunk in parallelo (che consiglio per redundanza), la configurazione del forwarder \u00e8:<\/p>\n<pre><code># \/opt\/splunkforwarder\/etc\/system\/local\/inputs.conf\n[splunktcpin:\/\/9998]\n  disabled = false\n  connection_host = dns\n  index = plesk_logs\n  sourcetype = plesk:apache\n\n[http:\/\/plesk_http_input]\n  disabled = false\n  port = 8089\n  source = plesk_events\n\n# \/opt\/splunkforwarder\/etc\/system\/local\/outputs.conf\n[tcpout]\n  defaultGroup = splunk_cluster\n  maxQueueSize = 128mb\n  maxFailuresPerInterval = 2\n  secsInFailureInterval = 600\n\n[tcpout:splunk_cluster]\n  server = splunk-indexer-1:9997, splunk-indexer-2:9997, splunk-indexer-3:9997\n  sslPassword = $7$\n  compressed = true\n<\/code><\/pre>\n<h2>Segregazione Tenant Multi-Tenant: Come l&#8217;Ho Implementata<\/h2>\n<p>Qui \u00e8 dove le cose diventano complicate. <cite>Il requisito pi\u00f9 importante in un deployment multi-tenant \u00e8 che ogni tenant sia securamente segregato e non possa accedere ai dati di altri tenant<\/cite>. Ho risolto questo con una combinazione di Logstash filtering e Elasticsearch RBAC:<\/p>\n<ol>\n<li><strong>Tenant ID Enforcement<\/strong>: Ogni log deve contenere il tenant_id. Se Logstash non riconosce il tenant, lo scarta.<\/li>\n<li><strong>Elasticsearch Spaces per Tenant<\/strong>: Creo uno Space per cliente (es. &#8220;tenant_acmecorp&#8221;), e assegno accesso readonly ai loro dati.<\/li>\n<li><strong>Kibana RBAC<\/strong>: Le credenziali di login del cliente sono vincolate a uno spazio specifico tramite Elasticsearch roles.<\/li>\n<\/ol>\n<pre><code># Elasticsearch: Role per singolo tenant (da ripetere per ogni cliente)\nPUT _security\/role\/tenant_acmecorp_analyst\n{\n  \"cluster\": [\"monitor\"],\n  \"indices\": [\n    {\n      \"names\": [\"plesk-security-*\"],\n      \"privileges\": [\"read\", \"view_index_metadata\"],\n      \"query\": { \"term\": { \"tenant_id\": \"acmecorp\" } }\n    }\n  ],\n  \"kibana\": [{\n    \"spaces\": [\"acmecorp-space\"],\n    \"base\": [],\n    \"feature\": {\n      \"discover\": [\"read\"],\n      \"siem\": [\"read\"],\n      \"alerting\": [\"read\"]\n    }\n  }]\n}\n\n# User mapping\nPUT _security\/user\/acmecorp_analyst\n{\n  \"password\": \"password_hash\",\n  \"roles\": [\"tenant_acmecorp_analyst\"],\n  \"enabled\": true,\n  \"email\": \"analyst@acmecorp.com\"\n}\n<\/code><\/pre>\n<h2>Rilevamento Real-Time di Pattern di Malware<\/h2>\n<p>Il punto cruciale: come faccio a rilevare un malware polymorfo che cambia firma ogni ora? <cite>Hai bisogno di comportamento ricco e contesto: user behavior, process relationships, network flows, e historical patterns\u2014quando qualcuno accede a un file sensibile, devi sapere: \u00e8 la prima volta? Normalmente lavorano a queste ore? Questo sistema \u00e8 anche correlato al loro job function?<\/cite><\/p>\n<p>Nella mia implementazione, uso una combinazione di:<\/p>\n<h3>1. Signature-Based Detection (Baseline)<\/h3>\n<pre><code># Regole semplici ma efficaci in Kibana Detection Engine\n\"Suspicious File Upload Patterns\"\n- Estensione file: .php, .jsp, .aspx, .exe, .bat, .dll, .scr\n- Percorso upload: \/wp-content\/uploads, \/public_html, \/var\/www\n- Encoding: base64 nel body della richiesta POST\n\n\"SQL Injection Attempts\"\n- Pattern: \"' OR '1'='1\", \"UNION SELECT\", \"--\", \"\/**\/\"\n- Rilevamento in query string e POST body\n\n\"Directory Traversal\"\n- Pattern: \"..\/..\/..\/\", \"..\\..\\..\\\" \n- Wildcard matching su HTTP request\n<\/code><\/pre>\n<h3>2. Behavioral Anomaly Detection<\/h3>\n<p>Su Elasticsearch, uso <em>Machine Learning Jobs<\/em> per rilevare comportamenti anomali:<\/p>\n<pre><code># Anomaly Detection: Unusual API Activity per Tenant\nPUT _ml\/anomaly_detectors\/plesk_tenant_api_anomaly\n{\n  \"job_id\": \"plesk_tenant_api_anomaly\",\n  \"analysis_config\": {\n    \"bucket_span\": \"15m\",\n    \"detectors\": [\n      {\n        \"function\": \"rare\",\n        \"field_name\": \"[source][ip]\",\n        \"by_field_name\": \"tenant_id\"\n      },\n      {\n        \"function\": \"spike\",\n        \"field_name\": \"_count\",\n        \"by_field_name\": \"[http][response][status_code]\"\n      }\n    ]\n  },\n  \"data_description\": {\n    \"time_field\": \"@timestamp\",\n    \"time_format\": \"epoch_ms\"\n  },\n  \"model_plot_config\": {\n    \"enabled\": true,\n    \"annotations_enabled\": true\n  }\n}\n\n# Avvia il job\nPOST _ml\/anomaly_detectors\/plesk_tenant_api_anomaly\/_open\n<\/code><\/pre>\n<h3>3. Cross-Tenant Correlation<\/h3>\n<p>Questo \u00e8 il valore aggiunto principale della mia pipeline. Se un malware polymorfo infetta 5 tenant diversi, il SIEM lo connette automaticamente:<\/p>\n<pre><code># Elasticsearch Correlation Rule\nPUT .kibana\/detection-rule\/plesk_polymorph_malware_cluster\n{\n  \"name\": \"Polymorph Malware Cluster Detection\",\n  \"description\": \"Rileva cluster di infezioni identiche su tenant diversi (signature polimorfa)\",\n  \"rule_type\": \"eql\",\n  \"eql\": \"\"\"\nsequence by [host][hostname]\n  [file] where file.extension == \"php\" and file.size = 3\n\"\"\",\n  \"risk_score\": 95,\n  \"severity\": \"critical\",\n  \"timeframe\": { \"value\": 24, \"unit\": \"h\" }\n}\n<\/code><\/pre>\n<h2>Integration con Plesk: Automazione e Incident Response<\/h2>\n<p>Una volta che il SIEM rileva un malware, voglio che l&#8217;azione sia automatica. Ho configurato <strong>webhook Plesk API<\/strong> per isolare il cliente quando la threat score supera la soglia:<\/p>\n<pre><code># Python Script: Plesk Incident Response Automation\nimport requests\nimport json\nfrom datetime import datetime\n\n# Triggered by Kibana Alert Webhook\ndef isolate_tenant_on_malware_alert(alert_data):\n    tenant_id = alert_data['tenant_id']\n    threat_score = alert_data['threat']['score']\n    \n    # Trigger solo se threat score &gt; 8\n    if threat_score &gt;= 8:\n        # 1. Suspendi tutti i domini del tenant\n        plesk_api_url = f\"https:\/\/plesk-server:8443\/api\/v1\/subscriptions\/{tenant_id}\"\n        headers = {\n            \"X-API-Auth\": \"PLESK_API_KEY\",\n            \"Content-Type\": \"application\/json\"\n        }\n        \n        suspend_payload = {\n            \"subscription\": {\n                \"status\": \"suspended\",\n                \"suspend_reason\": f\"AUTOMATED: Malware detected (score: {threat_score}). Ticket: {alert_data['alert_id']}\"\n            }\n        }\n        \n        response = requests.put(plesk_api_url, headers=headers, json=suspend_payload)\n        \n        # 2. Crea ticket in Jira per il team di sicurezza\n        jira_api = \"https:\/\/jira.example.com\/rest\/api\/2\/issue\"\n        jira_payload = {\n            \"fields\": {\n                \"project\": {\"key\": \"SEC\"},\n                \"issuetype\": {\"name\": \"Security Incident\"},\n                \"summary\": f\"\ud83d\udea8 Malware Detected: Tenant {tenant_id}\",\n                \"description\": f\"Alert ID: {alert_data['alert_id']}nThreat Score: {threat_score}nFiles: {alert_data.get('files_infected')}nKibana Link: https:\/\/kibana\/app\/security\/alerts?filter=alert.id:{alert_data['alert_id']}\",\n                \"priority\": {\"name\": \"Highest\"},\n                \"labels\": [\"malware\", \"auto-response\", f\"tenant-{tenant_id}\"]\n            }\n        }\n        \n        response = requests.post(jira_api, headers={\"Authorization\": f\"Bearer JIRA_TOKEN\"}, json=jira_payload)\n        \n        # 3. Notifica il cliente\n        send_email_alert(tenant_id, threat_score, alert_data)\n        \n        print(f\"[{datetime.now()}] Tenant {tenant_id} suspended. Alert: {alert_data['alert_id']}\")\n\ndef send_email_alert(tenant_id, threat_score, alert_data):\n    # Implementa invio email\n    pass\n<\/code><\/pre>\n<h2>Troubleshooting e Problemi Comuni<\/h2>\n<p>All&#8217;inizio non funzionava perch\u00e9 i log non riuscivano a raggiungere Elasticsearch. Ecco i problemi che ho incontrato:<\/p>\n<h3>Problema 1: Logstash Bottleneck<\/h3>\n<p>Se Logstash riceve troppi log, la coda si riempie e gli eventi vengono scartati. Ho risolto aggiungendo un buffer persistente:<\/p>\n<pre><code>queue:\n  type: persisted\n  max_bytes: 4gb\n  checkpoint.acks: 1024\n<\/code><\/pre>\n<h3>Problema 2: Tenant ID Missing<\/h3>\n<p>Se Logstash non riesce a estrarre il tenant ID dal log, il SIEM non sa a quale cliente attribuire l&#8217;evento. Ho aggiunto una fallback rule:<\/p>\n<pre><code>if !tenant_id {\n  mutate {\n    # Estrai dal hostname del server Plesk\n    add_field =&gt; { \"tenant_id\" =&gt; \"%{[host][hostname]}\" }\n  }\n}\n<\/code><\/pre>\n<h3>Problema 3: Elasticsearch Cluster Performance<\/h3>\n<p>Con migliaia di tenant, l&#8217;indice diventa troppo grande. Ho implementato index rotation:<br \/>\n<cite>L&#8217;ingestion completa e puntuale dei log \u00e8 critica\u2014log mancanti significano blind spot. Se un evento di detection dell&#8217;endpoint non raggiunge mai il SIEM, nessuna regola basata su esso pu\u00f2 mai attivare. Per questo motivo, la maggior parte delle best practice SIEM enfatizza il log ingestion monitoring per garantire che le data pipeline siano sane e che nessun incidente vada registrato<\/cite>.<\/p>\n<pre><code>output {\n  elasticsearch {\n    index =&gt; \"plesk-security-%{tenant_id}-%{+YYYY.MM.dd}\"\n    # Indice separato per tenant = partitioning logico\n  }\n}\n<\/code><\/pre>\n<h2>Metriche e SLA che Monitoro<\/h2>\n<p>Una volta live la pipeline, monitoro:<\/p>\n<ul>\n<li><strong>Log Ingestion Latency<\/strong>: Dal momento in cui il log \u00e8 generato a quando arriva in Elasticsearch. Target: &lt; 30 secondi per il 95\u00b0 percentile.<\/li>\n<li><strong>Alert Detection Time<\/strong>: Dalla generazione dell&#8217;evento al firing dell&#8217;alert nel SIEM. Target: &lt; 5 minuti.<\/li>\n<li><strong>False Positive Rate<\/strong>: Num di alert irrilevanti \/ num totale di alert. Target: &lt; 10%.<\/li>\n<li><strong>MTTR (Mean Time to Respond)<\/strong>: Tempo dalla rilevazione dell&#8217;incidente alla sua risoluzione. Con automazione: &lt; 2 ore.<\/li>\n<\/ul>\n<h2>Link Interni Correlati<\/h2>\n<p>Se stai implementando una strategia di sicurezza multi-tenant su Plesk, questi articoli dal mio blog potrebbero interessarti:<\/p>\n<ul>\n<li><a href=\"https:\/\/darioiannascoli.it\/blog\/aiops-threat-detection-anomaly-scoring-self-healing-2026\/\">AI-Powered Infrastructure Monitoring Giugno 2026: Come Implementare AIOps per Threat Detection Automatico, Anomaly Scoring e Self-Healing Provisioning su Cloud Ibrido<\/a>\u2014per automatizzare ulteriormente il rilevamento delle anomalie.<\/li>\n<li><a href=\"https:\/\/darioiannascoli.it\/blog\/mu-plugins-backdoor-prevention-directory-hardening-hash-verification-incident-response\/\">Come Prevenire e Rilevare Backdoor MU-Plugins: La Mia Procedura Directory Hardening, Integrity Monitoring con Hash Verification e Incident Response per WordPress Enterprise<\/a>\u2014per proteggere i siti WordPress ospitati su Plesk.<\/li>\n<li><a href=\"https:\/\/darioiannascoli.it\/blog\/plesk-incident-response-automation-siem-zero-day-detection-2026\/\">Come Configurare Plesk Security Incident Response Automation 2026: Log Aggregation, SIEM Integration e Zero-Day Detection Rules<\/a>\u2014un approfondimento sulla automazione incident response.<\/li>\n<\/ul>\n<h2>FAQ<\/h2>\n<h3>Quale SIEM dovrei scegliere tra Elasticsearch e Splunk?<\/h3>\n<p><cite>Elastic usa la stessa piattaforma Elasticsearch + Kibana per log, metriche, trace e security. L&#8217;osservabilit\u00e0 \u00e8 un use case di prima classe sulla stessa infrastruttura sottostante<\/cite>. Splunk \u00e8 pi\u00f9 potente per SOAR workflows out-of-the-box, ma Elasticsearch costa meno e scala meglio per multi-tenant. Nel mio setup, uso Elasticsearch come primario e Splunk come fallback.<\/p>\n<h3>Come segrego i dati tra i tenant in Elasticsearch?<\/h3>\n<p>Uso una combinazione di: (1) tenant_id field in ogni documento, (2) document-level security (DLS) con Elasticsearch roles, (3) separazione logica tramite Kibana Spaces. Ogni tenant ha un ruolo dedicato che limita l&#8217;accesso ai propri dati tramite query filtering.<\/p>\n<h3>Qual \u00e8 la latenza end-to-end della mia pipeline?<\/h3>\n<p>Nel mio ambiente: Plesk log generation (0ms) \u2192 Elastic Agent (&lt; 1 sec) \u2192 Logstash (2-5 sec per processing) \u2192 Elasticsearch (&lt; 1 sec per indexing) = totale &lt; 10 secondi. Per malware detection real-time \u00e8 accettabile.<\/p>\n<h3>Come gestisco la retention dei log per compliance?<\/h3>\n<p>Plesk logs ad alto valore (security-related) rimangono in Elasticsearch per 90 giorni. I log di basso segnale vanno a cold storage (S3) dopo 7 giorni, dove rimangono per 7 anni per audit trail. Costo: ~$50\/TB\/anno su S3 vs $1000+\/TB\/anno su Elasticsearch.<\/p>\n<h3>Posso usare questa pipeline anche per non-Plesk servers?<\/h3>\n<p>Assolutamente. La pipeline \u00e8 agnostica alla sorgente log. Puoi inviare log da qualsiasi server (cPanel, Nginx, Apache, Windows Server) a Logstash usando syslog, Filebeat, o l&#8217;Elastic Agent. L&#8217;unico requisito \u00e8 che il log contenga (o sia arricchito con) il tenant_id per la segregazione multi-tenant.<\/p>\n<p>Nel mio ambiente di produzione, la pipeline serve oltre 500 tenant e rileva malware polymorfi con una latenza media di rilevamento di 8 minuti dall&#8217;infezione iniziale. \u00c8 lo standard di sicurezza che dovresti implementare se gestisci hosting multi-tenant.<\/p>\n<p>Se hai domande sulla configurazione di Logstash, Elasticsearch, o sulla segregazione multi-tenant, lascia un commento qui sotto. Sono sempre disponibile per discussion sui challenge della sicurezza infrastrutturale su larga scala.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Come connettere Plesk 2026 a Elasticsearch, Splunk e Logstash per aggregazione centralizzata di log e rilevamento real-time di malware polymorfi in ambienti multi-tenant: la mia procedura completa.<\/p>\n","protected":false},"author":1,"featured_media":2709,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"","_seopress_titles_title":"Plesk Log Aggregation Multi-Tenant | Elastic + Logstash","_seopress_titles_desc":"Aggregazione centralizzata log Plesk 2026 con Elasticsearch, Splunk e Logstash: malware detection real-time, segregazione tenant, incident response automatico. La mia procedura.","_seopress_robots_index":"","footnotes":""},"categories":[4],"tags":[1045,950,1044,783,916,116,948,1046],"class_list":["post-2708","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-plesk","tag-elasticsearch","tag-log-aggregation","tag-logstash","tag-malware-detection","tag-multi-tenant","tag-plesk","tag-siem","tag-splunk"],"_links":{"self":[{"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/posts\/2708","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/comments?post=2708"}],"version-history":[{"count":0,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/posts\/2708\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/media\/2709"}],"wp:attachment":[{"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/media?parent=2708"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/categories?post=2708"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/darioiannascoli.it\/blog\/wp-json\/wp\/v2\/tags?post=2708"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}