Flusso di lavoro del protocollo API REST IBM Security Randori
È possibile personalizzare i parametri del workflow e del flusso di lavoro in base al workflow predefinito.
Un workflow è un documento XML che descrive il processo di richiamo eventi. Il flusso di lavoro definisce uno o più parametri, che possono essere esplicitamente assegnati valori nel flusso di lavoro XML o possono derivare valori dal documento XML dei valori dei parametri del flusso di lavoro. Il flusso di lavoro è costituito da più azioni che vengono eseguite in sequenza.
Il flusso di lavoro predefinito e i file XML dei parametri del flusso di lavoro sono disponibili su GitHub. Per ulteriori informazioni, consultare IBM Security Randori® (https://github.com/IBM/IBM-QRadar-Universal-Cloud-REST-API/tree/master/IBM%20Verified/IBM%20Security%20Randori).
Randori flusso di lavoro predefinito
Il seguente esempio mostra il workflow Randori predefinito:
<?xml version="1.0" encoding="UTF-8" ?>
<Workflow name="IBMSecurityRandoriRestAPI" version="1.0" xmlns="http://qradar.ibm.com/UniversalCloudRESTAPI/Workflow/V2">
<Parameters>
<Parameter name="instance" label="Instance" required="true" />
<Parameter name="apiKey" label="API Key" secret="true" required="true" />
<Parameter name="minimumPriority" label="Minimum Priority" required="true" />
<Parameter name="minimumTemptation" label="Minimum Temptation" required="true" />
<Parameter name="initialDaysOfHistoricalData" label="Initial Days of Historical Data" required="true" default="1"/>
</Parameters>
<Actions>
<Initialize path="/randoriDetections/detections/status_code" value="200"/> <!-- Sets the initial status to 200. Once we get a value from the API, if the value is not 200 we will sleep an additional 20 seconds. This prevents the protocol test event retriever from running multiple times on failures. -->
<If condition="${/randoriDetections/detections/status_code} != 200">
<!-- __________________________ Setting an internal sleep to slow down the protocol test. Also applies in the main code, but only applies when the status code is in a bad state.________________________ -->
<Sleep duration="20000" />
</If>
<!-- _________________________ Clears the status and sets the workflow to running _________________________ -->
<ClearStatus />
<SetStatus type="INFO" message="Workflow has started." />
<!-- __________________________Initialization Code_________________________ -->
<Initialize path="/randoriDetections/startTimeFirstSeenUnixTime" value="${time() - (60000 * 60 * 24 * ${/initialDaysOfHistoricalData})}"/> <!-- days previous to initialize -->
<Initialize path="/randoriDetections/startTimeTemptationLastModifiedUnixTime" value="${time() - (60000 * 60 * 24 * ${/initialDaysOfHistoricalData})}"/> <!-- days previous to initialize -->
<Initialize path="/randoriDetections/limit" value="2000"/> <!-- How many we pullback at once, maximum of 2000 per request -->
<!-- __________________________Set the query bounds based off time values _________________________ -->
<Set path="/randoriDetections/detectionOffset" value="0"/>
<Set path="/randoriDetections/startTimeFirstSeenUnixTime" value="${/randoriDetections/startTimeFirstSeenUnixTime}"/>
<Set path="/randoriDetections/startTimeTemptationLastModifiedUnixTime" value="${/randoriDetections/startTimeTemptationLastModifiedUnixTime}"/>
<!-- __________________________Creates the formatted date for both temptation and first seen in ISO-8601 format _________________________ -->
<FormatDate pattern="yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX" savePath="/randoriDetections/startTimeFirstSeen" time="${/randoriDetections/startTimeFirstSeenUnixTime}"/>
<FormatDate pattern="yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX" savePath="/randoriDetections/startTimeTemptationLastModified" time="${/randoriDetections/startTimeTemptationLastModifiedUnixTime}"/>
<FormatDate pattern="yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX" savePath="/randoriDetections/endtime" time="${/randoriDetections/endtimeMilli}"/>
<!-- _________________________ Sets the query that will be used for API Calls _________________________ -->
<Set path="/randoriDetections/query" value='{"condition":"AND","rules":[{"field":"table.authority","operator":"equal","value":"True"},{"field":"table.affiliation_state","operator":"equal","value":"None"},{"condition":"OR","rules":[{"condition":"AND","rules":[{"ui_id":"target_first_seen","id":"table.target_first_seen","field":"table.target_first_seen","type":"datetime","input":"text","randoriOnly":false,"label":"after","operator":"greater","value":"${/randoriDetections/startTimeFirstSeen}"},{"ui_id":"target_first_seen","id":"table.target_first_seen","field":"table.target_first_seen","type":"datetime","input":"text","randoriOnly":false,"label":"before","operator":"less_or_equal","value":"${/randoriDetections/endtime}"},{"field":"table.priority_score","operator":"greater_or_equal","value":${/minimumPriority}}]},{"condition":"AND","rules":[{"field":"table.temptation_last_modified","id":"table.temptation_last_modified","input":"text","type":"datetime","ui_id":"temptation_last_modified","randoriOnly":false,"label":"after","operator":"greater","value":"${/randoriDetections/startTimeTemptationLastModified}"},{"field":"table.temptation_last_modified","id":"table.temptation_last_modified","input":"text","type":"datetime","ui_id":"temptation_last_modified","randoriOnly":false,"label":"before","operator":"less_or_equal","value":"${/randoriDetections/endtime}"},{"field":"table.target_temptation","operator":"greater_or_equal","value":${/minimumTemptation}}]}]}]}'/>
<!-- _________________________ Stores the Tracked Newest Time in a separate variable. This is updated and used only once the doWhile ends. _________________________ -->
<Set path="/randoriDetections/startTimeFirstSeenUnixTimeTemp" value="${/randoriDetections/startTimeFirstSeenUnixTime}"/>
<Set path="/randoriDetections/startTimeTemptationLastModifiedUnixTimeTemp" value="${/randoriDetections/startTimeTemptationLastModifiedUnixTime}"/>
<!--Note the following : We do not have a way to check this at the moment, but the data can change between calls. Shouldn't happen, but if it does there should be minimal risk. -->
<!-- _________________________ Request events and loop if the event count = the offset limit. _________________________ -->
<DoWhile condition="${/randoriDetections/detections/body/count} = ${/randoriDetections/limit}">
<CallEndpoint url="https://${/instance}/recon/api/v1/all-detections-for-target" method="GET" savePath="/randoriDetections/detections">
<BearerAuthentication token="${/apiKey}" />
<QueryParameter name="limit" value="${/randoriDetections/limit}" />
<QueryParameter name="offset" value="${/randoriDetections/detectionOffset}"/>
<QueryParameter name="sort" value="id" />
<!-- The query must be in base64 encoding. -->
<QueryParameter name="q" value="${base64_encode(/randoriDetections/query)}" />
<RequestHeader name="Accept" value="application/json" />
<RequestHeader name="Content-Type" value="application/json" />
</CallEndpoint>
<!-- _________________________ Catch any status code other than 200 (success). Note 502's for this protocol are throttle issues. _________________________ -->
<If condition="${/randoriDetections/detections/status_code} != 200">
<If condition="${/randoriDetections/detections/status_code} = 502">
<Log type="ERROR" message="A 502 exception indicates the API throttle limit was hit." />
</If>
<Log type="ERROR" message="${/randoriDetections/detections/status_code}: ${/randoriDetections/detections/status_message}" />
<Abort reason="${/randoriDetections/detections/status_code}: ${/randoriDetections/detections/status_message}" />
</If>
<Else>
<SetStatus type="INFO" message="Successfully Queried for events."/>
</Else>
<!-- _________________________ Post Events _________________________ -->
<PostEvents path="/randoriDetections/detections/body/data" source="${/instance}" />
<Log type="INFO" message="We received a total of ${count(/randoriDetections/detections/body/data)} detections." />
<!-- _________________________ Update the last event time. Checks each event for the time. _________________________ -->
<ForEach items="/randoriDetections/detections/body/data" item="/randoriDetections/individualEventData">
<!-- _________________________ Formats the events first seen and temptation values into usuable unix timestamps _________________________ -->
<ParseDate pattern="yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX" date="${/randoriDetections/individualEventData/target_first_seen}" savePath="/randoriDetections/tempfirstseen" />
<ParseDate pattern="yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX" date="${/randoriDetections/individualEventData/temptation_last_modified}" savePath="/randoriDetections/temptemptationlastmodified" />
<!-- _________________________ Checks the doWhile loops tracked temp value against each events time stamp to get the newest time value for temptation and first seen. _________________________ -->
<If condition="/randoriDetections/tempfirstseen > /randoriDetections/startTimeFirstSeenUnixTimeTemp">
<Set path="/randoriDetections/startTimeFirstSeenUnixTimeTemp" value="${/randoriDetections/tempfirstseen}"/>
</If>
<If condition="/randoriDetections/temptemptationlastmodified > /randoriDetections/startTimeTemptationLastModifiedUnixTimeTemp">
<Set path="/randoriDetections/startTimeTemptationLastModifiedUnixTimeTemp" value="${/randoriDetections/temptemptationlastmodified}"/>
</If>
</ForEach>
<!-- _________________________ Set new offset value for next query. _________________________ -->
<Set path="/randoriDetections/detectionOffset" value="${/randoriDetections/detectionOffset + count(/randoriDetections/detections/body/data)}"/>
<Log type="INFO" message="New offset to use: ${/randoriDetections/detectionOffset}" />
</DoWhile>
<!-- _________________________ Updates the tracked unix time with the value obtained through the doWhile to only get new data from the next call._________________________ -->
<Set path="/randoriDetections/startTimeFirstSeenUnixTime" value="${/randoriDetections/startTimeFirstSeenUnixTimeTemp}"/>
<Set path="/randoriDetections/startTimeTemptationLastModifiedUnixTime" value="${/randoriDetections/startTimeTemptationLastModifiedUnixTimeTemp}"/>
<Log type="INFO" message="Completed receiving all of the detections for the current time period." />
<!-- No need to increment as the end time is excluded from the query-->
</Actions>
<Tests>
<DNSResolutionTest host="${/instance}"/>
<TCPConnectionTest host="${/instance}"/>
<SSLHandshakeTest host="${/instance}"/>
<HTTPConnectionThroughProxyTest url ="${/instance}"/>
</Tests>
</Workflow>
Parametri predefiniti del flusso di lavoro Randori
Il seguente esempio mostra i parametri del flusso di lavoro Randori predefiniti:
<?xml version="1.0" encoding="UTF-8" ?>
<WorkflowParameterValues xmlns="http://qradar.ibm.com/UniversalCloudRESTAPI/WorkflowParameterValues/V2">
<Value name="instance" value=""/>
<Value name="apiKey" value=""/>
<Value name="minimumPriority" value=""/>
<Value name="minimumTemptation" value=""/>
<Value name="initialDaysOfHistoricalData" value=""/>
</WorkflowParameterValues>