🕵️‍♂️ Escáner automático de GitHub – Detección de claves de AWS IAM expuestas

Avanzado

Este es unSecOpsflujo de automatización del dominio deautomatización que contiene 18 nodos.Utiliza principalmente nodos como If, Code, Wait, Slack, HttpRequest. Escáner automático de GitHub para detectar claves de AWS IAM expuestas

Requisitos previos
  • Bot Token de Slack o URL de Webhook
  • Pueden requerirse credenciales de autenticación para la API de destino
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "id": "Tcy2xebw2oGWMxUN",
  "meta": {
    "instanceId": "c62c01f3e843893075a10f252ec7d6d69e5ab593af019f50055d506cb3081b99",
    "templateCredsSetupCompleted": true
  },
  "name": "🕵️‍♂️ Automated GitHub Scanner for Exposed AWS IAM Keys",
  "tags": [
    {
      "id": "XuoVybTXeUXuim6G",
      "name": "✅ Live",
      "createdAt": "2025-06-08T07:59:43.586Z",
      "updatedAt": "2025-06-08T07:59:43.586Z"
    },
    {
      "id": "MbPHhZHgb39Syuoa",
      "name": "🔐 SecOps",
      "createdAt": "2025-04-20T05:18:20.689Z",
      "updatedAt": "2025-06-08T08:01:56.494Z"
    }
  ],
  "nodes": [
    {
      "id": "84edf6c4-fc87-4b34-86c6-ad72c15cafe8",
      "name": "Al hacer clic en 'Ejecutar flujo de trabajo'",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -880,
        75
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "b2c1157f-c1eb-4d22-95d0-6ec166a93a4a",
      "name": "Dividir Usuarios para Procesamiento",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -220,
        75
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "ae5a0e4f-892c-4a75-bdcc-36253fbc7274",
      "name": "Obtener Claves de Acceso de Usuario",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        0,
        0
      ],
      "parameters": {
        "url": "https://iam.amazonaws.com",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "Action",
              "value": "ListAccessKeys"
            },
            {
              "name": "Version",
              "value": "2010-05-08"
            },
            {
              "name": "UserName",
              "value": "={{ $json.username }}"
            }
          ]
        },
        "nodeCredentialType": "aws"
      },
      "credentials": {
        "aws": {
          "id": "Y0EXCbx12345678",
          "name": "AWS account"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "0946f05d-11f0-480b-934a-c996bbb9551e",
      "name": "Filtrar Solo Claves Activas",
      "type": "n8n-nodes-base.if",
      "position": [
        220,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "active-key-check",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata[0].Status }}",
              "rightValue": "Active"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "8f9db031-245e-4c00-bdb9-4ed55e9b57b2",
      "name": "Buscar GitHub en busca de Claves Expuestas",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        880,
        0
      ],
      "parameters": {
        "url": "={{ $json.simpleSearch.searchUrl }}",
        "options": {
          "timeout": 10000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "githubApi"
      },
      "credentials": {
        "githubApi": {
          "id": "3fz93A0mgyxzXGOL",
          "name": "GitHub account"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "a6cd482c-86d2-49ac-aefe-6beec92c98af",
      "name": "Agregar Resultados de Búsqueda",
      "type": "n8n-nodes-base.code",
      "position": [
        1100,
        0
      ],
      "parameters": {
        "jsCode": "// Aggregate all search results\nconst allResults = [];\nconst accessKeyId = $input.first().json.accessKeyId;\nconst userName = $input.first().json.userName;\n\nfor (const item of $input.all()) {\n  if (item.json.total_count > 0) {\n    allResults.push(...item.json.items);\n  }\n}\n\n// Remove duplicates based on repository and file path\nconst uniqueResults = allResults.filter((item, index, self) => \n  index === self.findIndex(t => t.repository.full_name === item.repository.full_name && t.path === item.path)\n);\n\nreturn [{\n  accessKeyId,\n  userName,\n  totalMatches: uniqueResults.length,\n  repositories: uniqueResults,\n  isCompromised: uniqueResults.length > 0\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "75ed15ec-fdee-4644-a83c-6b47005dcac1",
      "name": "Verificar Claves Comprometidas",
      "type": "n8n-nodes-base.if",
      "position": [
        1320,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ebf33a67-f8f3-4700-8579-1d33b7a642d5",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "isCompromised",
              "rightValue": "={{ $json.isCompromised }}"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "57753be8-33d2-4172-94a2-0d5a4f7c73ec",
      "name": "Generar Informe de Seguridad",
      "type": "n8n-nodes-base.code",
      "position": [
        1540,
        0
      ],
      "parameters": {
        "jsCode": "// Generate comprehensive security report - Notification Only (No Automatic Actions)\nconst data = $input.item.json;\n\nconst report = {\n  timestamp: new Date().toISOString(),\n  accessKeyId: data.accessKeyId,\n  userName: data.userName,\n  status: data.isCompromised ? 'COMPROMISED' : 'SAFE',\n  totalRepositories: data.totalMatches,\n  repositories: data.repositories.map(repo => ({\n    name: repo.repository.full_name,\n    url: repo.html_url,\n    path: repo.path,\n    score: repo.score\n  })),\n  actionTaken: data.isCompromised ? 'Security team notified - Manual review required' : 'No action required',\n  riskLevel: data.totalMatches > 5 ? 'HIGH' : data.totalMatches > 0 ? 'MEDIUM' : 'LOW',\n  notificationSent: data.isCompromised ? true : false,\n  requiresManualAction: data.isCompromised ? true : false,\n  recommendedActions: data.isCompromised ? [\n    'Manually disable the compromised access key',\n    'Generate new access keys for affected services',\n    'Remove exposed keys from repositories',\n    'Audit recent API usage for this key'\n  ] : []\n};\n\nreturn [report];"
      },
      "typeVersion": 2
    },
    {
      "id": "f2634090-b035-4592-ad56-b970c2bff14c",
      "name": "Continuar Escaneo",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2340,
        80
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "158340f1-4dc4-4b4c-933f-95a28be524dc",
      "name": "Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        2020,
        0
      ],
      "webhookId": "47dc1fb0-71c0-40f6-8263-88880f01a436",
      "parameters": {
        "text": "={{ $json.message }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "C08Q2H8SRUP"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "i1yhHILyYn12345678",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "c0300832-418b-4fa8-98b6-2b799f2bcfe6",
      "name": "Formatear Alerta Slack",
      "type": "n8n-nodes-base.code",
      "position": [
        1760,
        0
      ],
      "parameters": {
        "jsCode": "/**\n * GitHub Scanner for Exposed AWS IAM Keys - Data Processor\n * \n * This script processes the results from the AWS IAM Key scanner workflow\n * and formats them for reporting and notification purposes.\n */\n\n// Main entry point - this is what n8n will call\n// Input: items array from n8n workflow\n// Output: Slack Block Kit UI format (blocks array only)\nconst items = $input.all();\n\n// Process the input data\nconst scanResults = items.map(item => item.json);\nconst processedResults = processIAMScanResults(scanResults);\n\n// Format for markdown notification\nconst markdownNotification = formatForMarkdownNotification(processedResults);\n// Return as array of objects for n8n\nreturn [{ message: markdownNotification }];\n\n/**\n * Process scan results and format them for reporting\n * @param {Array} scanResults - Array of scan result objects from the workflow\n * @returns {Array} Array of formatted result objects\n */\nfunction processIAMScanResults(scanResults) {\n  if (!Array.isArray(scanResults) || scanResults.length === 0) {\n    return [{\n      status: 'NO_RESULTS',\n      timestamp: new Date().toISOString(),\n      message: 'No scan results to process'\n    }];\n  }\n\n  // Process each scan result\n  const processedResults = scanResults.map(result => {\n    // Create a deep copy to avoid modifying the original data\n    const processedResult = JSON.parse(JSON.stringify(result));\n    \n    // Ensure we have the required fields\n    if (!processedResult.timestamp) {\n      processedResult.timestamp = new Date().toISOString();\n    }\n    \n    // Calculate risk metrics if not provided\n    if (!processedResult.riskLevel) {\n      processedResult.riskLevel = calculateRiskLevel(processedResult);\n    }\n    \n    // Generate recommended actions if not provided\n    if (!processedResult.recommendedActions || processedResult.recommendedActions.length === 0) {\n      processedResult.recommendedActions = generateRecommendedActions(processedResult);\n    }\n    \n    return processedResult;\n  });\n\n  return processedResults;\n}\n  \n  /**\n   * Calculate risk level based on scan result data\n   * @param {Object} result - Individual scan result\n   * @returns {string} Risk level (HIGH, MEDIUM, LOW)\n   */\n  function calculateRiskLevel(result) {\n    // Default to MEDIUM if we can't determine\n    if (!result || !result.status) {\n      return 'MEDIUM';\n    }\n    \n    // Determine risk level based on status and other factors\n    if (result.status === 'COMPROMISED') {\n      // Public repositories or repositories with many contributors increase risk\n      if (result.repositories && result.repositories.some(repo => {\n        return repo.score >= 0.8; // High score indicates higher risk\n      })) {\n        return 'HIGH';\n      }\n      return 'MEDIUM';\n    } else if (result.status === 'POTENTIAL_EXPOSURE') {\n      return 'MEDIUM';\n    } else {\n      return 'LOW';\n    }\n  }\n  \n  /**\n   * Generate recommended actions based on scan result\n   * @param {Object} result - Individual scan result\n   * @returns {Array} List of recommended actions\n   */\n  function generateRecommendedActions(result) {\n    const commonActions = [\n      'Review the exposure details in the security report',\n      'Rotate affected access keys immediately'\n    ];\n    \n    if (result.status === 'COMPROMISED') {\n      return [\n        ...commonActions,\n        'Disable the compromised access key',\n        'Generate new access keys for affected services',\n        'Remove exposed keys from repositories',\n        'Audit recent API usage for this key'\n      ];\n    } else if (result.status === 'POTENTIAL_EXPOSURE') {\n      return [\n        ...commonActions,\n        'Verify if the exposure is a false positive',\n        'Consider rotating keys as a precaution'\n      ];\n    } else {\n      return [\n        'No immediate action required',\n        'Continue monitoring for potential exposures'\n      ];\n    }\n  }\n  \n  /**\n   * Format scan results for Slack-compatible markdown notification\n   * @param {Array} processedResults - Processed scan results\n   * @returns {string} Slack-compatible markdown formatted notification text\n   */\n  function formatForMarkdownNotification(processedResults) {\n    if (!Array.isArray(processedResults) || processedResults.length === 0) {\n      return `🔒 *AWS IAM Key Scan Completed*\\n\\nNo exposed AWS IAM keys were detected in this scan.`;\n    }\n  \n    // Count compromised keys\n    const compromisedCount = processedResults.filter(r => r.status === 'COMPROMISED').length;\n    \n    if (compromisedCount === 0) {\n      return `🔒 *AWS IAM Key Scan Completed*\\n\\nNo exposed AWS IAM keys were detected in this scan.`;\n    }\n    \n    // Create Slack-compatible notification for compromised keys\n    let markdown = `⚠️ *ALERT: AWS IAM Keys Exposed*\\n\\n*${compromisedCount}* AWS IAM keys have been potentially exposed on GitHub. Immediate action required.\\n\\n`;\n    \n    // Add details for each compromised key\n    processedResults.filter(r => r.status === 'COMPROMISED').forEach((result, index) => {\n      markdown += `*Exposure ${index + 1}*\\n\\n`;\n      \n      // Add repository information in a cleaner format\n      markdown += `*Exposure Details:*\\n`;\n      result.repositories.forEach(repo => {\n        markdown += `• *Repository:* ${repo.name}\\n`;\n        markdown += `• *Path:* \\`${repo.path}\\`\\n`;\n        markdown += `• *Risk Score:* ${repo.score.toFixed(2)}\\n\\n`;\n      });\n      \n      // Add risk level and action taken in a compact format\n      markdown += `*Risk Level:* ${result.riskLevel} | *Action Taken:* ${result.actionTaken || 'None'}\\n\\n`;\n      \n      // Add recommended actions with better formatting\n      markdown += `*Recommended Actions:*\\n`;\n      result.recommendedActions.forEach(action => {\n        markdown += `• ${action}\\n`;\n      });\n      markdown += `\\n`;\n    });\n    \n    return markdown;\n  }\n\n  \n  // Export functions for use in n8n workflow\n  module.exports = {\n    processIAMScanResults,\n    calculateRiskLevel,\n    generateRecommendedActions,\n    formatForMarkdownNotification\n  };"
      },
      "typeVersion": 2
    },
    {
      "id": "3ed685c7-27b5-4a00-840a-6f9dddff6d3f",
      "name": "Preparar Búsqueda Github",
      "type": "n8n-nodes-base.code",
      "position": [
        440,
        0
      ],
      "parameters": {
        "jsCode": "/**\n * Simplified GitHub Search for AWS Access Keys\n * This script generates optimized search queries for finding exposed AWS access keys on GitHub\n */\n\n/**\n * Generates a GitHub API search URL for a given AWS access key\n * @param {Object} inputData - The input data containing AWS access key information\n * @returns {Object} - Search information including URL and query\n */\nfunction generateGitHubSearchQuery(inputData) {\n  try {\n    // Extract access key information from input\n    let accessKeyId;\n    let userName;\n    \n    // Handle different input formats\n    if (inputData && typeof inputData === 'object') {\n      // Check for n8n workflow format\n      if (inputData.ListAccessKeysResponse && \n          inputData.ListAccessKeysResponse.ListAccessKeysResult && \n          inputData.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata && \n          Array.isArray(inputData.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata) && \n          inputData.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata.length > 0) {\n        \n        accessKeyId = inputData.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata[0].AccessKeyId;\n        userName = inputData.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata[0].UserName;\n      } \n      // Direct object format\n      else if (inputData.accessKeyId) {\n        accessKeyId = inputData.accessKeyId;\n        userName = inputData.userName || 'unknown';\n      }\n    }\n    \n    // Validate we have an access key\n    if (!accessKeyId) {\n      console.error('No valid AWS access key ID found in input');\n      return { error: 'No valid AWS access key ID found in input' };\n    }\n    \n    // Create the most effective search query\n    // Based on testing, the exact match with quotes is most reliable\n    const searchQuery = `\"${accessKeyId}\" in:file`;\n    \n    // Generate the GitHub API search URL\n    const searchUrl = `https://api.github.com/search/code?q=${encodeURIComponent(searchQuery)}`;\n    \n    return {\n      accessKeyId,\n      userName,\n      searchQuery,\n      searchUrl,\n      note: 'A single exact match query is typically sufficient for finding exposed AWS keys'\n    };\n  } catch (error) {\n    console.error('Error generating GitHub search query:', error);\n    return { error: `Error generating GitHub search query: ${error.message}` };\n  }\n}\n\n/**\n * For more comprehensive searches, this function generates multiple search patterns\n * This is optional and can be used if the simple search doesn't yield results\n * @param {string} accessKeyId - The AWS access key ID to search for\n * @returns {Array} - Array of search queries and URLs\n */\nfunction generateComprehensiveSearch(accessKeyId) {\n  if (!accessKeyId) {\n    return { error: 'No access key ID provided' };\n  }\n  \n  // Search patterns for access keys (in order of effectiveness)\n  const searchQueries = [\n    `\"${accessKeyId}\" in:file`,           // Exact match (most effective)\n    `${accessKeyId} in:file`,              // Without quotes (catches more results but may have false positives)\n    `AWS_ACCESS_KEY_ID=${accessKeyId} in:file`,  // Environment variable format\n    `aws_access_key_id: ${accessKeyId} in:file`, // YAML/config format\n    `accessKeyId: ${accessKeyId} in:file`        // JavaScript/JSON format\n  ];\n  \n  return searchQueries.map(query => ({\n    searchQuery: query,\n    searchUrl: `https://api.github.com/search/code?q=${encodeURIComponent(query)}`\n  }));\n}\n\n// For n8n integration\nfunction processForN8n() {\n  try {\n    // Get input data\n    const inputData = $input.item.json;\n    \n    // Generate the simplified search (recommended approach)\n    const simpleSearch = generateGitHubSearchQuery(inputData);\n    \n    // For backward compatibility, also generate the comprehensive search\n    // if an access key was successfully extracted\n    let comprehensiveSearch = [];\n    if (simpleSearch.accessKeyId) {\n      comprehensiveSearch = generateComprehensiveSearch(simpleSearch.accessKeyId);\n    }\n    \n    return {\n      simpleSearch,\n      comprehensiveSearch,\n      recommendation: 'The simple search is recommended for most cases. Only use comprehensive search if simple search yields no results.'\n    };\n  } catch (error) {\n    console.error('Error in n8n processing:', error);\n    return { error: `Error in n8n processing: ${error.message}` };\n  }\n}\n\n// For standalone usage\nif (typeof module !== 'undefined' && module.exports) {\n  module.exports = {\n    generateGitHubSearchQuery,\n    generateComprehensiveSearch\n  };\n} else {\n  // For n8n execution\n  return processForN8n();\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "e58f0cd8-13df-41eb-9a9c-99efc7eba0c4",
      "name": "Nota Adhesiva",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -900,
        -680
      ],
      "parameters": {
        "width": 1120,
        "height": 580,
        "content": "# 🔐🕵️‍♂️ GitHub Scanner for Exposed AWS IAM Keys – Quick Overview\n\n## ⚙️ Workflow at a Glance\n\n1. 🔍 **Automated Discovery**  \n   Scans GitHub repositories for exposed AWS IAM access keys associated with your AWS account.\n\n2. 🧠 **Intelligent Filtering**  \n   Processes only active access keys and eliminates duplicate findings.\n\n3. 🚨 **Risk Assessment**  \n   Evaluates exposure severity and assigns risk levels (High/Medium/Low) based on findings.\n\n4. 📣 **Actionable Alerts**  \n   Sends detailed Slack notifications with interactive buttons for immediate response.\n\n5. 🛠️ **Remediation Guidance**  \n   Provides step-by-step instructions for securing compromised credentials.\n\n6. 🔄 **Continuous Monitoring**  \n   Maintains ongoing surveillance to detect new exposures quickly.\n\n---\n\n*🛡️ This workflow helps security teams quickly identify and respond to potential security breaches from exposed AWS credentials.*\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ef29b02b-f2a4-4642-a5c4-c9685b0e2c22",
      "name": "Espera por Límite de Tasa",
      "type": "n8n-nodes-base.wait",
      "position": [
        660,
        0
      ],
      "webhookId": "850e337e-d261-456a-86c1-1725d77f9e52",
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "714724b6-9aaf-4d17-97b7-1a3fd3dcaeae",
      "name": "Listar Usuarios AWS1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -660,
        80
      ],
      "parameters": {
        "url": "https://iam.amazonaws.com",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "Action",
              "value": "ListUsers"
            },
            {
              "name": "Version",
              "value": "2010-05-08"
            }
          ]
        },
        "nodeCredentialType": "aws"
      },
      "credentials": {
        "aws": {
          "id": "Y0EXCbx12345678",
          "name": "AWS account"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "a1448a68-81aa-4571-8f62-617c57daa6e6",
      "name": "Extraer Nombres de Usuario AWS",
      "type": "n8n-nodes-base.code",
      "position": [
        -440,
        75
      ],
      "parameters": {
        "jsCode": "// n8n Function node: Extract usernames from AWS ListUsersResponse\n\nconst allInputs = $input.all();\n\n// Find the ListUsersResponse input\nconst listUsersInput = allInputs.find(item => item.json.ListUsersResponse);\n\nif (!listUsersInput) {\n  throw new Error('No ListUsersResponse found in input data');\n}\n\n// Extract users array from the response\nconst users = listUsersInput.json\n  .ListUsersResponse\n  .ListUsersResult\n  .Users || [];\n\n// Extract usernames and return each as a separate item for looping\nconst usernameItems = users.map(user => ({\n  json: { username: user.UserName }\n}));\n\n// Return array of individual username objects\nreturn usernameItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "2339c570-93a3-4c1a-ae0d-2eb9810eeee8",
      "name": "Deshabilitar Claves de Acceso",
      "type": "n8n-nodes-base.httpRequest",
      "disabled": true,
      "position": [
        1200,
        -620
      ],
      "parameters": {
        "url": "https://iam.amazonaws.com",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "Action",
              "value": "UpdateAccessKey"
            },
            {
              "name": "AccessKeyId",
              "value": "AKIAEXAMPLEACCESSKEY1"
            },
            {
              "name": "UserName",
              "value": "user@domain.com"
            },
            {
              "name": "Status",
              "value": "Inactive"
            },
            {
              "name": "Version",
              "value": "2010-05-08"
            }
          ]
        },
        "nodeCredentialType": "aws"
      },
      "credentials": {
        "aws": {
          "id": "Y0EXCbx12345678",
          "name": "AWS account"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "99938eb1-580b-4a91-b7a7-83464b33053e",
      "name": "Nota Adhesiva1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        -680
      ],
      "parameters": {
        "color": 6,
        "width": 1200,
        "height": 580,
        "content": "## 🚨 Automate Disable Access Keys\n\n### 1. Prerequisites\n\n- Configure AWS credentials in n8n with appropriate IAM permissions  \n- Create an `Extract_Key_Info` node that provides the compromised key's ID and username  \n\n### 2. Workflow Integration\n\n- Add this node after your key detection logic  \n- Connect it to trigger when a compromised key is confirmed  \n\n### 3. Security Considerations\n\n- Ensure your AWS credentials have the `iam:UpdateAccessKey` permission  \n- Consider adding verification steps before automatic disabling  \n- Implement notification steps after key disabling (e.g., Slack, email)  \n\n---\n\nThis implementation enables **immediate remediation of security risks** by automatically disabling compromised AWS access keys as soon as they're discovered in GitHub repositories.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d96b586a-4739-4ef5-84c8-c71ff9f3e1e6",
  "connections": {
    "158340f1-4dc4-4b4c-933f-95a28be524dc": {
      "main": [
        [
          {
            "node": "f2634090-b035-4592-ad56-b970c2bff14c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "714724b6-9aaf-4d17-97b7-1a3fd3dcaeae": {
      "main": [
        [
          {
            "node": "a1448a68-81aa-4571-8f62-617c57daa6e6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ef29b02b-f2a4-4642-a5c4-c9685b0e2c22": {
      "main": [
        [
          {
            "node": "8f9db031-245e-4c00-bdb9-4ed55e9b57b2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "f2634090-b035-4592-ad56-b970c2bff14c": {
      "main": [
        [
          {
            "node": "b2c1157f-c1eb-4d22-95d0-6ec166a93a4a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c0300832-418b-4fa8-98b6-2b799f2bcfe6": {
      "main": [
        [
          {
            "node": "158340f1-4dc4-4b4c-933f-95a28be524dc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ae5a0e4f-892c-4a75-bdcc-36253fbc7274": {
      "main": [
        [
          {
            "node": "0946f05d-11f0-480b-934a-c996bbb9551e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a1448a68-81aa-4571-8f62-617c57daa6e6": {
      "main": [
        [
          {
            "node": "b2c1157f-c1eb-4d22-95d0-6ec166a93a4a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3ed685c7-27b5-4a00-840a-6f9dddff6d3f": {
      "main": [
        [
          {
            "node": "ef29b02b-f2a4-4642-a5c4-c9685b0e2c22",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0946f05d-11f0-480b-934a-c996bbb9551e": {
      "main": [
        [
          {
            "node": "3ed685c7-27b5-4a00-840a-6f9dddff6d3f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a6cd482c-86d2-49ac-aefe-6beec92c98af": {
      "main": [
        [
          {
            "node": "75ed15ec-fdee-4644-a83c-6b47005dcac1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "57753be8-33d2-4172-94a2-0d5a4f7c73ec": {
      "main": [
        [
          {
            "node": "c0300832-418b-4fa8-98b6-2b799f2bcfe6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "75ed15ec-fdee-4644-a83c-6b47005dcac1": {
      "main": [
        [
          {
            "node": "57753be8-33d2-4172-94a2-0d5a4f7c73ec",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b2c1157f-c1eb-4d22-95d0-6ec166a93a4a": {
      "main": [
        [],
        [
          {
            "node": "ae5a0e4f-892c-4a75-bdcc-36253fbc7274",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8f9db031-245e-4c00-bdb9-4ed55e9b57b2": {
      "main": [
        [
          {
            "node": "a6cd482c-86d2-49ac-aefe-6beec92c98af",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "84edf6c4-fc87-4b34-86c6-ad72c15cafe8": {
      "main": [
        [
          {
            "node": "714724b6-9aaf-4d17-97b7-1a3fd3dcaeae",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Avanzado - Operaciones de seguridad

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Avanzado
Número de nodos18
Categoría1
Tipos de nodos9
Descripción de la dificultad

Adecuado para usuarios avanzados, flujos de trabajo complejos con 16+ nodos

Autor
Niranjan G

Niranjan G

@niranjan

Cybersecurity leader turning complex workflows into seamless, AI-driven automations.

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34