7
7
import logging
8
8
from glob import glob
9
9
from datetime import datetime
10
- from tempfile import NamedTemporaryFile
10
+ from tempfile import NamedTemporaryFile , gettempdir
11
11
try :
12
12
# python 2
13
13
from urllib import quote as urlencode
21
21
from insights .client .utilities import (
22
22
generate_machine_id , write_data_to_file , get_time
23
23
)
24
- from insights .util .subproc import call , CalledProcessError
24
+ from insights .core .exceptions import CalledProcessError
25
+ from insights .util .subproc import call
25
26
26
27
logger = logging .getLogger (__name__ )
27
28
MIN_YARA_VERSION = "4.1.0"
@@ -186,6 +187,7 @@ def __init__(self, insights_config):
186
187
self .add_metadata = self ._get_config_option ('add_metadata' , False )
187
188
188
189
self .matches = 0
190
+ self .potential_matches = 0
189
191
190
192
def run (self ):
191
193
# Start the scans and record the time they were started
@@ -201,7 +203,11 @@ def run(self):
201
203
202
204
# Write a message to user informing them if there were matches or not and what to do next
203
205
if self .matches == 0 :
204
- logger .info ("No rule matches found.\n " )
206
+ if self .potential_matches == 0 :
207
+ logger .info ("No rule matches found.\n " )
208
+ else :
209
+ logger .info ("Rule matches potentially found but problems encountered parsing them, so no match data to upload." )
210
+ logger .info ("Please contact support.\n " )
205
211
else :
206
212
logger .info ("Found %d rule match%s." , self .matches , 'es' if self .matches > 1 else '' )
207
213
if not self .test_scan :
@@ -604,11 +610,12 @@ def _get_rules(self):
604
610
# However it can happen that the rules file isn't removed for some reason, so remove any existing
605
611
# rules files before beginning a new scan, otherwise they may show up as matches in the scan results.
606
612
old_rules_files = sum ([glob (os .path .join (path , rules ))
607
- for path in ('/tmp' , '/var/tmp' )
613
+ for path in ('/tmp' , '/var/tmp' , '/usr/tmp' , gettempdir () )
608
614
for rules in ('.tmpmdsigs*' , 'tmp_malware-detection-client_rules.*' )], [])
609
615
for old_rules_file in old_rules_files :
610
- logger .debug ("Removing old rules file %s" , old_rules_file )
611
- os .remove (old_rules_file )
616
+ if os .path .exists (old_rules_file ):
617
+ logger .debug ("Removing old rules file %s" , old_rules_file )
618
+ os .remove (old_rules_file )
612
619
613
620
self .rules_location = self ._get_config_option ('rules_location' , '' )
614
621
@@ -741,8 +748,16 @@ def scan_filesystem(self):
741
748
return False
742
749
743
750
# Exclude the rules file and insights-client log files, unless they are things we specifically want to scan
744
- if self .rules_file not in self .scan_fsobjects :
745
- self .filesystem_scan_exclude_list .append (self .rules_file )
751
+ # Get a list of potential rules files locations,eg /tmp, /var/tmp, /usr/tmp and gettempdir()
752
+ # eg customers may have /tmp linked to /var/tmp so both must be checked for excluding the downloaded rules
753
+ rules_file_name = os .path .basename (self .rules_file )
754
+ potential_tmp_dirs = set ([gettempdir (), '/tmp' , '/var/tmp' , '/usr/tmp' ])
755
+ potential_rules_files = set (list (map (lambda d : os .path .join (d , rules_file_name ), potential_tmp_dirs )) + [self .rules_file ])
756
+ rules_files = list (filter (lambda f : os .path .isfile (f ), potential_rules_files ))
757
+ for rules_file in rules_files :
758
+ if rules_file not in self .scan_fsobjects :
759
+ self .filesystem_scan_exclude_list .append (rules_file )
760
+ logger .debug ("Excluding rules file: %s" , rules_file )
746
761
insights_log_files = glob (constants .default_log_file + '*' )
747
762
self .filesystem_scan_exclude_list .extend (list (set (insights_log_files ) - set (self .scan_fsobjects )))
748
763
@@ -795,7 +810,12 @@ def scan_filesystem(self):
795
810
logger .debug ("Unable to scan %s: %s" , toplevel_dir , cpe .output .strip ())
796
811
continue
797
812
798
- self .parse_scan_output (output .strip ())
813
+ try :
814
+ self .parse_scan_output (output .strip ())
815
+ except Exception as e :
816
+ self .potential_matches += 1
817
+ logger .exception ("Rule match(es) potentially found in %s but problems encountered parsing the results: %s. Skipping ..." ,
818
+ toplevel_dir , str (e ))
799
819
800
820
dir_scan_end = time .time ()
801
821
logger .info ("Scan time for %s: %d seconds" , toplevel_dir , (dir_scan_end - dir_scan_start ))
@@ -862,7 +882,12 @@ def scan_processes(self):
862
882
logger .debug ("Unable to scan process %s: %s" , scan_pid , cpe .output .strip ())
863
883
continue
864
884
865
- self .parse_scan_output (output )
885
+ try :
886
+ self .parse_scan_output (output )
887
+ except Exception as e :
888
+ self .potential_matches += 1
889
+ logger .exception ("Rule match(es) potentially found in process %s but problems encountered parsing the results: %s. Skipping ..." ,
890
+ scan_pid , str (e ))
866
891
867
892
pid_scan_end = time .time ()
868
893
logger .info ("Scan time for process %s: %d seconds" , scan_pid , (pid_scan_end - pid_scan_start ))
@@ -969,11 +994,15 @@ def skip_string_data_lines(string_data_lines):
969
994
rule_match ['matches' ] = [rule_match_dict ]
970
995
971
996
if self .add_metadata :
972
- # Add extra data to each rule match, beyond what yara provides
973
- # Eg, for files: line numbers & context, checksums; for processes: process name
974
- # TODO: find more pythonic ways of doing this stuff instead of using system commands
975
- metadata_func = self ._add_file_metadata if source_type == 'file' else self ._add_process_metadata
976
- metadata_func (rule_match ['matches' ])
997
+ try :
998
+ # Add extra data to each rule match, beyond what yara provides
999
+ # Eg, for files: line numbers & context, checksums; for processes: process name
1000
+ # TODO: find more pythonic ways of doing this stuff instead of using system commands
1001
+ metadata_func = self ._add_file_metadata if source_type == 'file' else self ._add_process_metadata
1002
+ metadata_func (rule_match ['matches' ])
1003
+ except Exception as e :
1004
+ logger .error ("Error adding metadata to rule match %s in %s %s: %s. Skipping ..." ,
1005
+ rule_name , source_type , source , str (e ))
977
1006
978
1007
self .matches += 1
979
1008
logger .info ("Matched rule %s in %s %s" , rule_name , source_type , source )
0 commit comments