OTP Generator Added

This commit is contained in:
=
2025-09-11 10:25:16 -04:00
parent 3bb69aaab7
commit 8098fc665c
6 changed files with 288 additions and 275 deletions
+26 -27
View File
@@ -16,11 +16,8 @@ import argparse
import dotenv import dotenv
import os import os
import pandas as pd import pandas as pd
import time
import urllib3 import urllib3
import utils.allowlist
import utils.clientfunctions import utils.clientfunctions
import utils.getdeviceevents
import utils.hashfunctions import utils.hashfunctions
import utils.otpfunctions import utils.otpfunctions
import utils.pathfunctions import utils.pathfunctions
@@ -112,16 +109,16 @@ def menu_main():
while True: while True:
ct.displayIntro(); ct.displayIntro();
print(ct.colorText("1. Get All Events for Single Device", "yellow")) print(ct.colorText("1. Get All Events for Single Device", "yellow"))
print(ct.colorText("2. Placeholder for Local Approval", "yellow")) print(ct.colorText("2. OTP", "yellow"))
print(ct.colorText("3. Placeholder for Another Tool", "yellow")) print(ct.colorText("3. Placeholder for Another Tool", "yellow"))
print(ct.colorText("4. Prepare Policy For Enforcement", "yellow")) print(ct.colorText("4. Prepare Policy For Enforcement", "yellow"))
print(ct.colorText("Q. Quit", "yellow")) print(ct.colorText("Q. Quit", "yellow"))
choice = input(ct.colorText("\nEnter Menu Item: ", "white")) choice = input(ct.colorText("\nEnter Menu Item: ", "white"))
if choice == '1': if choice == '1':
utils.getdeviceevents.devicehistory(url,False) utils.clientfunctions.devicehistory(url,False)
elif choice == "2": elif choice == "2":
menu_local_approve() menu_otp()
elif choice == "3": elif choice == "3":
menu_feature2() menu_feature2()
elif choice == "4": elif choice == "4":
@@ -131,23 +128,25 @@ def menu_main():
else: else:
print(ct.colorText("Invalid choice. Please try again.","red")) print(ct.colorText("Invalid choice. Please try again.","red"))
def menu_local_approve(): def menu_otp():
while True: while True:
print("\n--- Submenu ---") print(ct.colorText("\n--- OTP Submenu ---","cyan"))
print("1. Sub-option A") print(ct.colorText("1. Generate OTP","cyan"))
print("2. Sub-option B") #print(ct.colorText("2. Sub-option B","cyan"))
print("3. Return to Main Menu") print(ct.colorText("Q. Return to Main Menu","cyan"))
choice = input("Enter your choice: ") choice = input("Enter your choice: ")
if choice == "1": if choice == "1":
print("You selected Sub-option A") utils.otpfunctions.generateOTP(url, utils.clientfunctions.findAgentID(url))
elif choice == "2": break
print("You selected Sub-option B")
elif choice == "3": elif choice == "2":
print("Returning to Main Menu...") print("You selected Sub-option B")
break elif choice == "Q":
else: print("Returning to Main Menu...")
print("Invalid choice. Please try again.") break
else:
print("Invalid choice. Please try again.")
def menu_feature2(): def menu_feature2():
while True: while True:
@@ -192,12 +191,12 @@ def menu_prepare_to_enforce():
if choice == "1": if choice == "1":
choice, policynames, policyid = utils.allowlist.listPolicies(url) choice, policynames, policyid = utils.policyfunctions.listPolicies(url)
first_policy = policynames[choice] first_policy = policynames[choice]
while True: while True:
answer = input(ct.colorText(f"{"Do you want to load a second policy?"} (yes/no): ", "white").strip().lower()) answer = input(ct.colorText(f"{"Do you want to load a second policy?"} (yes/no): ", "white").strip().lower())
if answer in ("yes", "y"): if answer in ("yes", "y"):
choice, policynames, policyid = utils.allowlist.listPolicies(url) choice, policynames, policyid = utils.policyfunctions.listPolicies(url)
second_policy = policynames[choice] second_policy = policynames[choice]
break break
@@ -250,19 +249,19 @@ def menu_prepare_to_enforce():
elif choice == "5": elif choice == "5":
print(ct.colorText(f"Please choose destination_name Policy for Path Exclusions","white")) print(ct.colorText(f"Please choose destination_name Policy for Path Exclusions","white"))
choice, policynames, policyid = utils.allowlist.listPolicies(url) choice, policynames, policyid = utils.policyfunctions.listPolicies(url)
#print(allowlist_parent_tuple) #print(allowlist_parent_tuple)
destination_name = policynames[choice] destination_name = policynames[choice]
destination_id = policyid[choice] destination_id = policyid[choice]
print(ct.colorText(f"Please choose Parent Allowlist for Known Hashes","white")) print(ct.colorText(f"Please choose Parent Allowlist for Known Hashes","white"))
choice, allowlists,allowid = utils.allowlist.listAllowlists(url) choice, allowlists,allowid = utils.policyfunctions.listAllowlists(url)
#print(allowlist_parent_tuple) #print(allowlist_parent_tuple)
allowlist_parent_name = allowlists[choice] allowlist_parent_name = allowlists[choice]
allowlist_parent_id = allowid[choice] allowlist_parent_id = allowid[choice]
print(ct.colorText(f"Please choose Child Allowlist for Less-Known Hashes","white")) print(ct.colorText(f"Please choose Child Allowlist for Less-Known Hashes","white"))
choice, allowlists, allowid = utils.allowlist.listAllowlists(url) choice, allowlists, allowid = utils.policyfunctions.listAllowlists(url)
#print(allowlist_child_tuple) #print(allowlist_child_tuple)
allowlist_child_name = allowlists[choice] allowlist_child_name = allowlists[choice]
allowlist_child_id = allowid[choice] allowlist_child_id = allowid[choice]
-155
View File
@@ -1,155 +0,0 @@
# Copyright (C) 2025 James Brotosky, Brandon Wickline
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import datetime
import requests
import json
import os
import utils.pretty as ct
import ijson
import os
from bson import ObjectId
import datetime
import tqdm
import sys
def pullPolicyExechistories(url, policiesnames, days, outputjson: bool):
file_path = 'chunkinator.json'
if not os.path.exists(file_path):
with open(file_path, 'w') as file:
json.dump({'error': 'Success', 'response': {'exechistories': []}}, file)
print(f"File '{file_path}' has been crated.")
else:
print(f"File '{file_path}' already exists.")
headers = {"X-APIKey": os.getenv('APIKEY')}
checkpoint = str(skipback(days))
json_output = {'error': 'Success', 'response': {'exechistories': []}}
with tqdm.tqdm(file=sys.stdout, leave=True, total=10000, desc=f"Checkpoint Progess: {checkpoint}", colour="blue", initial=1) as filebar:
with tqdm.tqdm(file=sys.stdout, leave=True, total=100, desc=f"Total of {policiesnames} Complete: ") as pbar:
while True:
json_response_data = checkpoint_stomper(checkpoint, url, policiesnames, headers)
histories = json_response_data['response']['exechistories']
filebar.total=len(histories)
if not histories:
break
match_found = True
if match_found == True:
for index, item in enumerate(histories):
if index == len(histories) - 1:
checkpoint = item['checkpoint']
filebar.desc = f"Checkpoint Progress: {checkpoint}"
break
else:
if (datetime.date.today() - datetime.timedelta(days=days) > datetime.datetime.strptime(item['datetime'].replace(' +0000 UTC', ''), '%Y-%m-%dT%H:%M:%SZ').date()):
pass
else: json_output['response']['exechistories'].append(item)
filebar.update(1)
filebar.refresh()
seen = {}
if os.path.exists(file_path):
with open(file_path, 'r') as file:
existing_data = json.load(file)
combined = existing_data['response']['exechistories'] + json_output['response']['exechistories']
else:
combined = json_output['response']['exechistories']
for item in combined:
key = (item.get('sha256'), item.get('filename'), item.get('hostname'))
seen[key] = item
deduplicated = list(seen.values())
with open(file_path, 'w') as file:
json.dump({'error': 'Success', 'response': {'exechistories': deduplicated}}, file)
json_output['response']['exechistories'].clear()
date_diff = datetime.date.today() - datetime.datetime.strptime(item['datetime'].replace(' +0000 UTC', ''), '%Y-%m-%dT%H:%M:%SZ').date()
percentage_diff = (((days + 10) - date_diff.days) / (days + 10)) * 100
pbar.n = round(percentage_diff)
pbar.set_description_str(f"Total of {policiesnames} Complete: ")
pbar.refresh()
filebar.n = 1
with open(file_path, 'r') as file:
final_output = json.load(file)
os.remove(file_path)
return json.dumps(final_output) if outputjson else None
def checkpoint_stomper(checkpoint, url, policy, headers):
json_output = {'error': 'Success', 'response': {'exechistories': []}}
endpoint = url + '/v1/logging/exechistories'
payload_dict = {
"type":[1,2,6,7],
"checkpoint": checkpoint,
"policy": [policy]
}
payload = json.dumps(payload_dict)
with requests.request("POST", endpoint, headers=headers, data=payload, verify=False, stream=True) as response:
parser = ijson.items(response.raw, 'response.exechistories.item')
for item in parser:
key = (item.get('sha256'), item.get('hostname'))
if key not in json_output:
json_output['response']['exechistories'].append(item)
parse_text = json.loads(json.dumps(json_output))
return parse_text
def listPolicies(url):
endpoint = url + '/v1/group'
print(ct.colorText("[+] Grabbing All Policies", "cyan"))
payload = {}
headers = {
"X-APIKey": os.getenv('APIKEY')
}
response = requests.request("POST", endpoint, headers=headers, data=payload, verify=False)
parse_text = json.loads(response.text)
policiesnames = []
policyids = []
for index, list in enumerate(parse_text['response']['groups'], start=1):
print(ct.colorText(f"{index}. {list['name']}", "yellow"))
policiesnames.append(list['name'])
policyids.append(list['groupid'])
choice = input(ct.colorText("Select Policy Group: ", "white"))
choice = int(choice) - 1
return choice, policiesnames, policyids
def listAllowlists(url):
endpoint = url + '/v1/application'
print(ct.colorText("[+] Grabbing All Allowlists", "cyan"))
payload = {}
headers = {
"X-APIKey": os.getenv('APIKEY')
}
response = requests.request("POST", endpoint, headers=headers, data=payload, verify=False)
parse_text = json.loads(response.text)
policiesnames = []
policyids = []
for index, list in enumerate(parse_text['response']['applications'], start=1):
if index >= 38:
print(ct.colorText(f"{index}. {list['name']}", "yellow"))
policiesnames.append(list['name'])
policyids.append(list['applicationid'])
choice = int(input(ct.colorText("Select allowlist: ", "white")))
if choice < 38:
print(ct.colorText("Please only choose an allowlist designed for this use - '38+'","red"))
elif choice >= 38:
choice = choice - 38
return choice, policiesnames, policyids
#Need else and catch for upper bound
def skipback(days):
"""
Generate a MongoDB ObjectId for a given number of days ago from today.
Adds 1 extra day to the input to look further back.
"""
adjusted_days = days + 10
date_days_ago = datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=adjusted_days)
timestamp = int(date_days_ago.timestamp())
hex_timestamp = format(timestamp, '08x')
objectid_hex = hex_timestamp + '0000000000000000'
return ObjectId(objectid_hex)
+87 -1
View File
@@ -5,6 +5,25 @@ import pandas as pd
import utils.pretty as ct import utils.pretty as ct
def findAgentID(url):
print(ct.colorText("WARNING: Device Name is Case Sensitive", "red"))
hostname = input(ct.colorText("Enter Device Name: ", "white"))
endpoint = url + '/v1/agent/find'
payload = {
"hostname" : f"{hostname}"
}
headers = {"X-APIKey": os.getenv('APIKEY')}
payload = json.dumps(payload)
response = requests.post(endpoint, headers=headers, data=payload, verify=False)
result = json.loads(response.text)
data = pd.DataFrame(result["response"]["agents"])
return data.loc[0, "agentid"]
def getDestAllowlistFromClientID(url, clientid): def getDestAllowlistFromClientID(url, clientid):
#This is dependant on their being an allowlist in the policy containing the name "localapproval" #This is dependant on their being an allowlist in the policy containing the name "localapproval"
@@ -76,4 +95,71 @@ def getPolicyName(url, groupid):
result = json.loads(response.text) result = json.loads(response.text)
data = pd.DataFrame(result["response"]["groups"]) data = pd.DataFrame(result["response"]["groups"])
name = data.loc[data['groupid'] == f"{groupid}", 'name'].values[0] name = data.loc[data['groupid'] == f"{groupid}", 'name'].values[0]
return name return name
import datetime
import requests
import json
import os
import utils.pretty as ct
def devicehistory(url, outputjson: bool):
endpoint = url + '/v1/getexechistory'
print("\n")
print(ct.colorText("1. Today", "yellow"))
print(ct.colorText("2. Last 24 Hours", "yellow"))
print(ct.colorText("3. Past 7 Days", "yellow"))
print(ct.colorText("4. Past 30 Days", "yellow"))
print(ct.colorText("5. Custom Date Range","yellow"))
choice = input(ct.colorText("\nSelect Date Range: ", "white"))
today = datetime.date.today()
today = today.strftime("%Y-%m-%d")
if choice == '1':
date_selected = today
elif choice == '2':
date_selected = datetime.date.today() - datetime.timedelta(days=1)
date_selected = date_selected.strftime('%Y-%m-%d')
elif choice == '3':
date_selected = datetime.date.today() - datetime.timedelta(days=7)
date_selected = date_selected.strftime('%Y-%m-%d')
elif choice == '4':
date_selected = datetime.date.today() - datetime.timedelta(days=30)
date_selected = date_selected.strftime('%Y-%m-%d')
elif choice == "5":
print(ct.colorText("Please Input Dates as YYYY-MM-DD", "cyan"))
date_selected = input(ct.colorText("From: ", "white"))
today = input(ct.colorText("Date To: ", "white"))
print(ct.colorText("WARNING: Device Name is Case Sensitive", "red"))
device = input(ct.colorText("Enter Device Name: ", "white"))
payload_dict = {
"datefrom": date_selected,
"dateto": today,
"hostname": device
}
payload = json.dumps(payload_dict)
print(ct.colorText(payload, "green"))
headers = {
"X-APIKey": os.getenv('APIKEY')
}
response = requests.request("POST", endpoint, headers=headers, data=payload, verify=False)
if outputjson:
return response
parse_text = json.loads(response.text)
# Safely get exechistory
exechistory = parse_text.get('response', {}).get('exechistory')
if isinstance(exechistory, list):
for block in exechistory:
print(ct.colorText(f"Command: {block.get('commandline', 'N/A')}", "green"))
print(ct.colorText(f"Date: {block.get('datetime', 'N/A')}", "green"))
print(ct.colorText(f"Filename: {block.get('filename', 'N/A')}", "green"))
print(ct.colorText(f"Policy Name: {block.get('policyname', 'N/A')}", "green"))
print(ct.colorText(f"Hostname: {block.get('hostname', 'N/A')}", "green"))
print(ct.colorText(f"Hash: {block.get('sha256', 'N/A')}", "green"))
print("\n")
else:
print(ct.colorText("No execution history found or data is not in expected format.", "red"))
-80
View File
@@ -1,80 +0,0 @@
# Copyright (C) 2025 James Brotosky, Brandon Wickline
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import datetime
import requests
import json
import os
import utils.pretty as ct
def devicehistory(url, outputjson: bool):
endpoint = url + '/v1/getexechistory'
print("\n")
print(ct.colorText("1. Today", "yellow"))
print(ct.colorText("2. Last 24 Hours", "yellow"))
print(ct.colorText("3. Past 7 Days", "yellow"))
print(ct.colorText("4. Past 30 Days", "yellow"))
print(ct.colorText("5. Custom Date Range","yellow"))
choice = input(ct.colorText("\nSelect Date Range: ", "white"))
today = datetime.date.today()
today = today.strftime("%Y-%m-%d")
if choice == '1':
date_selected = today
elif choice == '2':
date_selected = datetime.date.today() - datetime.timedelta(days=1)
date_selected = date_selected.strftime('%Y-%m-%d')
elif choice == '3':
date_selected = datetime.date.today() - datetime.timedelta(days=7)
date_selected = date_selected.strftime('%Y-%m-%d')
elif choice == '4':
date_selected = datetime.date.today() - datetime.timedelta(days=30)
date_selected = date_selected.strftime('%Y-%m-%d')
elif choice == "5":
print(ct.colorText("Please Input Dates as YYYY-MM-DD", "cyan"))
date_selected = input(ct.colorText("From: ", "white"))
today = input(ct.colorText("Date To: ", "white"))
print(ct.colorText("WARNING: Device Name is Case Sensitive", "red"))
device = input(ct.colorText("Enter Device Name: ", "white"))
payload_dict = {
"datefrom": date_selected,
"dateto": today,
"hostname": device
}
payload = json.dumps(payload_dict)
print(ct.colorText(payload, "green"))
headers = {
"X-APIKey": os.getenv('APIKEY')
}
response = requests.request("POST", endpoint, headers=headers, data=payload, verify=False)
if outputjson:
return response
parse_text = json.loads(response.text)
# Safely get exechistory
exechistory = parse_text.get('response', {}).get('exechistory')
if isinstance(exechistory, list):
for block in exechistory:
print(ct.colorText(f"Command: {block.get('commandline', 'N/A')}", "green"))
print(ct.colorText(f"Date: {block.get('datetime', 'N/A')}", "green"))
print(ct.colorText(f"Filename: {block.get('filename', 'N/A')}", "green"))
print(ct.colorText(f"Policy Name: {block.get('policyname', 'N/A')}", "green"))
print(ct.colorText(f"Hostname: {block.get('hostname', 'N/A')}", "green"))
print(ct.colorText(f"Hash: {block.get('sha256', 'N/A')}", "green"))
print("\n")
else:
print(ct.colorText("No execution history found or data is not in expected format.", "red"))
+37 -10
View File
@@ -11,10 +11,6 @@ import utils.pathfunctions as pathf
import utils.policyfunctions as policyf import utils.policyfunctions as policyf
from utils.perstscheduler import register_function, run_once_job, recurring_job, reload_jobs, start_scheduler from utils.perstscheduler import register_function, run_once_job, recurring_job, reload_jobs, start_scheduler
def getActiveOTP(url): def getActiveOTP(url):
endpoint = url + f'/v1/otp/usage' endpoint = url + f'/v1/otp/usage'
@@ -36,7 +32,6 @@ def getActiveOTP(url):
if not otp.empty: if not otp.empty:
ct.style_dataframe_dark(otp, f"newest_active_OTP.html") ct.style_dataframe_dark(otp, f"newest_active_OTP.html")
def getOTPActivities(url, otpid): def getOTPActivities(url, otpid):
endpoint = url + f'/v1/otp/activities' endpoint = url + f'/v1/otp/activities'
payload = {"otpid": f"{otpid}"} payload = {"otpid": f"{otpid}"}
@@ -137,10 +132,6 @@ def monitorOTP(url, pups):
os.remove(f"OTP\\PARQ\\otp_activities_{pid}.parquet") os.remove(f"OTP\\PARQ\\otp_activities_{pid}.parquet")
del finalhashesadded del finalhashesadded
def addOTPHashes(url, clientid, otpid, pups): def addOTPHashes(url, clientid, otpid, pups):
path = f"OTP\\PARQ\\otp_activities_{otpid}.parquet" path = f"OTP\\PARQ\\otp_activities_{otpid}.parquet"
activities = pd.read_parquet(path) activities = pd.read_parquet(path)
@@ -160,7 +151,7 @@ def addOTPHashes(url, clientid, otpid, pups):
# Add hashes to policy # Add hashes to policy
if hashes_to_add: if hashes_to_add:
policyf.addHashReal(url, allowlist, hashes_to_add) policyf.addHash(url, allowlist, hashes_to_add)
# Update 'hash_added' column # Update 'hash_added' column
activities["hash_added"] = activities.apply( activities["hash_added"] = activities.apply(
@@ -171,3 +162,39 @@ def addOTPHashes(url, clientid, otpid, pups):
# Save the updated DataFrame # Save the updated DataFrame
activities.to_parquet(path) activities.to_parquet(path)
def generateOTP(url, agentid):
purpose = input(ct.colorText(" Please enter the purpose for the OTP: ", "white"))
possible_durations = [15, 60, 360, 1440, 10080]
duration_selected = " "
print(ct.colorText("Please select a duration:", "white"))
for i, option in enumerate(possible_durations, start=1):
print(f"{i}. {option}")
try:
choice = int(input("Enter the number of your choice: "))
if 1 <= choice <= len(possible_durations):
duration_selected = possible_durations[choice - 1]
print(ct.colorText(f"You selected: {duration_selected}", "yellow"))
else:
print(ct.colorText("Invalid choice.", "red"))
except ValueError:
print(ct.colorText("Invalid input. Please enter a number.", "red"))
endpoint = url + '/v1/otp/retrieve'
payload = {
"duration" : f"{duration_selected}",
"agentid" : f"{agentid}",
"purpose" : f"{purpose}"
}
headers = {"X-APIKey": os.getenv('APIKEY')}
payload = json.dumps(payload)
response = requests.post(endpoint, headers=headers, data=payload, verify=False)
result = json.loads(response.text)
otpcode = result["response"]["otpcode"]
print(ct.colorText(f"The OPT code is: {otpcode}", "yellow"))
+138 -2
View File
@@ -19,7 +19,13 @@ import pandas as pd
import re import re
import requests import requests
import utils.pretty as ct import utils.pretty as ct
import utils.allowlist import datetime
import requests
import ijson
from bson import ObjectId
import datetime
import tqdm
import sys
@@ -69,7 +75,7 @@ def addPathReal(url, grouplistID, pathlist):
def getPolicyInfo(url, policy, days): def getPolicyInfo(url, policy, days):
executionhist_policy = pd.DataFrame() executionhist_policy = pd.DataFrame()
exehist = utils.allowlist.pullPolicyExechistories(url, policy, days, True) exehist = pullPolicyExechistories(url, policy, days, True)
data = json.loads(exehist) data = json.loads(exehist)
executionhist_policy = pd.DataFrame(data["response"]["exechistories"]) executionhist_policy = pd.DataFrame(data["response"]["exechistories"])
if not executionhist_policy.empty: if not executionhist_policy.empty:
@@ -120,4 +126,134 @@ def sendToPolicy(url, first_policy, second_policy, destination_name, destination
else: else:
print(ct.colorText("Operation aborted. You MUST EXPLICITLY AGREE to proceed.", "red")) print(ct.colorText("Operation aborted. You MUST EXPLICITLY AGREE to proceed.", "red"))
def pullPolicyExechistories(url, policiesnames, days, outputjson: bool):
file_path = 'chunkinator.json'
if not os.path.exists(file_path):
with open(file_path, 'w') as file:
json.dump({'error': 'Success', 'response': {'exechistories': []}}, file)
print(f"File '{file_path}' has been crated.")
else:
print(f"File '{file_path}' already exists.")
headers = {"X-APIKey": os.getenv('APIKEY')}
checkpoint = str(skipback(days))
json_output = {'error': 'Success', 'response': {'exechistories': []}}
with tqdm.tqdm(file=sys.stdout, leave=True, total=10000, desc=f"Checkpoint Progess: {checkpoint}", colour="blue", initial=1) as filebar:
with tqdm.tqdm(file=sys.stdout, leave=True, total=100, desc=f"Total of {policiesnames} Complete: ") as pbar:
while True:
json_response_data = checkpoint_stomper(checkpoint, url, policiesnames, headers)
histories = json_response_data['response']['exechistories']
filebar.total=len(histories)
if not histories:
break
match_found = True
if match_found == True:
for index, item in enumerate(histories):
if index == len(histories) - 1:
checkpoint = item['checkpoint']
filebar.desc = f"Checkpoint Progress: {checkpoint}"
break
else:
if (datetime.date.today() - datetime.timedelta(days=days) > datetime.datetime.strptime(item['datetime'].replace(' +0000 UTC', ''), '%Y-%m-%dT%H:%M:%SZ').date()):
pass
else: json_output['response']['exechistories'].append(item)
filebar.update(1)
filebar.refresh()
seen = {}
if os.path.exists(file_path):
with open(file_path, 'r') as file:
existing_data = json.load(file)
combined = existing_data['response']['exechistories'] + json_output['response']['exechistories']
else:
combined = json_output['response']['exechistories']
for item in combined:
key = (item.get('sha256'), item.get('filename'), item.get('hostname'))
seen[key] = item
deduplicated = list(seen.values())
with open(file_path, 'w') as file:
json.dump({'error': 'Success', 'response': {'exechistories': deduplicated}}, file)
json_output['response']['exechistories'].clear()
date_diff = datetime.date.today() - datetime.datetime.strptime(item['datetime'].replace(' +0000 UTC', ''), '%Y-%m-%dT%H:%M:%SZ').date()
percentage_diff = (((days + 10) - date_diff.days) / (days + 10)) * 100
pbar.n = round(percentage_diff)
pbar.set_description_str(f"Total of {policiesnames} Complete: ")
pbar.refresh()
filebar.n = 1
with open(file_path, 'r') as file:
final_output = json.load(file)
os.remove(file_path)
return json.dumps(final_output) if outputjson else None
def checkpoint_stomper(checkpoint, url, policy, headers):
json_output = {'error': 'Success', 'response': {'exechistories': []}}
endpoint = url + '/v1/logging/exechistories'
payload_dict = {
"type":[1,2,6,7],
"checkpoint": checkpoint,
"policy": [policy]
}
payload = json.dumps(payload_dict)
with requests.request("POST", endpoint, headers=headers, data=payload, verify=False, stream=True) as response:
parser = ijson.items(response.raw, 'response.exechistories.item')
for item in parser:
key = (item.get('sha256'), item.get('hostname'))
if key not in json_output:
json_output['response']['exechistories'].append(item)
parse_text = json.loads(json.dumps(json_output))
return parse_text
def listPolicies(url):
endpoint = url + '/v1/group'
print(ct.colorText("[+] Grabbing All Policies", "cyan"))
payload = {}
headers = {
"X-APIKey": os.getenv('APIKEY')
}
response = requests.request("POST", endpoint, headers=headers, data=payload, verify=False)
parse_text = json.loads(response.text)
policiesnames = []
policyids = []
for index, list in enumerate(parse_text['response']['groups'], start=1):
print(ct.colorText(f"{index}. {list['name']}", "yellow"))
policiesnames.append(list['name'])
policyids.append(list['groupid'])
choice = input(ct.colorText("Select Policy Group: ", "white"))
choice = int(choice) - 1
return choice, policiesnames, policyids
def listAllowlists(url):
endpoint = url + '/v1/application'
print(ct.colorText("[+] Grabbing All Allowlists", "cyan"))
payload = {}
headers = {
"X-APIKey": os.getenv('APIKEY')
}
response = requests.request("POST", endpoint, headers=headers, data=payload, verify=False)
parse_text = json.loads(response.text)
policiesnames = []
policyids = []
for index, list in enumerate(parse_text['response']['applications'], start=1):
if index >= 38:
print(ct.colorText(f"{index}. {list['name']}", "yellow"))
policiesnames.append(list['name'])
policyids.append(list['applicationid'])
choice = int(input(ct.colorText("Select allowlist: ", "white")))
if choice < 38:
print(ct.colorText("Please only choose an allowlist designed for this use - '38+'","red"))
elif choice >= 38:
choice = choice - 38
return choice, policiesnames, policyids
#Need else and catch for upper bound
def skipback(days):
"""
Generate a MongoDB ObjectId for a given number of days ago from today.
Adds 1 extra day to the input to look further back.
"""
adjusted_days = days + 10
date_days_ago = datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=adjusted_days)
timestamp = int(date_days_ago.timestamp())
hex_timestamp = format(timestamp, '08x')
objectid_hex = hex_timestamp + '0000000000000000'
return ObjectId(objectid_hex)