Skip to content

Commit d230909

Browse files
committed
Refactor security risk tests and update storage class references in configurations
1 parent a94a759 commit d230909

File tree

6 files changed

+305
-52
lines changed

6 files changed

+305
-52
lines changed

configurations/scenarios-test-env/attack-chain-5/01-mysql.yaml

-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ metadata:
66
labels:
77
type: local
88
spec:
9-
storageClassName: manual
109
capacity:
1110
storage: 20Gi
1211
accessModes:
@@ -20,7 +19,6 @@ kind: PersistentVolumeClaim
2019
metadata:
2120
name: mysql-pv-claim
2221
spec:
23-
storageClassName: manual
2422
accessModes:
2523
- ReadWriteOnce
2624
resources:

configurations/system/tests_cases/security_risks_tests.py

+21
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,27 @@
88

99
class SecurityRisksTests(object):
1010

11+
12+
@staticmethod
13+
def securityrisks_all():
14+
"""
15+
check multiple security risks scenarios.
16+
once the security risks has been detected on the backend, fix the security risks and verify that is has been solved
17+
by triggering a new control scan.
18+
"""
19+
from tests_scripts.helm.ks_microservice import ScanSecurityRisksWithKubescapeHelmChartMultiple
20+
return TestConfiguration(
21+
name=inspect.currentframe().f_code.co_name,
22+
test_obj=ScanSecurityRisksWithKubescapeHelmChartMultiple,
23+
test_job=[
24+
{"test_scenario": "attack-chain-5", "fix_object": "control", "security_risks_ids": ["R_0035"]}, # attack chain security risk
25+
{"test_scenario": "attack-chain-5", "fix_object": "control", "security_risks_ids": ["R_0005"]}, # control security risk
26+
# {"test_scenario": "attack-chain-5", "fix_object": "control", "security_risks_ids": ["R_0007"], "with_network_policy": True}, # control networkpolicy security risk
27+
{"test_scenario": "nginx", "fix_object": "vulnerability", "security_risks_ids": ["R_0037"]}, # vulnerability security risk
28+
],
29+
)
30+
31+
1132
@staticmethod
1233
# test security risks detection and resolve with kubescape helm chart
1334
# based on attack chain 5 scenarios.

system_test_mapping.json

+28-13
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@
897897
"skip_on_environment": "",
898898
"owner": "[email protected]"
899899
},
900-
"sr_r_0035_attack_chain": {
900+
"securityrisks_all": {
901901
"target": [
902902
"In cluster",
903903
"Backend"
@@ -912,16 +912,31 @@
912912
"skip_on_environment": "",
913913
"owner": "[email protected]"
914914
},
915+
"sr_r_0035_attack_chain": {
916+
"target": [
917+
"In cluster",
918+
"Backend"
919+
],
920+
"target_repositories": [
921+
"cadashboardbe-dummy",
922+
"careportsreceiver-dummy",
923+
"event-ingester-service-dummy",
924+
"gateway-dummy"
925+
],
926+
"description": "",
927+
"skip_on_environment": "",
928+
"owner": "[email protected]"
929+
},
915930
"sr_r_0005_control": {
916931
"target": [
917932
"In cluster",
918933
"Backend"
919934
],
920935
"target_repositories": [
921-
"cadashboardbe",
922-
"careportsreceiver",
923-
"event-ingester-service",
924-
"gateway"
936+
"cadashboardbe-dummy",
937+
"careportsreceiver-dummy",
938+
"event-ingester-service-dummy",
939+
"gateway-dummy"
925940
],
926941
"description": "",
927942
"skip_on_environment": "",
@@ -933,10 +948,10 @@
933948
"Backend"
934949
],
935950
"target_repositories": [
936-
"cadashboardbe",
937-
"careportsreceiver",
938-
"event-ingester-service",
939-
"gateway"
951+
"cadashboardbe-dummy",
952+
"careportsreceiver-dummy",
953+
"event-ingester-service-dummy",
954+
"gateway-dummy"
940955
],
941956
"description": "",
942957
"skip_on_environment": "",
@@ -948,10 +963,10 @@
948963
"Backend"
949964
],
950965
"target_repositories": [
951-
"cadashboardbe",
952-
"careportsreceiver",
953-
"event-ingester-service",
954-
"gateway"
966+
"cadashboardbe-dummy",
967+
"careportsreceiver-dummy",
968+
"event-ingester-service-dummy",
969+
"gateway-dummy"
955970
],
956971
"description": "test security risk vulnerability type, R-0037",
957972
"skip_on_environment": "",

systest_utils/scenarios_manager.py

+53-34
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def __init__(self, test_obj, backend: backend_api.ControlPanelAPI, cluster, name
5050
self.cluster = cluster
5151
self.scenario_path = scenario_path
5252
self.namespace = namespace
53+
self.scenario_key = self.test_scenario
5354

5455
def __del__(self):
5556
pass
@@ -100,6 +101,9 @@ def verify_scenario(self):
100101

101102
def verify_fix(self):
102103
raise Exception("Not implemented")
104+
105+
def construct_message(self,message):
106+
return f"{self.scenario_key}: cluster: {self.cluster}, namespace: {self.namespace}, message: {message}"
103107

104108

105109

@@ -244,11 +248,15 @@ class SecurityRisksScenarioManager(ScenarioManager):
244248

245249
def __init__(self, test_obj, backend: backend_api.ControlPanelAPI, cluster, namespace):
246250
super().__init__(test_obj, backend, cluster, namespace, SCENARIOS_TEST_PATH)
247-
251+
self.test_scenario = test_obj["test_job"][0].get("test_scenario", "not defined")
252+
self.fix_object = test_obj["test_job"][0].get("fix_object", "control")
248253
self.test_security_risk_ids = test_obj["test_job"][0].get("security_risks_ids", [])
254+
self.scenario_key = self.test_scenario + " fix: " + self.fix_object + " security_risk_ids: " + ','.join(self.test_security_risk_ids)
249255
self.with_network_policy = test_obj["test_job"][0].get("with_network_policy", False)
256+
Logger.logger.info(f"Generated ScenarioManager for {self.test_scenario} scenario on {self.cluster} cluster in {self.namespace} namespace")
250257

251-
def verify_scenario(self):
258+
259+
def verify_scenario(self, timeout=600):
252260
"""
253261
verify_scenario validate the security risks results on the backend
254262
validations supported:
@@ -263,34 +271,34 @@ def verify_scenario(self):
263271
Logger.logger.info("validating security risks list")
264272
res = self.wait_for_report(
265273
self.verify_security_risks_list,
266-
timeout=600,
267-
sleep_interval=10
274+
timeout=timeout,
275+
sleep_interval=15
268276
)
269277

270278
return res[0]
271279

272280

273-
def verify_fix(self):
281+
def verify_fix(self, timeout=600):
274282
"""
275283
verify_fix validate the security risks fix results on the backend
276284
"""
277285
Logger.logger.info("wait for response from BE")
278286
isEmpty, t = self.wait_for_report(
279287
self.is_security_risk_empty,
280288
security_risk_ids=self.test_security_risk_ids,
281-
timeout=600,
282-
sleep_interval=10
289+
timeout=timeout,
290+
sleep_interval=15
283291
)
284292

285293
return isEmpty
286294

287-
def apply_fix(self, fix_type):
295+
def apply_fix(self):
288296
"""
289297
apply_fix apply the fix to the cluster
290298
"""
291-
fix_command= os.path.join(self.scenario_path, self.test_scenario, "delete_deployments") + ' --namespace ' + self.namespace
299+
fix_command= "bash " + os.path.join(self.scenario_path, self.test_scenario, "delete_deployments") + ' --namespace ' + self.namespace
292300
TestUtil.run_command(command_args=fix_command, display_stdout=True, timeout=300)
293-
super().apply_fix(fix_type)
301+
# super().apply_fix(self.fix_object)
294302

295303
def get_exceptions_list(self):
296304
"""
@@ -459,7 +467,7 @@ def check_security_risks_resources_results(self, result, expected):
459467
}
460468

461469
if 'total' in result and 'total' in expected:
462-
assert result['total']['value'] == expected['total']['value'], f"'Total' value mismatch: result: {result['total']['value']} != expected: {expected['total']['value']}"
470+
assert result['total']['value'] == expected['total']['value'], self.construct_message(f"'Total' value mismatch: result: {result['total']['value']} != expected: {expected['total']['value']}")
463471

464472

465473
if 'response' in result and 'response' in expected:
@@ -485,7 +493,7 @@ def check_security_risks_results(self, result, expected):
485493

486494
if len(result['response']) != len(expected['response']):
487495
missingSecurityRiskIDs =self.find_missing_security_risks(result, expected)
488-
raise Exception(f"Length mismatch: result: {len(result['response'])} != expected: {len(expected['response'])}, missing security risks: {missingSecurityRiskIDs}")
496+
raise Exception(self.construct_message(f"Length mismatch: result: {len(result['response'])} != expected: {len(expected['response'])}, missing security risks: {missingSecurityRiskIDs}"))
489497

490498
compare_lists(result['response'], expected['response'], ignore_keys)
491499

@@ -499,10 +507,9 @@ def check_security_risks_categories(self, result, expected):
499507
assert "total" in result, f"'Total' key not found in the result"
500508

501509
if 'total' in result and 'total' in expected:
502-
assert result['total']['value'] == expected['total']['value'], f"'Total' value mismatch: result: {result['total']['value']} != expected: {expected['total']['value']}"
510+
assert result['total']['value'] == expected['total']['value'], self.construct_message(f"'Total' value mismatch: result: {result['total']['value']} != expected: {expected['total']['value']}")
503511

504-
505-
assert result['response'] == expected['response'], f"Security risks categories response differs from the expected one. Response: {result['response']}, Expected: {expected['response']}"
512+
assert result['response'] == expected['response'], self.construct_message(f"Security risks categories response differs from the expected one. Response: {result['response']}, Expected: {expected['response']}")
506513

507514

508515
def check_security_risks_severities(self, result, expected):
@@ -517,8 +524,8 @@ def check_security_risks_severities(self, result, expected):
517524
if 'total' in result and 'total' in expected:
518525
assert result['total']['value'] == expected['total']['value'], f"'Total' value mismatch: result: {result['total']['value']} != expected: {expected['total']['value']}"
519526

520-
assert result['response']['severityResourceCounter'] == expected['response']['severityResourceCounter'], f"Security risks severities resource counter response differs from the expected one. Response: {result['response']['severityResourceCounter']}, Expected: {expected['response']['severityResourceCounter']}"
521-
assert result['response']['totalResources'] == expected['response']['totalResources'], f"Security risks severities total resources response differs from the expected one. Response: {result['response']['totalResources']}, Expected: {expected['response']['totalResources']}"
527+
assert result['response']['severityResourceCounter'] == expected['response']['severityResourceCounter'], self.construct_message(f"Security risks severities resource counter response differs from the expected one. Response: {result['response']['severityResourceCounter']}, Expected: {expected['response']['severityResourceCounter']}")
528+
assert result['response']['totalResources'] == expected['response']['totalResources'], self.construct_message(f"Security risks severities total resources response differs from the expected one. Response: {result['response']['totalResources']}, Expected: {expected['response']['totalResources']}")
522529

523530

524531

@@ -548,7 +555,7 @@ def is_security_risk_resources_empty(self, security_risk_ids):
548555
)
549556

550557
response = json.loads(r.text)
551-
assert response['total']['value'] == 0, "Security risks resources found, expecting no security risks resources"
558+
assert response['total']['value'] == 0, self.construct_message("Security risks resources found, expecting no security risks resources")
552559
return True
553560

554561
def verify_security_risks_trends(self, expected_n_events_detected, expected_n_events_resolved, expected_current_detected, expected_change_from_beginning_of_period):
@@ -563,12 +570,12 @@ def verify_security_risks_trends(self, expected_n_events_detected, expected_n_ev
563570

564571
Logger.logger.info('comparing security risks trends result with expected ones')
565572

566-
assert len(response['securityIssuesTrends']) == EXPECTED_TRENDS_DAYS_BACK, f"Security risks trends response differs from the expected one. Response: {len(response['securityIssuesTrends'])} != Expected: {EXPECTED_TRENDS_DAYS_BACK}"
567-
568-
assert response["totalDetectedForPeriod"] == expected_n_events_detected, f"Security risks trends total detected for period response differs from the expected one. Response: {response['totalDetectedForPeriod']} != Expected: {expected_n_events_detected}"
569-
assert response["totalResolvedForPeriod"] == expected_n_events_resolved, f"Security risks trends total resolved for period response differs from the expected one. Response: {response['totalResolvedForPeriod']} != Expected: {expected_n_events_resolved}"
570-
assert response["currentDetected"] == expected_current_detected, f"Security risks trends current detected response differs from the expected one. Response: {response['currentDetected']} != Expected: {expected_current_detected}"
571-
assert response["changeFromBeginningOfPeriod"] == expected_change_from_beginning_of_period, f"Security risks trends change from beginning of period response differs from the expected one. Response: {response['changeFromBeginningOfPeriod']} != Expected: {expected_change_from_beginning_of_period}"
573+
assert len(response['securityIssuesTrends']) == EXPECTED_TRENDS_DAYS_BACK, self.construct_message(f"Security risks trends response differs from the expected one. Response: {len(response['securityIssuesTrends'])} != Expected: {EXPECTED_TRENDS_DAYS_BACK}")
574+
575+
assert response["totalDetectedForPeriod"] == expected_n_events_detected, self.construct_message(f"Security risks trends total detected for period response differs from the expected one. Response: {response['totalDetectedForPeriod']} != Expected: {expected_n_events_detected}")
576+
assert response["totalResolvedForPeriod"] == expected_n_events_resolved, self.construct_message(f"Security risks trends total resolved for period response differs from the expected one. Response: {response['totalResolvedForPeriod']} != Expected: {expected_n_events_resolved}")
577+
assert response["currentDetected"] == expected_current_detected, self.construct_message(f"Security risks trends current detected response differs from the expected one. Response: {response['currentDetected']} != Expected: {expected_current_detected}")
578+
assert response["changeFromBeginningOfPeriod"] == expected_change_from_beginning_of_period, self.construct_message(f"Security risks trends change from beginning of period response differs from the expected one. Response: {response['changeFromBeginningOfPeriod']} != Expected: {expected_change_from_beginning_of_period}")
572579

573580
def verify_security_risks_list_uniquevalues(self, list_result):
574581
"""
@@ -597,7 +604,7 @@ def verify_security_risks_list_uniquevalues(self, list_result):
597604
expected = summarize_uniquevalues(list_result, fieldName)
598605
response = json.loads(r.text)
599606

600-
assert response == expected, f"verify_security_risks_list_uniquevalues - security risks unique values for '{fieldName}' response differs from the expected one. Response: {response}, Expected: {expected}"
607+
assert response == expected, self.construct_message(f"security risks unique values for '{fieldName}' response differs from the expected one. Response: {response}, Expected: {expected}")
601608

602609

603610
def verify_security_risks_severities(self, list_result):
@@ -614,7 +621,10 @@ def verify_security_risks_severities(self, list_result):
614621
response = json.loads(r.text)
615622

616623
Logger.logger.info('comparing security risks severities result with expected ones')
617-
self.check_security_risks_severities(response, expected)
624+
try:
625+
self.check_security_risks_severities(response, expected)
626+
except Exception as e:
627+
raise Exception(self.construct_message(f"Failed to validate security risks severities: {e}, response: {response}, expected: {expected}"))
618628

619629
def verify_security_risks_categories(self, list_result):
620630
"""
@@ -630,26 +640,32 @@ def verify_security_risks_categories(self, list_result):
630640
response = json.loads(r.text)
631641

632642
Logger.logger.info('comparing security risks categories result with expected ones')
633-
self.check_security_risks_categories(response, expected)
643+
try:
644+
self.check_security_risks_categories(response, expected)
645+
except Exception as e:
646+
raise Exception(self.construct_message(f"Failed to validate security risks categories: {e}, response: {response}, expected: {expected}"))
634647

635648

636649
def verify_security_risks_list(self):
637650
"""
638651
verify_security_risks_list validate the security risks results on the backend
639652
"""
640653
# current_datetime = datetime.now(timezone.utc)
641-
Logger.logger.info("wait for response from BE")
654+
Logger.logger.info(f"getting security risks list for {self.test_security_risk_ids}, cluster: {self.cluster}, namespace: {self.namespace}")
642655
r = self.backend.get_security_risks_list(self.cluster, self.namespace, self.test_security_risk_ids)
643656

644-
Logger.logger.info('loading security risks scenario to validate it')
657+
Logger.logger.info(f"loading security risks scenario_key {self.scenario_key} to validate it")
645658
f = open(os.path.join(SCENARIOS_EXPECTED_VALUES, self.test_scenario+'_security-risks-list.json'))
646659
expected = json.load(f)
647660
response = json.loads(r.text)
648661

649662
filtered_expected = filter_security_risks_list(expected, self.test_security_risk_ids)
650663

651-
Logger.logger.info('comparing security risks result with expected ones')
652-
self.check_security_risks_results(response, filtered_expected)
664+
Logger.logger.info(self.construct_message("comparing security risks result with expected ones"))
665+
try:
666+
self.check_security_risks_results(response, filtered_expected)
667+
except Exception as e:
668+
raise Exception(self.construct_message(f"Failed to validate security risks list: {e}, response: {response}, expected: {filtered_expected}"))
653669

654670
return response
655671

@@ -661,16 +677,19 @@ def verify_security_risks_resources(self):
661677

662678
for security_risk_id, expectedPrefix in SECURITY_RISKS_RESOURCES_PREFIX.items():
663679
if security_risk_id in self.test_security_risk_ids:
664-
Logger.logger.info(f"wait for response from BE with filter: {security_risk_id}")
680+
Logger.logger.info(self.construct_message(f"getting security risks resources"))
665681
r = self.backend.get_security_risks_resources(self.cluster, self.namespace, security_risk_id)
666682

667683
Logger.logger.info('loading security risks scenario to validate it')
668684
f = open(os.path.join(SCENARIOS_EXPECTED_VALUES, self.test_scenario+expectedPrefix+'.json'))
669685
expected = json.load(f)
670686
response = json.loads(r.text)
671687

672-
Logger.logger.info('comparing security risks result with expected ones')
673-
self.check_security_risks_resources_results(response, expected)
688+
Logger.logger.info(self.construct_message(f"comparing security risks resources result with expected ones"))
689+
try:
690+
self.check_security_risks_resources_results(response, expected)
691+
except Exception as e:
692+
raise Exception(self.construct_message(f"Failed to validate security risks resources for scenario_key : {self.scenario_key}, security risk id: {security_risk_id}: {e}, response: {response}, expected: {expected}"))
674693

675694

676695
def find_missing_security_risks(self, result, expected):

0 commit comments

Comments
 (0)