AI分类处理的安全中心警报
中级
这是一个SecOps, Multimodal AI领域的自动化工作流,包含 12 个节点。主要使用 If, Set, Code, Gmail, Webhook 等节点。 使用GPT-4.1 Mini分类AWS安全配置错误并向Gmail发送警报
前置要求
- •Google 账号和 Gmail API 凭证
- •HTTP Webhook 端点(n8n 会自动生成)
- •Airtable API Key
- •可能需要目标 API 的认证凭证
- •OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "bBRp9TmumfujcoHs",
"meta": {
"instanceId": "b9d26382fbc087c17fe86e193d09f32e5d99f4a254d13f3b8ee28079e71766cf",
"templateCredsSetupCompleted": true
},
"name": "AI 分类处理的安全中心警报",
"tags": [],
"nodes": [
{
"id": "7be0eeba-8700-4b51-a40f-db84c7c533b1",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
0,
-272
],
"webhookId": "bebea408-3564-49c8-9407-14a4102fe0cf",
"parameters": {
"path": "aws-misconfig",
"options": {},
"httpMethod": "POST",
"responseMode": "lastNode"
},
"typeVersion": 2
},
{
"id": "ac0b1a8d-14a0-4e6d-be3a-779a57603869",
"name": "标准化发现结果",
"type": "n8n-nodes-base.code",
"position": [
672,
-176
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Code created by ca7ai\n// n8n Code node (Run Once for Each Item)\n// Normalizes Security Hub / AWS Config events whether they arrive at root or under body\nconst evt = $json.body ?? $json;\n\n// Security Hub finding (EventBridge or raw)\nconst sh = evt?.detail?.findings?.[0] || (Array.isArray(evt.findings) ? evt.findings[0] : null);\n// AWS Config notification\nconst cfg = evt?.detail?.configRuleName ? evt.detail : null;\n// Raw Security Hub finding at root\nconst rawSh = (!sh && evt?.ProductArn) ? evt : null;\n\nconst f = sh || rawSh || {};\n\nconst sev = f?.Severity?.Label || (cfg ? \"MEDIUM\" : \"UNKNOWN\");\nconst title = f?.Title || cfg?.configRuleName || \"Finding\";\nconst desc = f?.Description || cfg?.newEvaluationResult?.annotation || \"—\";\nconst id = f?.Id\n || cfg?.newEvaluationResult?.evaluationResultIdentifier?.evaluationResultQualifier?.configRuleName\n || String(Date.now());\nconst res = f?.Resources?.[0]?.Id || cfg?.resourceId || \"unknown\";\nconst types = f?.Types || [];\nconst account = evt?.account || f?.AwsAccountId || \"unknown\";\nconst region = evt?.region || f?.Region || \"unknown\";\n\n// Derive service + hints\nlet service = \"UNKNOWN\";\nif (/^arn:aws:s3:::/.test(res) || types.some(t => t.includes(\"S3\"))) service = \"S3\";\nelse if (types.some(t => /SecurityGroup/i.test(t)) || /sg-/.test(res)) service = \"EC2-SG\";\nelse if (types.some(t => /IAM/i.test(t))) service = \"IAM\";\nelse if (types.some(t => /RDS|SQL|DB/i.test(t))) service = \"RDS\";\nelse if (f?.ProductArn) service = (f.ProductArn.split(\":\")[5] || \"UNKNOWN\");\n\nconst misconfig_hints = [];\nif (service === \"S3\") misconfig_hints.push(\"s3\");\nif (/0\\.0\\.0\\.0\\/0|Public|Open|world/i.test(desc)) misconfig_hints.push(\"public\");\nif (service === \"EC2-SG\") misconfig_hints.push(\"sg\");\nif (service === \"IAM\") misconfig_hints.push(\"iam\");\nif (service === \"RDS\") misconfig_hints.push(\"db\");\n\n// IMPORTANT: return a SINGLE object (not an array) in this mode\nreturn {\n finding_id: id,\n title,\n description: desc,\n severity: sev,\n resource_id: res,\n service,\n account,\n region,\n product_types: types,\n misconfig_hints,\n raw: evt,\n};"
},
"typeVersion": 2
},
{
"id": "be7fa618-9c8c-4418-a405-a4f2787faaf5",
"name": "发送消息",
"type": "n8n-nodes-base.gmail",
"position": [
1520,
-176
],
"webhookId": "cfac9d61-e17a-467c-a742-7cb9da960a7f",
"parameters": {
"sendTo": "test@gmail.com",
"message": "=={{ (() => { const nf = $node[\"Normalize Finding\"].json; const ai = typeof $node[\"AI Prioritizer\"].json.message.content === 'string' ? JSON.parse($node[\"AI Prioritizer\"].json.message.content) : $node[\"AI Prioritizer\"].json.message.content; const steps = (ai.remediation || []).map(s => `<li>${s}</li>`).join(''); const tags = (ai.tags || []).join(', '); const airtableId = $node[\"Airtable - Create Record\"].json?.id || ''; const airtableLine = airtableId ? `<p><b>Airtable Record ID:</b> ${airtableId}</p>` : ''; return ` <h2>AWS Misconfig Alert</h2> <p><b>Priority:</b> ${ai.priority} <b>Severity:</b> ${nf.severity}</p> <p><b>Title:</b> ${nf.title}</p> <p><b>Service:</b> ${nf.service} <b>Resource:</b> ${nf.resource_id}</p> <p><b>Account:</b> ${nf.account} <b>Region:</b> ${nf.region}</p> <p><b>Why:</b> ${ai.rationale}</p> <p><b>Remediation:</b></p> <ol>${steps}</ol> <p><b>Tags:</b> ${tags || '—'}</p> ${airtableLine} <details><summary>Raw finding</summary> <pre style=\"background:#f6f8fa;padding:12px;border-radius:6px;white-space:pre-wrap\">${JSON.stringify(nf.raw || nf, null, 2)}</pre> </details> `;})() }}",
"options": {},
"subject": "=={{ `[${JSON.parse($node[\"AI Prioritizer\"].json.message.content).priority}] ${$node[\"Normalize Finding\"].json.title} — ${$node[\"Normalize Finding\"].json.resource_id} (${ $node[\"Normalize Finding\"].json.service })` }}"
},
"credentials": {
"gmailOAuth2": {
"id": "3P9F7770YiCuujN",
"name": "Gmail account"
}
},
"typeVersion": 2.1
},
{
"id": "c0fb42e3-e670-44f9-a3fa-0b2c3dec2ae1",
"name": "AI 优先级排序器",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
896,
-176
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "GPT-4.1-MINI"
},
"options": {},
"messages": {
"values": [
{
"content": "=You are a cloud SecOps triage assistant. Given a normalized AWS finding JSON, return a STRICT JSON object:\n\n{\n \"priority\": \"P0|P1|P2|P3\",\n \"rationale\": \"one-paragraph reason referencing severity, resource, and exposure\",\n \"remediation\": [\"step 1\", \"step 2\", \"...\"],\n \"tags\": [\"s3\",\"iam\",\"public\", \"...\"]\n}\n\nMapping guidance:\n- Treat publicly accessible data (e.g., public S3 buckets, 0.0.0.0/0 on admin ports, open RDS) as P0 or P1 depending on blast radius.\n- Internal-only or low impact → P2/P3.\n- If severity label is CRITICAL/HIGH, bias to P0/P1.\n\nFinding:\n{{ JSON.stringify($json, null, 2) }}\n"
}
]
},
"jsonOutput": true
},
"credentials": {
"openAiApi": {
"id": "IZ5MCCCsozmZld3",
"name": "OpenAi account"
}
},
"typeVersion": 1.8
},
{
"id": "42721c67-8c6d-4063-826b-b59e01a3d8ca",
"name": "Airtable - 创建记录",
"type": "n8n-nodes-base.airtable",
"position": [
1296,
-176
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "appzIE2wRRYUbvl50",
"cachedResultUrl": "https://airtable.com/uuuu",
"cachedResultName": "misconfigs"
},
"table": {
"__rl": true,
"mode": "list",
"value": "tblPDewIrVYYYYNyi",
"cachedResultUrl": "https://airtable.com/uuuu/uuuu",
"cachedResultName": "finding_table"
},
"columns": {
"value": {
"id": "={{ $('Normalize Finding').item.json.finding_id }}",
"Tags": "={{ $json.message.content.tags[0] }}{{ $json.message.content.tags[1] }}{{ $json.message.content.tags[2] }}{{ $json.message.content.tags[3] }}{{ $json.message.content.tags[4] }}",
"Title": "={{ $('Normalize Finding').item.json.title }}",
"Region": "={{ $('Normalize Finding').item.json.region }}",
"Account": "={{ $('Normalize Finding').item.json.account }}",
"Service": "={{ $('Normalize Finding').item.json.service }}",
"Priority": "={{ $json.message.content.priority }}",
"Resource": "={{ $('Normalize Finding').item.json.raw.detail.findings[0].Resources[0].Id }}",
"Severity": "={{ $('Normalize Finding').item.json.severity }}",
"Rationale": "={{ $json.message.content.rationale }}",
"Finding ID": "={{ $('Normalize Finding').item.json.raw.detail.findings[0].Id }}",
"Remediation": "={{ $json.message.content.remediation[0] }}{{ $json.message.content.remediation[1] }}{{ $json.message.content.remediation[2] }}{{ $json.message.content.remediation[3] }}"
},
"schema": [
{
"id": "id",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "id",
"defaultMatch": true
},
{
"id": "Finding ID",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Finding ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Title",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Severity",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Severity",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Priority",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Priority",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Resource",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Resource",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Service",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Service",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Account",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Account",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Region",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Region",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Tags",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Tags",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Rationale",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Rationale",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Remediation",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Remediation",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "upsert"
},
"credentials": {
"airtableTokenApi": {
"id": "aftfB5RyLZKQ1111",
"name": "Airtable Access Token"
}
},
"typeVersion": 2.1
},
{
"id": "6f9bf9c6-61ee-4b25-844c-5f03c9979f9e",
"name": "编辑字段",
"type": "n8n-nodes-base.set",
"position": [
1744,
-176
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{\n {\n resp: {\n status: \"processed\",\n priority: $node[\"Airtable - Create Record\"].json.fields.Priority,\n finding_id: $node[\"Normalize Finding\"].json.finding_id\n }\n }\n}}\n"
},
"typeVersion": 3.4
},
{
"id": "fbb5d2af-7eb2-414f-b79e-2a51ddb9b21f",
"name": "SNS 处理器",
"type": "n8n-nodes-base.code",
"position": [
224,
-272
],
"parameters": {
"jsCode": "const b = $json.body ?? $json;\nconst token = $json.query?.token ?? b.token;\nif (token !== 'MY_SUPER_TOKEN') throw new Error('unauthorized');\n\nif (b.Type === 'SubscriptionConfirmation' && b.SubscribeURL) {\n return { mode: 'confirm', subscribeUrl: b.SubscribeURL };\n}\n\nlet event = b;\nif (b.Type === 'Notification' && b.Message) {\n try { event = JSON.parse(b.Message); } catch {}\n}\nreturn { mode: 'notify', event };\n"
},
"typeVersion": 2
},
{
"id": "b61e5e70-697d-4fe4-9897-9a116aa5aff1",
"name": "条件判断",
"type": "n8n-nodes-base.if",
"position": [
448,
-272
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "d192995f-8809-4b60-8f6a-b7bd2e3e47b0",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "=={{ $json.mode === 'confirm' }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "5c1145c7-6dd6-47e3-9fee-e1fb15318a22",
"name": "SNS 确认",
"type": "n8n-nodes-base.httpRequest",
"position": [
672,
-368
],
"parameters": {
"url": "=={{ $json.subscribeUrl }}",
"options": {
"timeout": 15000,
"response": {
"response": {
"fullResponse": true,
"responseFormat": "json"
}
}
}
},
"typeVersion": 4.2
},
{
"id": "831507c3-b00f-44ec-8506-c0310904eb6e",
"name": "编辑字段1",
"type": "n8n-nodes-base.set",
"position": [
984,
-368
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "346708e7-629e-4d8a-8a98-994b9526b55d",
"name": "resp",
"type": "object",
"value": "=resp = { status: \"subscribed\", statusCode: $json.statusCode || 200 }"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b39a925c-911d-4e61-a0e6-5aadc4ccfd38",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-464,
-32
],
"parameters": {
"width": 336,
"content": "## 注意"
},
"typeVersion": 1
},
{
"id": "1bea05cd-6468-4c74-aeec-8c60d69411c4",
"name": "便签 1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-464,
-368
],
"parameters": {
"color": 4,
"width": 336,
"height": 304,
"content": "## 标题:工作原理(连接)"
},
"typeVersion": 1
}
],
"active": true,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "044dc52b-81c7-43ab-a1c2-5be287a0d970",
"connections": {
"If": {
"main": [
[
{
"node": "SNS Confirm",
"type": "main",
"index": 0
}
],
[
{
"node": "Normalize Finding",
"type": "main",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "SNS Handler",
"type": "main",
"index": 0
}
]
]
},
"SNS Confirm": {
"main": [
[
{
"node": "Edit Fields1",
"type": "main",
"index": 0
}
]
]
},
"SNS Handler": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields1": {
"main": [
[]
]
},
"AI Prioritizer": {
"main": [
[
{
"node": "Airtable - Create Record",
"type": "main",
"index": 0
}
]
]
},
"Send a message": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Normalize Finding": {
"main": [
[
{
"node": "AI Prioritizer",
"type": "main",
"index": 0
}
]
]
},
"Airtable - Create Record": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
中级 - 安全运维, 多模态 AI
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
GRC - 安全问卷自动填写
自动化安全问卷回复:GPT-4o和Google Sheets
If
Set
Code
+7
11 节点Adnan Tariq
安全运维
带AI的URL检查器生产版
网站运行时间监控(GPT-4分析和Gmail通知)
If
Gmail
Webhook
+3
9 节点Calistus Christian
开发运维
会议纪要和行动项跟踪器
基于AI的会议纪要:使用GPT-4、任务分配和多渠道分发
If
Set
Code
+10
38 节点Jitesh Dugar
内容创作
自动化潜在客户生成与个性化外联:Apollo、AI和Instantly.ai
自动化潜在客户生成与个性化外联:Apollo、AI和Instantly.ai
If
Set
Code
+15
166 节点Ruben AI
客户培育
自动化潜在客户捕获、AI资质鉴定及ElevenLabs个性化语音跟进
基于 OpenAI 和 ElevenLabs 的自动化线索捕获与 AI 个性化语音跟进
If
Set
Code
+10
22 节点Marth
客户培育
使用Airtable、OpenAI和Unipile的自动化LinkedIn潜在客户生成与私信触达
使用Airtable、OpenAI和Unipile的自动化LinkedIn潜在客户生成与私信触达
If
Set
Code
+15
143 节点Ruben AI
客户培育
工作流信息
难度等级
中级
节点数量12
分类2
节点类型9
作者
Calistus Christian
@ca7aiAutomation strategist and AI workflow architect creating intelligent, agent-driven processes that streamline operations. I build advanced n8n solutions integrating AI, cloud services, and real-time data orchestration for scalable impact. Explore my free workflows to get started. Premium, custom-built solutions are also available. Connect with me on LinkedIn for tailored automation expertise.
外部链接
在 n8n.io 查看 →
分享此工作流