ingestor added for ptr stream
This commit is contained in:
parent
b01e4fbbf1
commit
3673a60918
109
ingestors/ingest_ptrstream.py
Normal file
109
ingestors/ingest_ptrstream.py
Normal file
@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env python
|
||||
# Elasticsearch Recon Ingestion Scripts (ERIS) - Developed by Acidvegas (https://git.acid.vegas/eris)
|
||||
# ingestors/ingest_ptrstream.py
|
||||
|
||||
'''
|
||||
This ingestor is meant to be used with https://github.com/acidvegas/ptrstream
|
||||
'''
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
try:
|
||||
import aiofiles
|
||||
except ImportError:
|
||||
raise ImportError('Missing required \'aiofiles\' library. (pip install aiofiles)')
|
||||
|
||||
|
||||
# Set a default elasticsearch index if one is not provided
|
||||
default_index = 'havoc-ptr'
|
||||
|
||||
|
||||
def construct_map() -> dict:
|
||||
'''Construct the Elasticsearch index mapping for records'''
|
||||
|
||||
# Match on exact value or full text search
|
||||
keyword_mapping = { 'type': 'text', 'fields': { 'keyword': { 'type': 'keyword', 'ignore_above': 256 } } }
|
||||
|
||||
# Construct the index mapping
|
||||
mapping = {
|
||||
'mappings': {
|
||||
'properties': {
|
||||
'ip' : {'type': 'ip'},
|
||||
'nameserver' : {'type': 'ip'},
|
||||
'record' : keyword_mapping,
|
||||
'record_type' : {'type': 'keyword'},
|
||||
'ttl' : {'type': 'integer'},
|
||||
'seen' : {'type': 'date'}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mapping
|
||||
|
||||
|
||||
async def process_data(input_path: str):
|
||||
'''
|
||||
Read and process the input file
|
||||
|
||||
:param input_path: Path to the input file
|
||||
'''
|
||||
|
||||
# Open the input file
|
||||
async with aiofiles.open(input_path) as input_file:
|
||||
|
||||
# Read the input file line by line
|
||||
async for line in input_file:
|
||||
|
||||
# Strip whitespace
|
||||
line = line.strip()
|
||||
|
||||
# Skip empty lines and lines that do not start with a JSON object
|
||||
if not line or not line.startswith('{'):
|
||||
continue
|
||||
|
||||
# Parse the JSON record
|
||||
try:
|
||||
record = json.loads(line)
|
||||
except json.decoder.JSONDecodeError:
|
||||
logging.error(f'Failed to parse JSON record! ({line})')
|
||||
continue
|
||||
|
||||
# Get the IP address from the in-addr.arpa domain
|
||||
ip = record['ip']
|
||||
|
||||
# Do not index PTR records that have the same record as the in-addr.arpa domain
|
||||
if record['record'] == '.'.join(ip.split('.')[::-1]) + '.in-addr.arpa':
|
||||
continue
|
||||
|
||||
# Create the document structure
|
||||
yield {
|
||||
'_op_type' : 'update',
|
||||
'_id' : ip,
|
||||
'_index' : default_index,
|
||||
'doc' : record,
|
||||
'doc_as_upsert' : True # Create the document if it does not exist
|
||||
}
|
||||
|
||||
|
||||
async def test(input_path: str):
|
||||
'''
|
||||
Test the ingestion process
|
||||
|
||||
:param input_path: Path to the input file
|
||||
'''
|
||||
|
||||
async for document in process_data(input_path):
|
||||
print(document)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
import asyncio
|
||||
|
||||
parser = argparse.ArgumentParser(description='Ingestor for ERIS')
|
||||
parser.add_argument('input_path', help='Path to the input file or directory')
|
||||
args = parser.parse_args()
|
||||
|
||||
asyncio.run(test(args.input_path))
|
Loading…
Reference in New Issue
Block a user