From e51ed0543a581093b0285ce2ad2543abc6531a6e Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 28 Aug 2025 09:06:25 -0400 Subject: [PATCH] Fixed some logic, added functions to list allowlist, and category. Category list function will need work, the subcategories are not being parsed at this time --- AirlockTools.py | 39 +++++++++++++++-------------- utils/allowlist.py | 54 +++++++++++++++++++++++++++++++++++++++- utils/pathfunctions.py | 22 +++++++++++++--- utils/policyfunctions.py | 6 +++-- 4 files changed, 96 insertions(+), 25 deletions(-) diff --git a/AirlockTools.py b/AirlockTools.py index 2abcbb7..ad50df5 100644 --- a/AirlockTools.py +++ b/AirlockTools.py @@ -132,8 +132,8 @@ def menu_prepare_to_enforce(): first_policy = " " second_policy = " " - parentpolicy = " " - childpolicy = " " + parentallowlist = " " + childallowlist = " " df_aggregated_combo = pd.DataFrame() #If the directorys where we're going to store our output dont exist, make them. @@ -231,13 +231,13 @@ def menu_prepare_to_enforce(): print(ct.colorText(" [✗] Preflight hash approval list has not been generated","red")) print(ct.colorText(f"5. Choose the destination parent and child policy allow list", "cyan")) - if childpolicy == " " and parentpolicy == " ": + if childallowlist == " " and parentallowlist == " ": print(ct.colorText(f" [✗] No policies have been chosen","red")) - elif parentpolicy != " " and childpolicy != " " and parentpolicy is childpolicy: - print(ct.colorText(f" [✓] [✗] Only {parentpolicy} has been selected this is unusual, but potentially valid case, double check before proceeding,", "yellow")) - elif parentpolicy != " " and childpolicy != " " and parentpolicy is not childpolicy: - print(ct.colorText(f" [✓] {parentpolicy} has been selected as Parent Policy","green")) - print(ct.colorText(f" [✓] {childpolicy} has been selected as Child Policy","green")) + elif parentallowlist != " " and childallowlist != " " and parentallowlist is childallowlist: + print(ct.colorText(f" [✓] [✗] Only {parentallowlist} has been selected this is unusual, but potentially valid case, double check before proceeding,", "yellow")) + elif parentallowlist != " " and childallowlist != " " and parentallowlist is not childallowlist: + print(ct.colorText(f" [✓] {parentallowlist} has been selected as Parent Policy","green")) + print(ct.colorText(f" [✓] {childallowlist} has been selected as Child Policy","green")) print(ct.colorText(f"6. Liftoff ------------------------------------------------------", "cyan")) print(ct.colorText(f" Apply path exclusions according to allowed and approved paths", "cyan")) @@ -369,14 +369,17 @@ def menu_prepare_to_enforce(): elif choice == "5": - parent_policy_tuple = utils.allowlist.listPolicies(url) - parentpolicy = parent_policy_tuple[1][parent_policy_tuple[0]] + print(ct.colorText(f"Please choose Parent Allowlist","white")) + allowlist_parent_tuple = utils.allowlist.listAllowlists(url) + allowlist_parent = allowlist_parent_tuple[1][allowlist_parent_tuple[0]] + - child_policy_tuple = utils.allowlist.listPolicies(url) - childpolicy = child_policy_tuple[1][child_policy_tuple[0]] + print(ct.colorText(f"Please choose Child Allowlist","white")) + allowlist_child_tuple = utils.allowlist.listAllowlists(url) + allowlist_child = allowlist_child_tuple[1][allowlist_child_tuple[0]] elif choice == "6": - if os.path.exists(f"preflight\\final_pathexclusions_{first_policy}_{second_policy}.csv") and os.path.exists(f"preflight\\final_hash_approvals_{first_policy}_{second_policy}.csv") and parentpolicy != " " and childpolicy != " ": + if os.path.exists(f"preflight\\final_pathexclusions_{first_policy}_{second_policy}.csv") and os.path.exists(f"preflight\\final_hash_approvals_{first_policy}_{second_policy}.csv") and parentallowlist != " " and childallowlist != " ": pathexclusions = tryToReadCSV(f"preflight\\final_pathexclusions_{first_policy}_{second_policy}.csv") allowbyhash = tryToReadCSV(f"preflight\\final_hash_approvals_{first_policy}_{second_policy}.csv") @@ -393,13 +396,13 @@ def menu_prepare_to_enforce(): print(ct.colorText("Proceeding with the code...", "yellow")) pathexcludelist = pathexclusions['longestcfp'].unique().tolist - utils.policyfunctions.addPath(childpolicy,pathexcludelist) + utils.policyfunctions.addPath(childallowlist,pathexcludelist) - parentpolicyhashlist = allowbyhash[allowbyhash['reputation_status'] == 'KNOWN']['target_column'].tolist() - utils.policyfunctions.addHash(parentpolicy,parentpolicyhashlist) + parentallowlisthashlist = allowbyhash[allowbyhash['reputation_status'] == 'KNOWN']['target_column'].tolist() + utils.policyfunctions.addHash(parentallowlist,parentallowlisthashlist) - childpolicyhashlist = allowbyhash[allowbyhash['reputation_status'] == 'UNKNOWN']['target_column'].tolist() - utils.policyfunctions.addHash(childpolicy,childpolicyhashlist) + childallowlisthashlist = allowbyhash[allowbyhash['reputation_status'] == 'UNKNOWN']['target_column'].tolist() + utils.policyfunctions.addHash(childallowlist,childallowlisthashlist) else: print(ct.colorText("Operation aborted. You MUST EXPLICITLY AGREE to proceed.", "red")) diff --git a/utils/allowlist.py b/utils/allowlist.py index c4fb983..68ffe80 100644 --- a/utils/allowlist.py +++ b/utils/allowlist.py @@ -94,4 +94,56 @@ def listPolicies(url): policyids.append(list['groupid']) choice = input(ct.colorText("Select Policy Group: ", "white")) choice = int(choice) - 1 - return choice, policiesnames \ No newline at end of file + return choice, policiesnames + +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): + 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 = int(choice) - 1 + return choice, policiesnames + #Need else and catch for upper bound + + +def listCategories(url): + endpoint = url + '/v1/application/categories' + print(ct.colorText("[+] Grabbing All Categories", "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']['categories'], start=1): + print(ct.colorText(f"{index}. {list['name']}", "yellow")) + policiesnames.append(list['name']) + policyids.append(list['categoryid']) + + + choice = input(ct.colorText("Select Policy Group: ", "white")) + choice = int(choice) - 1 + return choice, policiesnames + + + + +else: + print(ct.colorText("Please choose only 38 or Aboove", "red")) + \ No newline at end of file diff --git a/utils/pathfunctions.py b/utils/pathfunctions.py index e15439a..24ea7fa 100644 --- a/utils/pathfunctions.py +++ b/utils/pathfunctions.py @@ -81,24 +81,38 @@ def export_groups_for_review(df, col="filename_x", group_col="longestcfp"): return grouped, df + def mask_from_csv(df, csv_path, filepath_col): """ Reads reviewed CSV of groups, keeps only files in approved groups. """ review_df = pd.read_csv(csv_path) - # Convert string representation of lists back to actual lists - review_df[filepath_col] = review_df[filepath_col].apply(ast.literal_eval) - + + def parse_paths(val): + if isinstance(val, str): + try: + # Try to parse as a list + parsed = ast.literal_eval(val) + # If it's not a list, wrap it + return parsed if isinstance(parsed, list) else [parsed] + except (ValueError, SyntaxError): + # If parsing fails, treat it as a single path + return [val] + return [val] + + review_df[filepath_col] = review_df[filepath_col].apply(parse_paths) + # Flatten all approved file paths into a set for masking approved_files = set() for paths in review_df[filepath_col]: approved_files.update(paths) - + # Keep only rows in df that are in approved_files masked_df = df[df[filepath_col].isin(approved_files)].copy() remainder = df[~df[filepath_col].isin(approved_files)].copy() return masked_df, remainder + def filter_and_drop(approved, eligiblepaths, min_hashes): """ Filters eligiblepaths to rows where all hashes are in approved, diff --git a/utils/policyfunctions.py b/utils/policyfunctions.py index aa75129..3b00496 100644 --- a/utils/policyfunctions.py +++ b/utils/policyfunctions.py @@ -16,7 +16,9 @@ def addHash(policy, hash): - pass + print(f"Adding the following hashes to {policy}:") + print(hash) def addPath(policy, hash): - pass \ No newline at end of file + print(f"Adding the following Path Exclusions to {policy}:") + print(hash) \ No newline at end of file