Add rotating file logging system with app and access loggers

Implement a centralized logging singleton using Python's built-in
  logging module with RotatingFileHandler. Replaces all print()
  statements with structured logging.

  - Create LoggerManager singleton in src/logger.py
  - Add two loggers: app (krawl.log) and access (access.log)
  - Configure 1MB file rotation with 5 backups
  - Output to both files and stdout for container compatibility
  - Update handler.py, server.py, wordlists.py to use new loggers

  Benefits over print():
  - Persistent logs survive restarts for forensic analysis
  - Automatic rotation prevents unbounded disk growth
  - Separate access/app logs for easier analysis and SIEM integration
  - Consistent timestamps and log levels across all messages
  - Configurable verbosity without code changes
This commit is contained in:
Phillip Tarrant
2025-12-26 08:23:38 -06:00
parent 749ffaff8e
commit 7916932ea7
4 changed files with 157 additions and 33 deletions

View File

@@ -11,6 +11,7 @@ from http.server import HTTPServer
from config import Config
from tracker import AccessTracker
from handler import Handler
from logger import initialize_logging, get_app_logger, get_access_logger
def print_usage():
@@ -39,13 +40,20 @@ def main():
print_usage()
exit(0)
# Initialize logging
initialize_logging()
app_logger = get_app_logger()
access_logger = get_access_logger()
config = Config.from_env()
tracker = AccessTracker()
Handler.config = config
Handler.tracker = tracker
Handler.counter = config.canary_token_tries
Handler.app_logger = app_logger
Handler.access_logger = access_logger
if len(sys.argv) == 2:
try:
@@ -53,29 +61,29 @@ def main():
Handler.webpages = f.readlines()
if not Handler.webpages:
print('The file provided was empty. Using randomly generated links.')
app_logger.warning('The file provided was empty. Using randomly generated links.')
Handler.webpages = None
except IOError:
print('Can\'t read input file. Using randomly generated links.')
app_logger.warning("Can't read input file. Using randomly generated links.")
try:
print(f'Starting deception server on port {config.port}...')
print(f'Dashboard available at: {config.dashboard_secret_path}')
app_logger.info(f'Starting deception server on port {config.port}...')
app_logger.info(f'Dashboard available at: {config.dashboard_secret_path}')
if config.canary_token_url:
print(f'Canary token will appear after {config.canary_token_tries} tries')
app_logger.info(f'Canary token will appear after {config.canary_token_tries} tries')
else:
print('No canary token configured (set CANARY_TOKEN_URL to enable)')
app_logger.info('No canary token configured (set CANARY_TOKEN_URL to enable)')
server = HTTPServer(('0.0.0.0', config.port), Handler)
print('Server started. Use <Ctrl-C> to stop.')
app_logger.info('Server started. Use <Ctrl-C> to stop.')
server.serve_forever()
except KeyboardInterrupt:
print('\nStopping server...')
app_logger.info('Stopping server...')
server.socket.close()
print('Server stopped')
app_logger.info('Server stopped')
except Exception as e:
print(f'Error starting HTTP server on port {config.port}: {e}')
print(f'Make sure you are root, if needed, and that port {config.port} is open.')
app_logger.error(f'Error starting HTTP server on port {config.port}: {e}')
app_logger.error(f'Make sure you are root, if needed, and that port {config.port} is open.')
exit(1)