mirror of
https://github.com/splunk/security_content
synced 2026-06-08 17:32:49 +00:00
3b58b30516
Adding custom functions & playbooks
92 lines
5.1 KiB
Python
92 lines
5.1 KiB
Python
def datetime_modify(input_datetime=None, input_format_string=None, modification_unit=None, amount_to_modify=None, output_format_string=None, **kwargs):
|
|
"""
|
|
Change a timestamp by adding or subtracting minutes, hours, or days.
|
|
|
|
Args:
|
|
input_datetime: The datetime to modify, which should be provided in a string format determined by input_format_string
|
|
input_format_string: The format string to use for the input according to the Python's datetime.strptime() formatting rules. If none is provided the default will be '%Y-%m-%dT%H:%M:%S.%fZ'. In addition to strptime() formats, the special format "epoch" can be used to accept unix epoch timestamps.
|
|
modification_unit: Choose a unit to modify the date by, which must be either seconds, minutes, hours, or days. If none is provided the default will be 'minutes'
|
|
amount_to_modify: The number of seconds, minutes, hours, or days to add or subtract. Use a negative number such as -1.5 to subtract time. Defaults to zero.
|
|
output_format_string: The format string to use for the output according to the Python's datetime.strftime() formatting rules. If none is provided the default will be '%Y-%m-%dT%H:%M:%S.%fZ'.
|
|
|
|
Returns a JSON-serializable object that implements the configured data paths:
|
|
datetime_string: The output datetime as formatted by the given output_format_string using Python's datetime.strftime()
|
|
epoch_time: An integer representing the output time as a number of seconds since January 1 1970 assuming a naive UTC timezone. This is easier to use for comparisons to other epoch timestamps.
|
|
seconds_modified: The number of seconds (positive or negative) by which the input was modified
|
|
"""
|
|
############################ Custom Code Goes Below This Line #################################
|
|
import json
|
|
import phantom.rules as phantom
|
|
import datetime
|
|
|
|
outputs = {}
|
|
|
|
# set the input format string to the phantom default if none is provided
|
|
if not input_format_string:
|
|
input_format_string = "%Y-%m-%dT%H:%M:%S.%fZ"
|
|
|
|
# set the date to the default, which is the current time if none is provided
|
|
if not input_datetime:
|
|
input_datetime = datetime.datetime.now().strftime(input_format_string)
|
|
|
|
# use the phantom default as the output format string if none is provided
|
|
if not output_format_string:
|
|
output_format_string = "%Y-%m-%dT%H:%M:%S.%fZ"
|
|
|
|
if input_format_string.lower() == 'epoch':
|
|
parsed_input = datetime.datetime.utcfromtimestamp(int(input_datetime))
|
|
else:
|
|
parsed_input = datetime.datetime.strptime(input_datetime, input_format_string)
|
|
phantom.debug("parsed the input datetime as: {}".format(parsed_input))
|
|
|
|
# validate the modification_unit parameter, which must be a unit of time
|
|
if modification_unit == None:
|
|
modification_unit = 'minutes'
|
|
if modification_unit not in ['seconds', 'minutes', 'hours', 'days']:
|
|
raise ValueError('invalid modification_unit. must be either seconds, minutes, hours, or days.')
|
|
|
|
# amount_to_modify defaults to zero
|
|
if not amount_to_modify:
|
|
amount_to_modify = 0
|
|
|
|
# validate that amount_to_modify is an int or float (booleans will work as 0 or 1, but should not be used)
|
|
if not isinstance(amount_to_modify, int) and not isinstance(amount_to_modify, float):
|
|
raise ValueError('invalid amount_to_modify. must be an int or float')
|
|
|
|
# convert all time units to seconds
|
|
conversions = {
|
|
"seconds": 1,
|
|
"minutes": 60,
|
|
"hours": 60*60,
|
|
"days": 60*60*24
|
|
}
|
|
conversion_multiplier = conversions.get(modification_unit, None)
|
|
if not conversion_multiplier:
|
|
raise KeyError("failed to convert modification_unit to seconds")
|
|
|
|
seconds_to_modify = amount_to_modify * conversion_multiplier
|
|
if seconds_to_modify < 0:
|
|
phantom.debug("subtracting {} {} which is {} seconds".format(amount_to_modify * -1, modification_unit, seconds_to_modify * -1))
|
|
else:
|
|
phantom.debug("adding {} {} which is {} seconds".format(amount_to_modify, modification_unit, seconds_to_modify))
|
|
|
|
outputs['seconds_modified'] = seconds_to_modify
|
|
seconds_to_modify = datetime.timedelta(seconds=seconds_to_modify)
|
|
|
|
# do the actual modification
|
|
phantom.debug("adding {} plus {}".format(parsed_input, seconds_to_modify))
|
|
result_time = parsed_input + seconds_to_modify
|
|
phantom.debug("the unformatted result is: {}".format(result_time))
|
|
|
|
# use the provided output_format_string to turn the output into a string
|
|
string_output = result_time.strftime(output_format_string)
|
|
phantom.debug("the formatted result is: {}".format(string_output))
|
|
outputs['datetime_string'] = string_output
|
|
|
|
# also return an epoch time (seconds since Jan 1 1970) which assumes the input is a naive UTC datetime for time zone purposes
|
|
epoch_time = (result_time - datetime.datetime.utcfromtimestamp(0)).total_seconds()
|
|
outputs['epoch_time'] = epoch_time
|
|
|
|
# Return a JSON-serializable object
|
|
assert json.dumps(outputs) # Will raise an exception if the :outputs: object is not JSON-serializable
|
|
return outputs |