Skip to content

Commit

Permalink
Merge pull request #170 from SumoLogic/mvirga-sumo-patch-6
Browse files Browse the repository at this point in the history
Add Build Signal Output Raw Break Lines (email)
  • Loading branch information
wjakelee authored Sep 19, 2024
2 parents f404417 + b8d4eff commit 7056ae7
Showing 1 changed file with 224 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
integration: 'Automation Tools'
name: 'Build Signal Output Raw Break Lines (email)'
type: Custom
script:
code: |
import json
import sys
import argparse
import traceback
from datetime import datetime
import pytz
import os
import re
def determine_and_format_timestamp(timestamp):
formats = [
"%Y-%m-%dT%H:%M:%S%z",
"%d/%m/%Y %H:%M:%S",
"%Y %b %d %H:%M:%S.%f %Z",
"%b %d %H:%M:%S %Z %Y",
"%d/%b/%Y:%H:%M:%S %Z",
"%b %d, %Y %I:%M:%S %p",
"%b %d %Y %H:%M:%S",
"%b %d %H:%M:%S %Y",
"%b %d %H:%M:%S %Z",
"%b %d %H:%M:%S",
"%Y-%m-%dT%H:%M:%S%z",
"%Y-%m-%dT%H:%M:%SZ",
"%Y-%m-%d %H:%M:%S %Z",
"%Y-%m-%d %H:%M:%S%z",
"%Y-%m-%d %H:%M:%S,%f",
"%Y/%m/%d*H:%M:%S",
"%Y %b %d %H:%M:%S.%f*%Z",
"%Y %b %d %H:%M:%S.%f",
"%Y-%m-%d %H:%M:%S,%f%Z",
"%Y-%m-%d %H:%M:%S.%f",
"%Y-%m-%dT%H:%M:%S.%f",
"%Y-%m-%dT%H:%M:%S",
"%Y-%m-%dT%H:%M:%SZ",
"%Y-%m-%dT%H:%M:%S.%f",
"%Y-%m-%dT%H:%M:%S",
"%Y-%m-%d*H:%M:%S:%f",
"%Y-%m-%d*H:%M:%S",
"%y-%m-%d %H:%M:%S,%f %Z",
"%y-%m-%d %H:%M:%S,%f",
"%y-%m-%d %H:%M:%S %Z",
"%y-%m-%d %H:%M:%S",
"%y/%m/%d %H:%M:%S",
"%y%m%d %H:%M:%S",
"%Y%m%d %H:%M:%S.%f",
"%m/%d/%y*H:%M:%S",
"%m/%d/%Y*H:%M:%S",
"%m/%d/%Y*H:%M:%S*%f",
"%m/%d/%y %H:%M:%S %Z",
"%m/%d/%Y %H:%M:%S %Z",
"%H:%M:%S",
"%H:%M:%S.%f",
"%H:%M:%S,%f",
"%d/%b %H:%M:%S,%f",
"%d/%b/%Y:%H:%M:%S,%f",
"%d/%b/%Y %H:%M:%S",
"%d-%b-%Y %H:%M:%S",
"%d %b %Y %H:%M:%S",
"%d %b %Y %H:%M:%S.%f",
"%m%d_%H:%M:%S",
"%m%d_%H:%M:%S.%f",
"%m/%d/%Y %I:%M:%S %p"
]
for date_format in formats:
try:
# Try parsing the timestamp with the current format
dt_object = datetime.strptime(timestamp, date_format)
# Return the formatted timestamp and format type if successful
return dt_object.strftime(date_format), date_format
except ValueError:
pass
# If none of the formats match, raise an exception or return a default value
raise ValueError("Invalid timestamp format")
def sanitize_json(json_string):
# Replace single quotes with double quotes
json_string = json_string.replace("'", "\'")
return json_string
def format_signals(signal,output_timezone,exclude_fields,include_fields):
aggregate_list = []
excludes_list = exclude_fields
includes_list=include_fields
# Initialize aggregate list
aggregate_list = []
# Extract relevant information
name = signal['name']
signal_time = signal['timestamp']
entity_name = signal['entity']['name']
#summary = signal['description']
rule_id = signal['ruleId']
stage = signal['stage']
additional_fields = ""
for record in signal['allRecords'][0]:
if excludes_list or not includes_list:
if signal['allRecords'][0][record] != {} and signal['allRecords'][0][record] != [] and record != "fields" and record not in excludes_list:
newField= signal['allRecords'][0][record]
if type(newField) == str:
newField= newField.replace('\\"', "'")
newField= newField.replace('"', "'")
newField= newField.replace('\\', '\\\\')
additional_fields += f"<br/>{str(record)}: {newField}"
elif includes_list:
if signal['allRecords'][0][record] != {} and signal['allRecords'][0][record] != [] and record != "fields" and record in includes_list:
newField= signal['allRecords'][0][record]
if type(newField) == str:
newField= newField.replace('\\"', "'")
newField= newField.replace('"', "'")
newField= newField.replace('\\', '\\\\')
additional_fields += f"<br/>{str(record)}: {newField}"
#formatTime
formatted_timestamp, timestamp_format = determine_and_format_timestamp(signal_time)
if "%z" not in timestamp_format and "%Z" not in timestamp_format:
formatted_timestamp = formatted_timestamp+"+0000"
timestamp_format = timestamp_format+"%z"
signal_time = datetime.strptime(formatted_timestamp, timestamp_format)
signal_time = signal_time.astimezone(pytz.timezone(output_timezone))
# Format output as a map and add to the aggregate list
formatted_map = {"signaldata": f"<br/><b>Signal time:</b> {signal_time}<br/><b>Name:</b> {name}<br/><b>Rule ID:</b> {rule_id}<br/><b>Stage:</b> {stage}<br/><b>Entity Name:</b> {entity_name}{additional_fields}<br/>"}
#formatted_map = {"signaldata": f"\\nSignal time: {signal_time}\\nSignal Name: {name}\\nRule: {rule_name}\\nStage: {stage}\\nEntity Name: {entity_name}{additional_fields}\\n"}
return formatted_map
class EnvDefault(argparse.Action):
def __init__(self, required=False, default=None, **kwargs):
envvar = kwargs.get("dest")
default = os.environ.get(envvar, default) if envvar in os.environ else default
required = False if required and default else required
super(EnvDefault, self).__init__(default=default, required=required, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, values)
try:
json_dict = []
parser = argparse.ArgumentParser()
parser.add_argument('--input_str', help='JSON', required=True, action=EnvDefault)
parser.add_argument('--output_timezone', help='valid TZ identifiers', required=False, action=EnvDefault)
parser.add_argument('--exclude_fields', help='Fields to Exlude from output', required=False, action=EnvDefault)
parser.add_argument('--include_fields', help='Fields to Exlude from output', required=False, action=EnvDefault)
args, unknown = parser.parse_known_args()
input_str = args.input_str
try:
with open(input_str) as json_file:
json_data = json.load(json_file)
if isinstance(json_data, dict):
enrichment_json = json_data.get("message", json_data)
else:
enrichment_json = json_data
except Exception as __:
enrichment_json = json.loads(str(input_str).strip(), strict=False)
output_timezone = args.output_timezone
#exclude_fields = args.exclude_fields
if args.exclude_fields is not None:
exclude_fields = list(args.exclude_fields.split(","))
else:
exclude_fields = []
if args.include_fields is not None:
include_fields = list(args.include_fields.split(","))
else:
include_fields = []
if not output_timezone:
output_timezone="UTC"
# Example usage with JSON input string
# sanitized_input = sanitize_json(input_str)
# recorddata = json.loads(sanitized_input)
for signal in enrichment_json['signals']:
format_signal = format_signals(signal,output_timezone,exclude_fields,include_fields)
json_dict.append(format_signal)
combined_signaldata = "".join(signals['signaldata'] for signals in json_dict)
# Convert the dictionary to JSON format using json.dumps()
wrapped_json = {
"signals": [combined_signaldata]
}
print(json.dumps(wrapped_json))
exit(0)
except ValueError as e:
err = str(e)
sys.stderr.write(str(e))
exit(-1)
fields:
- id: input_str
label: 'String Input'
incident_artifacts: true
type: text
required: true
hint: 'Accepts valid string input and returns escaped string in JSON format.'
- id: output_timezone
label: 'Display Time of Timezone Output'
type: text
required: false
hint: 'Accepts valid TZ identifiers: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones'
- id: exclude_fields
label: 'Fields to Exclude from output'
type: tag
required: false
- id: include_fields
label: 'Fields to include from output'
type: tag
required: false
hint: 'Exclude fields take precedence over include fields.'

output:
- path: 'input_string'
type: text
- path: 'signals'
type: text

0 comments on commit 7056ae7

Please sign in to comment.