regscale-cli 6.27.3.0__py3-none-any.whl → 6.28.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of regscale-cli might be problematic. Click here for more details.
- regscale/_version.py +1 -1
- regscale/core/app/utils/app_utils.py +11 -2
- regscale/dev/cli.py +26 -0
- regscale/dev/version.py +72 -0
- regscale/integrations/commercial/__init__.py +15 -1
- regscale/integrations/commercial/amazon/amazon/__init__.py +0 -0
- regscale/integrations/commercial/amazon/amazon/common.py +204 -0
- regscale/integrations/commercial/amazon/common.py +48 -58
- regscale/integrations/commercial/aws/audit_manager_compliance.py +2671 -0
- regscale/integrations/commercial/aws/cli.py +3093 -55
- regscale/integrations/commercial/aws/cloudtrail_control_mappings.py +333 -0
- regscale/integrations/commercial/aws/cloudtrail_evidence.py +501 -0
- regscale/integrations/commercial/aws/cloudwatch_control_mappings.py +357 -0
- regscale/integrations/commercial/aws/cloudwatch_evidence.py +490 -0
- regscale/integrations/commercial/aws/config_compliance.py +914 -0
- regscale/integrations/commercial/aws/conformance_pack_mappings.py +198 -0
- regscale/integrations/commercial/aws/evidence_generator.py +283 -0
- regscale/integrations/commercial/aws/guardduty_control_mappings.py +340 -0
- regscale/integrations/commercial/aws/guardduty_evidence.py +1053 -0
- regscale/integrations/commercial/aws/iam_control_mappings.py +368 -0
- regscale/integrations/commercial/aws/iam_evidence.py +574 -0
- regscale/integrations/commercial/aws/inventory/__init__.py +223 -22
- regscale/integrations/commercial/aws/inventory/base.py +107 -5
- regscale/integrations/commercial/aws/inventory/resources/audit_manager.py +513 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudtrail.py +315 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudtrail_logs_metadata.py +476 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudwatch.py +191 -0
- regscale/integrations/commercial/aws/inventory/resources/compute.py +66 -9
- regscale/integrations/commercial/aws/inventory/resources/config.py +464 -0
- regscale/integrations/commercial/aws/inventory/resources/containers.py +74 -9
- regscale/integrations/commercial/aws/inventory/resources/database.py +106 -31
- regscale/integrations/commercial/aws/inventory/resources/guardduty.py +286 -0
- regscale/integrations/commercial/aws/inventory/resources/iam.py +470 -0
- regscale/integrations/commercial/aws/inventory/resources/inspector.py +476 -0
- regscale/integrations/commercial/aws/inventory/resources/integration.py +175 -61
- regscale/integrations/commercial/aws/inventory/resources/kms.py +447 -0
- regscale/integrations/commercial/aws/inventory/resources/networking.py +103 -67
- regscale/integrations/commercial/aws/inventory/resources/s3.py +394 -0
- regscale/integrations/commercial/aws/inventory/resources/security.py +268 -72
- regscale/integrations/commercial/aws/inventory/resources/securityhub.py +473 -0
- regscale/integrations/commercial/aws/inventory/resources/storage.py +53 -29
- regscale/integrations/commercial/aws/inventory/resources/systems_manager.py +657 -0
- regscale/integrations/commercial/aws/inventory/resources/vpc.py +655 -0
- regscale/integrations/commercial/aws/kms_control_mappings.py +288 -0
- regscale/integrations/commercial/aws/kms_evidence.py +879 -0
- regscale/integrations/commercial/aws/ocsf/__init__.py +7 -0
- regscale/integrations/commercial/aws/ocsf/constants.py +115 -0
- regscale/integrations/commercial/aws/ocsf/mapper.py +435 -0
- regscale/integrations/commercial/aws/org_control_mappings.py +286 -0
- regscale/integrations/commercial/aws/org_evidence.py +666 -0
- regscale/integrations/commercial/aws/s3_control_mappings.py +356 -0
- regscale/integrations/commercial/aws/s3_evidence.py +632 -0
- regscale/integrations/commercial/aws/scanner.py +851 -206
- regscale/integrations/commercial/aws/security_hub.py +319 -0
- regscale/integrations/commercial/aws/session_manager.py +282 -0
- regscale/integrations/commercial/aws/ssm_control_mappings.py +291 -0
- regscale/integrations/commercial/aws/ssm_evidence.py +492 -0
- regscale/integrations/commercial/synqly/ticketing.py +27 -0
- regscale/integrations/compliance_integration.py +308 -38
- regscale/integrations/due_date_handler.py +3 -0
- regscale/integrations/scanner_integration.py +399 -84
- regscale/models/integration_models/cisa_kev_data.json +65 -5
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +17 -9
- regscale/models/regscale_models/assessment.py +2 -1
- regscale/models/regscale_models/control_objective.py +74 -5
- regscale/models/regscale_models/file.py +2 -0
- regscale/models/regscale_models/issue.py +2 -5
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/METADATA +1 -1
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/RECORD +113 -34
- tests/regscale/integrations/commercial/aws/__init__.py +0 -0
- tests/regscale/integrations/commercial/aws/test_audit_manager_compliance.py +1304 -0
- tests/regscale/integrations/commercial/aws/test_audit_manager_evidence_aggregation.py +341 -0
- tests/regscale/integrations/commercial/aws/test_aws_audit_manager_collector.py +1155 -0
- tests/regscale/integrations/commercial/aws/test_aws_cloudtrail_collector.py +534 -0
- tests/regscale/integrations/commercial/aws/test_aws_config_collector.py +400 -0
- tests/regscale/integrations/commercial/aws/test_aws_guardduty_collector.py +315 -0
- tests/regscale/integrations/commercial/aws/test_aws_iam_collector.py +458 -0
- tests/regscale/integrations/commercial/aws/test_aws_inspector_collector.py +353 -0
- tests/regscale/integrations/commercial/aws/test_aws_inventory_integration.py +530 -0
- tests/regscale/integrations/commercial/aws/test_aws_kms_collector.py +919 -0
- tests/regscale/integrations/commercial/aws/test_aws_s3_collector.py +722 -0
- tests/regscale/integrations/commercial/aws/test_aws_scanner_integration.py +722 -0
- tests/regscale/integrations/commercial/aws/test_aws_securityhub_collector.py +792 -0
- tests/regscale/integrations/commercial/aws/test_aws_systems_manager_collector.py +918 -0
- tests/regscale/integrations/commercial/aws/test_aws_vpc_collector.py +996 -0
- tests/regscale/integrations/commercial/aws/test_cli_evidence.py +431 -0
- tests/regscale/integrations/commercial/aws/test_cloudtrail_control_mappings.py +452 -0
- tests/regscale/integrations/commercial/aws/test_cloudtrail_evidence.py +788 -0
- tests/regscale/integrations/commercial/aws/test_config_compliance.py +298 -0
- tests/regscale/integrations/commercial/aws/test_conformance_pack_mappings.py +200 -0
- tests/regscale/integrations/commercial/aws/test_evidence_generator.py +386 -0
- tests/regscale/integrations/commercial/aws/test_guardduty_control_mappings.py +564 -0
- tests/regscale/integrations/commercial/aws/test_guardduty_evidence.py +1041 -0
- tests/regscale/integrations/commercial/aws/test_iam_control_mappings.py +718 -0
- tests/regscale/integrations/commercial/aws/test_iam_evidence.py +1375 -0
- tests/regscale/integrations/commercial/aws/test_kms_control_mappings.py +656 -0
- tests/regscale/integrations/commercial/aws/test_kms_evidence.py +1163 -0
- tests/regscale/integrations/commercial/aws/test_ocsf_mapper.py +370 -0
- tests/regscale/integrations/commercial/aws/test_org_control_mappings.py +546 -0
- tests/regscale/integrations/commercial/aws/test_org_evidence.py +1240 -0
- tests/regscale/integrations/commercial/aws/test_s3_control_mappings.py +672 -0
- tests/regscale/integrations/commercial/aws/test_s3_evidence.py +987 -0
- tests/regscale/integrations/commercial/aws/test_scanner_evidence.py +373 -0
- tests/regscale/integrations/commercial/aws/test_security_hub_config_filtering.py +539 -0
- tests/regscale/integrations/commercial/aws/test_session_manager.py +516 -0
- tests/regscale/integrations/commercial/aws/test_ssm_control_mappings.py +588 -0
- tests/regscale/integrations/commercial/aws/test_ssm_evidence.py +735 -0
- tests/regscale/integrations/commercial/test_aws.py +55 -56
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/LICENSE +0 -0
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/WHEEL +0 -0
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Unit tests for AWS Audit Manager Evidence-Based Compliance Aggregation."""
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
|
|
7
|
+
from regscale.integrations.commercial.aws.audit_manager_compliance import AWSAuditManagerComplianceItem
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestEvidenceAggregation(unittest.TestCase):
|
|
11
|
+
"""Test cases for evidence-based compliance aggregation logic."""
|
|
12
|
+
|
|
13
|
+
def setUp(self):
|
|
14
|
+
"""Set up test fixtures."""
|
|
15
|
+
self.assessment_data = {
|
|
16
|
+
"name": "Test Assessment",
|
|
17
|
+
"arn": "arn:aws:auditmanager:us-east-1:123456789012:assessment/test",
|
|
18
|
+
"framework": {"type": "Standard", "metadata": {"name": "NIST SP 800-53 Revision 5"}},
|
|
19
|
+
"complianceType": "NIST800-53",
|
|
20
|
+
"awsAccount": {"id": "123456789012", "name": "Test Account"},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
self.control_data = {
|
|
24
|
+
"id": "test-control-id",
|
|
25
|
+
"name": "CP-10(2) - Transaction Recovery",
|
|
26
|
+
"description": "Control description",
|
|
27
|
+
"status": "REVIEWED", # Workflow status - not used for compliance
|
|
28
|
+
"evidenceCount": 8,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def test_all_compliant_evidence_passes(self):
|
|
32
|
+
"""Test that all COMPLIANT evidence results in PASS."""
|
|
33
|
+
evidence = [
|
|
34
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Security Hub"},
|
|
35
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
36
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Security Hub"},
|
|
37
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
41
|
+
self.assertEqual(item.compliance_result, "PASS")
|
|
42
|
+
|
|
43
|
+
def test_any_failed_evidence_fails_control(self):
|
|
44
|
+
"""Test that ANY FAILED evidence causes control to FAIL."""
|
|
45
|
+
evidence = [
|
|
46
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
47
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
48
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
49
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"}, # ONE failure
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
53
|
+
self.assertEqual(item.compliance_result, "FAIL")
|
|
54
|
+
|
|
55
|
+
def test_multiple_failed_evidence_fails_control(self):
|
|
56
|
+
"""Test that multiple FAILED evidence items causes control to FAIL."""
|
|
57
|
+
evidence = [
|
|
58
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
59
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
60
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
61
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
65
|
+
self.assertEqual(item.compliance_result, "FAIL")
|
|
66
|
+
|
|
67
|
+
def test_all_failed_evidence_fails_control(self):
|
|
68
|
+
"""Test that all FAILED evidence results in FAIL."""
|
|
69
|
+
evidence = [
|
|
70
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
71
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
72
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
76
|
+
self.assertEqual(item.compliance_result, "FAIL")
|
|
77
|
+
|
|
78
|
+
def test_no_evidence_returns_none(self):
|
|
79
|
+
"""Test that no evidence results in None (control should not be updated)."""
|
|
80
|
+
evidence = []
|
|
81
|
+
|
|
82
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
83
|
+
self.assertIsNone(item.compliance_result)
|
|
84
|
+
|
|
85
|
+
def test_none_evidence_returns_none(self):
|
|
86
|
+
"""Test that None evidence results in None (control should not be updated)."""
|
|
87
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, None)
|
|
88
|
+
self.assertIsNone(item.compliance_result)
|
|
89
|
+
|
|
90
|
+
def test_inconclusive_evidence_only_returns_none(self):
|
|
91
|
+
"""Test that only inconclusive evidence (null checks) results in None (control should not be updated)."""
|
|
92
|
+
evidence = [
|
|
93
|
+
{"dataSource": "AWS CloudTrail"}, # No complianceCheck field
|
|
94
|
+
{"complianceCheck": None, "dataSource": "Manual"},
|
|
95
|
+
{"dataSource": "API Call"}, # No complianceCheck field
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
99
|
+
self.assertIsNone(item.compliance_result)
|
|
100
|
+
|
|
101
|
+
def test_compliant_with_inconclusive_passes(self):
|
|
102
|
+
"""Test that COMPLIANT evidence with some inconclusive results in PASS."""
|
|
103
|
+
evidence = [
|
|
104
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Security Hub"},
|
|
105
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
106
|
+
{"dataSource": "AWS CloudTrail"}, # No complianceCheck
|
|
107
|
+
{"complianceCheck": None, "dataSource": "Manual"}, # Null check
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
111
|
+
self.assertEqual(item.compliance_result, "PASS")
|
|
112
|
+
|
|
113
|
+
def test_failed_with_inconclusive_fails(self):
|
|
114
|
+
"""Test that FAILED evidence with inconclusive results in FAIL."""
|
|
115
|
+
evidence = [
|
|
116
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
117
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
118
|
+
{"dataSource": "AWS CloudTrail"}, # No complianceCheck
|
|
119
|
+
{"complianceCheck": None, "dataSource": "Manual"}, # Null check
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
123
|
+
self.assertEqual(item.compliance_result, "FAIL")
|
|
124
|
+
|
|
125
|
+
def test_real_world_mixed_evidence_cp10(self):
|
|
126
|
+
"""Test real-world scenario: CP-10(2) with 4 COMPLIANT and 4 FAILED."""
|
|
127
|
+
# Based on actual audit_manager_evidence_cp_10(2)_2025-10-17.jsonl data
|
|
128
|
+
evidence = [
|
|
129
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
130
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
131
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
132
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
133
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
134
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
135
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
136
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
140
|
+
# Should FAIL because there are FAILED evidence items
|
|
141
|
+
self.assertEqual(item.compliance_result, "FAIL")
|
|
142
|
+
|
|
143
|
+
def test_workflow_status_not_used_for_compliance(self):
|
|
144
|
+
"""Test that control workflow status (REVIEWED) does NOT determine compliance."""
|
|
145
|
+
# Control marked as REVIEWED (workflow status) but has failing evidence
|
|
146
|
+
self.control_data["status"] = "REVIEWED"
|
|
147
|
+
evidence = [
|
|
148
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
152
|
+
# Should FAIL based on evidence, not REVIEWED status
|
|
153
|
+
self.assertEqual(item.compliance_result, "FAIL")
|
|
154
|
+
# Verify workflow status is still REVIEWED
|
|
155
|
+
self.assertEqual(item.control_status, "REVIEWED")
|
|
156
|
+
|
|
157
|
+
def test_under_review_with_passing_evidence(self):
|
|
158
|
+
"""Test that UNDER_REVIEW workflow status with passing evidence results in PASS."""
|
|
159
|
+
self.control_data["status"] = "UNDER_REVIEW"
|
|
160
|
+
evidence = [
|
|
161
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
162
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Security Hub"},
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
166
|
+
# Should PASS based on evidence, regardless of UNDER_REVIEW status
|
|
167
|
+
self.assertEqual(item.compliance_result, "PASS")
|
|
168
|
+
# Verify workflow status is still UNDER_REVIEW
|
|
169
|
+
self.assertEqual(item.control_status, "UNDER_REVIEW")
|
|
170
|
+
|
|
171
|
+
def test_compliance_result_caching(self):
|
|
172
|
+
"""Test that compliance result is cached after first calculation."""
|
|
173
|
+
evidence = [
|
|
174
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
175
|
+
]
|
|
176
|
+
|
|
177
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
178
|
+
|
|
179
|
+
# First call
|
|
180
|
+
result1 = item.compliance_result
|
|
181
|
+
self.assertEqual(result1, "PASS")
|
|
182
|
+
|
|
183
|
+
# Verify cached value is used
|
|
184
|
+
self.assertEqual(item._aggregated_compliance_result, "PASS")
|
|
185
|
+
|
|
186
|
+
# Second call should return same cached result
|
|
187
|
+
result2 = item.compliance_result
|
|
188
|
+
self.assertEqual(result2, "PASS")
|
|
189
|
+
|
|
190
|
+
def test_severity_when_passed(self):
|
|
191
|
+
"""Test that severity is None when control passes."""
|
|
192
|
+
evidence = [
|
|
193
|
+
{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"},
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
197
|
+
self.assertIsNone(item.severity)
|
|
198
|
+
|
|
199
|
+
def test_severity_when_failed(self):
|
|
200
|
+
"""Test that severity is set when control fails."""
|
|
201
|
+
evidence = [
|
|
202
|
+
{"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"},
|
|
203
|
+
]
|
|
204
|
+
|
|
205
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
206
|
+
self.assertEqual(item.severity, "MEDIUM")
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class TestEvidenceAggregationEdgeCases(unittest.TestCase):
|
|
210
|
+
"""Test edge cases for evidence aggregation."""
|
|
211
|
+
|
|
212
|
+
def setUp(self):
|
|
213
|
+
"""Set up test fixtures."""
|
|
214
|
+
self.assessment_data = {
|
|
215
|
+
"name": "Edge Case Assessment",
|
|
216
|
+
"arn": "arn:aws:auditmanager:us-east-1:123456789012:assessment/test",
|
|
217
|
+
"framework": {"type": "Standard", "metadata": {"name": "NIST SP 800-53 Revision 5"}},
|
|
218
|
+
"complianceType": "NIST800-53",
|
|
219
|
+
"awsAccount": {"id": "123456789012"},
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
self.control_data = {
|
|
223
|
+
"id": "test-control-id",
|
|
224
|
+
"name": "AC-2 - Account Management",
|
|
225
|
+
"description": "Control description",
|
|
226
|
+
"status": "REVIEWED",
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
def test_case_sensitivity_compliant(self):
|
|
230
|
+
"""Test that complianceCheck is case-sensitive (COMPLIANT vs compliant)."""
|
|
231
|
+
evidence = [
|
|
232
|
+
{"complianceCheck": "compliant", "dataSource": "AWS Config"}, # lowercase
|
|
233
|
+
]
|
|
234
|
+
|
|
235
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
236
|
+
# Lowercase "compliant" should NOT match "COMPLIANT", treated as inconclusive
|
|
237
|
+
self.assertIsNone(item.compliance_result)
|
|
238
|
+
|
|
239
|
+
def test_case_sensitivity_failed(self):
|
|
240
|
+
"""Test that complianceCheck is case-sensitive (FAILED vs failed)."""
|
|
241
|
+
evidence = [
|
|
242
|
+
{"complianceCheck": "failed", "dataSource": "AWS Security Hub"}, # lowercase
|
|
243
|
+
]
|
|
244
|
+
|
|
245
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
246
|
+
# Lowercase "failed" should NOT match "FAILED", treated as inconclusive
|
|
247
|
+
self.assertIsNone(item.compliance_result)
|
|
248
|
+
|
|
249
|
+
def test_empty_string_compliance_check(self):
|
|
250
|
+
"""Test that empty string complianceCheck is treated as inconclusive."""
|
|
251
|
+
evidence = [
|
|
252
|
+
{"complianceCheck": "", "dataSource": "AWS Config"},
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
256
|
+
self.assertIsNone(item.compliance_result)
|
|
257
|
+
|
|
258
|
+
def test_whitespace_compliance_check(self):
|
|
259
|
+
"""Test that whitespace-only complianceCheck is treated as inconclusive."""
|
|
260
|
+
evidence = [
|
|
261
|
+
{"complianceCheck": " ", "dataSource": "AWS Config"},
|
|
262
|
+
]
|
|
263
|
+
|
|
264
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
265
|
+
self.assertIsNone(item.compliance_result)
|
|
266
|
+
|
|
267
|
+
def test_unexpected_compliance_check_value(self):
|
|
268
|
+
"""Test that unexpected values are treated as inconclusive."""
|
|
269
|
+
evidence = [
|
|
270
|
+
{"complianceCheck": "UNKNOWN", "dataSource": "AWS Config"},
|
|
271
|
+
{"complianceCheck": "PENDING", "dataSource": "AWS Config"},
|
|
272
|
+
{"complianceCheck": 123, "dataSource": "AWS Config"}, # Number instead of string
|
|
273
|
+
]
|
|
274
|
+
|
|
275
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
276
|
+
self.assertIsNone(item.compliance_result)
|
|
277
|
+
|
|
278
|
+
def test_large_number_of_evidence_items(self):
|
|
279
|
+
"""Test aggregation with large number of evidence items."""
|
|
280
|
+
# Create 1000 evidence items
|
|
281
|
+
evidence = [{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"} for _ in range(1000)]
|
|
282
|
+
|
|
283
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
284
|
+
self.assertEqual(item.compliance_result, "PASS")
|
|
285
|
+
|
|
286
|
+
def test_large_number_with_one_failure(self):
|
|
287
|
+
"""Test that one failure in many evidence items still causes FAIL."""
|
|
288
|
+
evidence = [{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"} for _ in range(999)]
|
|
289
|
+
evidence.append({"complianceCheck": "FAILED", "dataSource": "AWS Security Hub"}) # One failure
|
|
290
|
+
|
|
291
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
292
|
+
self.assertEqual(item.compliance_result, "FAIL")
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class TestComplianceItemCreation(unittest.TestCase):
|
|
296
|
+
"""Test creating compliance items with evidence."""
|
|
297
|
+
|
|
298
|
+
def setUp(self):
|
|
299
|
+
"""Set up test fixtures."""
|
|
300
|
+
self.assessment_data = {
|
|
301
|
+
"name": "Test Assessment",
|
|
302
|
+
"arn": "arn:aws:auditmanager:us-east-1:123456789012:assessment/test",
|
|
303
|
+
"framework": {"type": "Standard", "metadata": {"name": "NIST 800-53"}},
|
|
304
|
+
"awsAccount": {"id": "123456789012"},
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
self.control_data = {
|
|
308
|
+
"id": "test-id",
|
|
309
|
+
"name": "AC-2 - Account Management",
|
|
310
|
+
"status": "REVIEWED",
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
def test_create_with_evidence(self):
|
|
314
|
+
"""Test creating compliance item with evidence."""
|
|
315
|
+
evidence = [{"complianceCheck": "COMPLIANT", "dataSource": "AWS Config"}]
|
|
316
|
+
|
|
317
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, evidence)
|
|
318
|
+
|
|
319
|
+
self.assertEqual(item.control_id, "AC-2")
|
|
320
|
+
self.assertEqual(len(item.evidence_items), 1)
|
|
321
|
+
self.assertEqual(item.compliance_result, "PASS")
|
|
322
|
+
|
|
323
|
+
def test_create_without_evidence(self):
|
|
324
|
+
"""Test creating compliance item without evidence (backward compatibility)."""
|
|
325
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data)
|
|
326
|
+
|
|
327
|
+
self.assertEqual(item.control_id, "AC-2")
|
|
328
|
+
self.assertEqual(len(item.evidence_items), 0)
|
|
329
|
+
self.assertIsNone(item.compliance_result) # No evidence = None (skip update)
|
|
330
|
+
|
|
331
|
+
def test_create_with_explicit_none_evidence(self):
|
|
332
|
+
"""Test creating compliance item with explicit None evidence."""
|
|
333
|
+
item = AWSAuditManagerComplianceItem(self.assessment_data, self.control_data, None)
|
|
334
|
+
|
|
335
|
+
self.assertEqual(item.control_id, "AC-2")
|
|
336
|
+
self.assertEqual(len(item.evidence_items), 0)
|
|
337
|
+
self.assertIsNone(item.compliance_result) # No evidence = None (skip update)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
if __name__ == "__main__":
|
|
341
|
+
unittest.main()
|