From 7436e4e852a41d60171b41135ff80eb935826095 Mon Sep 17 00:00:00 2001 From: ljstella Date: Tue, 29 Apr 2025 16:01:15 -0500 Subject: [PATCH 1/8] Change offsets to align --- contentctl/input/director.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contentctl/input/director.py b/contentctl/input/director.py index e5db7a5f..4a2f19e6 100644 --- a/contentctl/input/director.py +++ b/contentctl/input/director.py @@ -306,7 +306,7 @@ def createSecurityContent( print("\n") # Clean separation print(f"{Colors.BOLD}{Colors.BRIGHT_MAGENTA}╔{'═' * 60}╗{Colors.END}") print( - f"{Colors.BOLD}{Colors.BRIGHT_MAGENTA}║{Colors.BLUE}{f'{Colors.SEARCH} Content Validation Summary':^60}{Colors.BRIGHT_MAGENTA}║{Colors.END}" + f"{Colors.BOLD}{Colors.BRIGHT_MAGENTA}║{Colors.BLUE}{f'{Colors.SEARCH} Content Validation Summary':^59}{Colors.BRIGHT_MAGENTA}║{Colors.END}" ) print(f"{Colors.BOLD}{Colors.BRIGHT_MAGENTA}╚{'═' * 60}╝{Colors.END}\n") @@ -322,7 +322,7 @@ def createSecurityContent( number_emoji = f"{index}️⃣" print(f"{Colors.YELLOW}┏{'━' * width}┓{Colors.END}") print( - f"{Colors.YELLOW}┃{Colors.BOLD} {number_emoji} File: {Colors.CYAN}{file_path}{Colors.END}{' ' * (width - len(str(file_path)) - 12)}{Colors.YELLOW}┃{Colors.END}" + f"{Colors.YELLOW}┃{Colors.BOLD} {number_emoji} File: {Colors.CYAN}{file_path}{Colors.END}{' ' * (width - len(str(file_path)) - 9)}{Colors.YELLOW}┃{Colors.END}" ) print(f"{Colors.YELLOW}┗{'━' * width}┛{Colors.END}") @@ -367,7 +367,7 @@ def createSecurityContent( max_width = max(60, max(len(str(e[0])) + 15 for e in validation_errors)) print(f"{Colors.BOLD}{Colors.CYAN}╔{'═' * max_width}╗{Colors.END}") print( - f"{Colors.BOLD}{Colors.CYAN}║{Colors.BLUE}{'🎯 Next Steps':^{max_width}}{Colors.CYAN}║{Colors.END}" + f"{Colors.BOLD}{Colors.CYAN}║{Colors.BLUE}{'🎯 Next Steps':^{max_width - 1}}{Colors.CYAN}║{Colors.END}" ) print(f"{Colors.BOLD}{Colors.CYAN}╚{'═' * max_width}╝{Colors.END}\n") From 321423e4437f6078150908bb40cee899cd7529a0 Mon Sep 17 00:00:00 2001 From: ljstella Date: Tue, 29 Apr 2025 16:12:19 -0500 Subject: [PATCH 2/8] use class of literals w/ windows fallbacks instead of emoji --- contentctl/input/director.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/contentctl/input/director.py b/contentctl/input/director.py index 4a2f19e6..b0d57635 100644 --- a/contentctl/input/director.py +++ b/contentctl/input/director.py @@ -351,23 +351,25 @@ def createSecurityContent( ) elif "Extra inputs" in error_msg: print( - f" {Colors.BLUE}❌ Unexpected Field: {err.get('loc', [''])[0]}{Colors.END}" + f" {Colors.BLUE}{Colors.ERROR} Unexpected Field: {err.get('loc', [''])[0]}{Colors.END}" ) elif "Failed to find" in error_msg: print( f" {Colors.RED}🔍 Missing Reference: {error_msg}{Colors.END}" ) else: - print(f" {Colors.RED}❌ {error_msg}{Colors.END}") + print( + f" {Colors.RED}{Colors.ERROR} {error_msg}{Colors.END}" + ) else: - print(f" {Colors.RED}❌ {str(error)}{Colors.END}") + print(f" {Colors.RED}{Colors.ERROR} {str(error)}{Colors.END}") print("") # Clean footer with next steps max_width = max(60, max(len(str(e[0])) + 15 for e in validation_errors)) print(f"{Colors.BOLD}{Colors.CYAN}╔{'═' * max_width}╗{Colors.END}") print( - f"{Colors.BOLD}{Colors.CYAN}║{Colors.BLUE}{'🎯 Next Steps':^{max_width - 1}}{Colors.CYAN}║{Colors.END}" + f"{Colors.BOLD}{Colors.CYAN}║{Colors.BLUE}{Colors.ARROW + ' Next Steps':^{max_width - 1}}{Colors.CYAN}║{Colors.END}" ) print(f"{Colors.BOLD}{Colors.CYAN}╚{'═' * max_width}╝{Colors.END}\n") From a29ee5af7dd663c08ccd4a1b0972df432ac43c69 Mon Sep 17 00:00:00 2001 From: ljstella Date: Tue, 29 Apr 2025 16:16:16 -0500 Subject: [PATCH 3/8] Manipulating template detection to ensure that Windows Runner hits a validation error --- .../templates/detections/endpoint/anomalous_usage_of_7zip.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml b/contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml index 23c15a16..bf2693e6 100644 --- a/contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml +++ b/contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml @@ -1,7 +1,6 @@ name: Anomalous usage of 7zip id: 9364ee8e-a39a-11eb-8f1d-acde48001122 version: 1 -date: '2021-04-22' author: Michael Haag, Teoderick Contreras, Splunk status: production type: Anomaly From 42286462eceff30283bd5606aa8580bb808fdc14 Mon Sep 17 00:00:00 2001 From: ljstella Date: Tue, 29 Apr 2025 16:20:48 -0500 Subject: [PATCH 4/8] Another instance of :magnifying_glass: --- contentctl/input/director.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contentctl/input/director.py b/contentctl/input/director.py index b0d57635..cc46c626 100644 --- a/contentctl/input/director.py +++ b/contentctl/input/director.py @@ -355,7 +355,7 @@ def createSecurityContent( ) elif "Failed to find" in error_msg: print( - f" {Colors.RED}🔍 Missing Reference: {error_msg}{Colors.END}" + f" {Colors.RED}{Colors.SEARCH} Missing Reference: {error_msg}{Colors.END}" ) else: print( From 3212a8d4022b04a339917fe4697d7b6d27b1f6e3 Mon Sep 17 00:00:00 2001 From: ljstella Date: Tue, 29 Apr 2025 16:27:52 -0500 Subject: [PATCH 5/8] Windows platform detection utf-8 stdout --- contentctl/input/director.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contentctl/input/director.py b/contentctl/input/director.py index cc46c626..7df5c4b1 100644 --- a/contentctl/input/director.py +++ b/contentctl/input/director.py @@ -303,6 +303,9 @@ def createSecurityContent( ) if len(validation_errors) > 0: + if sys.platform == "win32": + sys.stdout.reconfigure(encoding="utf-8") + print("\n") # Clean separation print(f"{Colors.BOLD}{Colors.BRIGHT_MAGENTA}╔{'═' * 60}╗{Colors.END}") print( From aa6d6d7bb6587ade21026958ccc5f37893024076 Mon Sep 17 00:00:00 2001 From: ljstella Date: Tue, 29 Apr 2025 16:31:54 -0500 Subject: [PATCH 6/8] Restoring detection --- .../templates/detections/endpoint/anomalous_usage_of_7zip.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml b/contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml index bf2693e6..23c15a16 100644 --- a/contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml +++ b/contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml @@ -1,6 +1,7 @@ name: Anomalous usage of 7zip id: 9364ee8e-a39a-11eb-8f1d-acde48001122 version: 1 +date: '2021-04-22' author: Michael Haag, Teoderick Contreras, Splunk status: production type: Anomaly From 45a811407f2879dee238a44b0083fed5cdd26637 Mon Sep 17 00:00:00 2001 From: ljstella Date: Tue, 29 Apr 2025 16:38:40 -0500 Subject: [PATCH 7/8] Add :sparkle: fallback --- contentctl/input/director.py | 1 + 1 file changed, 1 insertion(+) diff --git a/contentctl/input/director.py b/contentctl/input/director.py index 7df5c4b1..4e5d5816 100644 --- a/contentctl/input/director.py +++ b/contentctl/input/director.py @@ -131,6 +131,7 @@ class Colors: DOCS = "📚" if sys.platform != "win32" else "?" BULB = "💡" if sys.platform != "win32" else "i" SEARCH = "🔍" if sys.platform != "win32" else "@" + SPARKLE = "✨" if sys.platform != "win32" else "*" ZAP = "⚡" if sys.platform != "win32" else "!" From 17d4ac4a1a5640cbb3b9b765de202fcf5d7d15dd Mon Sep 17 00:00:00 2001 From: ljstella Date: Tue, 29 Apr 2025 16:40:12 -0500 Subject: [PATCH 8/8] Actually use it --- contentctl/input/director.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contentctl/input/director.py b/contentctl/input/director.py index 4e5d5816..260a5ede 100644 --- a/contentctl/input/director.py +++ b/contentctl/input/director.py @@ -315,7 +315,7 @@ def createSecurityContent( print(f"{Colors.BOLD}{Colors.BRIGHT_MAGENTA}╚{'═' * 60}╝{Colors.END}\n") print( - f"{Colors.BOLD}{Colors.GREEN}✨ Validation Completed{Colors.END} – Issues detected in {Colors.RED}{Colors.BOLD}{len(validation_errors)}{Colors.END} files.\n" + f"{Colors.BOLD}{Colors.GREEN}{Colors.SPARKLE} Validation Completed{Colors.END} – Issues detected in {Colors.RED}{Colors.BOLD}{len(validation_errors)}{Colors.END} files.\n" ) for index, entry in enumerate(validation_errors, 1):