Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up unit tests #1336

Merged
merged 12 commits into from
Jul 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- MongoDb now gets launched by the Island via python. #1148
- Create/check data directory on Island init. #1170
- The formatting of some log messages to make them more readable. #1283
- Some unit tests to run faster. #1125

### Removed
- Relevant dead code as reported by Vulture. #1149
Expand Down
2 changes: 1 addition & 1 deletion monkey/monkey_island/cc/services/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ def _encrypt_or_decrypt_config(config, is_decrypt=False):
parent_config_arr = config_arr
config_arr = config_arr[config_key_part]

if isinstance(config_arr, collections.Sequence) and not isinstance(config_arr, str):
if isinstance(config_arr, collections.abc.Sequence) and not isinstance(config_arr, str):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the rationale behind this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

for i in range(len(config_arr)):
# Check if array of shh key pairs and then decrypt
if isinstance(config_arr[i], dict) and "public_key" in config_arr[i]:
Expand Down
23 changes: 0 additions & 23 deletions monkey/tests/conftest.py

This file was deleted.

33 changes: 33 additions & 0 deletions monkey/tests/unit_tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,41 @@
import os
import sys
from pathlib import Path

import pytest
from _pytest.monkeypatch import MonkeyPatch

MONKEY_BASE_PATH = str(Path(__file__).parent.parent.parent)
sys.path.insert(0, MONKEY_BASE_PATH)


@pytest.fixture(scope="session")
def data_for_tests_dir(pytestconfig):
return Path(os.path.join(pytestconfig.rootdir, "monkey", "tests", "data_for_tests"))


@pytest.fixture(scope="session")
def stable_file(data_for_tests_dir) -> Path:
return data_for_tests_dir / "stable_file.txt"


@pytest.fixture(scope="session")
def stable_file_sha256_hash() -> str:
return "d9dcaadc91261692dafa86e7275b1bf39bb7e19d2efcfacd6fe2bfc9a1ae1062"


@pytest.fixture
def patched_home_env(monkeypatch, tmp_path):
monkeypatch.setenv("HOME", str(tmp_path))

return tmp_path


# The monkeypatch fixture is function scoped, so it cannot be used by session-scoped fixtures. This
# monkeypatch_session fixture can be session-scoped. For more information, see
# https://github.com/pytest-dev/pytest/issues/363#issuecomment-406536200
@pytest.fixture(scope="session")
def monkeypatch_session():
monkeypatch_ = MonkeyPatch()
yield monkeypatch_
monkeypatch_.undo()
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import pytest

from infection_monkey.exploit.zerologon import ZerologonExploiter
from infection_monkey.model.host import VictimHost

DOMAIN_NAME = "domain-name"
Expand All @@ -15,6 +14,8 @@

@pytest.fixture
def zerologon_exploiter_object(monkeypatch):
from infection_monkey.exploit.zerologon import ZerologonExploiter

def mock_report_login_attempt(**kwargs):
return None

Expand All @@ -25,32 +26,37 @@ def mock_report_login_attempt(**kwargs):
return obj


@pytest.mark.slow
def test_assess_exploit_attempt_result_no_error(zerologon_exploiter_object):
dummy_exploit_attempt_result = {"ErrorCode": 0}
assert zerologon_exploiter_object.assess_exploit_attempt_result(dummy_exploit_attempt_result)


@pytest.mark.slow
def test_assess_exploit_attempt_result_with_error(zerologon_exploiter_object):
dummy_exploit_attempt_result = {"ErrorCode": 1}
assert not zerologon_exploiter_object.assess_exploit_attempt_result(
dummy_exploit_attempt_result
)


@pytest.mark.slow
def test_assess_restoration_attempt_result_restored(zerologon_exploiter_object):
dummy_restoration_attempt_result = object()
assert zerologon_exploiter_object.assess_restoration_attempt_result(
dummy_restoration_attempt_result
)


@pytest.mark.slow
def test_assess_restoration_attempt_result_not_restored(zerologon_exploiter_object):
dummy_restoration_attempt_result = False
assert not zerologon_exploiter_object.assess_restoration_attempt_result(
dummy_restoration_attempt_result
)


@pytest.mark.slow
def test__extract_user_creds_from_secrets_good_data(zerologon_exploiter_object):
mock_dumped_secrets = [
f"{USERS[i]}:{RIDS[i]}:{LM_HASHES[i]}:{NT_HASHES[i]}:::" for i in range(len(USERS))
Expand All @@ -71,6 +77,7 @@ def test__extract_user_creds_from_secrets_good_data(zerologon_exploiter_object):
assert zerologon_exploiter_object._extracted_creds == expected_extracted_creds


@pytest.mark.slow
def test__extract_user_creds_from_secrets_bad_data(zerologon_exploiter_object):
mock_dumped_secrets = [
f"{USERS[i]}:{RIDS[i]}:::{LM_HASHES[i]}:{NT_HASHES[i]}:::" for i in range(len(USERS))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from nmb.NetBIOS import NetBIOS

from common.utils.exceptions import DomainControllerNameFetchError
from infection_monkey.exploit.zerologon_utils.vuln_assessment import get_dc_details
from infection_monkey.model.host import VictimHost

DOMAIN_NAME = "domain-name"
Expand All @@ -21,7 +20,10 @@ def stub_queryIPForName(*args, **kwargs):
return stub_queryIPForName


@pytest.mark.slow
def test_get_dc_details_multiple_netbios_names(host, monkeypatch):
from infection_monkey.exploit.zerologon_utils.vuln_assessment import get_dc_details

NETBIOS_NAMES = ["Name1", "Name2", "Name3"]

stub_queryIPForName = _get_stub_queryIPForName(NETBIOS_NAMES)
Expand All @@ -33,7 +35,10 @@ def test_get_dc_details_multiple_netbios_names(host, monkeypatch):
assert dc_handle == f"\\\\{NETBIOS_NAMES[0]}"


@pytest.mark.slow
def test_get_dc_details_no_netbios_names(host, monkeypatch):
from infection_monkey.exploit.zerologon_utils.vuln_assessment import get_dc_details

NETBIOS_NAMES = []

stub_queryIPForName = _get_stub_queryIPForName(NETBIOS_NAMES)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest

from infection_monkey.exploit.wmiexec import WmiExploiter
from infection_monkey.exploit.sshexec import SSHExploiter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we changing the exploiter ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See commit messages: 2496ed0

from infection_monkey.model.host import VictimHost
from infection_monkey.telemetry.exploit_telem import ExploitTelem

Expand All @@ -19,10 +19,10 @@
"default_tunnel": None,
"default_server": None,
}
EXPLOITER = WmiExploiter(HOST)
EXPLOITER_NAME = "WmiExploiter"
EXPLOITER = SSHExploiter(HOST)
EXPLOITER_NAME = "SSHExploiter"
EXPLOITER_INFO = {
"display_name": WmiExploiter._EXPLOITED_SERVICE,
"display_name": SSHExploiter._EXPLOITED_SERVICE,
"started": "",
"finished": "",
"vulnerable_urls": [],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import logging
import uuid
from time import sleep

import pytest

Expand All @@ -24,9 +23,9 @@ def test_is_dead(self):
mia_monkey_ttl.save()
mia_monkey = Monkey(guid=str(uuid.uuid4()), dead=False, ttl_ref=mia_monkey_ttl.id)
mia_monkey.save()

# Emulate timeout - ttl is manually deleted here, since we're using mongomock and not a
# real mongo instance.
sleep(1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this here in the first place?

Copy link
Collaborator Author

@mssalvatore mssalvatore Jul 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

¯\(ツ)

mia_monkey_ttl.delete()

dead_monkey = Monkey(guid=str(uuid.uuid4()), dead=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@
from monkey_island.cc.services.representations import output_json


# We can't scope to module, because monkeypatch is a function scoped decorator.
# Potential solutions: https://github.com/pytest-dev/pytest/issues/363#issuecomment-406536200 or
# https://stackoverflow.com/questions/53963822/python-monkeypatch-setattr-with-pytest-fixture-at-module-scope
@pytest.fixture(scope="function")
def flask_client(monkeypatch):
monkeypatch.setattr(flask_jwt_extended, "verify_jwt_in_request", lambda: None)
@pytest.fixture(scope="session")
def flask_client(monkeypatch_session):
monkeypatch_session.setattr(flask_jwt_extended, "verify_jwt_in_request", lambda: None)

with mock_init_app().test_client() as client:
yield client
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def test_is_config_encrypted__json(monkey_config_json):
assert not ConfigurationImport.is_config_encrypted(monkey_config_json)


@pytest.mark.slow
def test_is_config_encrypted__ciphertext(monkey_config_json):
encrypted_config = encrypt_string(monkey_config_json, PASSWORD)
assert ConfigurationImport.is_config_encrypted(encrypted_config)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from unittest import TestCase
import pytest

from monkey_island.cc.services.attack.mitre_api_interface import MitreApiInterface


class TestMitreApiInterface(TestCase):
def test_get_all_mitigations(self):
mitigations = MitreApiInterface.get_all_mitigations()
self.assertIsNotNone((len(mitigations.items()) >= 282))
mitigation = next(iter(mitigations.values()))
self.assertEqual(mitigation["type"], "course-of-action")
self.assertIsNotNone(mitigation["name"])
self.assertIsNotNone(mitigation["description"])
self.assertIsNotNone(mitigation["external_references"])
@pytest.mark.slow
def test_get_all_mitigations():
mitigations = MitreApiInterface.get_all_mitigations()
assert len(mitigations.items()) >= 282
mitigation = next(iter(mitigations.values()))
assert mitigation["type"] == "course-of-action"
assert mitigation["name"] is not None
assert mitigation["description"] is not None
assert mitigation["external_references"] is not None
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ def fake_mongo(monkeypatch):

@pytest.mark.usefixtures("uses_database")
def test_get_encrypted_files_table(fake_mongo, monkeypatch):
fake_mongo.db.monkey.insert(MONKEY_AT_ISLAND)
fake_mongo.db.monkey.insert(MONKEY_AT_VICTIM)
fake_mongo.db.edge.insert(EDGE_EXPLOITED)
fake_mongo.db.edge.insert(EDGE_SCANNED)
fake_mongo.db.telemetry.insert(ENCRYPTED)
fake_mongo.db.telemetry.insert(ENCRYPTED_2)
fake_mongo.db.telemetry.insert(ENCRYPTION_ERROR)
fake_mongo.db.telemetry.insert(ENCRYPTION_ONE_FILE)
fake_mongo.db.monkey.insert_one(MONKEY_AT_ISLAND)
fake_mongo.db.monkey.insert_one(MONKEY_AT_VICTIM)
fake_mongo.db.edge.insert_one(EDGE_EXPLOITED)
fake_mongo.db.edge.insert_one(EDGE_SCANNED)
fake_mongo.db.telemetry.insert_one(ENCRYPTED)
fake_mongo.db.telemetry.insert_one(ENCRYPTED_2)
fake_mongo.db.telemetry.insert_one(ENCRYPTION_ERROR)
fake_mongo.db.telemetry.insert_one(ENCRYPTION_ONE_FILE)

monkeypatch.setattr(
ReportService,
Expand Down Expand Up @@ -58,11 +58,11 @@ def test_get_encrypted_files_table(fake_mongo, monkeypatch):

@pytest.mark.usefixtures("uses_database")
def test_get_encrypted_files_table__only_errors(fake_mongo, monkeypatch):
fake_mongo.db.monkey.insert(MONKEY_AT_ISLAND)
fake_mongo.db.monkey.insert(MONKEY_AT_VICTIM)
fake_mongo.db.edge.insert(EDGE_EXPLOITED)
fake_mongo.db.edge.insert(EDGE_SCANNED)
fake_mongo.db.telemetry.insert(ENCRYPTION_ERROR)
fake_mongo.db.monkey.insert_one(MONKEY_AT_ISLAND)
fake_mongo.db.monkey.insert_one(MONKEY_AT_VICTIM)
fake_mongo.db.edge.insert_one(EDGE_EXPLOITED)
fake_mongo.db.edge.insert_one(EDGE_SCANNED)
fake_mongo.db.telemetry.insert_one(ENCRYPTION_ERROR)

monkeypatch.setattr(
ReportService,
Expand All @@ -84,10 +84,10 @@ def test_get_encrypted_files_table__only_errors(fake_mongo, monkeypatch):

@pytest.mark.usefixtures("uses_database")
def test_get_encrypted_files_table__no_telemetries(fake_mongo, monkeypatch):
fake_mongo.db.monkey.insert(MONKEY_AT_ISLAND)
fake_mongo.db.monkey.insert(MONKEY_AT_VICTIM)
fake_mongo.db.edge.insert(EDGE_EXPLOITED)
fake_mongo.db.edge.insert(EDGE_SCANNED)
fake_mongo.db.monkey.insert_one(MONKEY_AT_ISLAND)
fake_mongo.db.monkey.insert_one(MONKEY_AT_VICTIM)
fake_mongo.db.edge.insert_one(EDGE_EXPLOITED)
fake_mongo.db.edge.insert_one(EDGE_SCANNED)

monkeypatch.setattr(
ReportService,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,61 @@
VALID_CIPHER_TEXT = (
"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"
"5pnm3dizp6Q="
)

MALFORMED_CIPHER_TEXT_CORRUPTED = (
"QUVTAgAAGM0NKEYTESTURfQlkAcHlBZXNDcnlwdCA2LjAuMACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
Expand Down
Loading