{ "name": "Tenable IO Lease", "vendor_identifier": "Tenable IO", "comment": "Tenable IO Lease management", "version": "5.0", "type": "REST_EVENT", "event_type": [ "LEASE" ], "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" }, "steps": [{ "name": "Debug0", "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": "checkEventLease", "comment": "Check for LEASE event type.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E::event_type}", "op": "=~", "right": "LEASE" }], "else_stop": true } }, { "name": "checkIPv6AddressLease", "comment": "Check if LEASE address is an IPv6.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:address}", "op": "=~", "right": ":" }], "eval": "${XC:ASSIGN:{L:IPvTypeForAssets}:{S:ipv6}}${XC:ASSIGN:{L:IPvTypeForRef}:{S:ipv6address}}${XC:ASSIGN:{L:mac_address}:{S:}}", "else_eval": "${XC:ASSIGN:{L:IPvTypeForAssets}:{S:ipv4}}${XC:ASSIGN:{L:IPvTypeForRef}:{S:ipv4address}}${XC:COPY:{L:mac_address}:{E:hardware}}" } }, { "name": "checkLeaseState", "comment": "Check binding state of LEASE for ACTIVE (insertion). All other LEASE states are not supported.", "operation": "CONDITION", "condition": { "condition_type": "OR", "statements": [{ "left": "${E::binding_state}", "op": "==", "right": "ACTIVE" }], "else_stop": true } }, { "name": "verifyLeaseIPEAs", "comment": "Verify EAs for the IP the LEASE is leased to. If they are both empty, it is assumed the IP does not exist in Infoblox.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:ip.extattrs{TNBL_IO_Target_Group}}", "op": "==", "right": "" }, { "left": "${E:A:ip.extattrs{TNBL_IO_Scan_Template}}", "op": "==", "right": "" } ], "next": "verifyLeaseNetworkEAs", "else_eval": "${XC:COPY:{L:TNBL_IO_Scan_Template}:{E:ip.extattrs{TNBL_IO_Scan_Template}}}${XC:COPY:{L:TNBL_IO_Target_Group}:{E:ip.extattrs{TNBL_IO_Target_Group}}}${XC:COPY:{L:Temp_Value}:{E:address}}${XC:COPY:{L:ThisIP}:{E:address}}${XC:COPY:{L:TargetEntry}:{E:address}}${XC:ASSIGN:{L:source}:{S:NIOS}}" } }, { "name": "getIPData", "comment": "Get asset data of the IP so we can use its _ref for EA updating.", "operation": "GET", "wapi": "v2.7", "transport": { "path": "${L:A:IPvTypeForRef}?ip_address=${L:A:ThisIP}" } }, { "name": "setObj_refLease", "comment": "If an object in Infoblox uses this IP, update its TNBL_IO_Last_Scan EA if it is empty. Set the first object in objects to Obj_ref to use with EA updating.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${P:A:PARSE[0]{objects}[0]}", "op": "==", "right": "" }], "else_next": "checkEASourceTargetSync", "else_eval": "${XC:COPY:{L:Obj_ref}:{P:PARSE[0]{objects}[0]}}" } }, { "name": "verifyLeaseNetworkEAs", "comment": "Verify EAs for the network of the IP the LEASE is leased to. We need to grab the Target Group and Scan Template from somewhere, and we cannot grab them from an asset that does not exist in Infoblox. So, try the parent network.", "operation": "CONDITION", "condition": { "condition_type": "OR", "statements": [{ "left": "${E:A:network.extattrs{TNBL_IO_Target_Group}}", "op": "==", "right": "" }, { "left": "${E:A:network.extattrs{TNBL_IO_Scan_Template}}", "op": "==", "right": "" } ], "stop": true, "else_eval": "${XC:ASSIGN:{L:Obj_ref}:{S:}}${XC:ASSIGN:{L:EASource}:{S:network}}${XC:COPY:{L:TNBL_IO_Scan_Template}:{E:network.extattrs{TNBL_IO_Scan_Template}}}${XC:COPY:{L:TNBL_IO_Target_Group}:{E:network.extattrs{TNBL_IO_Target_Group}}}${XC:COPY:{L:Temp_Value}:{E:address}}${XC:COPY:{L:ThisIP}:{E:address}}${XC:COPY:{L:TargetEntry}:{E:address}}${XC:ASSIGN:{L:source}:{S:NIOS}}" } }, { "name": "checkEASourceTargetSync", "comment": "[TARGET SYNC CHECK] Check source of the EAs.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${L:A:EASource}", "op": "==", "right": "network" }], "next": "checkNetworkTargetSync" } }, { "name": "checkIPTargetSync", "comment": "[TARGET SYNC CHECK] Verify IP EAs for adding target to the Target Group.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:ip.extattrs{TNBL_IO_Sync}}", "op": "==", "right": "true" }], "next": "getTargetGroups", "else_next": "checkEASourceAssetSync" } }, { "name": "checkNetworkTargetSync", "comment": "[TARGET SYNC CHECK] Verify network EAs for adding target to the Target Group.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:network.extattrs{TNBL_IO_Sync}}", "op": "==", "right": "true" }], "else_next": "checkEASourceAssetSync" } }, { "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:TNBL_IO_Target_Group}", "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": "checkEASourceScanning" } }, { "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": "checkEASourceScanning", "comment": "[TARGET SCAN CHECK] Check source of the EAs.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${L:A:EASource}", "op": "==", "right": "network" }], "next": "checkNetworkScanning" } }, { "name": "checkIPScanning", "comment": "[TARGET SCAN CHECK] Verify IP EAs for scanning target.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:ip.extattrs{TNBL_IO_Scan_On_Add}}", "op": "==", "right": "true" }], "next": "getScans", "else_next": "checkEASourceAssetSync" } }, { "name": "checkNetworkScanning", "comment": "[TARGET SCAN CHECK] Verify network EAs for scanning target.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:network.extattrs{TNBL_IO_Scan_On_Add}}", "op": "==", "right": "true" }], "else_next": "checkEASourceAssetSync" } }, { "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:TNBL_IO_Scan_Template}", "op": "!=", "right": "${L:A:ThisScan{name}}" }], "next": "isEmptyScanList", "else_eval": "${XC:COPY:{L:Scan_ID}:{L:ThisScan{id}}", "else_next": "copyScan" } }, { "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}\"", "}", "}" ], "result": [{ "codes": "200,201,202,203,204", "next": "launchCopyScan" }] }, { "name": "launchCopyScan", "comment": "Launch scan.", "operation": "POST", "parse": "JSON", "transport": { "path": "scans/${P:A:id}/launch" } }, { "name": "isEmptyObj_ref", "comment": "If the object_ref is empty (nonexistent IP) we cannot update its timestamp.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${L:A:Obj_ref}", "op": "==", "right": "" }], "next": "checkEASourceAssetSync" } }, { "name": "updateLastScanTimestamp", "comment": "Use the Obj_ref local as the path to update the TNBL_IO_Last_Scan EA of added object when syncing.", "operation": "PUT", "transport": { "path": "${L:A:Obj_ref}" }, "wapi": "v2.7", "wapi_quoting": "JSON", "body_list": [ "{\"extattrs+\":{\"TNBL_IO_Last_Scan\": { \"value\": \"${E:A:timestamp}\"}}}" ] }, { "name": "checkEASourceAssetSync", "comment": "[SYNC ASSET CHECK] Check source of the EAs.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${L:A:EASource}", "op": "==", "right": "network" }], "next": "checkNetworkAssetSync" } }, { "name": "checkIPAssetSync", "comment": "[SYNC ASSET CHECK] Verify IP EAs for syncing asset.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:ip.extattrs{TNBL_IO_Asset_Sync}}", "op": "==", "right": "true" }], "next": "addAsset" } }, { "name": "checkNetworkAssetSync", "comment": "[SYNC ASSET CHECK] Verify network EAs for syncing asset.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:network.extattrs{TNBL_IO_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:ThisIP}\"}], \"source\": \"${L:A:source}\"", "}" ] }, { "name": "isEmptyLeaseTimestamp", "comment": "Only when the TNBL_IO_Sync_Time EA is empty and the Obj_ref is not empty should we update its timestamp.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "${E:A:ip.extattrs{TNBL_IO_Sync_Time}}", "op": "==", "right": "" }, { "left": "${L:A:Obj_ref}", "op": "!=", "right": "" } ], "else_stop": true } }, { "name": "updateAddAssetTimestamp", "comment": "Use the Obj_ref local as the path to update the TNBL_IO_Sync_Time EA of added asset when syncing.", "operation": "PUT", "wapi": "v2.7", "wapi_quoting": "JSON", "transport": { "path": "${L:A:Obj_ref}" }, "body_list": [ "{\"extattrs+\":{\"TNBL_IO_Sync_Time\":{\"value\":\"${E:A:timestamp}\"}}}" ] }, { "name": "haltTemplate", "comment": "Halt template.", "operation": "CONDITION", "condition": { "condition_type": "AND", "statements": [{ "left": "1", "op": "==", "right": "1" }], "stop": true } } ] }