forked from p34709852/monkey
Replaced Conclusive with Failed, and Positive with Passed
This commit is contained in:
parent
04005b14d7
commit
dfebf5e841
|
@ -16,11 +16,11 @@ DATA = u"Data"
|
|||
PILLARS = (DATA, PEOPLE, NETWORKS, DEVICES, WORKLOADS, VISIBILITY_ANALYTICS, AUTOMATION_ORCHESTRATION)
|
||||
|
||||
STATUS_UNEXECUTED = u"Unexecuted"
|
||||
STATUS_POSITIVE = u"Positive"
|
||||
STATUS_PASSED = u"Passed"
|
||||
STATUS_INCONCLUSIVE = u"Inconclusive"
|
||||
STATUS_CONCLUSIVE = u"Conclusive"
|
||||
STATUS_FAILED = u"Failed"
|
||||
# Don't change order! The statuses are ordered by importance/severity.
|
||||
ORDERED_TEST_STATUSES = [STATUS_CONCLUSIVE, STATUS_INCONCLUSIVE, STATUS_POSITIVE, STATUS_UNEXECUTED]
|
||||
ORDERED_TEST_STATUSES = [STATUS_FAILED, STATUS_INCONCLUSIVE, STATUS_PASSED, STATUS_UNEXECUTED]
|
||||
|
||||
TEST_DATA_ENDPOINT_ELASTIC = u"unencrypted_data_endpoint_elastic"
|
||||
TEST_DATA_ENDPOINT_HTTP = u"unencrypted_data_endpoint_http"
|
||||
|
@ -61,12 +61,12 @@ TESTS_MAP = {
|
|||
TEST_SEGMENTATION: {
|
||||
TEST_EXPLANATION_KEY: u"The Monkey tried to scan and find machines that it can communicate with from the machine it's running on, that belong to different network segments.",
|
||||
FINDING_EXPLANATION_BY_STATUS_KEY: {
|
||||
STATUS_CONCLUSIVE: "Monkey performed cross-segment communication. Check firewall rules and logs.",
|
||||
STATUS_POSITIVE: "Monkey couldn't perform cross-segment communication. If relevant, check firewall logs."
|
||||
STATUS_FAILED: "Monkey performed cross-segment communication. Check firewall rules and logs.",
|
||||
STATUS_PASSED: "Monkey couldn't perform cross-segment communication. If relevant, check firewall logs."
|
||||
},
|
||||
RECOMMENDATION_KEY: RECOMMENDATION_SEGMENTATION,
|
||||
PILLARS_KEY: [NETWORKS],
|
||||
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_POSITIVE, STATUS_CONCLUSIVE]
|
||||
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_PASSED, STATUS_FAILED]
|
||||
},
|
||||
TEST_MALICIOUS_ACTIVITY_TIMELINE: {
|
||||
TEST_EXPLANATION_KEY: u"The Monkeys in the network performed malicious-looking actions, like scanning and attempting exploitation.",
|
||||
|
@ -80,22 +80,22 @@ TESTS_MAP = {
|
|||
TEST_ENDPOINT_SECURITY_EXISTS: {
|
||||
TEST_EXPLANATION_KEY: u"The Monkey checked if there is an active process of an endpoint security software.",
|
||||
FINDING_EXPLANATION_BY_STATUS_KEY: {
|
||||
STATUS_CONCLUSIVE: "Monkey didn't find ANY active endpoint security processes. Install and activate anti-virus software on endpoints.",
|
||||
STATUS_POSITIVE: "Monkey found active endpoint security processes. Check their logs to see if Monkey was a security concern."
|
||||
STATUS_FAILED: "Monkey didn't find ANY active endpoint security processes. Install and activate anti-virus software on endpoints.",
|
||||
STATUS_PASSED: "Monkey found active endpoint security processes. Check their logs to see if Monkey was a security concern."
|
||||
},
|
||||
RECOMMENDATION_KEY: RECOMMENDATION_ENDPOINT_SECURITY,
|
||||
PILLARS_KEY: [DEVICES],
|
||||
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_CONCLUSIVE, STATUS_POSITIVE]
|
||||
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED]
|
||||
},
|
||||
TEST_MACHINE_EXPLOITED: {
|
||||
TEST_EXPLANATION_KEY: u"The Monkey tries to exploit machines in order to breach them and propagate in the network.",
|
||||
FINDING_EXPLANATION_BY_STATUS_KEY: {
|
||||
STATUS_CONCLUSIVE: "Monkey successfully exploited endpoints. Check IDS/IPS logs to see activity recognized and see which endpoints were compromised.",
|
||||
STATUS_POSITIVE: "Monkey didn't manage to exploit an endpoint."
|
||||
STATUS_FAILED: "Monkey successfully exploited endpoints. Check IDS/IPS logs to see activity recognized and see which endpoints were compromised.",
|
||||
STATUS_PASSED: "Monkey didn't manage to exploit an endpoint."
|
||||
},
|
||||
RECOMMENDATION_KEY: RECOMMENDATION_ENDPOINT_SECURITY,
|
||||
PILLARS_KEY: [DEVICES],
|
||||
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_CONCLUSIVE, STATUS_INCONCLUSIVE]
|
||||
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_INCONCLUSIVE]
|
||||
},
|
||||
TEST_SCHEDULED_EXECUTION: {
|
||||
TEST_EXPLANATION_KEY: "The Monkey was executed in a scheduled manner.",
|
||||
|
@ -109,22 +109,22 @@ TESTS_MAP = {
|
|||
TEST_DATA_ENDPOINT_ELASTIC: {
|
||||
TEST_EXPLANATION_KEY: u"The Monkey scanned for unencrypted access to ElasticSearch instances.",
|
||||
FINDING_EXPLANATION_BY_STATUS_KEY: {
|
||||
STATUS_CONCLUSIVE: "Monkey accessed ElasticSearch instances. Limit access to data by encrypting it in in-transit.",
|
||||
STATUS_POSITIVE: "Monkey didn't find open ElasticSearch instances. If you have such instances, look for alerts that indicate attempts to access them."
|
||||
STATUS_FAILED: "Monkey accessed ElasticSearch instances. Limit access to data by encrypting it in in-transit.",
|
||||
STATUS_PASSED: "Monkey didn't find open ElasticSearch instances. If you have such instances, look for alerts that indicate attempts to access them."
|
||||
},
|
||||
RECOMMENDATION_KEY: RECOMMENDATION_DATA_TRANSIT,
|
||||
PILLARS_KEY: [DATA],
|
||||
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_CONCLUSIVE, STATUS_POSITIVE]
|
||||
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED]
|
||||
},
|
||||
TEST_DATA_ENDPOINT_HTTP: {
|
||||
TEST_EXPLANATION_KEY: u"The Monkey scanned for unencrypted access to HTTP servers.",
|
||||
FINDING_EXPLANATION_BY_STATUS_KEY: {
|
||||
STATUS_CONCLUSIVE: "Monkey accessed HTTP servers. Limit access to data by encrypting it in in-transit.",
|
||||
STATUS_POSITIVE: "Monkey didn't find open HTTP servers. If you have such servers, look for alerts that indicate attempts to access them."
|
||||
STATUS_FAILED: "Monkey accessed HTTP servers. Limit access to data by encrypting it in in-transit.",
|
||||
STATUS_PASSED: "Monkey didn't find open HTTP servers. If you have such servers, look for alerts that indicate attempts to access them."
|
||||
},
|
||||
RECOMMENDATION_KEY: RECOMMENDATION_DATA_TRANSIT,
|
||||
PILLARS_KEY: [DATA],
|
||||
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_CONCLUSIVE, STATUS_POSITIVE]
|
||||
POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_FAILED, STATUS_PASSED]
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -16,12 +16,13 @@ class Finding(Document):
|
|||
This model represents a Zero-Trust finding: A result of a test the monkey/island might perform to see if a
|
||||
specific recommendation of zero trust is upheld or broken.
|
||||
|
||||
Findings might be
|
||||
Negative ❌
|
||||
Conclusive, meaning that we are sure that something is wrong (example: segmentation issue).
|
||||
Inconclusive, meaning that we need the user to check something himself (example: 2FA logs, AV missing).
|
||||
Positive ✔
|
||||
Conclusive, meaning that we are sure that something is correct (example: Monkey failed exploiting).
|
||||
Findings might have the following statuses:
|
||||
Failed ❌
|
||||
Meaning that we are sure that something is wrong (example: segmentation issue).
|
||||
Inconclusive ⁉
|
||||
Meaning that we need the user to check something himself (example: 2FA logs, AV missing).
|
||||
Passed ✔
|
||||
Meaning that we are sure that something is correct (example: Monkey failed exploiting).
|
||||
|
||||
This class has 2 main section:
|
||||
* The schema section defines the DB fields in the document. This is the data of the object.
|
||||
|
|
|
@ -1,30 +1,34 @@
|
|||
from mongoengine import StringField
|
||||
|
||||
from common.data.zero_trust_consts import TEST_SEGMENTATION, STATUS_CONCLUSIVE, STATUS_POSITIVE
|
||||
from common.data.zero_trust_consts import TEST_SEGMENTATION, STATUS_FAILED, STATUS_PASSED
|
||||
from monkey_island.cc.models.zero_trust.finding import Finding
|
||||
|
||||
|
||||
def need_to_overwrite_status(saved_status, new_status):
|
||||
return (saved_status == STATUS_POSITIVE) and (new_status == STATUS_CONCLUSIVE)
|
||||
return (saved_status == STATUS_PASSED) and (new_status == STATUS_FAILED)
|
||||
|
||||
|
||||
class SegmentationFinding(Finding):
|
||||
"""
|
||||
trying to add conclusive:
|
||||
If the finding doesn't exist at all: create conclusive
|
||||
else:
|
||||
if positive, turn to conclusive
|
||||
add event
|
||||
|
||||
trying to add positive:
|
||||
If the finding doesn't exist at all: create positive
|
||||
else: add event
|
||||
"""
|
||||
first_subnet = StringField()
|
||||
second_subnet = StringField()
|
||||
|
||||
@staticmethod
|
||||
def create_or_add_to_existing_finding(subnets, status, segmentation_event):
|
||||
"""
|
||||
If you're trying to add a Failed finding:
|
||||
If the finding doesn't exist at all: create failed
|
||||
else:
|
||||
if pass, turn to fail
|
||||
add event
|
||||
|
||||
If you're trying to add a Passed finding:
|
||||
If the finding doesn't exist at all: create Passed
|
||||
else: add event
|
||||
|
||||
:param subnets: the 2 subnets of this finding.
|
||||
:param status: STATUS_PASSED or STATUS_FAILED
|
||||
:param segmentation_event: The specific event
|
||||
"""
|
||||
assert len(subnets) == 2
|
||||
|
||||
# Sort them so A -> B and B -> A segmentation findings will be the same one.
|
||||
|
|
|
@ -19,7 +19,7 @@ class TestFinding(IslandTestCase):
|
|||
self.clean_finding_db()
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
_ = Finding.save_finding(test="bla bla", status=STATUS_CONCLUSIVE, events=[])
|
||||
_ = Finding.save_finding(test="bla bla", status=STATUS_FAILED, events=[])
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
_ = Finding.save_finding(test=TEST_SEGMENTATION, status="bla bla", events=[])
|
||||
|
@ -32,7 +32,7 @@ class TestFinding(IslandTestCase):
|
|||
|
||||
event_example = Event.create_event(
|
||||
title="Event Title", message="event message", event_type=EVENT_TYPE_MONKEY_NETWORK)
|
||||
Finding.save_finding(test=TEST_SEGMENTATION, status=STATUS_CONCLUSIVE, events=[event_example])
|
||||
Finding.save_finding(test=TEST_SEGMENTATION, status=STATUS_FAILED, events=[event_example])
|
||||
|
||||
self.assertEquals(len(Finding.objects(test=TEST_SEGMENTATION)), 1)
|
||||
self.assertEquals(len(Finding.objects(status=STATUS_CONCLUSIVE)), 1)
|
||||
self.assertEquals(len(Finding.objects(status=STATUS_FAILED)), 1)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from common.data.zero_trust_consts import STATUS_CONCLUSIVE, EVENT_TYPE_MONKEY_NETWORK
|
||||
from common.data.zero_trust_consts import STATUS_FAILED, EVENT_TYPE_MONKEY_NETWORK
|
||||
from monkey_island.cc.models.zero_trust.event import Event
|
||||
from monkey_island.cc.testing.IslandTestCase import IslandTestCase
|
||||
from monkey_island.cc.models.zero_trust.segmentation_finding import SegmentationFinding
|
||||
|
@ -16,7 +16,7 @@ class TestSegmentationFinding(IslandTestCase):
|
|||
|
||||
SegmentationFinding.create_or_add_to_existing_finding(
|
||||
subnets=[first_segment, second_segment],
|
||||
status=STATUS_CONCLUSIVE,
|
||||
status=STATUS_FAILED,
|
||||
segmentation_event=event
|
||||
)
|
||||
|
||||
|
@ -26,7 +26,7 @@ class TestSegmentationFinding(IslandTestCase):
|
|||
SegmentationFinding.create_or_add_to_existing_finding(
|
||||
# !!! REVERSE ORDER
|
||||
subnets=[second_segment, first_segment],
|
||||
status=STATUS_CONCLUSIVE,
|
||||
status=STATUS_FAILED,
|
||||
segmentation_event=event
|
||||
)
|
||||
|
||||
|
@ -36,7 +36,7 @@ class TestSegmentationFinding(IslandTestCase):
|
|||
SegmentationFinding.create_or_add_to_existing_finding(
|
||||
# !!! REVERSE ORDER
|
||||
subnets=[first_segment, third_segment],
|
||||
status=STATUS_CONCLUSIVE,
|
||||
status=STATUS_FAILED,
|
||||
segmentation_event=event
|
||||
)
|
||||
|
||||
|
@ -45,7 +45,7 @@ class TestSegmentationFinding(IslandTestCase):
|
|||
SegmentationFinding.create_or_add_to_existing_finding(
|
||||
# !!! REVERSE ORDER
|
||||
subnets=[second_segment, third_segment],
|
||||
status=STATUS_CONCLUSIVE,
|
||||
status=STATUS_FAILED,
|
||||
segmentation_event=event
|
||||
)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"server_config": "testing",
|
||||
"server_config": "standard",
|
||||
"deployment": "develop"
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ from monkey_island.cc.testing.IslandTestCase import IslandTestCase
|
|||
|
||||
def save_example_findings():
|
||||
# arrange
|
||||
Finding.save_finding(TEST_ENDPOINT_SECURITY_EXISTS, STATUS_POSITIVE, []) # devices positive = 1
|
||||
Finding.save_finding(TEST_ENDPOINT_SECURITY_EXISTS, STATUS_POSITIVE, []) # devices positive = 2
|
||||
Finding.save_finding(TEST_ENDPOINT_SECURITY_EXISTS, STATUS_CONCLUSIVE, []) # devices conclusive = 1
|
||||
Finding.save_finding(TEST_ENDPOINT_SECURITY_EXISTS, STATUS_PASSED, []) # devices passed = 1
|
||||
Finding.save_finding(TEST_ENDPOINT_SECURITY_EXISTS, STATUS_PASSED, []) # devices passed = 2
|
||||
Finding.save_finding(TEST_ENDPOINT_SECURITY_EXISTS, STATUS_FAILED, []) # devices failed = 1
|
||||
# devices unexecuted = 1
|
||||
# people inconclusive = 1
|
||||
# networks inconclusive = 1
|
||||
|
@ -17,22 +17,22 @@ def save_example_findings():
|
|||
# people inconclusive = 2
|
||||
# networks inconclusive = 2
|
||||
Finding.save_finding(TEST_SCHEDULED_EXECUTION, STATUS_INCONCLUSIVE, [])
|
||||
# data conclusive 1
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_CONCLUSIVE, [])
|
||||
# data conclusive 2
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_CONCLUSIVE, [])
|
||||
# data conclusive 3
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_CONCLUSIVE, [])
|
||||
# data conclusive 4
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_CONCLUSIVE, [])
|
||||
# data conclusive 5
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_CONCLUSIVE, [])
|
||||
# data failed 1
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_FAILED, [])
|
||||
# data failed 2
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_FAILED, [])
|
||||
# data failed 3
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_FAILED, [])
|
||||
# data failed 4
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_FAILED, [])
|
||||
# data failed 5
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_FAILED, [])
|
||||
# data inconclusive 1
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_INCONCLUSIVE, [])
|
||||
# data inconclusive 2
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_INCONCLUSIVE, [])
|
||||
# data positive 1
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_POSITIVE, [])
|
||||
# data passed 1
|
||||
Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_PASSED, [])
|
||||
|
||||
|
||||
class TestZeroTrustService(IslandTestCase):
|
||||
|
@ -44,52 +44,52 @@ class TestZeroTrustService(IslandTestCase):
|
|||
|
||||
expected = [
|
||||
{
|
||||
"Conclusive": 5,
|
||||
"Inconclusive": 2,
|
||||
"Positive": 1,
|
||||
"Unexecuted": 1,
|
||||
STATUS_FAILED: 5,
|
||||
STATUS_INCONCLUSIVE: 2,
|
||||
STATUS_PASSED: 1,
|
||||
STATUS_UNEXECUTED: 1,
|
||||
"pillar": "Data"
|
||||
},
|
||||
{
|
||||
"Conclusive": 0,
|
||||
"Inconclusive": 2,
|
||||
"Positive": 0,
|
||||
"Unexecuted": 0,
|
||||
STATUS_FAILED: 0,
|
||||
STATUS_INCONCLUSIVE: 2,
|
||||
STATUS_PASSED: 0,
|
||||
STATUS_UNEXECUTED: 0,
|
||||
"pillar": "People"
|
||||
},
|
||||
{
|
||||
"Conclusive": 0,
|
||||
"Inconclusive": 2,
|
||||
"Positive": 0,
|
||||
"Unexecuted": 2,
|
||||
STATUS_FAILED: 0,
|
||||
STATUS_INCONCLUSIVE: 2,
|
||||
STATUS_PASSED: 0,
|
||||
STATUS_UNEXECUTED: 2,
|
||||
"pillar": "Networks"
|
||||
},
|
||||
{
|
||||
"Conclusive": 1,
|
||||
"Inconclusive": 0,
|
||||
"Positive": 2,
|
||||
"Unexecuted": 1,
|
||||
STATUS_FAILED: 1,
|
||||
STATUS_INCONCLUSIVE: 0,
|
||||
STATUS_PASSED: 2,
|
||||
STATUS_UNEXECUTED: 1,
|
||||
"pillar": "Devices"
|
||||
},
|
||||
{
|
||||
"Conclusive": 0,
|
||||
"Inconclusive": 0,
|
||||
"Positive": 0,
|
||||
"Unexecuted": 0,
|
||||
STATUS_FAILED: 0,
|
||||
STATUS_INCONCLUSIVE: 0,
|
||||
STATUS_PASSED: 0,
|
||||
STATUS_UNEXECUTED: 0,
|
||||
"pillar": "Workloads"
|
||||
},
|
||||
{
|
||||
"Conclusive": 0,
|
||||
"Inconclusive": 0,
|
||||
"Positive": 0,
|
||||
"Unexecuted": 1,
|
||||
STATUS_FAILED: 0,
|
||||
STATUS_INCONCLUSIVE: 0,
|
||||
STATUS_PASSED: 0,
|
||||
STATUS_UNEXECUTED: 1,
|
||||
"pillar": "Visibility & Analytics"
|
||||
},
|
||||
{
|
||||
"Conclusive": 0,
|
||||
"Inconclusive": 0,
|
||||
"Positive": 0,
|
||||
"Unexecuted": 0,
|
||||
STATUS_FAILED: 0,
|
||||
STATUS_INCONCLUSIVE: 0,
|
||||
STATUS_PASSED: 0,
|
||||
STATUS_UNEXECUTED: 0,
|
||||
"pillar": "Automation & Orchestration"
|
||||
}
|
||||
]
|
||||
|
@ -109,14 +109,14 @@ class TestZeroTrustService(IslandTestCase):
|
|||
DATA: [
|
||||
{
|
||||
"recommendation": RECOMMENDATIONS[RECOMMENDATION_DATA_TRANSIT],
|
||||
"status": STATUS_CONCLUSIVE,
|
||||
"status": STATUS_FAILED,
|
||||
"tests": [
|
||||
{
|
||||
"status": STATUS_UNEXECUTED,
|
||||
"test": TESTS_MAP[TEST_DATA_ENDPOINT_ELASTIC][TEST_EXPLANATION_KEY]
|
||||
},
|
||||
{
|
||||
"status": STATUS_CONCLUSIVE,
|
||||
"status": STATUS_FAILED,
|
||||
"test": TESTS_MAP[TEST_DATA_ENDPOINT_HTTP][TEST_EXPLANATION_KEY]
|
||||
}
|
||||
]
|
||||
|
@ -125,10 +125,10 @@ class TestZeroTrustService(IslandTestCase):
|
|||
DEVICES: [
|
||||
{
|
||||
"recommendation": RECOMMENDATIONS[RECOMMENDATION_ENDPOINT_SECURITY],
|
||||
"status": STATUS_CONCLUSIVE,
|
||||
"status": STATUS_FAILED,
|
||||
"tests": [
|
||||
{
|
||||
"status": STATUS_CONCLUSIVE,
|
||||
"status": STATUS_FAILED,
|
||||
"test": TESTS_MAP[TEST_ENDPOINT_SECURITY_EXISTS][TEST_EXPLANATION_KEY]
|
||||
},
|
||||
{
|
||||
|
@ -221,12 +221,12 @@ class TestZeroTrustService(IslandTestCase):
|
|||
|
||||
expected = {
|
||||
AUTOMATION_ORCHESTRATION: STATUS_UNEXECUTED,
|
||||
DEVICES: STATUS_CONCLUSIVE,
|
||||
DEVICES: STATUS_FAILED,
|
||||
NETWORKS: STATUS_INCONCLUSIVE,
|
||||
PEOPLE: STATUS_INCONCLUSIVE,
|
||||
VISIBILITY_ANALYTICS: STATUS_UNEXECUTED,
|
||||
WORKLOADS: STATUS_UNEXECUTED,
|
||||
DATA: STATUS_CONCLUSIVE
|
||||
DATA: STATUS_FAILED
|
||||
}
|
||||
|
||||
self.assertEquals(ZeroTrustService.get_pillars_to_statuses(), expected)
|
||||
|
|
|
@ -16,9 +16,9 @@ class ZeroTrustService(object):
|
|||
all_findings = Finding.objects()
|
||||
pillar_grade = {
|
||||
"pillar": pillar,
|
||||
STATUS_CONCLUSIVE: 0,
|
||||
STATUS_FAILED: 0,
|
||||
STATUS_INCONCLUSIVE: 0,
|
||||
STATUS_POSITIVE: 0,
|
||||
STATUS_PASSED: 0,
|
||||
STATUS_UNEXECUTED: 0
|
||||
}
|
||||
|
||||
|
@ -123,9 +123,9 @@ class ZeroTrustService(object):
|
|||
@staticmethod
|
||||
def get_statuses_to_pillars():
|
||||
results = {
|
||||
STATUS_CONCLUSIVE: [],
|
||||
STATUS_FAILED: [],
|
||||
STATUS_INCONCLUSIVE: [],
|
||||
STATUS_POSITIVE: [],
|
||||
STATUS_PASSED: [],
|
||||
STATUS_UNEXECUTED: []
|
||||
}
|
||||
for pillar in PILLARS:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from monkey_island.cc.services.node import NodeService
|
||||
from monkey_island.cc.services.telemetry.zero_trust_tests.segmentation import \
|
||||
test_positive_findings_for_unreached_segments
|
||||
test_passed_findings_for_unreached_segments
|
||||
|
||||
|
||||
def process_state_telemetry(telemetry_json):
|
||||
|
@ -12,4 +12,4 @@ def process_state_telemetry(telemetry_json):
|
|||
NodeService.set_monkey_dead(monkey, False)
|
||||
|
||||
if telemetry_json['data']['done']:
|
||||
test_positive_findings_for_unreached_segments(telemetry_json)
|
||||
test_passed_findings_for_unreached_segments(telemetry_json)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import json
|
||||
|
||||
from common.data.zero_trust_consts import EVENT_TYPE_MONKEY_LOCAL, EVENT_TYPE_ISLAND, \
|
||||
STATUS_POSITIVE, STATUS_CONCLUSIVE, TEST_ENDPOINT_SECURITY_EXISTS
|
||||
STATUS_PASSED, STATUS_FAILED, TEST_ENDPOINT_SECURITY_EXISTS
|
||||
from monkey_island.cc.models import Monkey
|
||||
from monkey_island.cc.models.zero_trust.event import Event
|
||||
from monkey_island.cc.models.zero_trust.finding import Finding
|
||||
|
@ -28,9 +28,9 @@ def test_antivirus_existence(telemetry_json):
|
|||
))
|
||||
|
||||
if len(av_processes) > 0:
|
||||
test_status = STATUS_POSITIVE
|
||||
test_status = STATUS_PASSED
|
||||
else:
|
||||
test_status = STATUS_CONCLUSIVE
|
||||
test_status = STATUS_FAILED
|
||||
Finding.save_finding(test=TEST_ENDPOINT_SECURITY_EXISTS, status=test_status, events=events)
|
||||
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ HTTP_SERVERS_SERVICES_NAMES = ['tcp-80']
|
|||
def test_open_data_endpoints(telemetry_json):
|
||||
services = telemetry_json["data"]["machine"]["services"]
|
||||
current_monkey = Monkey.get_single_monkey_by_guid(telemetry_json['monkey_guid'])
|
||||
found_http_server_status = STATUS_POSITIVE
|
||||
found_elastic_search_server = STATUS_POSITIVE
|
||||
found_http_server_status = STATUS_PASSED
|
||||
found_elastic_search_server = STATUS_PASSED
|
||||
|
||||
events = [
|
||||
Event.create_event(
|
||||
|
@ -32,7 +32,7 @@ def test_open_data_endpoints(telemetry_json):
|
|||
event_type=EVENT_TYPE_ISLAND
|
||||
))
|
||||
if service_name in HTTP_SERVERS_SERVICES_NAMES:
|
||||
found_http_server_status = STATUS_CONCLUSIVE
|
||||
found_http_server_status = STATUS_FAILED
|
||||
events.append(Event.create_event(
|
||||
title="Scan telemetry analysis",
|
||||
message="Service {} on {} recognized as an open data endpoint! Service details: {}".format(
|
||||
|
@ -43,7 +43,7 @@ def test_open_data_endpoints(telemetry_json):
|
|||
event_type=EVENT_TYPE_ISLAND
|
||||
))
|
||||
if service_name in 'elastic-search-9200':
|
||||
found_elastic_search_server = STATUS_CONCLUSIVE
|
||||
found_elastic_search_server = STATUS_FAILED
|
||||
events.append(Event.create_event(
|
||||
title="Scan telemetry analysis",
|
||||
message="Service {} on {} recognized as an open data endpoint! Service details: {}".format(
|
||||
|
|
|
@ -18,7 +18,7 @@ def test_machine_exploited(telemetry_json):
|
|||
)
|
||||
]
|
||||
|
||||
status = STATUS_POSITIVE
|
||||
status = STATUS_PASSED
|
||||
|
||||
if telemetry_json['data']['result']:
|
||||
events.append(
|
||||
|
@ -31,7 +31,7 @@ def test_machine_exploited(telemetry_json):
|
|||
event_type=EVENT_TYPE_MONKEY_NETWORK,
|
||||
timestamp=telemetry_json['timestamp'])
|
||||
)
|
||||
status = STATUS_CONCLUSIVE
|
||||
status = STATUS_FAILED
|
||||
|
||||
Finding.save_finding(
|
||||
test=TEST_MACHINE_EXPLOITED,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import itertools
|
||||
from six import text_type
|
||||
|
||||
from common.data.zero_trust_consts import STATUS_CONCLUSIVE, EVENT_TYPE_MONKEY_NETWORK, STATUS_POSITIVE, \
|
||||
from common.data.zero_trust_consts import STATUS_FAILED, EVENT_TYPE_MONKEY_NETWORK, STATUS_PASSED, \
|
||||
EVENT_TYPE_ISLAND
|
||||
from common.network.network_range import NetworkRange
|
||||
from common.network.segmentation_utils import get_ip_in_src_and_not_in_dst, get_ip_if_in_subnet
|
||||
|
@ -45,7 +45,7 @@ def test_segmentation_violation(scan_telemetry_json):
|
|||
event = get_segmentation_violation_event(current_monkey, source_subnet, target_ip, target_subnet)
|
||||
SegmentationFinding.create_or_add_to_existing_finding(
|
||||
subnets=[source_subnet, target_subnet],
|
||||
status=STATUS_CONCLUSIVE,
|
||||
status=STATUS_FAILED,
|
||||
segmentation_event=event
|
||||
)
|
||||
|
||||
|
@ -64,7 +64,7 @@ def get_segmentation_violation_event(current_monkey, source_subnet, target_ip, t
|
|||
)
|
||||
|
||||
|
||||
def test_positive_findings_for_unreached_segments(state_telemetry_json):
|
||||
def test_passed_findings_for_unreached_segments(state_telemetry_json):
|
||||
flat_all_subnets = [item for sublist in get_config_network_segments_as_subnet_groups() for item in sublist]
|
||||
current_monkey = Monkey.get_single_monkey_by_guid(state_telemetry_json['monkey_guid'])
|
||||
create_or_add_findings_for_all_pairs(flat_all_subnets, current_monkey)
|
||||
|
@ -87,7 +87,7 @@ def create_or_add_findings_for_all_pairs(all_subnets, current_monkey):
|
|||
for subnet_pair in all_subnets_pairs_for_this_monkey:
|
||||
SegmentationFinding.create_or_add_to_existing_finding(
|
||||
subnets=list(subnet_pair),
|
||||
status=STATUS_POSITIVE,
|
||||
status=STATUS_PASSED,
|
||||
segmentation_event=Event.create_event(
|
||||
"Segmentation test done",
|
||||
message="Monkey on {hostname} is done attempting cross-segment communications from `{src_seg}` "
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import uuid
|
||||
|
||||
from common.data.zero_trust_consts import TEST_SEGMENTATION, STATUS_POSITIVE, STATUS_CONCLUSIVE, \
|
||||
from common.data.zero_trust_consts import TEST_SEGMENTATION, STATUS_PASSED, STATUS_FAILED, \
|
||||
EVENT_TYPE_MONKEY_NETWORK
|
||||
from monkey_island.cc.models import Monkey
|
||||
from monkey_island.cc.models.zero_trust.event import Event
|
||||
|
@ -32,20 +32,15 @@ class TestSegmentationTests(IslandTestCase):
|
|||
create_or_add_findings_for_all_pairs(all_subnets, monkey)
|
||||
|
||||
# There are 2 subnets in which the monkey is NOT
|
||||
self.assertEquals(len(Finding.objects(test=TEST_SEGMENTATION, status=STATUS_POSITIVE)), 2)
|
||||
self.assertEquals(len(Finding.objects(test=TEST_SEGMENTATION, status=STATUS_PASSED)), 2)
|
||||
|
||||
# This is a monkey from 2nd subnet communicated with 1st subnet.
|
||||
SegmentationFinding.create_or_add_to_existing_finding(
|
||||
[FIRST_SUBNET, SECOND_SUBNET],
|
||||
STATUS_CONCLUSIVE,
|
||||
STATUS_FAILED,
|
||||
Event.create_event(title="sdf", message="asd", event_type=EVENT_TYPE_MONKEY_NETWORK)
|
||||
)
|
||||
|
||||
print("Printing all segmentation findings")
|
||||
all_findings = Finding.objects(test=TEST_SEGMENTATION)
|
||||
for f in all_findings:
|
||||
print(f.to_json())
|
||||
|
||||
self.assertEquals(len(Finding.objects(test=TEST_SEGMENTATION, status=STATUS_POSITIVE)), 1)
|
||||
self.assertEquals(len(Finding.objects(test=TEST_SEGMENTATION, status=STATUS_CONCLUSIVE)), 1)
|
||||
self.assertEquals(len(Finding.objects(test=TEST_SEGMENTATION, status=STATUS_PASSED)), 1)
|
||||
self.assertEquals(len(Finding.objects(test=TEST_SEGMENTATION, status=STATUS_FAILED)), 1)
|
||||
self.assertEquals(len(Finding.objects(test=TEST_SEGMENTATION)), 2)
|
||||
|
|
|
@ -12,6 +12,7 @@ import StatusesToPillarsSummary from "../report-components/zerotrust/StatusesToP
|
|||
import PrintReportButton from "../report-components/common/PrintReportButton";
|
||||
import {extractExecutionStatusFromServerResponse} from "../report-components/common/ExecutionStatus";
|
||||
import ZeroTrustReportLegend from "../report-components/zerotrust/ReportLegend";
|
||||
import {ZeroTrustStatuses} from "../report-components/zerotrust/ZeroTrustPillars";
|
||||
|
||||
class ZeroTrustReportPageComponent extends AuthComponent {
|
||||
|
||||
|
@ -179,14 +180,6 @@ class ZeroTrustReportPageComponent extends AuthComponent {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
anyIssuesFound() {
|
||||
const severe = function(finding) {
|
||||
return (finding.status === "Conclusive" || finding.status === "Inconclusive");
|
||||
};
|
||||
|
||||
return this.state.findings.some(severe);
|
||||
}
|
||||
}
|
||||
|
||||
export default ZeroTrustReportPageComponent;
|
||||
|
|
|
@ -1,27 +1,11 @@
|
|||
import React, {Component} from "react";
|
||||
import PillarLabel from "./PillarLabel";
|
||||
import * as PropTypes from "prop-types";
|
||||
import ResponsiveVennDiagram from "./venn-components/ResponsiveVennDiagram";
|
||||
|
||||
const columns = [
|
||||
{
|
||||
Header: 'Pillar Grading',
|
||||
columns: [
|
||||
{ Header: 'Pillar', id: 'Pillar', accessor: x => {
|
||||
return (<PillarLabel pillar={x.pillar.name} status={x.pillar.status} />);
|
||||
}},
|
||||
{ Header: 'Conclusive', accessor: 'Conclusive'},
|
||||
{ Header: 'Inconclusive', accessor: 'Inconclusive'},
|
||||
{ Header: 'Unexecuted', accessor: 'Unexecuted'},
|
||||
{ Header: 'Positive', accessor: 'Positive'},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
class PillarOverview extends Component {
|
||||
render() {
|
||||
return (<div id={this.constructor.name}>
|
||||
<ResponsiveVennDiagram pillarsGrades={this.props.grades} />
|
||||
<ResponsiveVennDiagram pillarsGrades={this.props.grades}/>
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import AuthComponent from "../../AuthComponent";
|
|||
import 'styles/ZeroTrustPillars.css'
|
||||
import StatusLabel from "./StatusLabel";
|
||||
import * as PropTypes from "prop-types";
|
||||
import {ZeroTrustStatuses} from "./ZeroTrustPillars";
|
||||
|
||||
|
||||
const columns = [
|
||||
|
@ -30,17 +31,12 @@ const columns = [
|
|||
|
||||
class TestsStatus extends AuthComponent {
|
||||
render() {
|
||||
const positiveStatus = "Positive";
|
||||
const conclusiveStatus = "Conclusive";
|
||||
const inconclusiveStatus = "Inconclusive";
|
||||
const unexecutedStatus = "Unexecuted";
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{this.getFilteredTestsByStatusIfAny(conclusiveStatus)}
|
||||
{this.getFilteredTestsByStatusIfAny(inconclusiveStatus)}
|
||||
{this.getFilteredTestsByStatusIfAny(positiveStatus)}
|
||||
{this.getFilteredTestsByStatusIfAny(unexecutedStatus)}
|
||||
{this.getFilteredTestsByStatusIfAny(ZeroTrustStatuses.failed)}
|
||||
{this.getFilteredTestsByStatusIfAny(ZeroTrustStatuses.inconclusive)}
|
||||
{this.getFilteredTestsByStatusIfAny(ZeroTrustStatuses.passed)}
|
||||
{this.getFilteredTestsByStatusIfAny(ZeroTrustStatuses.unexecuted)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ class ZeroTrustReportLegend extends Component {
|
|||
<ul style={{listStyle: "none"}}>
|
||||
<li>
|
||||
<div style={{display: "inline-block"}}>
|
||||
<StatusLabel showText={true} status={ZeroTrustStatuses.conclusive}/>
|
||||
<StatusLabel showText={true} status={ZeroTrustStatuses.failed}/>
|
||||
</div>
|
||||
{"\t"}The test failed; the monkeys found something wrong.
|
||||
</li>
|
||||
|
@ -50,7 +50,7 @@ class ZeroTrustReportLegend extends Component {
|
|||
</li>
|
||||
<li>
|
||||
<div style={{display: "inline-block"}}>
|
||||
<StatusLabel showText={true} status={ZeroTrustStatuses.positive}/>
|
||||
<StatusLabel showText={true} status={ZeroTrustStatuses.passed}/>
|
||||
</div>
|
||||
{"\t"}This status means the test passed 🙂
|
||||
</li>
|
||||
|
|
|
@ -2,16 +2,16 @@ import React, {Component} from "react";
|
|||
import * as PropTypes from "prop-types";
|
||||
|
||||
const statusToIcon = {
|
||||
"Positive": "fa-check",
|
||||
"Passed": "fa-check",
|
||||
"Inconclusive": "fa-exclamation-triangle",
|
||||
"Conclusive": "fa-bomb",
|
||||
"Failed": "fa-bomb",
|
||||
"Unexecuted": "fa-question",
|
||||
};
|
||||
|
||||
export const statusToLabelType = {
|
||||
"Positive": "label-success",
|
||||
"Passed": "label-success",
|
||||
"Inconclusive": "label-warning",
|
||||
"Conclusive": "label-danger",
|
||||
"Failed": "label-danger",
|
||||
"Unexecuted": "label-default",
|
||||
};
|
||||
|
||||
|
|
|
@ -2,14 +2,15 @@ import React, {Component, Fragment} from "react";
|
|||
import PillarLabel from "./PillarLabel";
|
||||
import StatusLabel from "./StatusLabel";
|
||||
import * as PropTypes from "prop-types";
|
||||
import {ZeroTrustStatuses} from "./ZeroTrustPillars";
|
||||
|
||||
export default class StatusesToPillarsSummary extends Component {
|
||||
render() {
|
||||
return (<div id="piilar-summary">
|
||||
{this.getStatusSummary("Conclusive")}
|
||||
{this.getStatusSummary("Inconclusive")}
|
||||
{this.getStatusSummary("Positive")}
|
||||
{this.getStatusSummary("Unexecuted")}
|
||||
{this.getStatusSummary(ZeroTrustStatuses.failed)}
|
||||
{this.getStatusSummary(ZeroTrustStatuses.inconclusive)}
|
||||
{this.getStatusSummary(ZeroTrustStatuses.passed)}
|
||||
{this.getStatusSummary(ZeroTrustStatuses.unexecuted)}
|
||||
</div>);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@ export const ZeroTrustPillars = {
|
|||
};
|
||||
|
||||
export const ZeroTrustStatuses = {
|
||||
conclusive: "Conclusive",
|
||||
failed: "Failed",
|
||||
inconclusive: "Inconclusive",
|
||||
positive: "Positive",
|
||||
passed: "Passed",
|
||||
unexecuted: "Unexecuted"
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import CircularNode from './CircularNode'
|
|||
import ArcNode from './ArcNode'
|
||||
import {TypographicUtilities} from './Utility.js'
|
||||
import './VennDiagram.css'
|
||||
import {ZeroTrustStatuses} from "../ZeroTrustPillars";
|
||||
|
||||
class VennDiagram extends React.Component {
|
||||
constructor(props_) {
|
||||
|
@ -14,7 +15,7 @@ class VennDiagram extends React.Component {
|
|||
this.width = this.height = 512;
|
||||
|
||||
this.prefix = 'vennDiagram';
|
||||
this.suffices = ['', '|tests are|conclusive', '|tests were|inconclusive', '|tests|performed'];
|
||||
this.suffices = ['', '|tests are|failed', '|tests were|inconclusive', '|tests|performed'];
|
||||
this.fontStyles = [{size: Math.max(9, this.width / 32), color: 'white'}, {
|
||||
size: Math.max(6, this.width / 52),
|
||||
color: 'black'
|
||||
|
@ -65,23 +66,23 @@ class VennDiagram extends React.Component {
|
|||
this.rules = [
|
||||
|
||||
{
|
||||
id: 'Rule #1', status: 'Unexecuted', hex: '#777777', f: function (d_) {
|
||||
return d_['Conclusive'] + d_['Inconclusive'] + d_['Positive'] === 0;
|
||||
id: 'Rule #1', status: ZeroTrustStatuses.unexecuted, hex: '#777777', f: function (d_) {
|
||||
return d_[ZeroTrustStatuses.failed] + d_[ZeroTrustStatuses.inconclusive] + d_[ZeroTrustStatuses.passed] === 0;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'Rule #2', status: 'Conclusive', hex: '#D9534F', f: function (d_) {
|
||||
return d_['Conclusive'] > 0;
|
||||
id: 'Rule #2', status: ZeroTrustStatuses.failed, hex: '#D9534F', f: function (d_) {
|
||||
return d_[ZeroTrustStatuses.failed] > 0;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'Rule #3', status: 'Inconclusive', hex: '#F0AD4E', f: function (d_) {
|
||||
return d_['Conclusive'] === 0 && d_['Inconclusive'] > 0;
|
||||
return d_[ZeroTrustStatuses.failed] === 0 && d_['Inconclusive'] > 0;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'Rule #4', status: 'Positive', hex: '#5CB85C', f: function (d_) {
|
||||
return d_['Positive'] + d_['Unexecuted'] >= 2 && d_['Positive'] * d_['Unexecuted'] > 0;
|
||||
id: 'Rule #4', status: ZeroTrustStatuses.passed, hex: '#5CB85C', f: function (d_) {
|
||||
return d_[ZeroTrustStatuses.passed] + d_[ZeroTrustStatuses.unexecuted] >= 2 && d_[ZeroTrustStatuses.passed] * d_[ZeroTrustStatuses.unexecuted] > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue