Skip to content

Commit

Permalink
removed wait after shutdown & added acceptance test
Browse files Browse the repository at this point in the history
  • Loading branch information
jstucke committed Mar 6, 2024
1 parent 6bef887 commit 02bdba6
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 2 deletions.
5 changes: 3 additions & 2 deletions honeypots/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from atexit import register
from functools import wraps
from json import JSONDecodeError, loads
from threading import Event
from os import geteuid
from pathlib import Path
from signal import alarm, SIGALRM, SIGINT, signal, SIGTERM, SIGTSTP
Expand Down Expand Up @@ -116,6 +117,8 @@ def await_termination(self):
input("")
elif self.strategy == "signal":
SignalFence([SIGTERM, SIGINT, SIGTSTP]).wait_on_fence()
elif isinstance(self.strategy, Event): # used for testing only
self.strategy.wait()
else:
raise Exception(f"Unknown termination strategy: {self.strategy}")

Expand Down Expand Up @@ -278,8 +281,6 @@ def _stop_servers(self):
server.kill_server()
except Exception as error:
logger.exception(f"Error when killing server {name}: {error}")
logger.info("[x] Please wait few seconds")
sleep(5)

def _start_chameleon_mode(self): # noqa: C901,PLR0912
logger.info("[x] Chameleon mode")
Expand Down
Empty file added tests/acceptance/__init__.py
Empty file.
93 changes: 93 additions & 0 deletions tests/acceptance/test_full_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import logging
import sys
from contextlib import contextmanager
from threading import Event, Thread
from time import sleep

from paramiko.client import AutoAddPolicy, SSHClient

from honeypots import QSSHServer
from honeypots.__main__ import _parse_args, HoneypotsManager
from tests.conftest import config_for_testing
from tests.utils import (
assert_connect_is_logged,
IP,
load_logs_from_file,
PASSWORD,
USERNAME,
wait_for_server,
)

PORT = 50222
SERVER_CONFIG = {
"honeypots": {
"ssh": {
"options": ["capture_commands"],
"username": USERNAME,
"password": PASSWORD,
},
},
"logs": "file,terminal,json",
}


@contextmanager
def run_main(manager: HoneypotsManager):
event = Event()
thread = Thread(target=manager.main)
manager.options.termination_strategy = event
try:
thread.start()
yield
finally:
event.set()
thread.join(timeout=5)


def test_full_run(caplog):
with config_for_testing(SERVER_CONFIG) as config:
sys.argv = [
__file__,
"--setup",
"ssh",
"--port",
f"{PORT}",
"--ip",
IP,
"--config",
f"{config}",
]
manager = HoneypotsManager(*_parse_args())

with caplog.at_level(logging.INFO), run_main(manager), wait_for_server(PORT):
sleep(0.1) # make sure "connect" comes after "process"
ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(IP, port=PORT, username=USERNAME, password=PASSWORD)
ssh.close()

assert len(manager.honeypots) == 1
server, _, started = manager.honeypots[0]
assert isinstance(server, QSSHServer)
assert started is True
assert server.ip == IP
assert server.port == PORT
assert server.username == USERNAME
assert server.password == PASSWORD
assert "capture_commands" in server.options

logs = load_logs_from_file(config.parent / "logs")

for string in [
"Successfully loaded config file",
'"action": "process"',
"Everything looks good",
]:
assert any(string in log for log in caplog.messages)

assert len(logs) == 3
process, connect, login = logs
assert_connect_is_logged(connect, str(PORT))
assert process["action"] == "process"
assert login["action"] == "login"
assert login["username"] == USERNAME

0 comments on commit 02bdba6

Please sign in to comment.