def returner(ret): opts_list = _get_options() # Get aws details aws = get_aws_details() for opts in opts_list: logging.info('Options: %s' % json.dumps(opts)) http_event_collector_key = opts['token'] http_event_collector_host = opts['indexer'] hec_ssl = opts['http_event_server_ssl'] proxy = opts['proxy'] timeout = opts['timeout'] custom_fields = opts['custom_fields'] # Set up the collector hec = http_event_collector(http_event_collector_key, http_event_collector_host, http_event_server_ssl=hec_ssl, proxy=proxy, timeout=timeout) # st = 'salt:hubble:nova' data = ret['return'] minion_id = ret['id'] jid = ret['jid'] master = __grains__['master'] fqdn = __grains__['fqdn'] # Sometimes fqdn is blank. If it is, replace it with minion_id fqdn = fqdn if fqdn else minion_id try: fqdn_ip4 = __grains__['fqdn_ip4'][0] except IndexError: fqdn_ip4 = __grains__['ipv4'][0] if fqdn_ip4.startswith('127.'): for ip4_addr in __grains__['ipv4']: if ip4_addr and not ip4_addr.startswith('127.'): fqdn_ip4 = ip4_addr break if not data: return else: for query in data: for query_name, query_results in query.iteritems(): for query_result in query_results['data']: event = {} payload = {} event.update(query_result) event.update({'query': query_name}) event.update({'job_id': jid}) event.update({'master': master}) event.update({'minion_id': minion_id}) event.update({'dest_host': fqdn}) event.update({'dest_ip': fqdn_ip4}) if aws['aws_account_id'] is not None: event.update({'aws_ami_id': aws['aws_ami_id']}) event.update( {'aws_instance_id': aws['aws_instance_id']}) event.update( {'aws_account_id': aws['aws_account_id']}) for custom_field in custom_fields: custom_field_name = 'custom_' + custom_field custom_field_value = __salt__['config.get']( custom_field, '') if isinstance(custom_field_value, str): event.update( {custom_field_name: custom_field_value}) elif isinstance(custom_field_value, list): custom_field_value = ','.join( custom_field_value) event.update( {custom_field_name: custom_field_value}) payload.update({'host': fqdn}) payload.update({'index': opts['index']}) payload.update({'sourcetype': opts['sourcetype']}) payload.update({'event': event}) # If the osquery query includes a field called 'time' it will be checked. # If it's within the last year, it will be used as the eventtime. event_time = query_result.get('time', '') try: if (datetime.fromtimestamp(time.time()) - datetime.fromtimestamp( float(event_time))).days > 365: event_time = '' except: event_time = '' finally: hec.batchEvent(payload, eventtime=event_time) hec.flushBatch() return
def returner(ret): opts_list = _get_options() # Get aws details aws = get_aws_details() for opts in opts_list: logging.info('Options: %s' % json.dumps(opts)) http_event_collector_key = opts['token'] http_event_collector_host = opts['indexer'] hec_ssl = opts['http_event_server_ssl'] proxy = opts['proxy'] timeout = opts['timeout'] custom_fields = opts['custom_fields'] # Set up the collector hec = http_event_collector(http_event_collector_key, http_event_collector_host, http_event_server_ssl=hec_ssl, proxy=proxy, timeout=timeout) # st = 'salt:hubble:nova' data = ret['return'] minion_id = ret['id'] jid = ret['jid'] fqdn = __grains__['fqdn'] # Sometimes fqdn is blank. If it is, replace it with minion_id fqdn = fqdn if fqdn else minion_id master = __grains__['master'] try: fqdn_ip4 = __grains__['fqdn_ip4'][0] except IndexError: fqdn_ip4 = __grains__['ipv4'][0] if fqdn_ip4.startswith('127.'): for ip4_addr in __grains__['ipv4']: if ip4_addr and not ip4_addr.startswith('127.'): fqdn_ip4 = ip4_addr break if __grains__['master']: master = __grains__['master'] else: master = socket.gethostname( ) # We *are* the master, so use our hostname for fai in data.get('Failure', []): check_id = fai.keys()[0] payload = {} event = {} event.update({'check_result': 'Failure'}) event.update({'check_id': check_id}) event.update({'job_id': jid}) if not isinstance(fai[check_id], dict): event.update({'description': fai[check_id]}) elif 'description' in fai[check_id]: for key, value in fai[check_id].iteritems(): if key not in ['tag']: event[key] = value event.update({'master': master}) event.update({'minion_id': minion_id}) event.update({'dest_host': fqdn}) event.update({'dest_ip': fqdn_ip4}) if aws['aws_account_id'] is not None: event.update({'aws_ami_id': aws['aws_ami_id']}) event.update({'aws_instance_id': aws['aws_instance_id']}) event.update({'aws_account_id': aws['aws_account_id']}) for custom_field in custom_fields: custom_field_name = 'custom_' + custom_field custom_field_value = __salt__['config.get'](custom_field, '') if isinstance(custom_field_value, str): event.update({custom_field_name: custom_field_value}) elif isinstance(custom_field_value, list): custom_field_value = ','.join(custom_field_value) event.update({custom_field_name: custom_field_value}) payload.update({'host': fqdn}) payload.update({'index': opts['index']}) payload.update({'sourcetype': opts['sourcetype']}) payload.update({'event': event}) hec.batchEvent(payload) for suc in data.get('Success', []): check_id = suc.keys()[0] payload = {} event = {} event.update({'check_result': 'Success'}) event.update({'check_id': check_id}) event.update({'job_id': jid}) if not isinstance(suc[check_id], dict): event.update({'description': suc[check_id]}) elif 'description' in suc[check_id]: for key, value in suc[check_id].iteritems(): if key not in ['tag']: event[key] = value event.update({'master': master}) event.update({'minion_id': minion_id}) event.update({'dest_host': fqdn}) event.update({'dest_ip': fqdn_ip4}) if aws['aws_account_id'] is not None: event.update({'aws_ami_id': aws['aws_ami_id']}) event.update({'aws_instance_id': aws['aws_instance_id']}) event.update({'aws_account_id': aws['aws_account_id']}) for custom_field in custom_fields: custom_field_name = 'custom_' + custom_field custom_field_value = __salt__['config.get'](custom_field, '') if isinstance(custom_field_value, str): event.update({custom_field_name: custom_field_value}) elif isinstance(custom_field_value, list): custom_field_value = ','.join(custom_field_value) event.update({custom_field_name: custom_field_value}) payload.update({'host': fqdn}) payload.update({'sourcetype': opts['sourcetype']}) payload.update({'index': opts['index']}) payload.update({'event': event}) hec.batchEvent(payload) if data.get('Compliance', None): payload = {} event = {} event.update({'job_id': jid}) event.update({'compliance_percentage': data['Compliance']}) event.update({'master': master}) event.update({'minion_id': minion_id}) event.update({'dest_host': fqdn}) event.update({'dest_ip': fqdn_ip4}) if aws['aws_account_id'] is not None: event.update({'aws_ami_id': aws['aws_ami_id']}) event.update({'aws_instance_id': aws['aws_instance_id']}) event.update({'aws_account_id': aws['aws_account_id']}) for custom_field in custom_fields: custom_field_name = 'custom_' + custom_field custom_field_value = __salt__['config.get'](custom_field, '') if isinstance(custom_field_value, str): event.update({custom_field_name: custom_field_value}) elif isinstance(custom_field_value, list): custom_field_value = ','.join(custom_field_value) event.update({custom_field_name: custom_field_value}) payload.update({'host': fqdn}) payload.update({'sourcetype': opts['sourcetype']}) payload.update({'index': opts['index']}) payload.update({'event': event}) hec.batchEvent(payload) hec.flushBatch() return
def returner(ret): if isinstance(ret, dict) and not ret.get('return'): # Empty single return, let's not do any setup or anything return opts_list = _get_options() # Get aws details aws = get_aws_details() for opts in opts_list: logging.info('Options: %s' % json.dumps(opts)) http_event_collector_key = opts['token'] http_event_collector_host = opts['indexer'] hec_ssl = opts['http_event_server_ssl'] proxy = opts['proxy'] timeout = opts['timeout'] custom_fields = opts['custom_fields'] # Set up the collector hec = http_event_collector(http_event_collector_key, http_event_collector_host, http_event_server_ssl=hec_ssl, proxy=proxy, timeout=timeout) # Check whether or not data is batched: if isinstance(ret, dict): # Batching is disabled data = [ret] else: data = ret # Sometimes there are duplicate events in the list. Dedup them: data = _dedupList(data) minion_id = __opts__['id'] fqdn = __grains__['fqdn'] # Sometimes fqdn is blank. If it is, replace it with minion_id fqdn = fqdn if fqdn else minion_id master = __grains__['master'] try: fqdn_ip4 = __grains__['fqdn_ip4'][0] except IndexError: fqdn_ip4 = __grains__['ipv4'][0] alerts = [] for item in data: events = item['return'] if not isinstance(events, list): events = [events] alerts.extend(events) for alert in alerts: event = {} payload = {} if ('change' in alert): # Linux, normal pulsar # The second half of the change will be '|IN_ISDIR' for directories change = alert['change'].split('|')[0] # Skip the IN_IGNORED events if change == 'IN_IGNORED': continue if len(alert['change'].split('|')) == 2: object_type = 'directory' else: object_type = 'file' actions = defaultdict(lambda: 'unknown') actions['IN_ACCESS'] = 'read' actions['IN_ATTRIB'] = 'acl_modified' actions['IN_CLOSE_NOWRITE'] = 'read' actions['IN_CLOSE_WRITE'] = 'read' actions['IN_CREATE'] = 'created' actions['IN_DELETE'] = 'deleted' actions['IN_DELETE_SELF'] = 'deleted' actions['IN_MODIFY'] = 'modified' actions['IN_MOVE_SELF'] = 'modified' actions['IN_MOVED_FROM'] = 'modified' actions['IN_MOVED_TO'] = 'modified' actions['IN_OPEN'] = 'read' actions['IN_MOVE'] = 'modified' actions['IN_CLOSE'] = 'read' event['action'] = actions[change] event['change_type'] = 'filesystem' event['object_category'] = object_type event['object_path'] = alert['path'] event['file_name'] = alert['name'] event['file_path'] = alert['tag'] if alert[ 'stats']: # Gather more data if the change wasn't a delete stats = alert['stats'] event['object_id'] = stats['inode'] event['file_acl'] = stats['mode'] event['file_create_time'] = stats['ctime'] event['file_modify_time'] = stats['mtime'] event['file_size'] = stats[ 'size'] / 1024.0 # Convert bytes to kilobytes event['user'] = stats['user'] event['group'] = stats['group'] if object_type == 'file': event['file_hash'] = alert['checksum'] event['file_hash_type'] = alert['checksum_type'] else: # Windows, win_pulsar change = alert['Accesses'] if alert['Hash'] == 'Item is a directory': object_type = 'directory' else: object_type = 'file' actions = defaultdict(lambda: 'unknown') actions['Delete'] = 'deleted' actions['Read Control'] = 'read' actions['Write DAC'] = 'acl_modified' actions['Write Owner'] = 'modified' actions['Synchronize'] = 'modified' actions['Access Sys Sec'] = 'read' actions['Read Data'] = 'read' actions['Write Data'] = 'modified' actions['Append Data'] = 'modified' actions['Read EA'] = 'read' actions['Write EA'] = 'modified' actions['Execute/Traverse'] = 'read' actions['Read Attributes'] = 'read' actions['Write Attributes'] = 'acl_modified' actions['Query Key Value'] = 'read' actions['Set Key Value'] = 'modified' actions['Create Sub Key'] = 'created' actions['Enumerate Sub-Keys'] = 'read' actions['Notify About Changes to Keys'] = 'read' actions['Create Link'] = 'created' actions['Print'] = 'read' event['action'] = actions[change] event['change_type'] = 'filesystem' event['object_category'] = object_type event['object_path'] = alert['Object Name'] event['file_name'] = os.path.basename(alert['Object Name']) event['file_path'] = os.path.dirname(alert['Object Name']) # TODO: Should we be reporting 'EntryType' or 'TimeGenerated? # EntryType reports whether attempt to change was successful. event.update({'master': master}) event.update({'minion_id': minion_id}) event.update({'dest_host': fqdn}) event.update({'dest_ip': fqdn_ip4}) if aws['aws_account_id'] is not None: event.update({'aws_ami_id': aws['aws_ami_id']}) event.update({'aws_instance_id': aws['aws_instance_id']}) event.update({'aws_account_id': aws['aws_account_id']}) for custom_field in custom_fields: custom_field_name = 'custom_' + custom_field custom_field_value = __salt__['config.get'](custom_field, '') if isinstance(custom_field_value, str): event.update({custom_field_name: custom_field_value}) elif isinstance(custom_field_value, list): custom_field_value = ','.join(custom_field_value) event.update({custom_field_name: custom_field_value}) payload.update({'host': fqdn}) payload.update({'index': opts['index']}) payload.update({'sourcetype': opts['sourcetype']}) payload.update({'event': event}) hec.batchEvent(payload) hec.flushBatch() return
def returner(ret): opts_list = _get_options() # Get aws details aws = get_aws_details() for opts in opts_list: logging.info('Options: %s' % json.dumps(opts)) http_event_collector_key = opts['token'] http_event_collector_host = opts['indexer'] hec_ssl = opts['http_event_server_ssl'] proxy = opts['proxy'] timeout = opts['timeout'] custom_fields = opts['custom_fields'] # Set up the collector hec = http_event_collector(http_event_collector_key, http_event_collector_host, http_event_server_ssl=hec_ssl, proxy=proxy, timeout=timeout) # st = 'salt:hubble:nova' data = ret['return'] minion_id = ret['id'] jid = ret['jid'] master = __grains__['master'] fqdn = __grains__['fqdn'] # Sometimes fqdn is blank. If it is, replace it with minion_id fqdn = fqdn if fqdn else minion_id try: fqdn_ip4 = __grains__['fqdn_ip4'][0] except IndexError: fqdn_ip4 = __grains__['ipv4'][0] if not data: return else: for query in data: for query_name, query_results in query.iteritems(): for query_result in query_results['data']: event = {} payload = {} event.update(query_result) event.update({'query': query_name}) event.update({'job_id': jid}) event.update({'master': master}) event.update({'minion_id': minion_id}) event.update({'dest_host': fqdn}) event.update({'dest_ip': fqdn_ip4}) if aws['aws_account_id'] is not None: event.update({'aws_ami_id': aws['aws_ami_id']}) event.update( {'aws_instance_id': aws['aws_instance_id']}) event.update( {'aws_account_id': aws['aws_account_id']}) for custom_field in custom_fields: custom_field_name = 'custom_' + custom_field custom_field_value = __salt__['config.get']( custom_field, '') if isinstance(custom_field_value, str): event.update( {custom_field_name: custom_field_value}) elif isinstance(custom_field_value, list): custom_field_value = ','.join( custom_field_value) event.update( {custom_field_name: custom_field_value}) payload.update({'host': fqdn}) payload.update({'index': opts['index']}) payload.update({'sourcetype': opts['sourcetype']}) payload.update({'event': event}) hec.batchEvent(payload) hec.flushBatch() return