Flux de travaux du protocole d'API REST IBM Security Randori

Vous pouvez personnaliser votre flux de travaux et vos paramètres de flux de travaux en fonction du flux de travaux par défaut.

Un flux de travaux est un document XML qui décrit le processus de récupération d'événements. Le flux de travaux définit un ou plusieurs paramètres, auxquels des valeurs peuvent être explicitement affectées dans le XML du flux de travaux ou qui peuvent dériver des valeurs du document XML des valeurs des paramètres de flux de travaux. Le flux de travaux se compose de plusieurs actions qui s'exécutent de manière séquentielle.

Les fichiers XML du flux de travaux par défaut et des paramètres de flux de travaux sont disponibles sur GitHub. Pour plus d'informations, voir IBM Security Randori® (https://github.com/IBM/IBM-QRadar-Universal-Cloud-REST-API/tree/master/IBM%20Verified/IBM%20Security%20Randori).

Flux de travaux par défaut Randori

L'exemple suivant illustre le flux de travaux Randori par défaut:

<?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>

Paramètres de flux de travaux par défaut de Randori

L'exemple suivant illustre les paramètres de flux de travaux Randori par défaut:

<?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>