Creating a custom action
Overview
In Building a Custom Integration, you created a Ping Action for the Armis integration. In this tutorial, you will create an Action for the Armis integration that enriches entities. Knowledge of Python and object oriented programming is necessary for this tutorial. The SDK documentation and the Building a Custom Integration tutorial will be referenced frequently. Additionally, exploring the SDK modules themselves is highly recommended.
Creating a custom action
In the left navigation, navigate to Response > IDE. The IDE page is displayed.
Click Create New Item and select Action. Enter a name and select the integration. Click Create.
The IDE will create a new template that has some very useful code comments and explanations. Make sure to give this template a look over when possible.
The Siemplify Action Object
There are two things that must happen in a Siemplify Action. An object must be instantiated from the
SiemplifyAction
class and the object must utilize the class's
end
method to return an output message and a result value.
The Result Value
Every Action will have an Output Name that will represent the result value of what the Siemplify Action returns in its end method. The Default Output Name is
is_success
but it can be changed to anything from the IDE.
Additionally a Default Return Value can be set if the Action were to fail. For example, if the Action in the screenshot above were to time out after 5 minutes (or fail for any other reason), the ScriptResult would be set to the string 'Timeout'.
JSON Result Value
Arguably more important than the actual result value, is the JSON result that can be added via the Action. The JSON result is NOT mandatory, but it is extremely useful for pivoting on data within playbooks, or even for eyes on "manual" investigative analysis. The JSON result can be added via the SiemplifyAction result property's
add_result_json
method or via the
add_entity_json
method to attach a JSON result to the entity (not as useful but still covered
here).
Imports and Constants
The SiemplifyAction class from the SiemplifyAction module will always be imported. The specific methods imported from SiemplifyUtils are not mandatory
but output_handler is very useful for debugging and
add_prefix_to_dict_keys
and
convert_dict_to_json_result_dict
will be utilized for data transformation. The EntityTypes class helps determine what type of entity the Action will run on. The ArmisManager was
created in the Building a Custom Integration How To and it will be reused for the Armis API logic. The json library is also imported and a couple of
constants are set.
The Action Logic
This particular Action only has a main function that will be executed. In line 14 the
siemplify
object is instantiated from the SiemplifyAction class. The API Root and the API Token are imported from the Google Security Operations Marketplace Configuration for this
integration; this should look familiar from the Building a Custom Integration tutorial. In lines 26-27, an empty dictionary and an empty list are created
for use later. A default result value is also set to the string 'true' in line 28.
In line 31, an object is instantiated from the
ArmisManager
class. In lines 32-33, you iterate through the entities that exist in the Alert that this Action is running on.
Notice that in line 33, every entity has an entity_type property and it can be compared to the properties from the EntityTypes class. In this case, the
entity will only be passed to the Manager's
get_device_by_ip
method if it's an IP Address (which is what the ADDRESS property represents). This prevents the Action from using useless cycles on Entities that will return errors from the Armis API endpoint. In line 34 notice that you are passing the entity identifier property. The identifier property is simply a string representation of the Entity, so an Entity object for the IP Address of 192.168.1.2 would have an identifier of '192.168.1.2'.
In line 36, you utilize the empty dict that you created earlier by setting the key to the entity identifier and the value to the result returned by the Armis
API endpoint. In line 37, the identifier is appended to the empty list created earlier. In line 38, the
add_entity_json
method is used to create a JSON result for the entity. This method takes a mandatory two parameters: the identifier and the result in JSON format. In
line 40, a new empty dict is instantiated for the properties to be used for enrichment. In lines 41-52, the result from Armis is parsed and added to this
dict. In line 53, the dict is transformed by adding a string prefix of 'armis' to the keys. This is done to provide clarity in the
application for what integration provided what enrichment properties within the entity.
In lines 54-56, the entity is updated with the new enrichment properties. Notice in line 55 that the entity object is enriched, not the entity identifier. Also notice that it's in a list because this method expects a list of objects as input.
In lines 66-69, the output message is set based on whether there are any enriched entities in the list that was created earlier.
Line 72 may be the most important line of code in the Action. Here the
add_result_json
method is used to add an additional result to the Action. The
convert_dict_to_json_result_dict
method that was imported earlier is used to transform the json_results dictionary where the identifier is set as the key and the value is the results.
Line 73 ends the action with the output message and the result value. Lines 75 and 76 are mandatory for the Action to run.
Putting it all together in the application
Running this Action on an Alert with an Entity Identifier of 192.168.1.41 enriches the Entity with several new properties. Notice the 'armis' prefix on the properties that were added via this Enrichment Action. The values that correspond to the properties are censored in this screenshot.
You can also look at the Action on the case wall. The Output Message and Entity JSON results are on the Results tab:
The Technical Details tab has the Script Result (the result value) and the JSON results. Again they are censored here.