regscale-cli 6.27.2.0__py3-none-any.whl → 6.28.0.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/application.py +1 -0
- regscale/core/app/internal/control_editor.py +73 -21
- regscale/core/app/internal/login.py +4 -1
- regscale/core/app/internal/model_editor.py +219 -64
- regscale/core/app/utils/app_utils.py +11 -2
- regscale/core/login.py +21 -4
- regscale/core/utils/date.py +77 -1
- 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 +853 -205
- 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/query_builder.py +4 -1
- regscale/integrations/compliance_integration.py +308 -38
- regscale/integrations/control_matcher.py +78 -23
- regscale/integrations/due_date_handler.py +3 -0
- regscale/integrations/public/csam/csam.py +572 -763
- regscale/integrations/public/csam/csam_agency_defined.py +179 -0
- regscale/integrations/public/csam/csam_common.py +154 -0
- regscale/integrations/public/csam/csam_controls.py +432 -0
- regscale/integrations/public/csam/csam_poam.py +124 -0
- regscale/integrations/public/fedramp/click.py +17 -4
- regscale/integrations/public/fedramp/fedramp_cis_crm.py +271 -62
- regscale/integrations/public/fedramp/poam/scanner.py +74 -7
- regscale/integrations/scanner_integration.py +415 -85
- regscale/models/integration_models/cisa_kev_data.json +80 -20
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +44 -3
- regscale/models/integration_models/synqly_models/ocsf_mapper.py +41 -12
- regscale/models/platform.py +3 -0
- regscale/models/regscale_models/__init__.py +5 -0
- regscale/models/regscale_models/assessment.py +2 -1
- regscale/models/regscale_models/component.py +1 -1
- regscale/models/regscale_models/control_implementation.py +55 -24
- 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/models/regscale_models/organization.py +3 -0
- regscale/models/regscale_models/regscale_model.py +17 -5
- regscale/models/regscale_models/security_plan.py +1 -0
- regscale/regscale.py +11 -1
- {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/METADATA +1 -1
- {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/RECORD +140 -57
- tests/regscale/core/test_login.py +171 -4
- 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
- tests/regscale/integrations/test_control_matcher.py +24 -0
- tests/regscale/models/test_control_implementation.py +118 -3
- {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/LICENSE +0 -0
- {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/WHEEL +0 -0
- {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
"""Unit tests for AWS OCSF Mapper."""
|
|
2
|
+
|
|
3
|
+
import unittest
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from unittest.mock import MagicMock, patch
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from regscale.integrations.commercial.aws.ocsf import constants
|
|
10
|
+
from regscale.integrations.commercial.aws.ocsf.mapper import AWSOCSFMapper
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestAWSOCSFMapper(unittest.TestCase):
|
|
14
|
+
"""Test cases for AWSOCSFMapper."""
|
|
15
|
+
|
|
16
|
+
def setUp(self):
|
|
17
|
+
"""Set up test fixtures."""
|
|
18
|
+
self.mapper = AWSOCSFMapper()
|
|
19
|
+
|
|
20
|
+
def test_init(self):
|
|
21
|
+
"""Test AWSOCSFMapper initialization."""
|
|
22
|
+
assert self.mapper.ocsf_version == constants.OCSF_VERSION
|
|
23
|
+
|
|
24
|
+
def test_guardduty_to_ocsf(self):
|
|
25
|
+
"""Test GuardDuty finding to OCSF mapping."""
|
|
26
|
+
finding = {
|
|
27
|
+
"Id": "test-finding-123",
|
|
28
|
+
"Arn": "arn:aws:guardduty:us-east-1:123456789012:detector/test/finding/test-finding-123",
|
|
29
|
+
"AccountId": "123456789012",
|
|
30
|
+
"Region": "us-east-1",
|
|
31
|
+
"Partition": "aws",
|
|
32
|
+
"Severity": 8.0,
|
|
33
|
+
"Confidence": 7.5,
|
|
34
|
+
"Type": "UnauthorizedAccess:IAMUser/MaliciousIPCaller.Custom",
|
|
35
|
+
"Title": "Test Finding",
|
|
36
|
+
"Description": "Test description",
|
|
37
|
+
"CreatedAt": "2025-10-13T12:00:00Z",
|
|
38
|
+
"UpdatedAt": "2025-10-13T12:30:00Z",
|
|
39
|
+
"Service": {
|
|
40
|
+
"Archived": False,
|
|
41
|
+
"Count": 1,
|
|
42
|
+
},
|
|
43
|
+
"Resource": {
|
|
44
|
+
"ResourceType": "Instance",
|
|
45
|
+
"InstanceDetails": {
|
|
46
|
+
"InstanceId": "i-1234567890abcdef0",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
result = self.mapper.guardduty_to_ocsf(finding)
|
|
52
|
+
|
|
53
|
+
# Verify OCSF structure
|
|
54
|
+
assert result["class_uid"] == constants.CLASS_DETECTION_FINDING
|
|
55
|
+
assert result["class_name"] == "Detection Finding"
|
|
56
|
+
assert result["severity_id"] == constants.SEVERITY_HIGH
|
|
57
|
+
assert result["confidence_id"] == constants.CONFIDENCE_HIGH
|
|
58
|
+
assert result["finding_info"]["uid"] == "test-finding-123"
|
|
59
|
+
assert result["finding_info"]["title"] == "Test Finding"
|
|
60
|
+
assert result["cloud"]["provider"] == "AWS"
|
|
61
|
+
assert result["cloud"]["account"]["uid"] == "123456789012"
|
|
62
|
+
assert result["raw_data"] == finding
|
|
63
|
+
|
|
64
|
+
def test_securityhub_to_ocsf(self):
|
|
65
|
+
"""Test Security Hub finding to OCSF mapping."""
|
|
66
|
+
finding = {
|
|
67
|
+
"Id": "arn:aws:securityhub:us-east-1:123456789012:subscription/aws-foundational-security-best-practices/v/1.0.0/EC2.1/finding/test",
|
|
68
|
+
"ProductArn": "arn:aws:securityhub:us-east-1::product/aws/securityhub",
|
|
69
|
+
"ProductName": "Security Hub",
|
|
70
|
+
"AwsAccountId": "123456789012",
|
|
71
|
+
"Region": "us-east-1",
|
|
72
|
+
"Title": "Test Security Finding",
|
|
73
|
+
"Description": "Test security description",
|
|
74
|
+
"Severity": {
|
|
75
|
+
"Label": "HIGH",
|
|
76
|
+
"Normalized": 70,
|
|
77
|
+
},
|
|
78
|
+
"Workflow": {
|
|
79
|
+
"Status": "NEW",
|
|
80
|
+
},
|
|
81
|
+
"Types": [
|
|
82
|
+
"Software and Configuration Checks/AWS Security Best Practices",
|
|
83
|
+
],
|
|
84
|
+
"CreatedAt": "2025-10-13T12:00:00Z",
|
|
85
|
+
"UpdatedAt": "2025-10-13T12:30:00Z",
|
|
86
|
+
"FirstObservedAt": "2025-10-13T11:00:00Z",
|
|
87
|
+
"LastObservedAt": "2025-10-13T12:30:00Z",
|
|
88
|
+
"Compliance": {
|
|
89
|
+
"Status": "FAILED",
|
|
90
|
+
"RelatedRequirements": ["PCI-DSS 3.2.1/1.2.1"],
|
|
91
|
+
},
|
|
92
|
+
"Resources": [
|
|
93
|
+
{
|
|
94
|
+
"Type": "AwsEc2Instance",
|
|
95
|
+
"Id": "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0",
|
|
96
|
+
"Region": "us-east-1",
|
|
97
|
+
"Partition": "aws",
|
|
98
|
+
"Details": {},
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
"Vulnerabilities": [
|
|
102
|
+
{
|
|
103
|
+
"Id": "CVE-2021-1234",
|
|
104
|
+
"ReferenceUrls": ["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-1234"],
|
|
105
|
+
"Vendor": {"Name": "AWS"},
|
|
106
|
+
"Cvss": [{"BaseScore": 7.5}],
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"Remediation": {
|
|
110
|
+
"Recommendation": {
|
|
111
|
+
"Text": "Enable VPC flow logs",
|
|
112
|
+
"Url": "https://docs.aws.amazon.com/",
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
result = self.mapper.securityhub_to_ocsf(finding)
|
|
118
|
+
|
|
119
|
+
# Verify OCSF structure
|
|
120
|
+
assert result["class_uid"] == constants.CLASS_SECURITY_FINDING
|
|
121
|
+
assert result["class_name"] == "Security Finding"
|
|
122
|
+
assert result["severity_id"] == constants.SEVERITY_HIGH
|
|
123
|
+
assert result["status_id"] == constants.STATUS_NEW
|
|
124
|
+
assert result["finding_info"]["title"] == "Test Security Finding"
|
|
125
|
+
assert result["compliance"]["status"] == "FAILED"
|
|
126
|
+
assert len(result["resources"]) == 1
|
|
127
|
+
assert result["vulnerabilities"] is not None
|
|
128
|
+
assert result["remediation"]["desc"] == "Enable VPC flow logs"
|
|
129
|
+
|
|
130
|
+
def test_cloudtrail_event_to_ocsf(self):
|
|
131
|
+
"""Test CloudTrail event to OCSF mapping."""
|
|
132
|
+
event = {
|
|
133
|
+
"EventTime": "2025-10-13T12:00:00Z",
|
|
134
|
+
"EventName": "DescribeInstances",
|
|
135
|
+
"EventSource": "ec2.amazonaws.com",
|
|
136
|
+
"RequestID": "test-request-123",
|
|
137
|
+
"RecipientAccountId": "123456789012",
|
|
138
|
+
"AwsRegion": "us-east-1",
|
|
139
|
+
"UserIdentity": {
|
|
140
|
+
"Type": "IAMUser",
|
|
141
|
+
"PrincipalId": "AIDAI23HXS8K7EXAMPLE",
|
|
142
|
+
"UserName": "testuser",
|
|
143
|
+
},
|
|
144
|
+
"SourceIPAddress": "203.0.113.1",
|
|
145
|
+
"UserAgent": "aws-cli/2.0.0",
|
|
146
|
+
"Resources": [
|
|
147
|
+
{
|
|
148
|
+
"ARN": "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0",
|
|
149
|
+
"ResourceType": "AWS::EC2::Instance",
|
|
150
|
+
"ResourceName": "test-instance",
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
result = self.mapper.cloudtrail_event_to_ocsf(event)
|
|
156
|
+
|
|
157
|
+
# Verify OCSF structure
|
|
158
|
+
assert result["class_uid"] == constants.CLASS_CLOUD_API
|
|
159
|
+
assert result["class_name"] == "Cloud API"
|
|
160
|
+
assert result["activity_name"] == "DescribeInstances"
|
|
161
|
+
assert result["api"]["operation"] == "DescribeInstances"
|
|
162
|
+
assert result["api"]["service"]["name"] == "ec2"
|
|
163
|
+
assert result["actor"]["user"]["name"] == "testuser"
|
|
164
|
+
assert result["src_endpoint"]["ip"] == "203.0.113.1"
|
|
165
|
+
assert len(result["resources"]) == 1
|
|
166
|
+
|
|
167
|
+
def test_cloudtrail_event_with_error(self):
|
|
168
|
+
"""Test CloudTrail event with error code."""
|
|
169
|
+
event = {
|
|
170
|
+
"EventTime": "2025-10-13T12:00:00Z",
|
|
171
|
+
"EventName": "DescribeInstances",
|
|
172
|
+
"EventSource": "ec2.amazonaws.com",
|
|
173
|
+
"RequestID": "test-request-123",
|
|
174
|
+
"RecipientAccountId": "123456789012",
|
|
175
|
+
"AwsRegion": "us-east-1",
|
|
176
|
+
"ErrorCode": "AccessDenied",
|
|
177
|
+
"ErrorMessage": "User is not authorized",
|
|
178
|
+
"UserIdentity": {},
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
result = self.mapper.cloudtrail_event_to_ocsf(event)
|
|
182
|
+
|
|
183
|
+
# Error events should have higher severity
|
|
184
|
+
assert result["severity_id"] == constants.SEVERITY_MEDIUM
|
|
185
|
+
assert result["api"]["response"]["error"] == "AccessDenied"
|
|
186
|
+
assert result["api"]["response"]["message"] == "User is not authorized"
|
|
187
|
+
|
|
188
|
+
def test_map_guardduty_activity_create(self):
|
|
189
|
+
"""Test GuardDuty activity mapping for new finding."""
|
|
190
|
+
finding = {
|
|
191
|
+
"Service": {
|
|
192
|
+
"Archived": False,
|
|
193
|
+
"Count": 1,
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
result = self.mapper._map_guardduty_activity(finding)
|
|
198
|
+
assert result == constants.ACTIVITY_CREATE
|
|
199
|
+
|
|
200
|
+
def test_map_guardduty_activity_update(self):
|
|
201
|
+
"""Test GuardDuty activity mapping for updated finding."""
|
|
202
|
+
finding = {
|
|
203
|
+
"Service": {
|
|
204
|
+
"Archived": False,
|
|
205
|
+
"Count": 5,
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
result = self.mapper._map_guardduty_activity(finding)
|
|
210
|
+
assert result == constants.ACTIVITY_UPDATE
|
|
211
|
+
|
|
212
|
+
def test_map_guardduty_activity_close(self):
|
|
213
|
+
"""Test GuardDuty activity mapping for archived finding."""
|
|
214
|
+
finding = {
|
|
215
|
+
"Service": {
|
|
216
|
+
"Archived": True,
|
|
217
|
+
"Count": 3,
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
result = self.mapper._map_guardduty_activity(finding)
|
|
222
|
+
assert result == constants.ACTIVITY_CLOSE
|
|
223
|
+
|
|
224
|
+
def test_map_securityhub_activity(self):
|
|
225
|
+
"""Test Security Hub activity mapping."""
|
|
226
|
+
assert self.mapper._map_securityhub_activity("NEW") == constants.ACTIVITY_CREATE
|
|
227
|
+
assert self.mapper._map_securityhub_activity("NOTIFIED") == constants.ACTIVITY_UPDATE
|
|
228
|
+
assert self.mapper._map_securityhub_activity("RESOLVED") == constants.ACTIVITY_CLOSE
|
|
229
|
+
assert self.mapper._map_securityhub_activity("SUPPRESSED") == constants.ACTIVITY_CLOSE
|
|
230
|
+
assert self.mapper._map_securityhub_activity("UNKNOWN") == constants.ACTIVITY_OTHER
|
|
231
|
+
|
|
232
|
+
def test_map_guardduty_confidence(self):
|
|
233
|
+
"""Test GuardDuty confidence mapping."""
|
|
234
|
+
assert self.mapper._map_guardduty_confidence(8.0) == constants.CONFIDENCE_HIGH
|
|
235
|
+
assert self.mapper._map_guardduty_confidence(5.0) == constants.CONFIDENCE_MEDIUM
|
|
236
|
+
assert self.mapper._map_guardduty_confidence(2.0) == constants.CONFIDENCE_LOW
|
|
237
|
+
assert self.mapper._map_guardduty_confidence(0) == constants.CONFIDENCE_UNKNOWN
|
|
238
|
+
|
|
239
|
+
def test_map_securityhub_resources(self):
|
|
240
|
+
"""Test Security Hub resources mapping."""
|
|
241
|
+
resources = [
|
|
242
|
+
{
|
|
243
|
+
"Id": "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0",
|
|
244
|
+
"Type": "AwsEc2Instance",
|
|
245
|
+
"Region": "us-east-1",
|
|
246
|
+
"Partition": "aws",
|
|
247
|
+
"Details": {"AwsEc2Instance": {"InstanceId": "i-1234567890abcdef0"}},
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
|
|
251
|
+
result = self.mapper._map_securityhub_resources(resources)
|
|
252
|
+
|
|
253
|
+
assert len(result) == 1
|
|
254
|
+
assert result[0]["uid"] == "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0"
|
|
255
|
+
assert result[0]["type"] == "AwsEc2Instance"
|
|
256
|
+
assert result[0]["region"] == "us-east-1"
|
|
257
|
+
assert "data" in result[0]
|
|
258
|
+
|
|
259
|
+
def test_map_cloudtrail_resources(self):
|
|
260
|
+
"""Test CloudTrail resources mapping."""
|
|
261
|
+
resources = [
|
|
262
|
+
{
|
|
263
|
+
"ARN": "arn:aws:s3:::test-bucket",
|
|
264
|
+
"ResourceType": "AWS::S3::Bucket",
|
|
265
|
+
"ResourceName": "test-bucket",
|
|
266
|
+
}
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
result = self.mapper._map_cloudtrail_resources(resources)
|
|
270
|
+
|
|
271
|
+
assert len(result) == 1
|
|
272
|
+
assert result[0]["uid"] == "arn:aws:s3:::test-bucket"
|
|
273
|
+
assert result[0]["type"] == "AWS::S3::Bucket"
|
|
274
|
+
assert result[0]["name"] == "test-bucket"
|
|
275
|
+
|
|
276
|
+
def test_extract_vulnerabilities(self):
|
|
277
|
+
"""Test vulnerability extraction from Security Hub finding."""
|
|
278
|
+
finding = {
|
|
279
|
+
"Vulnerabilities": [
|
|
280
|
+
{
|
|
281
|
+
"Id": "CVE-2021-1234",
|
|
282
|
+
"ReferenceUrls": ["https://cve.mitre.org/"],
|
|
283
|
+
"Vendor": {"Name": "AWS"},
|
|
284
|
+
"Cvss": [{"BaseScore": 7.5}],
|
|
285
|
+
}
|
|
286
|
+
]
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
result = self.mapper._extract_vulnerabilities(finding)
|
|
290
|
+
|
|
291
|
+
assert len(result) == 1
|
|
292
|
+
assert result[0]["cve"]["uid"] == "CVE-2021-1234"
|
|
293
|
+
assert result[0]["vendor_name"] == "AWS"
|
|
294
|
+
assert "cvss" in result[0]
|
|
295
|
+
|
|
296
|
+
def test_extract_vulnerabilities_empty(self):
|
|
297
|
+
"""Test vulnerability extraction with no vulnerabilities."""
|
|
298
|
+
finding = {"Vulnerabilities": []}
|
|
299
|
+
|
|
300
|
+
result = self.mapper._extract_vulnerabilities(finding)
|
|
301
|
+
|
|
302
|
+
assert result is None
|
|
303
|
+
|
|
304
|
+
def test_determine_cloudtrail_severity(self):
|
|
305
|
+
"""Test CloudTrail event severity determination."""
|
|
306
|
+
# Unauthorized access
|
|
307
|
+
assert self.mapper._determine_cloudtrail_severity({"ErrorCode": "AccessDenied"}) == constants.SEVERITY_MEDIUM
|
|
308
|
+
assert (
|
|
309
|
+
self.mapper._determine_cloudtrail_severity({"ErrorCode": "UnauthorizedOperation"})
|
|
310
|
+
== constants.SEVERITY_MEDIUM
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
# Other errors
|
|
314
|
+
assert self.mapper._determine_cloudtrail_severity({"ErrorCode": "InvalidParameter"}) == constants.SEVERITY_LOW
|
|
315
|
+
|
|
316
|
+
# Success
|
|
317
|
+
assert self.mapper._determine_cloudtrail_severity({}) == constants.SEVERITY_INFORMATIONAL
|
|
318
|
+
|
|
319
|
+
@patch("regscale.integrations.commercial.aws.ocsf.mapper.logger")
|
|
320
|
+
def test_parse_aws_timestamp_success(self, mock_logger):
|
|
321
|
+
"""Test AWS timestamp parsing success."""
|
|
322
|
+
timestamp = "2025-10-13T12:00:00Z"
|
|
323
|
+
result = self.mapper._parse_aws_timestamp(timestamp)
|
|
324
|
+
|
|
325
|
+
assert result is not None
|
|
326
|
+
assert isinstance(result, int)
|
|
327
|
+
|
|
328
|
+
@patch("regscale.integrations.commercial.aws.ocsf.mapper.logger")
|
|
329
|
+
def test_parse_aws_timestamp_none(self, mock_logger):
|
|
330
|
+
"""Test AWS timestamp parsing with None."""
|
|
331
|
+
result = self.mapper._parse_aws_timestamp(None)
|
|
332
|
+
assert result is None
|
|
333
|
+
|
|
334
|
+
@patch("regscale.integrations.commercial.aws.ocsf.mapper.logger")
|
|
335
|
+
def test_parse_aws_timestamp_invalid(self, mock_logger):
|
|
336
|
+
"""Test AWS timestamp parsing with invalid format."""
|
|
337
|
+
result = self.mapper._parse_aws_timestamp("invalid-timestamp")
|
|
338
|
+
assert result is None
|
|
339
|
+
mock_logger.warning.assert_called_once()
|
|
340
|
+
|
|
341
|
+
def test_get_severity_name(self):
|
|
342
|
+
"""Test OCSF severity name retrieval."""
|
|
343
|
+
assert self.mapper._get_severity_name(constants.SEVERITY_CRITICAL) == "Critical"
|
|
344
|
+
assert self.mapper._get_severity_name(constants.SEVERITY_HIGH) == "High"
|
|
345
|
+
assert self.mapper._get_severity_name(constants.SEVERITY_MEDIUM) == "Medium"
|
|
346
|
+
assert self.mapper._get_severity_name(constants.SEVERITY_LOW) == "Low"
|
|
347
|
+
assert self.mapper._get_severity_name(constants.SEVERITY_INFORMATIONAL) == "Informational"
|
|
348
|
+
assert self.mapper._get_severity_name(constants.SEVERITY_UNKNOWN) == "Unknown"
|
|
349
|
+
assert self.mapper._get_severity_name(999) == "Unknown"
|
|
350
|
+
|
|
351
|
+
def test_get_status_name(self):
|
|
352
|
+
"""Test OCSF status name retrieval."""
|
|
353
|
+
assert self.mapper._get_status_name(constants.STATUS_NEW) == "New"
|
|
354
|
+
assert self.mapper._get_status_name(constants.STATUS_IN_PROGRESS) == "In Progress"
|
|
355
|
+
assert self.mapper._get_status_name(constants.STATUS_SUPPRESSED) == "Suppressed"
|
|
356
|
+
assert self.mapper._get_status_name(constants.STATUS_RESOLVED) == "Resolved"
|
|
357
|
+
assert self.mapper._get_status_name(constants.STATUS_OTHER) == "Other"
|
|
358
|
+
assert self.mapper._get_status_name(999) == "Other"
|
|
359
|
+
|
|
360
|
+
def test_get_activity_name(self):
|
|
361
|
+
"""Test OCSF activity name retrieval."""
|
|
362
|
+
assert self.mapper._get_activity_name(constants.ACTIVITY_CREATE) == "Create"
|
|
363
|
+
assert self.mapper._get_activity_name(constants.ACTIVITY_UPDATE) == "Update"
|
|
364
|
+
assert self.mapper._get_activity_name(constants.ACTIVITY_CLOSE) == "Close"
|
|
365
|
+
assert self.mapper._get_activity_name(constants.ACTIVITY_OTHER) == "Other"
|
|
366
|
+
assert self.mapper._get_activity_name(999) == "Other"
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
if __name__ == "__main__":
|
|
370
|
+
pytest.main([__file__, "-v"])
|