regscale-cli 6.27.1.0__py3-none-any.whl → 6.27.3.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 +41 -7
- regscale/core/login.py +21 -4
- regscale/core/utils/date.py +77 -1
- regscale/integrations/commercial/aws/scanner.py +7 -3
- regscale/integrations/commercial/microsoft_defender/defender_api.py +1 -1
- regscale/integrations/commercial/sicura/api.py +65 -29
- regscale/integrations/commercial/sicura/scanner.py +36 -7
- regscale/integrations/commercial/synqly/query_builder.py +4 -1
- regscale/integrations/commercial/tenablev2/commands.py +4 -4
- regscale/integrations/commercial/tenablev2/scanner.py +1 -2
- regscale/integrations/commercial/wizv2/scanner.py +40 -16
- regscale/integrations/control_matcher.py +78 -23
- regscale/integrations/public/cci_importer.py +400 -9
- 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 +16 -1
- regscale/models/integration_models/aqua.py +2 -2
- regscale/models/integration_models/cisa_kev_data.json +121 -18
- regscale/models/integration_models/flat_file_importer/__init__.py +4 -6
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +35 -2
- 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/component.py +1 -1
- regscale/models/regscale_models/control_implementation.py +55 -24
- 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.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/METADATA +1 -1
- {regscale_cli-6.27.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/RECORD +53 -49
- tests/regscale/core/test_login.py +171 -4
- tests/regscale/integrations/commercial/test_sicura.py +0 -1
- tests/regscale/integrations/commercial/wizv2/test_wizv2.py +86 -0
- tests/regscale/integrations/public/test_cci.py +596 -1
- tests/regscale/integrations/test_control_matcher.py +24 -0
- tests/regscale/models/test_control_implementation.py +118 -3
- {regscale_cli-6.27.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/LICENSE +0 -0
- {regscale_cli-6.27.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/WHEEL +0 -0
- {regscale_cli-6.27.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.27.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/top_level.txt +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import unittest
|
|
2
2
|
from unittest.mock import MagicMock, patch
|
|
3
3
|
|
|
4
|
+
from regscale.core.app.application import Application
|
|
4
5
|
from regscale.models import ControlImplementation
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class TestControlImplementation(unittest.TestCase):
|
|
8
|
-
@patch("regscale.models.regscale_models.control_implementation.ControlImplementation._get_api_handler
|
|
9
|
-
def test_get_control_map_by_plan_lower_case_keys(self,
|
|
9
|
+
@patch("regscale.models.regscale_models.control_implementation.ControlImplementation._get_api_handler")
|
|
10
|
+
def test_get_control_map_by_plan_lower_case_keys(self, mock_api_handler):
|
|
10
11
|
# Create a mock response object with 'ok' attribute and 'json' method
|
|
11
12
|
mock_response = MagicMock()
|
|
12
13
|
mock_response.ok = True
|
|
@@ -15,7 +16,10 @@ class TestControlImplementation(unittest.TestCase):
|
|
|
15
16
|
{"control": {"controlId": "AC-6"}, "id": 2},
|
|
16
17
|
]
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
# Set up the mock API handler to return the mock response when .get() is called
|
|
20
|
+
mock_handler = MagicMock()
|
|
21
|
+
mock_handler.get.return_value = mock_response
|
|
22
|
+
mock_api_handler.return_value = mock_handler
|
|
19
23
|
|
|
20
24
|
# Expected result should have lower case control IDs as keys
|
|
21
25
|
expected_result = {"ca-1": 1, "ac-6": 2}
|
|
@@ -25,3 +29,114 @@ class TestControlImplementation(unittest.TestCase):
|
|
|
25
29
|
|
|
26
30
|
# Assert that the result matches the expected result
|
|
27
31
|
self.assertEqual(result, expected_result)
|
|
32
|
+
|
|
33
|
+
@patch("regscale.core.app.api.Api.graph")
|
|
34
|
+
def test_get_export_query_with_none_control_owner(self, mock_graph):
|
|
35
|
+
"""Test get_export_query handles None controlOwner gracefully."""
|
|
36
|
+
# Mock API response with None controlOwner
|
|
37
|
+
mock_graph.return_value = {
|
|
38
|
+
"controlImplementations": {
|
|
39
|
+
"totalCount": 1,
|
|
40
|
+
"items": [
|
|
41
|
+
{
|
|
42
|
+
"id": 1,
|
|
43
|
+
"controlID": 100,
|
|
44
|
+
"controlOwner": None, # None control owner
|
|
45
|
+
"control": {
|
|
46
|
+
"title": "Test Control",
|
|
47
|
+
"description": "Test Description",
|
|
48
|
+
"controlId": "AC-1",
|
|
49
|
+
},
|
|
50
|
+
"status": "Implemented",
|
|
51
|
+
"policy": "Test Policy",
|
|
52
|
+
"implementation": "Test Implementation",
|
|
53
|
+
"responsibility": "Provider",
|
|
54
|
+
"inheritable": True,
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Call the method under test
|
|
61
|
+
app = Application()
|
|
62
|
+
result = ControlImplementation.get_export_query(app, parent_id=1, parent_module="securityplans")
|
|
63
|
+
|
|
64
|
+
# Verify the result handles None gracefully
|
|
65
|
+
self.assertEqual(len(result), 1)
|
|
66
|
+
self.assertEqual(result[0]["controlOwnerId"], "Unassigned")
|
|
67
|
+
|
|
68
|
+
@patch("regscale.core.app.api.Api.graph")
|
|
69
|
+
def test_get_export_query_with_none_control(self, mock_graph):
|
|
70
|
+
"""Test get_export_query handles None control gracefully."""
|
|
71
|
+
# Mock API response with None control
|
|
72
|
+
mock_graph.return_value = {
|
|
73
|
+
"controlImplementations": {
|
|
74
|
+
"totalCount": 1,
|
|
75
|
+
"items": [
|
|
76
|
+
{
|
|
77
|
+
"id": 1,
|
|
78
|
+
"controlID": 100,
|
|
79
|
+
"controlOwner": {
|
|
80
|
+
"firstName": "John",
|
|
81
|
+
"lastName": "Doe",
|
|
82
|
+
"userName": "jdoe",
|
|
83
|
+
},
|
|
84
|
+
"control": None, # None control
|
|
85
|
+
"status": "Implemented",
|
|
86
|
+
"policy": "Test Policy",
|
|
87
|
+
"implementation": "Test Implementation",
|
|
88
|
+
"responsibility": "Provider",
|
|
89
|
+
"inheritable": True,
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Call the method under test
|
|
96
|
+
app = Application()
|
|
97
|
+
result = ControlImplementation.get_export_query(app, parent_id=1, parent_module="securityplans")
|
|
98
|
+
|
|
99
|
+
# Verify the result handles None gracefully
|
|
100
|
+
self.assertEqual(len(result), 1)
|
|
101
|
+
self.assertEqual(result[0]["controlName"], "")
|
|
102
|
+
self.assertEqual(result[0]["controlTitle"], "")
|
|
103
|
+
self.assertEqual(result[0]["description"], "")
|
|
104
|
+
|
|
105
|
+
@patch("regscale.core.app.api.Api.graph")
|
|
106
|
+
def test_get_export_query_with_partial_control_owner(self, mock_graph):
|
|
107
|
+
"""Test get_export_query handles partial controlOwner data gracefully."""
|
|
108
|
+
# Mock API response with partial controlOwner data
|
|
109
|
+
mock_graph.return_value = {
|
|
110
|
+
"controlImplementations": {
|
|
111
|
+
"totalCount": 1,
|
|
112
|
+
"items": [
|
|
113
|
+
{
|
|
114
|
+
"id": 1,
|
|
115
|
+
"controlID": 100,
|
|
116
|
+
"controlOwner": {
|
|
117
|
+
"firstName": None,
|
|
118
|
+
"lastName": "Doe",
|
|
119
|
+
"userName": "jdoe",
|
|
120
|
+
},
|
|
121
|
+
"control": {
|
|
122
|
+
"title": "Test Control",
|
|
123
|
+
"description": "Test Description",
|
|
124
|
+
"controlId": "AC-1",
|
|
125
|
+
},
|
|
126
|
+
"status": "Implemented",
|
|
127
|
+
"policy": "Test Policy",
|
|
128
|
+
"implementation": "Test Implementation",
|
|
129
|
+
"responsibility": "Provider",
|
|
130
|
+
"inheritable": True,
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Call the method under test
|
|
137
|
+
app = Application()
|
|
138
|
+
result = ControlImplementation.get_export_query(app, parent_id=1, parent_module="securityplans")
|
|
139
|
+
|
|
140
|
+
# Verify the result handles partial data gracefully
|
|
141
|
+
self.assertEqual(len(result), 1)
|
|
142
|
+
self.assertEqual(result[0]["controlOwnerId"], "Doe, (jdoe)")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|