From 8a99fb60480d275562bdfc9ec3cccfd8a50a0233 Mon Sep 17 00:00:00 2001 From: frikky Date: Tue, 22 Dec 2020 11:41:11 +0100 Subject: [PATCH] FIXES: Added wazuh integration and loads more --- backend/app_sdk/app_base.py | 51 ++++-- backend/app_sdk/build.sh | 2 +- backend/go-app/docker.go | 1 + backend/go-app/main.go | 14 +- backend/go-app/walkoff.go | 6 +- docker-compose.yml | 4 +- frontend/src/views/Admin.jsx | 28 +++ frontend/src/views/AngularWorkflow.jsx | 40 ++++- frontend/src/views/Apps.jsx | 4 + frontend/src/views/LoginPage.jsx | 5 +- functions/extensions/wazuh/custom-shuffle | 36 ++++ functions/extensions/wazuh/custom-shuffle.py | 177 +++++++++++++++++++ functions/extensions/wazuh/ossec.conf | 4 +- functions/extensions/wazuh/requirements.txt | 1 - functions/extensions/wazuh/shuffle.py | 44 ----- functions/onprem/orborus/build.sh | 2 +- functions/onprem/orborus/orborus.go | 7 +- 17 files changed, 333 insertions(+), 93 deletions(-) create mode 100644 functions/extensions/wazuh/custom-shuffle create mode 100644 functions/extensions/wazuh/custom-shuffle.py delete mode 100644 functions/extensions/wazuh/requirements.txt delete mode 100644 functions/extensions/wazuh/shuffle.py diff --git a/backend/app_sdk/app_base.py b/backend/app_sdk/app_base.py index fd78155f..e226eefd 100644 --- a/backend/app_sdk/app_base.py +++ b/backend/app_sdk/app_base.py @@ -606,11 +606,14 @@ class AppBase: if "len" in thistype or "length" in thistype or "lenght" in thistype: tmp = "" try: - tmpdata = data.replace("\'", "\"") tmp = json.loads(tmpdata) except: - print("Passing bug") - pass + try: + tmpdata = data.replace("\'", "\"") + tmp = json.loads(tmpdata) + except: + print("[ERROR] Parsing bug for length in app sdk") + pass if isinstance(tmp, list): return len(tmp) @@ -649,14 +652,14 @@ class AppBase: return tmp except IndexError as e: return default_error - + # Parses the INNER value and recurses until everything is done def parse_wrapper(data): try: if "(" not in data or ")" not in data: - return data + return (data, False) except TypeError: - return data + return (data, False) #print("Running %s" % data) @@ -671,7 +674,7 @@ class AppBase: break if not found: - return data + return (data, False) # Do stuff here. innervalue = parse_nested_param(data, maxDepth(data)-0) @@ -692,10 +695,11 @@ class AppBase: parsed_value = parse_type(innervalue[0], thistype.lower()) print("Parsed value from %s: %s" % (thistype, parsed_value)) - return parsed_value + return (parsed_value, True) print("DATA: %s\n" % data) - return parse_wrapper(data) + return (parse_wrapper(data)[0], True) + # Looks for parantheses to grab special cases within a string, e.g: # int(1) lower(HELLO) or length(what's the length) @@ -737,15 +741,20 @@ class AppBase: if len(newstring) > 0: newdata.append(newstring) - print("Newdata: ", newdata) parsedlist = [] non_string = False + parsed = False for item in newdata: ret = parse_wrapper(item) - if not isinstance(ret, str): + if not isinstance(ret[0], str): non_string = True - - parsedlist.append(ret) + + parsedlist.append(ret[0]) + if ret[1]: + parsed = True + + if not parsed: + return data if len(parsedlist) > 0 and not non_string: print("Returning parsed list: ", parsedlist) @@ -949,7 +958,6 @@ class AppBase: if len(parsersplit) == 1: return str(baseresult)+str(appendresult), False - baseresult = baseresult.replace("\'", "\"") baseresult = baseresult.replace(" True,", " true,") baseresult = baseresult.replace(" False", " false,") @@ -958,8 +966,12 @@ class AppBase: try: basejson = json.loads(baseresult) except json.decoder.JSONDecodeError as e: - print("Parser issue with JSON: %s" % e) - return str(baseresult)+str(appendresult), False + try: + baseresult = baseresult.replace("\'", "\"") + basejson = json.loads(baseresult) + except json.decoder.JSONDecodeError as e: + print("Parser issue with JSON: %s" % e) + return str(baseresult)+str(appendresult), False print("After fourth parser return as JSON") @@ -1365,14 +1377,17 @@ class AppBase: if replacement.startswith("\"") and replacement.endswith("\""): replacement = replacement[1:len(replacement)-1] - replacement = replacement.replace("\'", "\"", -1) print("POST replacement: %s" % replacement) json_replacement = replacement try: json_replacement = json.loads(replacement) except json.decoder.JSONDecodeError as e: - print("JSON error singular: %s" % e) + try: + replacement = replacement.replace("\'", "\"", -1) + json_replacement = json.loads(replacement) + except: + print("JSON error singular: %s" % e) if len(json_replacement) > minlength: minlength = len(json_replacement) diff --git a/backend/app_sdk/build.sh b/backend/app_sdk/build.sh index fe988a1c..f96da989 100644 --- a/backend/app_sdk/build.sh +++ b/backend/app_sdk/build.sh @@ -1,6 +1,6 @@ #!/bin/bash NAME=shuffle-app_sdk -VERSION=0.8.32 +VERSION=0.8.4 docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force docker build . -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION diff --git a/backend/go-app/docker.go b/backend/go-app/docker.go index 3d48871c..03720e3b 100644 --- a/backend/go-app/docker.go +++ b/backend/go-app/docker.go @@ -230,6 +230,7 @@ func buildImageMemory(fs billy.Filesystem, tags []string, dockerfileFolder strin } // Build the actual image + log.Printf("Building %s. This may take up to a few minutes.", dockerfileFolder) imageBuildResponse, err := client.ImageBuild( ctx, dockerFileTarReader, diff --git a/backend/go-app/main.go b/backend/go-app/main.go index b29e9fcf..263e0872 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -2483,7 +2483,7 @@ func handleLogin(resp http.ResponseWriter, request *http.Request) { if len(users) != 1 { log.Printf(`Found multiple or no users with the same username: %s: %d`, data.Username, len(users)) resp.WriteHeader(401) - resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Found %d users with the same username: %s"}`, len(users), data.Username))) + resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error: %d users with username %s"}`, len(users), data.Username))) return } @@ -4785,7 +4785,7 @@ func getDocList(resp http.ResponseWriter, request *http.Request) { if len(item1) == 0 { resp.WriteHeader(500) - resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "No docs available."`))) + resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "No docs available."}`))) return } @@ -4844,7 +4844,7 @@ func getDocs(resp http.ResponseWriter, request *http.Request) { location := strings.Split(request.URL.String(), "/") if len(location) != 5 { resp.WriteHeader(404) - resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Bad path. Use e.g. /api/v1/docs/workflows.md"`))) + resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Bad path. Use e.g. /api/v1/docs/workflows.md"}`))) return } @@ -4868,7 +4868,7 @@ func getDocs(resp http.ResponseWriter, request *http.Request) { ) if err != nil { - resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Bad path. Use e.g. /api/v1/docs/workflows.md"`))) + resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Bad path. Use e.g. /api/v1/docs/workflows.md"}`))) resp.WriteHeader(404) //setBadMemcache(ctx, docPath) return @@ -4877,7 +4877,7 @@ func getDocs(resp http.ResponseWriter, request *http.Request) { newresp, err := client.Do(req) if err != nil { resp.WriteHeader(404) - resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Bad path. Use e.g. /api/v1/docs/workflows.md"`))) + resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Bad path. Use e.g. /api/v1/docs/workflows.md"}`))) //setBadMemcache(ctx, docPath) return } @@ -4885,7 +4885,7 @@ func getDocs(resp http.ResponseWriter, request *http.Request) { body, err := ioutil.ReadAll(newresp.Body) if err != nil { resp.WriteHeader(500) - resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Can't parse data"`))) + resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Can't parse data"}`))) //setBadMemcache(ctx, docPath) return } @@ -5958,7 +5958,7 @@ func echoOpenapiData(resp http.ResponseWriter, request *http.Request) { if err != nil { log.Printf("[ERROR] URLbody error: %s", err) resp.WriteHeader(500) - resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Can't get data from selected uri"`))) + resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Can't get data from selected uri"}`))) return } diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index 448d677c..d2d99d56 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -4015,7 +4015,7 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) { log.Printf("ID: %s", fileId) app, err := getApp(ctx, fileId) if err != nil { - log.Printf("Error getting app %s: %s", app.Name, err) + log.Printf("Error getting app (delete) %s: %s", fileId, err) resp.WriteHeader(401) resp.Write([]byte(`{"success": false}`)) return @@ -4169,7 +4169,7 @@ func getWorkflowAppConfig(resp http.ResponseWriter, request *http.Request) { ctx := context.Background() app, err := getApp(ctx, fileId) if err != nil { - log.Printf("Error getting app: %s", app.Name) + log.Printf("Error getting app (app config): %s", fileId) resp.WriteHeader(401) resp.Write([]byte(`{"success": false}`)) return @@ -4438,7 +4438,7 @@ func updateWorkflowAppConfig(resp http.ResponseWriter, request *http.Request) { ctx := context.Background() app, err := getApp(ctx, fileId) if err != nil { - log.Printf("Error getting app: %s (update app)", app.Name) + log.Printf("Error getting app (update app): %s", fileId) resp.WriteHeader(401) resp.Write([]byte(`{"success": false}`)) return diff --git a/docker-compose.yml b/docker-compose.yml index a39b58c7..7a356dff 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: frontend: #build: ./frontend - image: ghcr.io/frikky/shuffle-frontend:0.8.4 + image: ghcr.io/frikky/shuffle-frontend:0.8.42 container_name: shuffle-frontend hostname: shuffle-frontend ports: @@ -45,7 +45,7 @@ services: - database orborus: #build: ./functions/onprem/orborus - image: ghcr.io/frikky/shuffle-orborus:0.8.31 + image: ghcr.io/frikky/shuffle-orborus:0.8.32 container_name: shuffle-orborus hostname: shuffle-orborus networks: diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index e50a5a0c..b809cf62 100644 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -470,6 +470,33 @@ const Admin = (props) => { }) } + const flushQueue = (name) => { + // Just use this one? + const url = globalUrl + '/api/v1/flush_queue'; + fetch(url, { + method: 'DELETE', + credentials: "include", + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(response => + response.json().then(responseJson => { + if (responseJson["success"] === false) { + alert.error(responseJson.reason) + getEnvironments() + } else { + setLoginInfo("") + setModalOpen(false) + getEnvironments() + } + }), + ) + .catch(error => { + console.log("Error when deleting: ", error) + }) + } + const deleteEnvironment = (name) => { // FIXME - add some check here ROFL alert.info("Deleting environment " + name) @@ -2094,6 +2121,7 @@ const Admin = (props) => { style={{minWidth: 150, maxWidth: 150, overflow: "hidden"}} > + {/**/} { const cloudSyncEnabled = props.userdata !== undefined && props.userdata.active_org !== null && props.userdata.active_org !== undefined ? props.userdata.active_org.cloud_sync === true : false //const triggerEnvironments = cloudSyncEnabled ? ["cloud", "onprem"] : environments const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" - const triggerEnvironments = isCloud ? ["cloud"] : ["cloud", "onprem"] + const triggerEnvironments = isCloud ? ["cloud"] : ["onprem", "cloud"] const unloadText = 'Are you sure you want to leave without saving (CTRL+S)?' useBeforeunload(() => { @@ -2663,7 +2663,6 @@ const AngularWorkflow = (props) => { foundResult.result = foundResult.result.split(" None").join(" \"None\"") foundResult.result = foundResult.result.split(" False").join(" false") foundResult.result = foundResult.result.split(" True").join(" true") - foundResult.result = foundResult.result.split("\'").join("\"") var jsonvalid = true try { @@ -2672,7 +2671,15 @@ const AngularWorkflow = (props) => { jsonvalid = false } } catch (e) { - jsonvalid = false + try { + foundResult.result = foundResult.result.split("\'").join("\"") + const tmp = String(JSON.parse(foundResult.result)) + if (!foundResult.result.includes("{") && !foundResult.result.includes("[")) { + jsonvalid = false + } + } catch (e) { + jsonvalid = false + } } // Finds the FIRST json only @@ -5874,7 +5881,6 @@ const AngularWorkflow = (props) => { const parsedExecutionArgument = () => { var showResult = executionData.execution_argument.trim() showResult = showResult.split(" None").join(" \"None\"") - showResult = showResult.split("\'").join("\"") showResult = showResult.split(" False").join(" false") showResult = showResult.split(" True").join(" true") @@ -5885,7 +5891,16 @@ const AngularWorkflow = (props) => { jsonvalid = false } } catch (e) { - jsonvalid = false + showResult = showResult.split("\'").join("\"") + + try { + const tmp = String(JSON.parse(showResult)) + if (!showResult.includes("{") && !showResult.includes("[")) { + jsonvalid = false + } + } catch (e) { + jsonvalid = false + } } if (jsonvalid) { @@ -6070,21 +6085,28 @@ const AngularWorkflow = (props) => { // // FIXME: The latter replace doens't really work if ' is used in a string var showResult = data.result.trim() + //console.log(showResult) showResult = showResult.split(" None").join(" \"None\"") showResult = showResult.split(" False").join(" false") showResult = showResult.split(" True").join(" true") - showResult = showResult.split("\'").join("\"") var jsonvalid = true try { const tmp = String(JSON.parse(showResult)) if (!showResult.includes("{") && !showResult.includes("[")) { - //console.log("IN HERE: ", tmp) jsonvalid = false } } catch (e) { - //console.log("Error: ", e) - jsonvalid = false + showResult = showResult.split("\'").join("\"") + + try { + const tmp = String(JSON.parse(showResult)) + if (!showResult.includes("{") && !showResult.includes("[")) { + jsonvalid = false + } + } catch (e) { + jsonvalid = false + } } const curapp = apps.find(a => a.name === data.action.app_name && a.app_version === data.action.app_version) diff --git a/frontend/src/views/Apps.jsx b/frontend/src/views/Apps.jsx index dadbe288..c081f94f 100644 --- a/frontend/src/views/Apps.jsx +++ b/frontend/src/views/Apps.jsx @@ -46,6 +46,10 @@ const inputColor = "#383B40" export const GetParsedPaths = (inputdata, basekey) => { const splitkey = " > " var parsedValues = [] + if (inputdata === undefined || inputdata === null) { + return parsedValues + } + if (typeof(inputdata) !== "object") { return parsedValues } diff --git a/frontend/src/views/LoginPage.jsx b/frontend/src/views/LoginPage.jsx index 5f9e49f2..b365336f 100644 --- a/frontend/src/views/LoginPage.jsx +++ b/frontend/src/views/LoginPage.jsx @@ -69,7 +69,7 @@ const LoginDialog = props => { }), ) .catch(error => { - setLoginInfo("Error in userdata: ", error) + setLoginInfo("Error logging in: ", error) }) } @@ -80,6 +80,7 @@ const LoginDialog = props => { const onSubmit = (e) => { e.preventDefault() + setLoginInfo("") // FIXME - add some check here ROFL // Just use this one? @@ -114,7 +115,7 @@ const LoginDialog = props => { }), ) .catch(error => { - setLoginInfo("Error in userdata: " + error) + setLoginInfo("Error logging in: " + error) }); } else { url = baseurl + '/api/v1/users/register'; diff --git a/functions/extensions/wazuh/custom-shuffle b/functions/extensions/wazuh/custom-shuffle new file mode 100644 index 00000000..bd540414 --- /dev/null +++ b/functions/extensions/wazuh/custom-shuffle @@ -0,0 +1,36 @@ +#!/bin/sh +# Created by Shuffle, AS. . + +WPYTHON_BIN="framework/python/bin/python3" + +SCRIPT_PATH_NAME="$0" + +DIR_NAME="$(cd $(dirname ${SCRIPT_PATH_NAME}); pwd -P)" +SCRIPT_NAME="$(basename ${SCRIPT_PATH_NAME})" + +case ${DIR_NAME} in + */active-response/bin | */wodles*) + if [ -z "${WAZUH_PATH}" ]; then + WAZUH_PATH="$(cd ${DIR_NAME}/../..; pwd)" + fi + + PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py" + ;; + */bin) + if [ -z "${WAZUH_PATH}" ]; then + WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)" + fi + + PYTHON_SCRIPT="${WAZUH_PATH}/framework/scripts/${SCRIPT_NAME}.py" + ;; + */integrations) + if [ -z "${WAZUH_PATH}" ]; then + WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)" + fi + + PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py" + ;; +esac + + +${WAZUH_PATH}/${WPYTHON_BIN} ${PYTHON_SCRIPT} "$@" diff --git a/functions/extensions/wazuh/custom-shuffle.py b/functions/extensions/wazuh/custom-shuffle.py new file mode 100644 index 00000000..06fa4c7d --- /dev/null +++ b/functions/extensions/wazuh/custom-shuffle.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python +# Created by Shuffle, AS. . +# Based on the Slack integration using Webhooks + +import json +import sys +import time +import os + +try: + import requests + from requests.auth import HTTPBasicAuth +except Exception as e: + print("No module 'requests' found. Install: pip install requests") + sys.exit(1) + +# ADD THIS TO ossec.conf configuration: +# +# custom-shuffle +# http://:3001/api/v1/hooks/ +# 3 +# json +# + +# Global vars + +debug_enabled = False +pwd = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) +json_alert = {} +now = time.strftime("%a %b %d %H:%M:%S %Z %Y") + +# Set paths +log_file = '{0}/logs/integrations.log'.format(pwd) + + +def main(args): + debug("# Starting") + + # Read args + alert_file_location = args[1] + webhook = args[3] + + debug("# Webhook") + debug(webhook) + + debug("# File location") + debug(alert_file_location) + + # Load alert. Parse JSON object. + with open(alert_file_location) as alert_file: + json_alert = json.load(alert_file) + debug("# Processing alert") + debug(json_alert) + + debug("# Generating message") + msg = generate_msg(json_alert) + if isinstance(msg, str): + if len(msg) == 0: + return + debug(msg) + + debug("# Sending message") + send_msg(msg, webhook) + + +def debug(msg): + if debug_enabled: + msg = "{0}: {1}\n".format(now, msg) + print(msg) + f = open(log_file, "a") + f.write(msg) + f.close() + +# Skips container kills to stop self-recursion +def filter_msg(alert): + # These are things that recursively happen because Shuffle starts Docker containers + # Docker integration rules: https://github.com/wazuh/wazuh-ruleset/blob/ae36745db1d3f312db0392f5925c2f2b0ec009a9/rules/0560-docker_integration_rules.xml + skip = ["87924", "87900", "87901", "87902", "87903", "87904", "86001", "86002", "86003", "87932", "80710", "87929", "87928",] + if alert["rule"]["id"] in skip: + return False + + #try: + # if "docker" in alert["rule"]["description"].lower() and " + #msg['text'] = alert.get('full_log') + #except: + # pass + #msg['title'] = alert['rule']['description'] if 'description' in alert['rule'] else "N/A" + + return True + +def generate_msg(alert): + if not filter_msg(alert): + print("Skipping rule %s" % alert["rule"]["id"]) + return "" + + level = alert['rule']['level'] + + if (level <= 4): + color = "good" + elif (level >= 5 and level <= 7): + color = "warning" + else: + color = "danger" + + msg = {} + msg['color'] = color + msg['pretext'] = "WAZUH Alert" + msg['title'] = alert['rule']['description'] if 'description' in alert['rule'] else "N/A" + msg['text'] = alert.get('full_log') + msg['rule_id'] = alert["rule"]["id"] + msg['timestamp'] = alert["timestamp"] + msg['id'] = alert['id'] + msg["all_fields"] = alert + + #msg['fields'] = [] + # msg['fields'].append({ + # "title": "Agent", + # "value": "({0}) - {1}".format( + # alert['agent']['id'], + # alert['agent']['name'] + # ), + # }) + #if 'agentless' in alert: + # msg['fields'].append({ + # "title": "Agentless Host", + # "value": alert['agentless']['host'], + # }) + + #msg['fields'].append({"title": "Location", "value": alert['location']}) + #msg['fields'].append({ + # "title": "Rule ID", + # "value": "{0} _(Level {1})_".format(alert['rule']['id'], level), + #}) + + #attach = {'attachments': [msg]} + + return json.dumps(msg) + + +def send_msg(msg, url): + headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'} + res = requests.post(url, data=msg, headers=headers) + debug(res) + + +if __name__ == "__main__": + try: + # Read arguments + bad_arguments = False + if len(sys.argv) >= 4: + msg = '{0} {1} {2} {3} {4}'.format( + now, + sys.argv[1], + sys.argv[2], + sys.argv[3], + sys.argv[4] if len(sys.argv) > 4 else '', + ) + debug_enabled = (len(sys.argv) > 4 and sys.argv[4] == 'debug') + else: + msg = '{0} Wrong arguments'.format(now) + bad_arguments = True + + # Logging the call + f = open(log_file, 'a') + f.write(msg + '\n') + f.close() + + if bad_arguments: + debug("# Exiting: Bad arguments.") + sys.exit(1) + + # Main function + main(sys.argv) + + except Exception as e: + debug(str(e)) + raise diff --git a/functions/extensions/wazuh/ossec.conf b/functions/extensions/wazuh/ossec.conf index dfaf0394..5b55f5d3 100644 --- a/functions/extensions/wazuh/ossec.conf +++ b/functions/extensions/wazuh/ossec.conf @@ -1,7 +1,5 @@ - Shuffle + custom-shuffle http://:3001/api/v1/hooks/webhook_ - 2 - multiple_drops|authentication_failures json diff --git a/functions/extensions/wazuh/requirements.txt b/functions/extensions/wazuh/requirements.txt deleted file mode 100644 index f2293605..00000000 --- a/functions/extensions/wazuh/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -requests diff --git a/functions/extensions/wazuh/shuffle.py b/functions/extensions/wazuh/shuffle.py deleted file mode 100644 index 306d3715..00000000 --- a/functions/extensions/wazuh/shuffle.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python - -# Based on -# https://wazuh.com/blog/how-to-integrate-external-software-using-integrator/ - -import sys -import json -import requests -from requests.auth import HTTPBasicAuth - -# Set the project attributes -project_alias = 'TI' -issue_name ='FIM' - -# Read configuration parameters -alert_file = open(sys.argv[1]) -user = sys.argv[2].split(':')[0] -api_key = sys.argv[2].split(':')[1] -hook_url = sys.argv[3] - -# Read the alert file -alert_json = json.loads(alert_file.read()) -alert_file.close() - -# Extract issue fields -alert_level = alert_json['rule']['level'] -description = alert_json['rule']['description'] -path = alert_json['syscheck']['path'] - -# Generate request -msg_data = {} -msg_data['fields'] = {} -msg_data['fields']['project'] = {} -msg_data['fields']['project']['key'] = project_alias -msg_data['fields']['summary'] = 'FIM alert on [' + path + ']' -msg_data['fields']['description'] = '- State: ' + description + '\n- Alert level: ' + str(alert_level) -msg_data['fields']['issuetype'] = {} -msg_data['fields']['issuetype']['name'] = issue_name -headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'} - -# Send the request -requests.post(hook_url, data=json.dumps(msg_data), headers=headers, auth=(user, api_key)) - -sys.exit(0) diff --git a/functions/onprem/orborus/build.sh b/functions/onprem/orborus/build.sh index a580aefc..57fe63a2 100644 --- a/functions/onprem/orborus/build.sh +++ b/functions/onprem/orborus/build.sh @@ -1,5 +1,5 @@ NAME=shuffle-orborus -VERSION=0.8.31 +VERSION=0.8.32 echo "Running docker build with $NAME:$VERSION" #docker rmi frikky/shuffle:$NAME --force diff --git a/functions/onprem/orborus/orborus.go b/functions/onprem/orborus/orborus.go index 8e5cf442..06a938ff 100644 --- a/functions/onprem/orborus/orborus.go +++ b/functions/onprem/orborus/orborus.go @@ -562,6 +562,7 @@ func zombiecheck(workerTimeout int) error { stopContainers := []string{} removeContainers := []string{} + log.Printf("Workertimeout: %d", int64(workerTimeout)) for _, container := range containers { // Skip random containers. Only handle things related to Shuffle. if !strings.Contains(container.Image, baseimagename) { @@ -587,10 +588,10 @@ func zombiecheck(workerTimeout int) error { continue } - log.Printf("[INFO] NAME: %s", name) + currenttime := time.Now().Unix() + log.Printf("[INFO] (%s) NAME: %s. TIME: %d", container.State, name, currenttime-container.Created) // Need to check time here too because a container can be removed the same instant as its created - currenttime := time.Now().Unix() if container.State != "running" && currenttime-container.Created > int64(workerTimeout) { removeContainers = append(removeContainers, container.ID) containerNames[container.ID] = name @@ -606,6 +607,7 @@ func zombiecheck(workerTimeout int) error { } // FIXME - add killing of apps with same execution ID too + log.Printf("[INFO] Should STOP %d containers.", len(stopContainers)) for _, containername := range stopContainers { log.Printf("[INFO] Stopping and removing container %s", containerNames[containername]) go dockercli.ContainerStop(ctx, containername, nil) @@ -617,6 +619,7 @@ func zombiecheck(workerTimeout int) error { Force: true, } + log.Printf("[INFO] Should REMOVE %d containers.", len(removeContainers)) for _, containername := range removeContainers { go dockercli.ContainerRemove(ctx, containername, removeOptions) }