{ "name": "Tenable IO Discovery", "vendor_identifier": "Tenable IO", "comment": "Tenable IO Discovery management", "version": "5.0", "type": "REST_EVENT", "event_type": [ "DISCOVERY_DATA" ], "content_type": "application/json", "quoting": "XMLA", "headers": { "X-apikeys": "accessKey=${S:A:accessKey};secretKey=${S:A:secretKey}", "vendor": "Infoblox", "product": "Infoblox_Outbound_Notification", "build": "1.0.2" }, "instance_variables": [{ "name": "Add_Discovery_Data", "type": "STRING", "value": "true" }, { "name": "Scan_Discovery_Data", "type": "STRING", "value": "true" }, { "name": "Discovery_Asset_Sync", "type": "STRING", "value": "true" }, { "name": "Discovery_Scan_Template", "type": "STRING", "value": "Infoblox_Scan" }, { "name": "Discovery_Target_Group", "type": "STRING", "value": "TargetGroup_Test" } ], "steps": [{ "name": "DebugStart", "operation": "NOP", "body": "${XC:DEBUG:{H:}}${XC:DEBUG:{E:}}${XC:DEBUG:{I:}}${XC:DEBUG:{L:}}${XC:DEBUG:{S:}}${XC:DEBUG:{P:}}${XC:DEBUG:{R:}}${XC:DEBUG:{RH:}}${XC:DEBUG:{UT:}}" }, { "name": "checkOperation", "comment": "Check operation_type. DISCOVERY works with both MODIFY and INSERT.", "operation": "CONDITION", "condition": { "condition_type": "OR", "statements": [{ "left": "${E:A:operation_type}", "op": "==", "right": "MODIFY" }, { "left": "${E:A:operation_type}", "op": "==", "right": "INSERT" } ], "else_stop": true } }, { "name": "checkEventTypeDiscovery", "comment": "Check for DISCOVERY_DATA event_type, EAs and set locals.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:event_type}", "op": "==", "right": "DISCOVERY_DATA" }], "eval": "${XC:COPY:{L:ThisIP}:{E:values{ip_address}}}${XC:COPY:{L:TargetEntry}:{E:values{ip_address}}}", "else_stop": true } }, { "name": "checkIPv6", "comment": "Check for IPv6 address.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${L:A:ThisIP}", "op": "=~", "right": ":" }], "eval": "${XC:ASSIGN:{L:IPvTypeForAssets}:{S:ipv6}}", "else_eval": "${XC:ASSIGN:{L:IPvTypeForAssets}:{S:ipv4}}" } }, { "name": "setDiscoveryName", "comment": "If a DISCOVERY event has a discovered_name we can use it as a netbios_name for asset adding. Many discovered devices are named 'unknown', which causes unexpected results in Tenable.io since the netbios_name is a primary key. If the name is unknown, we do not know the name anyway, so don't use it.", "operation": "CONDITION", "condition": { "condition_type": "OR", "statements": [{ "left": "${E:A:values{discovered_name}}", "op": "==", "right": "unknown" }, { "left": "${E:A:values{discovered_name}}", "op": "==", "right": "" } ], "eval": "${XC:ASSIGN:{L:netbios_name}:{S:}}", "else_eval": "${XC:COPY:{L:netbios_name}:{E:values{discovered_name}}}" } }, { "name": "setDiscoveryOSWithos", "comment": "If a DISCOVERY event has an os we can use it as an OS for asset adding.", "operation": "CONDITION", "condition": { "condition_type": "OR", "statements": [{ "left": "${E:A:values{os}}", "op": "==", "right": "" }, { "left": "${E:A:values{os}}", "op": "==", "right": "None" }, { "left": "${E:A:values{os}}", "op": "==", "right": "unknown" } ], "else_eval": "${XC:COPY:{L:operating_system}:{E:values{os}}}", "else_next": "setDiscoveryMAC" } }, { "name": "setDiscoveryOSWithdevice_type", "comment": "If a DISCOVERY event has a device_type we can use it as an OS for asset adding.", "operation": "CONDITION", "condition": { "condition_type": "OR", "statements": [{ "left": "${E:A:values{device_type}}", "op": "==", "right": "" }, { "left": "${E:A:values{device_type}}", "op": "==", "right": "None" } ], "else_eval": "${XC:COPY:{L:operating_system}:{E:values{device_type}}}", "else_next": "setDiscoveryMAC" } }, { "name": "setDiscoveryOSWithdevice_model", "comment": "If a DISCOVERY event has a device_model we can use it as an OS for asset adding.", "operation": "CONDITION", "condition": { "condition_type": "OR", "statements": [{ "left": "${E:A:values{device_model}}", "op": "==", "right": "" }, { "left": "${E:A:values{device_model}}", "op": "==", "right": "None" }, { "left": "${E:A:values{device_model}}", "op": "==", "right": "unknown" } ], "eval": "${XC:ASSIGN:{L:operating_system}:{S:}}", "else_eval": "${XC:COPY:{L:operating_system}:{E:values{device_model}}}" } }, { "name": "setDiscoveryMAC", "comment": "If a DISCOVERY event has a mac_address we can use it as a MAC for asset adding.", "operation": "CONDITION", "condition": { "condition_type": "OR", "statements": [{ "left": "${E:A:values{mac_address}}", "op": "==", "right": "None" }, { "left": "${E:A:values{mac_address}}", "op": "==", "right": "" } ], "eval": "${XC:ASSIGN:{L:mac_address}:{S:}}", "else_eval": "${XC:COPY:{L:mac_address}:{E:values{mac_address}}}" } }, { "name": "setDiscoverySource", "comment": "If a DISCOVERY event has a discoverer we can use it as a source scan for asset adding.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:values{discoverer}}", "op": "==", "right": "" }], "eval": "${XC:ASSIGN:{L:source}:{S:}}", "else_eval": "${XC:COPY:{L:source}:{E:values{discoverer}}}" } }, { "name": "verifyAddToTargetGroupEA", "comment": "Verify Add_Discovery_Data is true. Otherwise we can't add it to the Target Group nor scan it.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${I:A:Add_Discovery_Data}", "op": "==", "right": "true" }], "else_next": "verifyEAsforAddingAsset", "eval": "${XC:COPY:{L:TenableIO_TargetGroup}:{I:Discovery_Target_Group}}" } }, { "name": "getTargetGroups", "comment": "Get all Target Groups.", "operation": "GET", "parse": "JSON", "transport": { "path": "target-groups" } }, { "name": "setLocalTargetGroupList", "comment": "Set list of target_groups to a local.", "operation": "NOP", "body": "${XC:COPY:{L:TargetGroups}:{P:target_groups}" }, { "name": "isEmptyTargetGroupList", "comment": "[START TARGET GROUP LOOP] Check if we are out of target groups to check.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${L:L:TargetGroups}", "op": "==", "right": "0" }], "stop": true } }, { "name": "getNextTargetGroup", "comment": "[TARGET GROUP LOOP] Pop top of TargetGroups.", "operation": "VARIABLEOP", "variable_ops": [{ "operation": "POP", "type": "DICTIONARY", "destination": "L:ThisTargetGroup", "source": "L:TargetGroups" }] }, { "name": "verifyCorrectTargetGroup", "comment": "[TARGET GROUP LOOP] Verify the current Target Group matches the EA.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${L:A:TenableIO_TargetGroup}", "op": "==", "right": "${L:A:ThisTargetGroup{name}}" }], "eval": "${XC:COPY:{L:TargetID}:{L:ThisTargetGroup{id}}", "next": "checkExistingTarget" } }, { "name": "loopBackForNextTargetGroup", "comment": "[END TARGET GROUP LOOP] Loop back to check if list is empty.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "0", "op": "==", "right": "0" }], "next": "isEmptyTargetGroupList" } }, { "name": "checkExistingTarget", "comment": "Verify the target doesn't already exist in the Targets list. If it does, no need to add a duplicate.", "operation": "CONDITION", "condition": { "condition_type": "OR", "statements": [{ "left": "${L:A:ThisTargetGroup{members}}", "op": "=~", "right": "${L:A:TargetEntry}" }], "next": "verifyEAsforScanning" } }, { "name": "updateTargetList", "comment": "Add item to list of Targets.", "operation": "PUT", "parse": "JSON", "transport": { "path": "target-groups/${L:A:TargetID}" }, "body_list": [ "{", "\"members\": \"${L:A:ThisTargetGroup{members}} ,${L:A:TargetEntry}\"}" ] }, { "name": "verifyEAsforScanning", "comment": "Verify correct EAs to scan item.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${I:A:Scan_Discovery_Data}", "op": "==", "right": "true" }, { "left": "${I:A:Discovery_Scan_Template}", "op": "!=", "right": "" } ], "eval": "${XC:COPY:{L:TenableIO_ScanTemplate}:{I:Discovery_Scan_Template}}", "else_next": "verifyEAsforAddingAsset" } }, { "name": "getScans", "comment": "Get list of all scans.", "operation": "GET", "parse": "JSON", "transport": { "path": "scans" } }, { "name": "setLocalScansList", "comment": "Set list of scans to a local.", "operation": "NOP", "body": "${XC:COPY:{L:Scans}:{P:scans}" }, { "name": "isEmptyScanList", "comment": "[START SCAN LOOP] Check if we are out of scans to check.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${L:L:Scans}", "op": "==", "right": "0" }], "stop": true } }, { "name": "getNextScan", "comment": "[SCAN LOOP] Pop top of Scans.", "operation": "VARIABLEOP", "variable_ops": [{ "operation": "POP", "type": "DICTIONARY", "destination": "L:ThisScan", "source": "L:Scans" }] }, { "name": "verifyCorrectScan", "comment": "[END SCAN LOOP] Verify the current Scan matches the EA.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${L:A:TenableIO_ScanTemplate}", "op": "!=", "right": "${L:A:ThisScan{name}}" }], "next": "isEmptyScanList", "else_eval": "${XC:COPY:{L:Scan_ID}:{L:ThisScan{id}}" } }, { "name": "copyScan", "comment": "Create copy of scan.", "operation": "POST", "parse": "JSON", "transport": { "path": "scans/${L:A:Scan_ID}/copy" } }, { "name": "configureCopiedScan", "comment": "Add some data for scan.", "operation": "PUT", "parse": "JSON", "transport": { "path": "scans/${P:A:id}/" }, "body_list": [ "{", "\"scan_id\":\"${P:A:id}\",", "\"settings\":{", "\"name\":\"Infoblox Scan for ${L:A:TargetEntry} on ${UT:A:TIME}\",", "\"description\": \"Scan occured because of a ${E:A:event_type} event\",", "\"enabled\":\"false\",", "\"text_targets\":\"${L:A:TargetEntry}\"", "}", "}" ] }, { "name": "launchCopyScan", "comment": "Launch scan.", "operation": "POST", "parse": "JSON", "transport": { "path": "scans/${P:A:id}/launch" } }, { "name": "verifyEAsforAddingAsset", "comment": "Verify EAs for adding asset.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${I:A:Discovery_Asset_Sync}", "op": "==", "right": "true" }], "else_stop": true } }, { "name": "addAsset", "comment": "Add asset.", "operation": "POST", "parse": "JSON", "transport": { "path": "import/assets?accessKey=${S:A:accessKey}&secretKey=${S:A:secretKey}" }, "body_list": ["{", "\"assets\": [{\"${L:A:IPvTypeForAssets}\": [\"${L:A:ThisIP}\"], \"mac_address\": [\"${L:A:mac_address}\"],\"netbios_name\": \"${L:A:netbios_name}\",\"operating_system\": [\"${L:A:operating_system}\"]}], \"source\": \"${L:A:source}\"", "}" ] }, { "name": "haltTemplate", "comment": "Halt template.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "1", "op": "==", "right": "1" }], "stop": true } } ] }