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.

Files changed (53) hide show
  1. regscale/_version.py +1 -1
  2. regscale/core/app/application.py +1 -0
  3. regscale/core/app/internal/control_editor.py +73 -21
  4. regscale/core/app/internal/login.py +4 -1
  5. regscale/core/app/internal/model_editor.py +219 -64
  6. regscale/core/app/utils/app_utils.py +41 -7
  7. regscale/core/login.py +21 -4
  8. regscale/core/utils/date.py +77 -1
  9. regscale/integrations/commercial/aws/scanner.py +7 -3
  10. regscale/integrations/commercial/microsoft_defender/defender_api.py +1 -1
  11. regscale/integrations/commercial/sicura/api.py +65 -29
  12. regscale/integrations/commercial/sicura/scanner.py +36 -7
  13. regscale/integrations/commercial/synqly/query_builder.py +4 -1
  14. regscale/integrations/commercial/tenablev2/commands.py +4 -4
  15. regscale/integrations/commercial/tenablev2/scanner.py +1 -2
  16. regscale/integrations/commercial/wizv2/scanner.py +40 -16
  17. regscale/integrations/control_matcher.py +78 -23
  18. regscale/integrations/public/cci_importer.py +400 -9
  19. regscale/integrations/public/csam/csam.py +572 -763
  20. regscale/integrations/public/csam/csam_agency_defined.py +179 -0
  21. regscale/integrations/public/csam/csam_common.py +154 -0
  22. regscale/integrations/public/csam/csam_controls.py +432 -0
  23. regscale/integrations/public/csam/csam_poam.py +124 -0
  24. regscale/integrations/public/fedramp/click.py +17 -4
  25. regscale/integrations/public/fedramp/fedramp_cis_crm.py +271 -62
  26. regscale/integrations/public/fedramp/poam/scanner.py +74 -7
  27. regscale/integrations/scanner_integration.py +16 -1
  28. regscale/models/integration_models/aqua.py +2 -2
  29. regscale/models/integration_models/cisa_kev_data.json +121 -18
  30. regscale/models/integration_models/flat_file_importer/__init__.py +4 -6
  31. regscale/models/integration_models/synqly_models/capabilities.json +1 -1
  32. regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +35 -2
  33. regscale/models/integration_models/synqly_models/ocsf_mapper.py +41 -12
  34. regscale/models/platform.py +3 -0
  35. regscale/models/regscale_models/__init__.py +5 -0
  36. regscale/models/regscale_models/component.py +1 -1
  37. regscale/models/regscale_models/control_implementation.py +55 -24
  38. regscale/models/regscale_models/organization.py +3 -0
  39. regscale/models/regscale_models/regscale_model.py +17 -5
  40. regscale/models/regscale_models/security_plan.py +1 -0
  41. regscale/regscale.py +11 -1
  42. {regscale_cli-6.27.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/METADATA +1 -1
  43. {regscale_cli-6.27.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/RECORD +53 -49
  44. tests/regscale/core/test_login.py +171 -4
  45. tests/regscale/integrations/commercial/test_sicura.py +0 -1
  46. tests/regscale/integrations/commercial/wizv2/test_wizv2.py +86 -0
  47. tests/regscale/integrations/public/test_cci.py +596 -1
  48. tests/regscale/integrations/test_control_matcher.py +24 -0
  49. tests/regscale/models/test_control_implementation.py +118 -3
  50. {regscale_cli-6.27.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/LICENSE +0 -0
  51. {regscale_cli-6.27.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/WHEEL +0 -0
  52. {regscale_cli-6.27.1.0.dist-info → regscale_cli-6.27.3.0.dist-info}/entry_points.txt +0 -0
  53. {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().get")
9
- def test_get_control_map_by_plan_lower_case_keys(self, mock_get):
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
- mock_get.return_value = mock_response
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)")