regscale-cli 6.20.9.1__py3-none-any.whl → 6.21.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.

Files changed (56) hide show
  1. regscale/_version.py +1 -1
  2. regscale/core/app/application.py +12 -5
  3. regscale/core/app/internal/set_permissions.py +58 -27
  4. regscale/integrations/commercial/defender.py +9 -0
  5. regscale/integrations/commercial/nessus/scanner.py +2 -0
  6. regscale/integrations/commercial/sonarcloud.py +35 -36
  7. regscale/integrations/commercial/synqly/ticketing.py +51 -0
  8. regscale/integrations/commercial/wizv2/async_client.py +325 -0
  9. regscale/integrations/commercial/wizv2/constants.py +756 -0
  10. regscale/integrations/commercial/wizv2/scanner.py +1301 -89
  11. regscale/integrations/commercial/wizv2/utils.py +280 -36
  12. regscale/integrations/commercial/wizv2/variables.py +2 -10
  13. regscale/integrations/integration_override.py +15 -6
  14. regscale/integrations/scanner_integration.py +221 -37
  15. regscale/integrations/variables.py +1 -0
  16. regscale/models/integration_models/amazon_models/inspector_scan.py +32 -57
  17. regscale/models/integration_models/aqua.py +92 -78
  18. regscale/models/integration_models/cisa_kev_data.json +47 -4
  19. regscale/models/integration_models/defenderimport.py +64 -59
  20. regscale/models/integration_models/ecr_models/ecr.py +100 -147
  21. regscale/models/integration_models/flat_file_importer/__init__.py +52 -38
  22. regscale/models/integration_models/ibm.py +29 -47
  23. regscale/models/integration_models/nexpose.py +156 -68
  24. regscale/models/integration_models/prisma.py +46 -66
  25. regscale/models/integration_models/qualys.py +99 -93
  26. regscale/models/integration_models/snyk.py +229 -158
  27. regscale/models/integration_models/synqly_models/capabilities.json +1 -1
  28. regscale/models/integration_models/veracode.py +15 -20
  29. regscale/models/integration_models/xray.py +276 -82
  30. regscale/models/regscale_models/__init__.py +13 -0
  31. regscale/models/regscale_models/classification.py +23 -0
  32. regscale/models/regscale_models/control_implementation.py +14 -12
  33. regscale/models/regscale_models/cryptography.py +56 -0
  34. regscale/models/regscale_models/deviation.py +4 -4
  35. regscale/models/regscale_models/group.py +3 -2
  36. regscale/models/regscale_models/interconnection.py +1 -1
  37. regscale/models/regscale_models/issue.py +140 -41
  38. regscale/models/regscale_models/milestone.py +40 -0
  39. regscale/models/regscale_models/property.py +0 -1
  40. regscale/models/regscale_models/rbac.py +22 -0
  41. regscale/models/regscale_models/regscale_model.py +29 -18
  42. regscale/models/regscale_models/team.py +55 -0
  43. {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/METADATA +1 -1
  44. {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/RECORD +56 -49
  45. tests/fixtures/test_fixture.py +58 -2
  46. tests/regscale/core/test_app.py +5 -3
  47. tests/regscale/integrations/test_integration_mapping.py +522 -40
  48. tests/regscale/integrations/test_issue_due_date.py +1 -1
  49. tests/regscale/integrations/test_property_and_milestone_creation.py +684 -0
  50. tests/regscale/integrations/test_update_finding_dates.py +336 -0
  51. tests/regscale/models/test_asset.py +406 -50
  52. tests/regscale/models/test_report.py +105 -29
  53. {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/LICENSE +0 -0
  54. {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/WHEEL +0 -0
  55. {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/entry_points.txt +0 -0
  56. {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/top_level.txt +0 -0
@@ -2,8 +2,8 @@ from typing import List, Optional, Union
2
2
 
3
3
  from regscale.core.app.logz import create_logger
4
4
  from regscale.core.app.utils.app_utils import get_current_datetime
5
- from regscale.integrations.scanner_integration import IntegrationFinding
6
- from regscale.models import Asset, Vulnerability, ImportValidater, IssueStatus
5
+ from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding
6
+ from regscale.models import Asset, ImportValidater, IssueStatus, Vulnerability
7
7
  from regscale.models.integration_models.flat_file_importer import FlatFileImporter
8
8
 
9
9
  APP_NAME = "@app_name"
@@ -77,31 +77,26 @@ class Veracode(FlatFileImporter):
77
77
  else:
78
78
  name = self.mapping.get_value(dat, "Source", "")
79
79
  account_id = str(self.mapping.get_value(dat, "ID", ""))
80
- asset = Asset(
80
+ asset = IntegrationAsset(
81
81
  **{
82
- "id": 0,
83
82
  "name": name,
84
- "otherTrackingNumber": account_id,
85
- "ipAddress": "0.0.0.0",
86
- "isPublic": True,
83
+ "ip_address": "0.0.0.0",
84
+ "identifier": name,
85
+ "other_tracking_number": account_id,
87
86
  "status": "Active (On Network)",
88
- "assetCategory": "Software",
89
- "bLatestScan": True,
90
- "bAuthenticatedScan": True,
91
- "scanningTool": self.name,
92
- "assetOwnerId": self.config["userId"],
93
- "assetType": "Other",
94
- "softwareVendor": "Veracode",
95
- "softwareName": name,
96
- "softwareVersion": version,
97
- "systemAdministratorId": self.config["userId"],
98
- "parentId": self.attributes.parent_id,
99
- "parentModule": self.attributes.parent_module,
87
+ "asset_category": "Hardware",
88
+ "software_vendor": "Veracode",
89
+ "software_name": name,
90
+ "software_version": version,
91
+ "asset_type": "Other",
92
+ "scanning_tool": self.name,
100
93
  }
101
94
  )
102
95
  return [asset]
103
96
 
104
- def create_vuln(self, dat: Optional[dict] = None, **kwargs) -> Union[List[Vulnerability], List[IntegrationFinding]]:
97
+ def create_vuln(
98
+ self, dat: Optional[dict] = None, **kwargs
99
+ ) -> Union[List[IntegrationFinding], List[IntegrationFinding]]:
105
100
  """
106
101
  Create a RegScale vulnerability from a vulnerability in the Veracode export file
107
102
 
@@ -1,16 +1,21 @@
1
1
  """
2
- Nexpose Scan information
2
+ JFrog Xray Scan information
3
3
  """
4
4
 
5
- from typing import List, Optional
5
+ import logging
6
+ import traceback
7
+ from typing import Callable, Iterator, Optional
6
8
 
7
9
  from regscale.core.app.application import Application
8
10
  from regscale.core.app.logz import create_logger
9
- from regscale.core.app.utils.app_utils import epoch_to_datetime, get_current_datetime
10
- from regscale.models import ImportValidater, Mapping
11
+ from regscale.core.app.utils.app_utils import epoch_to_datetime, get_current_datetime, is_valid_fqdn
12
+ from regscale.exceptions import ValidationException
13
+ from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding
14
+ from regscale.models import ImportValidater
11
15
  from regscale.models.integration_models.flat_file_importer import FlatFileImporter
12
- from regscale.models.regscale_models.asset import Asset
13
- from regscale.models.regscale_models.vulnerability import Vulnerability
16
+ from regscale.models.regscale_models import IssueStatus, Vulnerability
17
+
18
+ logger = logging.getLogger(__name__)
14
19
 
15
20
 
16
21
  class XRay(FlatFileImporter):
@@ -25,31 +30,46 @@ class XRay(FlatFileImporter):
25
30
  def __init__(self, **kwargs):
26
31
  self.name = kwargs.get("name")
27
32
  regscale_ssp_id = kwargs.get("regscale_ssp_id")
28
- self.cvss3_score = "cvss_v3_score"
29
- self.vuln_title = "cve"
30
- self.required_headers = [
31
- "impacted_artifact",
32
- ]
33
- self.mapping_file = kwargs.get("mappings_path")
34
- self.disable_mapping = kwargs.get("disable_mapping")
33
+ # Combine related attributes to reduce instance attribute count
34
+ self.scanner_config = {
35
+ "cvss3_score": "cvss_v3_score",
36
+ "vuln_title": "cve",
37
+ "required_headers": ["impacted_artifact"],
38
+ }
39
+ # Combine mapping-related attributes
40
+ self.mapping_config = {
41
+ "mapping_file": kwargs.get("mappings_path"),
42
+ "disable_mapping": kwargs.get("disable_mapping"),
43
+ }
35
44
  self.validater = ImportValidater(
36
- self.required_headers, kwargs.get("file_path"), self.mapping_file, self.disable_mapping
45
+ self.scanner_config["required_headers"],
46
+ kwargs.get("file_path"),
47
+ self.mapping_config["mapping_file"],
48
+ self.mapping_config["disable_mapping"],
37
49
  )
38
50
  self.headers = self.validater.parsed_headers
39
51
  self.mapping = self.validater.mapping
40
- logger = create_logger()
52
+ xray_logger = create_logger()
53
+ # set vuln count and asset count in constructor
54
+ vuln_count = 0
55
+ asset_count = 0
56
+ for dat in self.validater.data:
57
+ vuln_count += len(self.mapping.get_value(dat, "cves", []))
58
+ asset_count += 1
41
59
  super().__init__(
42
- logger=logger,
60
+ logger=xray_logger,
43
61
  app=Application(),
44
62
  headers=None,
45
63
  parent_id=regscale_ssp_id,
46
64
  parent_module="securityplans",
47
65
  asset_func=self.create_asset,
48
66
  vuln_func=self.create_vuln,
67
+ vuln_count=vuln_count,
68
+ asset_count=asset_count,
49
69
  **kwargs,
50
70
  )
51
71
 
52
- def create_asset(self, dat: Optional[dict] = None) -> Optional[Asset]:
72
+ def create_asset(self, dat: Optional[dict] = None) -> Optional[IntegrationAsset]:
53
73
  """
54
74
  Create an asset from a row in the Xray JSON file
55
75
 
@@ -59,77 +79,251 @@ class XRay(FlatFileImporter):
59
79
  """
60
80
 
61
81
  if asset_name := self.mapping.get_value(dat, "impacted_artifact") if isinstance(dat, dict) else dat:
62
- return Asset(
82
+ return IntegrationAsset(
63
83
  **{
64
- "id": 0,
65
84
  "name": asset_name,
66
- "ipAddress": "0.0.0.0",
67
- "isPublic": True,
85
+ "ip_address": "0.0.0.0",
86
+ "identifier": asset_name,
87
+ "other_tracking_number": asset_name,
68
88
  "status": "Active (On Network)",
69
- "assetCategory": "Software",
70
- "bLatestScan": True,
71
- "bAuthenticatedScan": True,
72
- "scanningTool": self.name,
73
- "assetOwnerId": self.config["userId"],
74
- "assetType": "Other",
75
- "fqdn": None,
76
- "operatingSystem": "Linux",
77
- "systemAdministratorId": self.config["userId"],
78
- "parentId": self.attributes.parent_id,
79
- "parentModule": self.attributes.parent_module,
89
+ "asset_category": "Hardware",
90
+ "asset_type": "Other",
91
+ "scanning_tool": self.name,
92
+ "fqdn": asset_name if is_valid_fqdn(asset_name) else None,
93
+ "operating_system": "Linux",
80
94
  }
81
95
  )
82
96
  return None
83
97
 
84
- def create_vuln(self, dat: Optional[dict] = None, **kwargs) -> List[Vulnerability]:
98
+ def create_asset_from_name(self, asset_name: str) -> IntegrationAsset:
99
+ """Create an IntegrationAsset from an asset name
100
+
101
+ :param str asset_name: The name of the asset
102
+ :return: IntegrationAsset object
103
+ :rtype: IntegrationAsset
85
104
  """
86
- Create a vulnerability from a row in the JFrog Xray JSON file
105
+ return IntegrationAsset(
106
+ **{
107
+ "name": asset_name,
108
+ "ip_address": "0.0.0.0",
109
+ "identifier": asset_name,
110
+ "other_tracking_number": asset_name,
111
+ "status": "Active (On Network)",
112
+ "asset_category": "Hardware",
113
+ "asset_type": "Other",
114
+ "scanning_tool": self.name,
115
+ "fqdn": asset_name if is_valid_fqdn(asset_name) else None,
116
+ "operating_system": "Linux",
117
+ }
118
+ )
87
119
 
88
- :param Optional[dict] dat: Data row from JSON file, defaults to None
89
- :return: List of RegScale Vulnerability object, if any
90
- :rtype: List[Vulnerability]
91
- """
92
- asset_match = [
93
- asset for asset in self.data["assets"] if asset.name == self.mapping.get_value(dat, "impacted_artifact")
94
- ]
95
- asset = asset_match[0] if asset_match else None
96
- vulns = []
97
- for vuln in self.mapping.get_value(dat, "cves", []):
98
- # CVE IS A VULN, A VULN IS A CVE, Finkle is Einhorn
99
- regscale_vuln = None
100
- severity = (
101
- Vulnerability.determine_cvss3_severity_text(float(vuln[self.cvss3_score]))
102
- if vuln.get(self.cvss3_score)
103
- else "low"
104
- )
105
- if asset_match:
106
- cves = [c["cve"] for c in self.mapping.get_value(dat, "cves", []) if c.get("cve")]
107
- for cve in cves:
108
- regscale_vuln = Vulnerability(
109
- id=0,
110
- scanId=0, # set later
111
- parentId=asset.id,
112
- parentModule="assets",
113
- ipAddress="0.0.0.0", # No ip address available
114
- lastSeen=self.scan_date,
115
- firstSeen=epoch_to_datetime(self.create_epoch),
116
- daysOpen=None,
117
- dns=self.mapping.get_value(dat, "impacted_artifact"),
118
- mitigated=None,
119
- operatingSystem="Linux",
120
- severity=severity,
121
- plugInName=self.mapping.get_value(dat, "issue_id", "XRay"),
122
- plugInId=int(self.mapping.get_value(dat, "issue_id", "Xray-0000")[5:]),
123
- cve=cve,
124
- vprScore=None,
125
- tenantsId=0, # Need a way to figure this out programmatically
126
- title=f"{self.mapping.get_value(dat, 'issue_id') or self.mapping.get_value(dat, 'summary', f'XRay Vulnerability from Import {get_current_datetime()}')} on asset {asset.name}",
127
- description=self.mapping.get_value(dat, "summary"),
128
- plugInText=vuln.get("cve"),
129
- extra_data={
130
- "references": self.mapping.get_value(dat, "references", "None"),
131
- "solution": self.mapping.get_value(dat, "fixed_versions", "None"),
132
- },
133
- )
134
- vulns.append(regscale_vuln)
135
- return vulns
120
+ def _extract_asset_name(self, data_item) -> Optional[str]:
121
+ """Extract asset name from data item
122
+
123
+ :param data_item: Data item to extract asset name from
124
+ :return: Asset name if found, None otherwise
125
+ :rtype: Optional[str]
126
+ """
127
+ if isinstance(data_item, dict):
128
+ return self.mapping.get_value(data_item, "impacted_artifact")
129
+ return data_item if data_item else None
130
+
131
+ def _process_list_data(self) -> Iterator[IntegrationAsset]:
132
+ """Process list data and yield assets
133
+
134
+ :return: Iterator of IntegrationAsset objects
135
+ :rtype: Iterator[IntegrationAsset]
136
+ """
137
+ for data_item in self.file_data:
138
+ if asset_name := self._extract_asset_name(data_item):
139
+ yield self.create_asset_from_name(asset_name)
140
+
141
+ def _process_dict_data(self) -> Iterator[IntegrationAsset]:
142
+ """Process dict data and yield assets
143
+
144
+ :return: Iterator of IntegrationAsset objects
145
+ :rtype: Iterator[IntegrationAsset]
146
+ """
147
+ if asset_name := self._extract_asset_name(self.file_data):
148
+ yield self.create_asset_from_name(asset_name)
149
+
150
+ def asset_generator(self) -> Iterator[IntegrationAsset]:
151
+ """Generate IntegrationAsset objects from the data
152
+
153
+ :return: Iterator of IntegrationAsset objects
154
+ :rtype: Iterator[IntegrationAsset]
155
+ """
156
+ if isinstance(self.file_data, list):
157
+ yield from self._process_list_data()
158
+ elif isinstance(self.file_data, dict):
159
+ yield from self._process_dict_data()
160
+
161
+ def process_assets(self, func: Callable) -> None:
162
+ """
163
+ Process the assets in the data and create an iterator of IntegrationAsset objects
164
+
165
+ :param Callable func: Function to create asset (not used)
166
+ :return: None
167
+ """
168
+
169
+ # Set the assets as an iterator directly
170
+ self.data["assets"] = self.asset_generator()
171
+ self.integration_assets = self.data["assets"]
172
+
173
+ def create_vuln(self, _dat: Optional[dict] = None, **kwargs) -> Iterator[IntegrationFinding]:
174
+ """
175
+ Fetches findings from the processed json files
176
+
177
+ :param Optional[dict] _dat: Data row from JSON file (unused, kept for compatibility)
178
+ :param **kwargs: Additional keyword arguments including index
179
+ :return: A list of findings
180
+ :rtype: Iterator[IntegrationFinding]
181
+ """
182
+ if findings := self.fetch_findings(**kwargs):
183
+ yield from findings
184
+
185
+ def _validate_cve_data(self, cve_data) -> bool:
186
+ """Validate CVE data structure
187
+
188
+ :param cve_data: CVE data to validate
189
+ :return: True if valid, False otherwise
190
+ :rtype: bool
191
+ """
192
+ if not isinstance(cve_data, list):
193
+ logger.warning("CVE data is not a list, skipping vulnerability creation")
194
+ return False
195
+ return True
196
+
197
+ def _get_valid_cve_data(self, cve_data: list) -> list:
198
+ """Filter CVE data to only include valid entries
199
+
200
+ :param list cve_data: Raw CVE data
201
+ :return: Filtered CVE data with actual CVE IDs
202
+ :rtype: list
203
+ """
204
+ return [c for c in cve_data if c.get("cve")]
205
+
206
+ def _determine_severity_from_cve(self, cve_dat: dict) -> str:
207
+ """Determine severity from CVE data
208
+
209
+ :param dict cve_dat: CVE data dictionary
210
+ :return: Severity string
211
+ :rtype: str
212
+ """
213
+ cvss3_score = cve_dat.get("cvss_v3_score", 0.0)
214
+ if cve_dat.get(self.scanner_config["cvss3_score"]):
215
+ return Vulnerability.determine_cvss3_severity_text(float(cvss3_score))
216
+ return "low"
217
+
218
+ def _extract_plugin_id(self, data_item: dict) -> int:
219
+ """Extract plugin ID from issue ID
220
+
221
+ :param dict data_item: Data item containing issue information
222
+ :return: Plugin ID as integer
223
+ :rtype: int
224
+ """
225
+ issue_id = self.mapping.get_value(data_item, "issue_id", "Xray-0000")
226
+ try:
227
+ if len(issue_id) > 5:
228
+ return int(issue_id[5:])
229
+ return 0
230
+ except (ValueError, TypeError):
231
+ logger.warning("Could not parse plugin_id from issue_id: %s", issue_id)
232
+ return 0
233
+
234
+ def _get_title_base(self, data_item: dict) -> str:
235
+ """Get title base for the finding
236
+
237
+ :param dict data_item: Data item containing issue information
238
+ :return: Title base string
239
+ :rtype: str
240
+ """
241
+ return self.mapping.get_value(data_item, "issue_id") or self.mapping.get_value(
242
+ data_item, "summary", f"XRay Vulnerability from Import {get_current_datetime()}"
243
+ )
244
+
245
+ def _create_finding_from_cve(self, data_item: dict, asset_name: str, cve_dat: dict) -> IntegrationFinding:
246
+ """Create a single finding from CVE data
247
+
248
+ :param dict data_item: Data item containing vulnerability information
249
+ :param str asset_name: Asset name for the finding
250
+ :param dict cve_dat: CVE data dictionary
251
+ :return: IntegrationFinding object
252
+ :rtype: IntegrationFinding
253
+ """
254
+ cve = cve_dat.get("cve")
255
+ cvss3_score = cve_dat.get("cvss_v3_score", 0.0)
256
+ severity = self._determine_severity_from_cve(cve_dat)
257
+ plugin_id = self._extract_plugin_id(data_item)
258
+ title_base = self._get_title_base(data_item)
259
+
260
+ return IntegrationFinding(
261
+ title=f"{title_base} on asset {asset_name}",
262
+ description=self.mapping.get_value(data_item, "summary"),
263
+ severity=self.determine_severity(severity),
264
+ status=IssueStatus.Open.value,
265
+ cvss_v3_score=cvss3_score,
266
+ cvss_v3_vector=cve_dat.get("cvss_v3_vector", ""),
267
+ plugin_name=self.mapping.get_value(data_item, "issue_id", "XRay"),
268
+ plugin_id=plugin_id,
269
+ asset_identifier=asset_name,
270
+ cve=cve,
271
+ first_seen=epoch_to_datetime(self.create_epoch),
272
+ last_seen=self.scan_date,
273
+ scan_date=self.scan_date,
274
+ category="Software",
275
+ control_labels=[],
276
+ )
277
+
278
+ def _create_findings_from_data_item(self, data_item: dict, asset_name: str) -> Iterator[IntegrationFinding]:
279
+ """Create findings from a single data item
280
+
281
+ :param dict data_item: The data item containing vulnerability information
282
+ :param str asset_name: The asset name for the finding
283
+ :yields: IntegrationFinding objects
284
+ """
285
+ cve_data = self.mapping.get_value(data_item, "cves", [])
286
+ if not self._validate_cve_data(cve_data):
287
+ return
288
+
289
+ valid_cve_data = self._get_valid_cve_data(cve_data)
290
+ for cve_dat in valid_cve_data:
291
+ yield self._create_finding_from_cve(data_item, asset_name, cve_dat)
292
+
293
+ def _process_list_findings(self) -> Iterator[IntegrationFinding]:
294
+ """Process findings from list data
295
+
296
+ :yields: IntegrationFinding objects
297
+ """
298
+ for data_item in self.file_data:
299
+ if isinstance(data_item, list):
300
+ continue
301
+ asset_name = self._extract_asset_name(data_item)
302
+ if asset_name:
303
+ yield from self._create_findings_from_data_item(data_item, asset_name)
304
+
305
+ def _process_dict_findings(self) -> Iterator[IntegrationFinding]:
306
+ """Process findings from dict data
307
+
308
+ :yields: IntegrationFinding objects
309
+ """
310
+ asset_name = self._extract_asset_name(self.file_data)
311
+ if asset_name:
312
+ yield from self._create_findings_from_data_item(self.file_data, asset_name)
313
+
314
+ def fetch_findings(self, **_) -> Iterator[IntegrationFinding]:
315
+ """
316
+ Fetch findings from Xray scan data.
317
+
318
+ :raises ValidationException: If there is an error fetching/parsing findings
319
+ :yields: Iterator[IntegrationFinding]
320
+ """
321
+ try:
322
+ if isinstance(self.file_data, list):
323
+ yield from self._process_list_findings()
324
+ elif isinstance(self.file_data, dict):
325
+ yield from self._process_dict_findings()
326
+ except Exception as exc:
327
+ error_message = traceback.format_exc()
328
+ logger.error("Error fetching findings: %s", error_message)
329
+ raise ValidationException(f"Error fetching findings: {error_message}") from exc
@@ -1,6 +1,7 @@
1
1
  """RegScale models."""
2
2
 
3
3
  from .assessment_plan import *
4
+ from .assessment_result import *
4
5
  from .assessment import *
5
6
  from .asset import *
6
7
  from .asset_mapping import *
@@ -10,6 +11,7 @@ from .case import *
10
11
  from .cci import *
11
12
  from .change import *
12
13
  from .checklist import *
14
+ from .classification import *
13
15
  from .comment import *
14
16
  from .compliance_settings import *
15
17
  from .component import *
@@ -21,23 +23,32 @@ from .control_parameter import *
21
23
  from .control_test import *
22
24
  from .control_test_plan import *
23
25
  from .control_test_result import *
26
+ from .cryptography import *
24
27
  from .custom_field import *
25
28
  from .data import *
26
29
  from .data_center import *
30
+ from .deviation import *
27
31
  from .email import *
28
32
  from .evidence import *
29
33
  from .evidence_mapping import *
30
34
  from .facility import *
31
35
  from .file import *
36
+ from .filetag import *
37
+ from .form_field_value import *
38
+ from .functional_roles import *
39
+ from .group import *
32
40
  from .implementation_objective import *
33
41
  from .implementation_option import *
42
+ from .implementation_role import *
34
43
  from .incident import *
35
44
  from .inherited_control import *
36
45
  from .interconnection import *
37
46
  from .issue import *
38
47
  from .leveraged_authorization import *
48
+ from .line_of_inquiry import *
39
49
  from .link import *
40
50
  from .master_assessment import *
51
+ from .milestone import *
41
52
  from .meta_data import *
42
53
  from .objective import *
43
54
  from .parameter import *
@@ -52,6 +63,7 @@ from .property import *
52
63
  from .question import *
53
64
  from .questionnaire import *
54
65
  from .questionnaire_instance import *
66
+ from .rbac import *
55
67
  from .reference import *
56
68
  from .requirement import *
57
69
  from .risk import *
@@ -69,6 +81,7 @@ from .system_role import *
69
81
  from .system_role_external_assignment import *
70
82
  from .task import *
71
83
  from .threat import *
84
+ from .team import *
72
85
  from .user import *
73
86
  from .vulnerability import *
74
87
  from .vulnerability_mapping import *
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Model for Classification Records in the application"""
4
+
5
+ from typing import Optional, Union
6
+
7
+ from pydantic import ConfigDict
8
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
9
+
10
+
11
+ class ClassifiedRecord(RegScaleModel):
12
+ _module_slug = "classifiedRecords"
13
+
14
+ id: Optional[int] = None
15
+ parentRecordId: Optional[int] = 0
16
+ parentModule: Optional[str] = None
17
+ classificationTypeId: Optional[int] = 0
18
+ adjustedConfidentiality: Optional[str] = None
19
+ confidentialityJustification: Optional[str] = None
20
+ adjustedAvailability: Optional[str] = None
21
+ availabilityJustification: Optional[str] = None
22
+ adjustedIntegrity: Optional[str] = None
23
+ integrityJustification: Optional[str] = None
@@ -70,6 +70,7 @@ class ControlImplementation(RegScaleModel):
70
70
 
71
71
  _module_slug = "controlImplementation"
72
72
  _module_string = "controls"
73
+ _unique_fields = [["controlID", "parentId", "parentModule"]]
73
74
  _get_objects_for_list = True
74
75
 
75
76
  controlOwnerId: str = Field(default_factory=RegScaleModel.get_user_id)
@@ -248,18 +249,19 @@ class ControlImplementation(RegScaleModel):
248
249
  return response.json()
249
250
  return None
250
251
 
251
- def find_by_unique(self, **kwargs: dict) -> Optional["ControlImplementation"]:
252
- """
253
- Find an object by unique query.
254
-
255
- :param dict **kwargs: The unique query parameters
256
- :return: The object or None if not found
257
- :rtype: Optional[ControlImplementation]
258
- """
259
-
260
- for instance in self.get_by_security_control_id(security_control_id=self.controlID):
261
- return instance
262
- return None
252
+ # Removed for now, will need to be added back once platform changes are made
253
+ # def find_by_unique(self, **kwargs: dict) -> Optional["ControlImplementation"]:
254
+ # """
255
+ # Find an object by unique query.
256
+ #
257
+ # :param dict **kwargs: The unique query parameters
258
+ # :return: The object or None if not found
259
+ # :rtype: Optional[ControlImplementation]
260
+ # """
261
+ #
262
+ # for instance in self.get_by_security_control_id(security_control_id=self.controlID):
263
+ # return instance
264
+ # return None
263
265
 
264
266
  def _get_status_enum(self) -> List["ControlImplementationStatus"]:
265
267
  """
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Model for Cryptography in the application"""
4
+
5
+ from typing import Optional
6
+
7
+ from pydantic import ConfigDict, Field
8
+ from regscale.core.app.utils.app_utils import get_current_datetime
9
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
10
+
11
+
12
+ class Cryptography(RegScaleModel):
13
+ _module_slug = "cryptography"
14
+
15
+ id: Optional[int] = None
16
+ cryptographyType: str
17
+ sourceArea: Optional[str] = None
18
+ sourceVendorName: Optional[str] = None
19
+ sourceModule: Optional[str] = None
20
+ fipsNumber: Optional[str] = None
21
+ bSourceEmbedded: Optional[bool] = False
22
+ bSourceThirdParty: Optional[bool] = False
23
+ bSourceOS: Optional[bool] = False
24
+ bSourceFIPS: Optional[bool] = False
25
+ bSourceOther: Optional[bool] = False
26
+ sourceExplanationOther: Optional[str] = None
27
+ destinationArea: Optional[str] = None
28
+ destinationVendorName: Optional[str] = None
29
+ destinationModule: Optional[str] = None
30
+ bDestinationEmbedded: Optional[bool] = False
31
+ bDestinationThirdParty: Optional[bool] = False
32
+ bDestinationOS: Optional[bool] = False
33
+ bDestinationFIPS: Optional[bool] = False
34
+ bDestinationOther: Optional[bool] = False
35
+ destinationExplanationOther: Optional[str] = None
36
+ bUsageTLS11: Optional[bool] = False
37
+ bUsageTLS12: Optional[bool] = False
38
+ bUsageTLS13: Optional[bool] = False
39
+ bUsageOther: Optional[bool] = False
40
+ usageExplanationOther: Optional[str] = None
41
+ usage: str
42
+ bRestFullDisk: Optional[bool] = False
43
+ bRestFile: Optional[bool] = False
44
+ bRestRecord: Optional[bool] = False
45
+ bRestNone: Optional[bool] = False
46
+ encryptionExplanationOther: Optional[str] = None
47
+ encryptionType: Optional[str] = None
48
+ notes: Optional[str] = None
49
+ referenceUrl: Optional[str] = None
50
+ isPublic: Optional[bool] = False
51
+ parentId: Optional[int] = 0
52
+ parentModule: Optional[str] = None
53
+ dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
54
+ lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
55
+ dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
56
+ tenantsId: int = 1