The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "CyberShield Universal Workflow v4",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "ejecutar-ataque",
"responseMode": "responseNode",
"options": {}
},
"id": "cs-webhook",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
400
]
},
{
"parameters": {
"operation": "find",
"collection": "attack-templates",
"query": "={{ JSON.stringify({ name: $json.body.task_name || $json.task_name || 'unknown' }) }}",
"limit": 1,
"options": {}
},
"id": "cs-mongo-find",
"name": "MongoDB",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
480,
400
],
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// ============================================================\n// CONSTRUIR COMANDO desde la plantilla de MongoDB + params del usuario\n// ============================================================\n// MongoDB devuelve la plantilla con command_base y params por defecto.\n// El webhook envia los params del usuario que sobreescriben los defaults.\n// Este nodo fusiona ambos y reemplaza los {{placeholders}}.\n// ============================================================\n\nconst mongoResult = $input.first().json;\nconst webhookData = $('Webhook').first().json;\nconst body = webhookData.body || webhookData;\n\nconst taskName = body.task_name || 'unknown';\nconst userParams = body.params || {};\nconst ts = Date.now();\n\n// Si MongoDB devolvio plantilla, usarla; si no, fallback\nlet commandBase = '';\nlet templateParams = {};\nlet postNotify = '';\nlet mitreId = 'N/A';\nlet severity = 'medium';\n\nif (mongoResult && mongoResult.command_base) {\n commandBase = mongoResult.command_base;\n templateParams = mongoResult.params || {};\n postNotify = mongoResult.post_attack_notify || '';\n mitreId = mongoResult.mitre_id || 'N/A';\n severity = mongoResult.severity || 'medium';\n} else {\n // FALLBACK: si no hay plantilla en MongoDB para este ataque\n commandBase = 'echo \"Ataque no encontrado en MongoDB: ' + taskName + '\"';\n}\n\n// Fusionar params: defaults de MongoDB + overrides del usuario\nconst mergedParams = Object.assign({}, templateParams, userParams);\nmergedParams.timestamp = String(ts);\n\n// Reemplazar todos los {{placeholder}} en el comando\nlet command = commandBase;\nfor (const [key, value] of Object.entries(mergedParams)) {\n const regex = new RegExp('\\\\{\\\\{' + key + '\\\\}\\\\}', 'g');\n command = command.replace(regex, String(value));\n}\n\n// Construir el post_attack_notify (logger para Wazuh)\nlet loggerCmd = postNotify;\nfor (const [key, value] of Object.entries(mergedParams)) {\n const regex = new RegExp('\\\\{\\\\{' + key + '\\\\}\\\\}', 'g');\n loggerCmd = loggerCmd.replace(regex, String(value));\n}\n\n// Encadenar: comando del ataque + logger para Wazuh\nconst fullCommand = loggerCmd\n ? command + '; ' + loggerCmd\n : command;\n\nreturn [{\n json: {\n command: fullCommand,\n task_name: taskName,\n params: mergedParams,\n mitre_id: mitreId,\n severity: severity,\n timestamp: ts,\n started_at: new Date().toISOString()\n }\n}];"
},
"id": "cs-build-cmd",
"name": "Code in JavaScript",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
720,
400
]
},
{
"parameters": {
"command": "={{ $json.command }}"
},
"id": "cs-ssh-exec",
"name": "Execute a command",
"type": "n8n-nodes-base.ssh",
"typeVersion": 1,
"position": [
960,
400
],
"credentials": {
"sshPassword": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Post-procesado: recoger output y preparar datos para informe PDF\nconst ssh = $input.first().json;\nconst prev = $('Code in JavaScript').first().json;\nconst stdout = ssh.stdout || '';\nconst stderr = ssh.stderr || '';\nconst exitCode = ssh.exitCode || 0;\nconst durationSec = Math.round((Date.now() - new Date(prev.started_at).getTime()) / 1000);\n\nreturn [{\n json: {\n task_name: prev.task_name,\n params: prev.params,\n mitre_id: prev.mitre_id,\n severity: prev.severity,\n timestamp: prev.timestamp,\n started_at: prev.started_at,\n finished_at: new Date().toISOString(),\n duration_seconds: durationSec,\n output: stdout,\n stderr: stderr,\n exit_code: exitCode,\n success: exitCode === 0,\n xml_output: stdout.includes('<?xml') ? stdout : '',\n target: prev.params.target || prev.params.bssid || prev.params.interface || 'N/A',\n scan_target: prev.params.target || 'N/A'\n }\n}];"
},
"id": "cs-post-process",
"name": "Post-Procesado",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1200,
400
]
},
{
"parameters": {
"method": "POST",
"url": "http://host.docker.internal:3010/generate-attack-report",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify($json) }}",
"options": {
"timeout": 30000
}
},
"id": "cs-gen-report",
"name": "Generar Informe PDF",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1440,
400
],
"continueOnFail": true
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ ok: true, task_name: $('Post-Procesado').first().json.task_name, success: $('Post-Procesado').first().json.success, exit_code: $('Post-Procesado').first().json.exit_code, output_preview: ($('Post-Procesado').first().json.output || '').slice(0, 500), duration: $('Post-Procesado').first().json.duration_seconds, timestamp: new Date().toISOString() }) }}",
"options": {}
},
"id": "cs-respond",
"name": "Responder Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1680,
400
]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "MongoDB",
"type": "main",
"index": 0
}
]
]
},
"MongoDB": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Execute a command",
"type": "main",
"index": 0
}
]
]
},
"Execute a command": {
"main": [
[
{
"node": "Post-Procesado",
"type": "main",
"index": 0
}
]
]
},
"Post-Procesado": {
"main": [
[
{
"node": "Generar Informe PDF",
"type": "main",
"index": 0
}
]
]
},
"Generar Informe PDF": {
"main": [
[
{
"node": "Responder Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true
},
"triggerCount": 1
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
mongoDbsshPassword
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
CyberShield Universal Workflow v4. Uses mongoDb, ssh, httpRequest. Webhook trigger; 7 nodes.
Source: https://github.com/alexgc04/CyberShield-TFG/blob/53e88aeb49b058b532d3cb94db532c7f1d9596da/n8n-flows/webhook-universal.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
CyberShield — Attack Executor. Uses mongoDb, ssh, httpRequest. Webhook trigger; 6 nodes.
UFRO PP3 Orchestrator Workflow. Uses httpRequest, mongoDb. Webhook trigger; 7 nodes.
Seoul hackathon. Uses httpRequest, mongoDb. Webhook trigger; 5 nodes.
DAta lake 1. Uses openAi, httpRequest, googleSheets, mongoDb. Webhook trigger; 23 nodes.
BP_check. Uses googleSheets, @n-octo-n/n8n-nodes-json-database, httpRequest, itemLists. Webhook trigger; 99 nodes.