regscale-cli 6.16.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 (481) hide show
  1. regscale/__init__.py +1 -0
  2. regscale/airflow/__init__.py +9 -0
  3. regscale/airflow/azure/__init__.py +9 -0
  4. regscale/airflow/azure/cli.py +89 -0
  5. regscale/airflow/azure/upload_dags.py +116 -0
  6. regscale/airflow/click_dags.py +127 -0
  7. regscale/airflow/click_mixins.py +82 -0
  8. regscale/airflow/config.py +25 -0
  9. regscale/airflow/factories/__init__.py +0 -0
  10. regscale/airflow/factories/connections.py +58 -0
  11. regscale/airflow/factories/workflows.py +78 -0
  12. regscale/airflow/hierarchy.py +88 -0
  13. regscale/airflow/operators/__init__.py +0 -0
  14. regscale/airflow/operators/click.py +36 -0
  15. regscale/airflow/sensors/__init__.py +0 -0
  16. regscale/airflow/sensors/sql.py +107 -0
  17. regscale/airflow/sessions/__init__.py +0 -0
  18. regscale/airflow/sessions/sql/__init__.py +3 -0
  19. regscale/airflow/sessions/sql/queries.py +64 -0
  20. regscale/airflow/sessions/sql/sql_server_queries.py +248 -0
  21. regscale/airflow/tasks/__init__.py +0 -0
  22. regscale/airflow/tasks/branches.py +22 -0
  23. regscale/airflow/tasks/cli.py +116 -0
  24. regscale/airflow/tasks/click.py +73 -0
  25. regscale/airflow/tasks/debugging.py +9 -0
  26. regscale/airflow/tasks/groups.py +116 -0
  27. regscale/airflow/tasks/init.py +60 -0
  28. regscale/airflow/tasks/states.py +47 -0
  29. regscale/airflow/tasks/workflows.py +36 -0
  30. regscale/ansible/__init__.py +9 -0
  31. regscale/core/__init__.py +0 -0
  32. regscale/core/app/__init__.py +3 -0
  33. regscale/core/app/api.py +571 -0
  34. regscale/core/app/application.py +665 -0
  35. regscale/core/app/internal/__init__.py +136 -0
  36. regscale/core/app/internal/admin_actions.py +230 -0
  37. regscale/core/app/internal/assessments_editor.py +873 -0
  38. regscale/core/app/internal/catalog.py +316 -0
  39. regscale/core/app/internal/comparison.py +459 -0
  40. regscale/core/app/internal/control_editor.py +571 -0
  41. regscale/core/app/internal/encrypt.py +79 -0
  42. regscale/core/app/internal/evidence.py +1240 -0
  43. regscale/core/app/internal/file_uploads.py +151 -0
  44. regscale/core/app/internal/healthcheck.py +66 -0
  45. regscale/core/app/internal/login.py +305 -0
  46. regscale/core/app/internal/migrations.py +240 -0
  47. regscale/core/app/internal/model_editor.py +1701 -0
  48. regscale/core/app/internal/poam_editor.py +632 -0
  49. regscale/core/app/internal/workflow.py +105 -0
  50. regscale/core/app/logz.py +74 -0
  51. regscale/core/app/utils/XMLIR.py +258 -0
  52. regscale/core/app/utils/__init__.py +0 -0
  53. regscale/core/app/utils/api_handler.py +358 -0
  54. regscale/core/app/utils/app_utils.py +1110 -0
  55. regscale/core/app/utils/catalog_utils/__init__.py +0 -0
  56. regscale/core/app/utils/catalog_utils/common.py +91 -0
  57. regscale/core/app/utils/catalog_utils/compare_catalog.py +193 -0
  58. regscale/core/app/utils/catalog_utils/diagnostic_catalog.py +97 -0
  59. regscale/core/app/utils/catalog_utils/download_catalog.py +103 -0
  60. regscale/core/app/utils/catalog_utils/update_catalog.py +718 -0
  61. regscale/core/app/utils/catalog_utils/update_catalog_v2.py +1378 -0
  62. regscale/core/app/utils/catalog_utils/update_catalog_v3.py +1272 -0
  63. regscale/core/app/utils/catalog_utils/update_plans.py +334 -0
  64. regscale/core/app/utils/file_utils.py +238 -0
  65. regscale/core/app/utils/parser_utils.py +81 -0
  66. regscale/core/app/utils/pickle_file_handler.py +57 -0
  67. regscale/core/app/utils/regscale_utils.py +319 -0
  68. regscale/core/app/utils/report_utils.py +119 -0
  69. regscale/core/app/utils/variables.py +226 -0
  70. regscale/core/decorators.py +31 -0
  71. regscale/core/lazy_group.py +65 -0
  72. regscale/core/login.py +63 -0
  73. regscale/core/server/__init__.py +0 -0
  74. regscale/core/server/flask_api.py +473 -0
  75. regscale/core/server/helpers.py +373 -0
  76. regscale/core/server/rest.py +64 -0
  77. regscale/core/server/static/css/bootstrap.css +6030 -0
  78. regscale/core/server/static/css/bootstrap.min.css +6 -0
  79. regscale/core/server/static/css/main.css +176 -0
  80. regscale/core/server/static/images/regscale-cli.svg +49 -0
  81. regscale/core/server/static/images/regscale.svg +38 -0
  82. regscale/core/server/templates/base.html +74 -0
  83. regscale/core/server/templates/index.html +43 -0
  84. regscale/core/server/templates/login.html +28 -0
  85. regscale/core/server/templates/make_base64.html +22 -0
  86. regscale/core/server/templates/upload_STIG.html +109 -0
  87. regscale/core/server/templates/upload_STIG_result.html +26 -0
  88. regscale/core/server/templates/upload_ssp.html +144 -0
  89. regscale/core/server/templates/upload_ssp_result.html +128 -0
  90. regscale/core/static/__init__.py +0 -0
  91. regscale/core/static/regex.py +14 -0
  92. regscale/core/utils/__init__.py +117 -0
  93. regscale/core/utils/click_utils.py +13 -0
  94. regscale/core/utils/date.py +238 -0
  95. regscale/core/utils/graphql.py +254 -0
  96. regscale/core/utils/urls.py +23 -0
  97. regscale/dev/__init__.py +6 -0
  98. regscale/dev/analysis.py +454 -0
  99. regscale/dev/cli.py +235 -0
  100. regscale/dev/code_gen.py +492 -0
  101. regscale/dev/dirs.py +69 -0
  102. regscale/dev/docs.py +384 -0
  103. regscale/dev/monitoring.py +26 -0
  104. regscale/dev/profiling.py +216 -0
  105. regscale/exceptions/__init__.py +4 -0
  106. regscale/exceptions/license_exception.py +7 -0
  107. regscale/exceptions/validation_exception.py +9 -0
  108. regscale/integrations/__init__.py +1 -0
  109. regscale/integrations/commercial/__init__.py +486 -0
  110. regscale/integrations/commercial/ad.py +433 -0
  111. regscale/integrations/commercial/amazon/__init__.py +0 -0
  112. regscale/integrations/commercial/amazon/common.py +106 -0
  113. regscale/integrations/commercial/aqua/__init__.py +0 -0
  114. regscale/integrations/commercial/aqua/aqua.py +91 -0
  115. regscale/integrations/commercial/aws/__init__.py +6 -0
  116. regscale/integrations/commercial/aws/cli.py +322 -0
  117. regscale/integrations/commercial/aws/inventory/__init__.py +110 -0
  118. regscale/integrations/commercial/aws/inventory/base.py +64 -0
  119. regscale/integrations/commercial/aws/inventory/resources/__init__.py +19 -0
  120. regscale/integrations/commercial/aws/inventory/resources/compute.py +234 -0
  121. regscale/integrations/commercial/aws/inventory/resources/containers.py +113 -0
  122. regscale/integrations/commercial/aws/inventory/resources/database.py +101 -0
  123. regscale/integrations/commercial/aws/inventory/resources/integration.py +237 -0
  124. regscale/integrations/commercial/aws/inventory/resources/networking.py +253 -0
  125. regscale/integrations/commercial/aws/inventory/resources/security.py +240 -0
  126. regscale/integrations/commercial/aws/inventory/resources/storage.py +91 -0
  127. regscale/integrations/commercial/aws/scanner.py +823 -0
  128. regscale/integrations/commercial/azure/__init__.py +0 -0
  129. regscale/integrations/commercial/azure/common.py +32 -0
  130. regscale/integrations/commercial/azure/intune.py +488 -0
  131. regscale/integrations/commercial/azure/scanner.py +49 -0
  132. regscale/integrations/commercial/burp.py +78 -0
  133. regscale/integrations/commercial/cpe.py +144 -0
  134. regscale/integrations/commercial/crowdstrike.py +1117 -0
  135. regscale/integrations/commercial/defender.py +1511 -0
  136. regscale/integrations/commercial/dependabot.py +210 -0
  137. regscale/integrations/commercial/durosuite/__init__.py +0 -0
  138. regscale/integrations/commercial/durosuite/api.py +1546 -0
  139. regscale/integrations/commercial/durosuite/process_devices.py +101 -0
  140. regscale/integrations/commercial/durosuite/scanner.py +637 -0
  141. regscale/integrations/commercial/durosuite/variables.py +21 -0
  142. regscale/integrations/commercial/ecr.py +90 -0
  143. regscale/integrations/commercial/gcp/__init__.py +237 -0
  144. regscale/integrations/commercial/gcp/auth.py +96 -0
  145. regscale/integrations/commercial/gcp/control_tests.py +238 -0
  146. regscale/integrations/commercial/gcp/variables.py +18 -0
  147. regscale/integrations/commercial/gitlab.py +332 -0
  148. regscale/integrations/commercial/grype.py +165 -0
  149. regscale/integrations/commercial/ibm.py +90 -0
  150. regscale/integrations/commercial/import_all/__init__.py +0 -0
  151. regscale/integrations/commercial/import_all/import_all_cmd.py +467 -0
  152. regscale/integrations/commercial/import_all/scan_file_fingerprints.json +27 -0
  153. regscale/integrations/commercial/jira.py +1046 -0
  154. regscale/integrations/commercial/mappings/__init__.py +0 -0
  155. regscale/integrations/commercial/mappings/csf_controls.json +713 -0
  156. regscale/integrations/commercial/mappings/nist_800_53_r5_controls.json +1516 -0
  157. regscale/integrations/commercial/nessus/__init__.py +0 -0
  158. regscale/integrations/commercial/nessus/nessus_utils.py +429 -0
  159. regscale/integrations/commercial/nessus/scanner.py +416 -0
  160. regscale/integrations/commercial/nexpose.py +90 -0
  161. regscale/integrations/commercial/okta.py +798 -0
  162. regscale/integrations/commercial/opentext/__init__.py +0 -0
  163. regscale/integrations/commercial/opentext/click.py +99 -0
  164. regscale/integrations/commercial/opentext/scanner.py +143 -0
  165. regscale/integrations/commercial/prisma.py +91 -0
  166. regscale/integrations/commercial/qualys.py +1462 -0
  167. regscale/integrations/commercial/salesforce.py +980 -0
  168. regscale/integrations/commercial/sap/__init__.py +0 -0
  169. regscale/integrations/commercial/sap/click.py +31 -0
  170. regscale/integrations/commercial/sap/sysdig/__init__.py +0 -0
  171. regscale/integrations/commercial/sap/sysdig/click.py +57 -0
  172. regscale/integrations/commercial/sap/sysdig/sysdig_scanner.py +190 -0
  173. regscale/integrations/commercial/sap/tenable/__init__.py +0 -0
  174. regscale/integrations/commercial/sap/tenable/click.py +49 -0
  175. regscale/integrations/commercial/sap/tenable/scanner.py +196 -0
  176. regscale/integrations/commercial/servicenow.py +1756 -0
  177. regscale/integrations/commercial/sicura/__init__.py +0 -0
  178. regscale/integrations/commercial/sicura/api.py +855 -0
  179. regscale/integrations/commercial/sicura/commands.py +73 -0
  180. regscale/integrations/commercial/sicura/scanner.py +481 -0
  181. regscale/integrations/commercial/sicura/variables.py +16 -0
  182. regscale/integrations/commercial/snyk.py +90 -0
  183. regscale/integrations/commercial/sonarcloud.py +260 -0
  184. regscale/integrations/commercial/sqlserver.py +369 -0
  185. regscale/integrations/commercial/stig_mapper_integration/__init__.py +0 -0
  186. regscale/integrations/commercial/stig_mapper_integration/click_commands.py +38 -0
  187. regscale/integrations/commercial/stig_mapper_integration/mapping_engine.py +353 -0
  188. regscale/integrations/commercial/stigv2/__init__.py +0 -0
  189. regscale/integrations/commercial/stigv2/ckl_parser.py +349 -0
  190. regscale/integrations/commercial/stigv2/click_commands.py +95 -0
  191. regscale/integrations/commercial/stigv2/stig_integration.py +202 -0
  192. regscale/integrations/commercial/synqly/__init__.py +0 -0
  193. regscale/integrations/commercial/synqly/assets.py +46 -0
  194. regscale/integrations/commercial/synqly/ticketing.py +132 -0
  195. regscale/integrations/commercial/synqly/vulnerabilities.py +223 -0
  196. regscale/integrations/commercial/synqly_jira.py +840 -0
  197. regscale/integrations/commercial/tenablev2/__init__.py +0 -0
  198. regscale/integrations/commercial/tenablev2/authenticate.py +31 -0
  199. regscale/integrations/commercial/tenablev2/click.py +1584 -0
  200. regscale/integrations/commercial/tenablev2/scanner.py +504 -0
  201. regscale/integrations/commercial/tenablev2/stig_parsers.py +140 -0
  202. regscale/integrations/commercial/tenablev2/utils.py +78 -0
  203. regscale/integrations/commercial/tenablev2/variables.py +17 -0
  204. regscale/integrations/commercial/trivy.py +162 -0
  205. regscale/integrations/commercial/veracode.py +96 -0
  206. regscale/integrations/commercial/wizv2/WizDataMixin.py +97 -0
  207. regscale/integrations/commercial/wizv2/__init__.py +0 -0
  208. regscale/integrations/commercial/wizv2/click.py +429 -0
  209. regscale/integrations/commercial/wizv2/constants.py +1001 -0
  210. regscale/integrations/commercial/wizv2/issue.py +361 -0
  211. regscale/integrations/commercial/wizv2/models.py +112 -0
  212. regscale/integrations/commercial/wizv2/parsers.py +339 -0
  213. regscale/integrations/commercial/wizv2/sbom.py +115 -0
  214. regscale/integrations/commercial/wizv2/scanner.py +416 -0
  215. regscale/integrations/commercial/wizv2/utils.py +796 -0
  216. regscale/integrations/commercial/wizv2/variables.py +39 -0
  217. regscale/integrations/commercial/wizv2/wiz_auth.py +159 -0
  218. regscale/integrations/commercial/xray.py +91 -0
  219. regscale/integrations/integration/__init__.py +2 -0
  220. regscale/integrations/integration/integration.py +26 -0
  221. regscale/integrations/integration/inventory.py +17 -0
  222. regscale/integrations/integration/issue.py +100 -0
  223. regscale/integrations/integration_override.py +149 -0
  224. regscale/integrations/public/__init__.py +103 -0
  225. regscale/integrations/public/cisa.py +641 -0
  226. regscale/integrations/public/criticality_updater.py +70 -0
  227. regscale/integrations/public/emass.py +411 -0
  228. regscale/integrations/public/emass_slcm_import.py +697 -0
  229. regscale/integrations/public/fedramp/__init__.py +0 -0
  230. regscale/integrations/public/fedramp/appendix_parser.py +548 -0
  231. regscale/integrations/public/fedramp/click.py +479 -0
  232. regscale/integrations/public/fedramp/components.py +714 -0
  233. regscale/integrations/public/fedramp/docx_parser.py +259 -0
  234. regscale/integrations/public/fedramp/fedramp_cis_crm.py +1124 -0
  235. regscale/integrations/public/fedramp/fedramp_common.py +3181 -0
  236. regscale/integrations/public/fedramp/fedramp_docx.py +388 -0
  237. regscale/integrations/public/fedramp/fedramp_five.py +2343 -0
  238. regscale/integrations/public/fedramp/fedramp_traversal.py +138 -0
  239. regscale/integrations/public/fedramp/import_fedramp_r4_ssp.py +279 -0
  240. regscale/integrations/public/fedramp/import_workbook.py +495 -0
  241. regscale/integrations/public/fedramp/inventory_items.py +244 -0
  242. regscale/integrations/public/fedramp/mappings/__init__.py +0 -0
  243. regscale/integrations/public/fedramp/mappings/fedramp_r4_parts.json +7388 -0
  244. regscale/integrations/public/fedramp/mappings/fedramp_r5_params.json +8636 -0
  245. regscale/integrations/public/fedramp/mappings/fedramp_r5_parts.json +9605 -0
  246. regscale/integrations/public/fedramp/mappings/system_roles.py +34 -0
  247. regscale/integrations/public/fedramp/mappings/user.py +175 -0
  248. regscale/integrations/public/fedramp/mappings/values.py +141 -0
  249. regscale/integrations/public/fedramp/markdown_parser.py +150 -0
  250. regscale/integrations/public/fedramp/metadata.py +689 -0
  251. regscale/integrations/public/fedramp/models/__init__.py +59 -0
  252. regscale/integrations/public/fedramp/models/leveraged_auth_new.py +168 -0
  253. regscale/integrations/public/fedramp/models/poam_importer.py +522 -0
  254. regscale/integrations/public/fedramp/parts_mapper.py +107 -0
  255. regscale/integrations/public/fedramp/poam/__init__.py +0 -0
  256. regscale/integrations/public/fedramp/poam/scanner.py +851 -0
  257. regscale/integrations/public/fedramp/properties.py +201 -0
  258. regscale/integrations/public/fedramp/reporting.py +84 -0
  259. regscale/integrations/public/fedramp/resources.py +496 -0
  260. regscale/integrations/public/fedramp/rosetta.py +110 -0
  261. regscale/integrations/public/fedramp/ssp_logger.py +87 -0
  262. regscale/integrations/public/fedramp/system_characteristics.py +922 -0
  263. regscale/integrations/public/fedramp/system_control_implementations.py +582 -0
  264. regscale/integrations/public/fedramp/system_implementation.py +190 -0
  265. regscale/integrations/public/fedramp/xml_utils.py +87 -0
  266. regscale/integrations/public/nist_catalog.py +275 -0
  267. regscale/integrations/public/oscal.py +1946 -0
  268. regscale/integrations/public/otx.py +169 -0
  269. regscale/integrations/scanner_integration.py +2692 -0
  270. regscale/integrations/variables.py +25 -0
  271. regscale/models/__init__.py +7 -0
  272. regscale/models/app_models/__init__.py +5 -0
  273. regscale/models/app_models/catalog_compare.py +213 -0
  274. regscale/models/app_models/click.py +252 -0
  275. regscale/models/app_models/datetime_encoder.py +21 -0
  276. regscale/models/app_models/import_validater.py +321 -0
  277. regscale/models/app_models/mapping.py +260 -0
  278. regscale/models/app_models/pipeline.py +37 -0
  279. regscale/models/click_models.py +413 -0
  280. regscale/models/config.py +154 -0
  281. regscale/models/email_style.css +67 -0
  282. regscale/models/hierarchy.py +8 -0
  283. regscale/models/inspect_models.py +79 -0
  284. regscale/models/integration_models/__init__.py +0 -0
  285. regscale/models/integration_models/amazon_models/__init__.py +0 -0
  286. regscale/models/integration_models/amazon_models/inspector.py +262 -0
  287. regscale/models/integration_models/amazon_models/inspector_scan.py +206 -0
  288. regscale/models/integration_models/aqua.py +247 -0
  289. regscale/models/integration_models/azure_alerts.py +255 -0
  290. regscale/models/integration_models/base64.py +23 -0
  291. regscale/models/integration_models/burp.py +433 -0
  292. regscale/models/integration_models/burp_models.py +128 -0
  293. regscale/models/integration_models/cisa_kev_data.json +19333 -0
  294. regscale/models/integration_models/defender_data.py +93 -0
  295. regscale/models/integration_models/defenderimport.py +143 -0
  296. regscale/models/integration_models/drf.py +443 -0
  297. regscale/models/integration_models/ecr_models/__init__.py +0 -0
  298. regscale/models/integration_models/ecr_models/data.py +69 -0
  299. regscale/models/integration_models/ecr_models/ecr.py +239 -0
  300. regscale/models/integration_models/flat_file_importer.py +1079 -0
  301. regscale/models/integration_models/grype_import.py +247 -0
  302. regscale/models/integration_models/ibm.py +126 -0
  303. regscale/models/integration_models/implementation_results.py +85 -0
  304. regscale/models/integration_models/nexpose.py +140 -0
  305. regscale/models/integration_models/prisma.py +202 -0
  306. regscale/models/integration_models/qualys.py +720 -0
  307. regscale/models/integration_models/qualys_scanner.py +160 -0
  308. regscale/models/integration_models/sbom/__init__.py +0 -0
  309. regscale/models/integration_models/sbom/cyclone_dx.py +139 -0
  310. regscale/models/integration_models/send_reminders.py +620 -0
  311. regscale/models/integration_models/snyk.py +155 -0
  312. regscale/models/integration_models/synqly_models/__init__.py +0 -0
  313. regscale/models/integration_models/synqly_models/capabilities.json +1 -0
  314. regscale/models/integration_models/synqly_models/connector_types.py +22 -0
  315. regscale/models/integration_models/synqly_models/connectors/__init__.py +7 -0
  316. regscale/models/integration_models/synqly_models/connectors/assets.py +97 -0
  317. regscale/models/integration_models/synqly_models/connectors/ticketing.py +583 -0
  318. regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +169 -0
  319. regscale/models/integration_models/synqly_models/ocsf_mapper.py +331 -0
  320. regscale/models/integration_models/synqly_models/param.py +72 -0
  321. regscale/models/integration_models/synqly_models/synqly_model.py +733 -0
  322. regscale/models/integration_models/synqly_models/tenants.py +39 -0
  323. regscale/models/integration_models/tenable_models/__init__.py +0 -0
  324. regscale/models/integration_models/tenable_models/integration.py +187 -0
  325. regscale/models/integration_models/tenable_models/models.py +513 -0
  326. regscale/models/integration_models/trivy_import.py +231 -0
  327. regscale/models/integration_models/veracode.py +217 -0
  328. regscale/models/integration_models/xray.py +135 -0
  329. regscale/models/locking.py +100 -0
  330. regscale/models/platform.py +110 -0
  331. regscale/models/regscale_models/__init__.py +67 -0
  332. regscale/models/regscale_models/assessment.py +570 -0
  333. regscale/models/regscale_models/assessment_plan.py +52 -0
  334. regscale/models/regscale_models/asset.py +567 -0
  335. regscale/models/regscale_models/asset_mapping.py +190 -0
  336. regscale/models/regscale_models/case.py +42 -0
  337. regscale/models/regscale_models/catalog.py +261 -0
  338. regscale/models/regscale_models/cci.py +46 -0
  339. regscale/models/regscale_models/change.py +167 -0
  340. regscale/models/regscale_models/checklist.py +372 -0
  341. regscale/models/regscale_models/comment.py +49 -0
  342. regscale/models/regscale_models/compliance_settings.py +112 -0
  343. regscale/models/regscale_models/component.py +412 -0
  344. regscale/models/regscale_models/component_mapping.py +65 -0
  345. regscale/models/regscale_models/control.py +38 -0
  346. regscale/models/regscale_models/control_implementation.py +1128 -0
  347. regscale/models/regscale_models/control_objective.py +261 -0
  348. regscale/models/regscale_models/control_parameter.py +100 -0
  349. regscale/models/regscale_models/control_test.py +34 -0
  350. regscale/models/regscale_models/control_test_plan.py +75 -0
  351. regscale/models/regscale_models/control_test_result.py +52 -0
  352. regscale/models/regscale_models/custom_field.py +245 -0
  353. regscale/models/regscale_models/data.py +109 -0
  354. regscale/models/regscale_models/data_center.py +40 -0
  355. regscale/models/regscale_models/deviation.py +203 -0
  356. regscale/models/regscale_models/email.py +97 -0
  357. regscale/models/regscale_models/evidence.py +47 -0
  358. regscale/models/regscale_models/evidence_mapping.py +40 -0
  359. regscale/models/regscale_models/facility.py +59 -0
  360. regscale/models/regscale_models/file.py +382 -0
  361. regscale/models/regscale_models/filetag.py +37 -0
  362. regscale/models/regscale_models/form_field_value.py +94 -0
  363. regscale/models/regscale_models/group.py +169 -0
  364. regscale/models/regscale_models/implementation_objective.py +335 -0
  365. regscale/models/regscale_models/implementation_option.py +275 -0
  366. regscale/models/regscale_models/implementation_role.py +33 -0
  367. regscale/models/regscale_models/incident.py +177 -0
  368. regscale/models/regscale_models/interconnection.py +43 -0
  369. regscale/models/regscale_models/issue.py +1176 -0
  370. regscale/models/regscale_models/leveraged_authorization.py +125 -0
  371. regscale/models/regscale_models/line_of_inquiry.py +52 -0
  372. regscale/models/regscale_models/link.py +205 -0
  373. regscale/models/regscale_models/meta_data.py +64 -0
  374. regscale/models/regscale_models/mixins/__init__.py +0 -0
  375. regscale/models/regscale_models/mixins/parent_cache.py +124 -0
  376. regscale/models/regscale_models/module.py +224 -0
  377. regscale/models/regscale_models/modules.py +191 -0
  378. regscale/models/regscale_models/objective.py +14 -0
  379. regscale/models/regscale_models/parameter.py +87 -0
  380. regscale/models/regscale_models/ports_protocol.py +81 -0
  381. regscale/models/regscale_models/privacy.py +89 -0
  382. regscale/models/regscale_models/profile.py +50 -0
  383. regscale/models/regscale_models/profile_link.py +68 -0
  384. regscale/models/regscale_models/profile_mapping.py +124 -0
  385. regscale/models/regscale_models/project.py +63 -0
  386. regscale/models/regscale_models/property.py +278 -0
  387. regscale/models/regscale_models/question.py +85 -0
  388. regscale/models/regscale_models/questionnaire.py +87 -0
  389. regscale/models/regscale_models/questionnaire_instance.py +177 -0
  390. regscale/models/regscale_models/rbac.py +132 -0
  391. regscale/models/regscale_models/reference.py +86 -0
  392. regscale/models/regscale_models/regscale_model.py +1643 -0
  393. regscale/models/regscale_models/requirement.py +29 -0
  394. regscale/models/regscale_models/risk.py +274 -0
  395. regscale/models/regscale_models/sbom.py +54 -0
  396. regscale/models/regscale_models/scan_history.py +436 -0
  397. regscale/models/regscale_models/search.py +53 -0
  398. regscale/models/regscale_models/security_control.py +132 -0
  399. regscale/models/regscale_models/security_plan.py +204 -0
  400. regscale/models/regscale_models/software_inventory.py +159 -0
  401. regscale/models/regscale_models/stake_holder.py +64 -0
  402. regscale/models/regscale_models/stig.py +647 -0
  403. regscale/models/regscale_models/supply_chain.py +152 -0
  404. regscale/models/regscale_models/system_role.py +188 -0
  405. regscale/models/regscale_models/system_role_external_assignment.py +40 -0
  406. regscale/models/regscale_models/tag.py +37 -0
  407. regscale/models/regscale_models/tag_mapping.py +19 -0
  408. regscale/models/regscale_models/task.py +133 -0
  409. regscale/models/regscale_models/threat.py +196 -0
  410. regscale/models/regscale_models/user.py +175 -0
  411. regscale/models/regscale_models/user_group.py +55 -0
  412. regscale/models/regscale_models/vulnerability.py +242 -0
  413. regscale/models/regscale_models/vulnerability_mapping.py +162 -0
  414. regscale/models/regscale_models/workflow.py +55 -0
  415. regscale/models/regscale_models/workflow_action.py +34 -0
  416. regscale/models/regscale_models/workflow_instance.py +269 -0
  417. regscale/models/regscale_models/workflow_instance_step.py +114 -0
  418. regscale/models/regscale_models/workflow_template.py +58 -0
  419. regscale/models/regscale_models/workflow_template_step.py +45 -0
  420. regscale/regscale.py +815 -0
  421. regscale/utils/__init__.py +7 -0
  422. regscale/utils/b64conversion.py +14 -0
  423. regscale/utils/click_utils.py +118 -0
  424. regscale/utils/decorators.py +48 -0
  425. regscale/utils/dict_utils.py +59 -0
  426. regscale/utils/files.py +79 -0
  427. regscale/utils/fxns.py +30 -0
  428. regscale/utils/graphql_client.py +113 -0
  429. regscale/utils/lists.py +16 -0
  430. regscale/utils/numbers.py +12 -0
  431. regscale/utils/shell.py +148 -0
  432. regscale/utils/string.py +121 -0
  433. regscale/utils/synqly_utils.py +165 -0
  434. regscale/utils/threading/__init__.py +8 -0
  435. regscale/utils/threading/threadhandler.py +131 -0
  436. regscale/utils/threading/threadsafe_counter.py +47 -0
  437. regscale/utils/threading/threadsafe_dict.py +242 -0
  438. regscale/utils/threading/threadsafe_list.py +83 -0
  439. regscale/utils/version.py +104 -0
  440. regscale/validation/__init__.py +0 -0
  441. regscale/validation/address.py +37 -0
  442. regscale/validation/record.py +48 -0
  443. regscale/visualization/__init__.py +5 -0
  444. regscale/visualization/click.py +34 -0
  445. regscale_cli-6.16.0.0.dist-info/LICENSE +21 -0
  446. regscale_cli-6.16.0.0.dist-info/METADATA +659 -0
  447. regscale_cli-6.16.0.0.dist-info/RECORD +481 -0
  448. regscale_cli-6.16.0.0.dist-info/WHEEL +5 -0
  449. regscale_cli-6.16.0.0.dist-info/entry_points.txt +6 -0
  450. regscale_cli-6.16.0.0.dist-info/top_level.txt +2 -0
  451. tests/fixtures/__init__.py +2 -0
  452. tests/fixtures/api.py +87 -0
  453. tests/fixtures/models.py +91 -0
  454. tests/fixtures/test_fixture.py +144 -0
  455. tests/mocks/__init__.py +0 -0
  456. tests/mocks/objects.py +3 -0
  457. tests/mocks/response.py +32 -0
  458. tests/mocks/xml.py +13 -0
  459. tests/regscale/__init__.py +0 -0
  460. tests/regscale/core/__init__.py +0 -0
  461. tests/regscale/core/test_api.py +232 -0
  462. tests/regscale/core/test_app.py +406 -0
  463. tests/regscale/core/test_login.py +37 -0
  464. tests/regscale/core/test_logz.py +66 -0
  465. tests/regscale/core/test_sbom_generator.py +87 -0
  466. tests/regscale/core/test_validation_utils.py +163 -0
  467. tests/regscale/core/test_version.py +78 -0
  468. tests/regscale/models/__init__.py +0 -0
  469. tests/regscale/models/test_asset.py +71 -0
  470. tests/regscale/models/test_config.py +26 -0
  471. tests/regscale/models/test_control_implementation.py +27 -0
  472. tests/regscale/models/test_import.py +97 -0
  473. tests/regscale/models/test_issue.py +36 -0
  474. tests/regscale/models/test_mapping.py +52 -0
  475. tests/regscale/models/test_platform.py +31 -0
  476. tests/regscale/models/test_regscale_model.py +346 -0
  477. tests/regscale/models/test_report.py +32 -0
  478. tests/regscale/models/test_tenable_integrations.py +118 -0
  479. tests/regscale/models/test_user_model.py +121 -0
  480. tests/regscale/test_about.py +19 -0
  481. tests/regscale/test_authorization.py +65 -0
@@ -0,0 +1,169 @@
1
+ """Vulnerabilities Connector Model"""
2
+
3
+ from typing import Iterator, Optional
4
+
5
+ from pydantic import ConfigDict
6
+
7
+ from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding, ScannerIntegration
8
+ from regscale.models.integration_models.synqly_models.synqly_model import SynqlyModel
9
+ from regscale.models.regscale_models import IssueSeverity
10
+
11
+
12
+ class VulnerabilitiesIntegration(ScannerIntegration):
13
+ title = "Vulnerabilities Connector Integration"
14
+ # Required fields from ScannerIntegration
15
+ asset_identifier_field = "otherTrackingNumber"
16
+ finding_severity_map = {
17
+ "Critical": IssueSeverity.Critical,
18
+ "High": IssueSeverity.High,
19
+ "Medium": IssueSeverity.Moderate,
20
+ "Low": IssueSeverity.Low,
21
+ }
22
+
23
+ def fetch_assets(self, *args, **kwargs) -> Iterator[IntegrationAsset]:
24
+ """
25
+ Fetches assets from Synqly
26
+
27
+ :yields: Iterator[IntegrationAsset]
28
+ """
29
+ integration_assets = kwargs.get("integration_assets")
30
+ for asset in integration_assets:
31
+ yield asset
32
+
33
+ def fetch_findings(self, *args, **kwargs) -> Iterator[IntegrationFinding]:
34
+ """
35
+ Fetches findings from the Synqly
36
+
37
+ :yields: Iterator[IntegrationFinding]
38
+ """
39
+ integration_findings = kwargs.get("integration_findings")
40
+ for finding in integration_findings:
41
+ yield finding
42
+
43
+
44
+ class Vulnerabilities(SynqlyModel):
45
+ """Vulnerabilities Connector Model"""
46
+
47
+ model_config = ConfigDict(populate_by_name=True, use_enum_values=True, arbitrary_types_allowed=True)
48
+
49
+ integration_id: str = ""
50
+ scanner_integration: Optional["VulnerabilitiesIntegration"] = None
51
+ provider: str = ""
52
+ can_fetch_assets: bool = False
53
+ can_fetch_vulns: bool = False
54
+
55
+ def __init__(self, integration: str, **kwargs):
56
+ SynqlyModel.__init__(self, connector_type=self.__class__.__name__, integration=integration, **kwargs)
57
+ self.integration_id = f"{self._connector_type.lower()}_{self.integration.lower()}"
58
+ integration_company = self.integration.split("_")[0] if "_" in self.integration else self.integration # noqa
59
+ self.provider = integration_company
60
+ self.can_fetch_assets = "query_assets" in self.capabilities
61
+ self.can_fetch_vulns = "query_findings" in self.capabilities
62
+
63
+ @staticmethod
64
+ def _handle_scan_date_options(regscale_ssp_id: int, **kwargs) -> list[str]:
65
+ """
66
+ Handle scan date options for the integration sync process
67
+
68
+ :param int regscale_ssp_id: The RegScale SSP ID
69
+ :return: List of strings to filter vulnerabilities
70
+ :rtype: list[str]
71
+ """
72
+ from regscale.integrations.commercial.tenablev2.utils import get_last_pull_epoch
73
+
74
+ if vuln_filter := kwargs.get("vuln_filter"):
75
+ kwargs.pop("vuln_filter")
76
+ if isinstance(vuln_filter, str):
77
+ vuln_filter = [f"severity[in]{vuln_filter}"]
78
+ else:
79
+ vuln_filter = ["severity[in]critical,high,medium,low"]
80
+ if kwargs.get("all_scans"):
81
+ vuln_filter.append("finding.last_seen_time[gte]915148800") # Friday, January 1, 1999 12:00:00 AM UTC
82
+ elif scan_date := kwargs.get("scan_date"):
83
+ from regscale.core.utils.date import date_obj
84
+
85
+ if scan_date := date_obj(scan_date):
86
+ vuln_filter.append(f"finding.last_seen_time[gte]{scan_date.isoformat()}")
87
+ else:
88
+ raise ValueError(f"Invalid scan date: {scan_date}")
89
+ else:
90
+ vuln_filter.append(f"finding.last_seen_time[gte]{get_last_pull_epoch(regscale_ssp_id)}")
91
+ return vuln_filter
92
+
93
+ def integration_sync(self, regscale_ssp_id: int, **kwargs) -> None:
94
+ """
95
+ Runs the integration sync process
96
+
97
+ :param int regscale_ssp_id: The RegScale SSP ID
98
+ :rtype: None
99
+ """
100
+ vuln_filter = self._handle_scan_date_options(regscale_ssp_id=regscale_ssp_id, **kwargs)
101
+ self.logger.debug(f"Vulnerability filter: {vuln_filter}")
102
+ self.logger.info(f"Fetching vulnerability data from {self.integration_name}...")
103
+ findings = (
104
+ self.fetch_integration_data(
105
+ func=self.tenant.engine_client.vulnerabilities.query_findings,
106
+ filter=vuln_filter,
107
+ **kwargs,
108
+ )
109
+ if self.can_fetch_vulns
110
+ else []
111
+ )
112
+ self.logger.info(f"Fetching asset data from {self.integration_name}...")
113
+ assets = (
114
+ self.fetch_integration_data(func=self.tenant.engine_client.vulnerabilities.query_assets, **kwargs)
115
+ if self.can_fetch_assets
116
+ else []
117
+ )
118
+
119
+ self.scanner_integration = VulnerabilitiesIntegration(plan_id=regscale_ssp_id)
120
+ self.logger.info(f"Mapping {self.provider} asset(s) data to RegScale asset(s)...")
121
+ if assets:
122
+ self.app.thread_manager.submit_tasks_from_list(
123
+ func=self.mapper.to_regscale,
124
+ items=assets,
125
+ args=None,
126
+ connector=self,
127
+ regscale_ssp_id=regscale_ssp_id,
128
+ **kwargs,
129
+ )
130
+ integration_assets = self.app.thread_manager.execute_and_verify(return_passed=True)
131
+ self.logger.info(f"Mapped {len(integration_assets)} {self.provider} asset(s) to RegScale asset(s)...")
132
+ self.scanner_integration.sync_assets(
133
+ title=f"{self.integration_name} Vulnerabilities",
134
+ plan_id=regscale_ssp_id,
135
+ integration_assets=integration_assets,
136
+ )
137
+
138
+ if findings:
139
+ integration_findings = []
140
+ self.logger.info(f"Mapping {self.provider} finding(s) data to RegScale finding(s)...")
141
+ self.app.thread_manager.submit_tasks_from_list(
142
+ func=self.mapper.to_regscale,
143
+ items=findings,
144
+ args=None,
145
+ connector=self,
146
+ regscale_ssp_id=regscale_ssp_id,
147
+ **kwargs,
148
+ )
149
+ mapped_findings = self.app.thread_manager.execute_and_verify(return_passed=True)
150
+ for finding in mapped_findings:
151
+ if isinstance(finding, list):
152
+ integration_findings.extend(finding)
153
+ else:
154
+ integration_findings.append(finding)
155
+ self.logger.info(f"Mapped {len(integration_findings)} {self.provider} finding(s) to RegScale finding(s)...")
156
+ self.scanner_integration.sync_findings(
157
+ title=f"{self.integration_name} Vulnerabilities",
158
+ plan_id=regscale_ssp_id,
159
+ integration_findings=integration_findings,
160
+ )
161
+ self.logger.info(f"[green]Sync from {self.integration_name} to RegScale completed.")
162
+
163
+ def run_sync(self, *args, **kwargs) -> None:
164
+ """
165
+ Syncs RegScale issues with Vulnerability connector using Synqly
166
+
167
+ :rtype: None
168
+ """
169
+ self.run_integration_sync(*args, **kwargs)
@@ -0,0 +1,331 @@
1
+ """Class to handle mapping RegScale models to OCSF models for Synqly integration"""
2
+
3
+ from datetime import datetime
4
+ from typing import Any, Union, TYPE_CHECKING, Optional
5
+
6
+ if TYPE_CHECKING:
7
+ from regscale.models.integration_models.synqly_models.connectors import Ticketing, Vulnerabilities
8
+ from synqly.engine.resources.ocsf.resources.v_1_1_0.resources.securityfinding import ResourceDetails, Vulnerability
9
+
10
+ from synqly import engine
11
+ from synqly.engine import CreateTicketRequest
12
+ from synqly.engine.resources.ticketing.types.priority import Priority
13
+
14
+ from regscale.core.app.utils.app_utils import (
15
+ error_and_exit,
16
+ convert_datetime_to_regscale_string,
17
+ )
18
+ from synqly.engine.resources.ticketing.types.ticket import Ticket
19
+ from synqly.engine.resources.vulnerabilities.types import Asset as OCSFAsset, SecurityFinding
20
+ from regscale.models.regscale_models import Issue
21
+ from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding
22
+
23
+
24
+ class Mapper:
25
+ """Mapping class to handle RegScale models to OCSF models for Synqly integration"""
26
+
27
+ date_format = "%Y-%m-%dT%H:%M:%S"
28
+
29
+ def to_ocsf(self, regscale_object: Any, **kwargs) -> Any:
30
+ """
31
+ Convert RegScale object to OCSF object
32
+
33
+ :param Any regscale_object: RegScale object to convert to an OCSF object
34
+ :return: The comparable OCSF object
35
+ :rtype: Any
36
+ """
37
+ if isinstance(regscale_object, Issue):
38
+ return self._regscale_issue_to_ticket(regscale_object, **kwargs)
39
+ else:
40
+ error_and_exit(f"Unsupported object type {type(regscale_object)}")
41
+
42
+ def to_regscale(self, ocsf_object: Any, connector: Union["Ticketing", "Vulnerabilities"], **kwargs) -> Any:
43
+ """
44
+ Convert OCSF object to RegScale object
45
+
46
+ :param Any ocsf_object: OCSF object to convert to a RegScale object
47
+ :param Union["Ticketing", "Vulnerabilities"] connector: Connector class object
48
+ :return: The comparable RegScale object
49
+ :rtype: Any
50
+ """
51
+ if isinstance(ocsf_object, Ticket):
52
+ return self._ticket_to_regscale(connector, ocsf_object, **kwargs)
53
+ elif isinstance(ocsf_object, OCSFAsset):
54
+ return self._ocsf_asset_to_regscale(connector, ocsf_object, **kwargs)
55
+ elif isinstance(ocsf_object, SecurityFinding):
56
+ return self._security_finding_to_regscale(connector, ocsf_object, **kwargs)
57
+ else:
58
+ error_and_exit(f"Unsupported object type {type(ocsf_object)}")
59
+
60
+ def _ticket_to_regscale(self, connector: "Ticketing", ticket: Ticket, **kwargs) -> Issue:
61
+ """
62
+ Convert OCSF Ticket to RegScale Issue
63
+
64
+ :param "Ticketing" connector: Ticketing connector class object
65
+ :param Ticket ticket: OCSF Ticket to convert to a RegScale Issue
66
+ :param dict **kwargs: Keyword Arguments
67
+ :return: The comparable RegScale Issue
68
+ :rtype: Issue
69
+ """
70
+ due_date = convert_datetime_to_regscale_string(ticket.due_date)
71
+ if not due_date:
72
+ due_date = self._determine_due_date(ticket.priority)
73
+ ticket_dict = ticket.dict()
74
+ key_val_desc = "All fields:\n"
75
+ for k, v in ticket_dict.items():
76
+ key_val_desc += f"{k.replace('_', ' ').title()}: {str(v) or 'NULL'}\n"
77
+ regscale_issue = Issue(
78
+ title=ticket.summary,
79
+ severityLevel=Issue.assign_severity(ticket.priority),
80
+ dueDate=due_date,
81
+ description=f"Description {ticket.description}\n{key_val_desc}",
82
+ status=("Closed" if ticket.status.lower() == "done" else "Draft"),
83
+ dateCompleted=(
84
+ convert_datetime_to_regscale_string(ticket.completion_date) if ticket.status.lower() == "done" else None
85
+ ),
86
+ **kwargs,
87
+ )
88
+ # update the correct integration field names or manual detection fields
89
+ if connector.has_integration_field:
90
+ setattr(regscale_issue, connector.integration_id_field, ticket.id)
91
+ else:
92
+ regscale_issue.manualDetectionSource = connector.integration
93
+ regscale_issue.manualDetectionId = ticket.id
94
+ return regscale_issue
95
+
96
+ @staticmethod
97
+ def _ocsf_asset_to_regscale(connector: "Vulnerabilities", asset: OCSFAsset, **kwargs) -> IntegrationAsset:
98
+ """
99
+ Convert OCSF Asset to RegScale Asset
100
+
101
+ :param Vulnerabilities connector: Vulnerabilities connector class object
102
+ :param OCSFAsset asset: OCSF Asset to convert to an IntegrationAsset
103
+ :return: The comparable IntegrationAsset object
104
+ :rtype: IntegrationAsset
105
+ """
106
+ from regscale.models.regscale_models import AssetCategory, SecurityPlan
107
+
108
+ device_data = asset.device
109
+ os_data = device_data.os
110
+ if device_data.sw_info:
111
+ software_inventory = [
112
+ {"name": sw.name, "version": sw.version} for sw in device_data.sw_info if getattr(sw, "name", None)
113
+ ]
114
+ else:
115
+ software_inventory = []
116
+ return IntegrationAsset(
117
+ name=device_data.name or device_data.hostname or f"{connector.provider} Asset: {device_data.instance_uid}",
118
+ identifier=device_data.uid,
119
+ asset_type=device_data.type,
120
+ asset_category=AssetCategory.Hardware,
121
+ parent_id=kwargs.pop("regscale_ssp_id"),
122
+ parent_module=SecurityPlan.get_module_string(),
123
+ mac_address=device_data.mac,
124
+ fqdn=device_data.hostname,
125
+ ip_address=", ".join(device_data.ip_addresses) if device_data.ip_addresses else device_data.ip,
126
+ location=device_data.location or device_data.zone,
127
+ vlan_id=device_data.vlan_uid,
128
+ other_tracking_number=device_data.uid,
129
+ serial_number=device_data.hw_info.serial_number if device_data.hw_info else None,
130
+ cpu=device_data.hw_info.cpu_cores if device_data.hw_info else None,
131
+ ram=device_data.hw_info.ram_size if device_data.hw_info else None,
132
+ operating_system=os_data.name if os_data else None,
133
+ os_version=os_data.version if os_data else None,
134
+ software_inventory=software_inventory,
135
+ )
136
+
137
+ @staticmethod
138
+ def _parse_finding_data(finding: "SecurityFinding", vuln: Optional["Vulnerability"] = None) -> dict:
139
+ """
140
+ Parse the data from the SecurityFinding object
141
+
142
+ :param Optional[Vulnerability] vuln: OCSF Vulnerability object, defaults to None
143
+ :return: A dictionary of the parsed data
144
+ :rtype: dict
145
+ """
146
+ from synqly.engine.resources.ocsf.resources.v_1_1_0.resources.securityfinding import Remediation
147
+
148
+ finding_data = {
149
+ "cve": None,
150
+ "first_seen": vuln.first_seen_time_dt if vuln else finding.finding.first_seen_time_dt,
151
+ "last_seen": vuln.last_seen_time_dt if vuln else finding.finding.last_seen_time_dt,
152
+ "plugin_id": vuln.cve.uid if vuln else finding.finding.product_uid,
153
+ "severity": int(vuln.severity) if vuln else finding.severity_id,
154
+ "remediation": getattr(vuln, "remediation") if vuln else finding.finding.remediation.desc,
155
+ }
156
+ if vuln:
157
+ finding_data["cve"] = vuln.cve.uid
158
+ else:
159
+ finding_data["cve"] = finding.finding.title if "cve" in finding.finding.title.lower() else None
160
+ if isinstance(finding_data["remediation"], Remediation):
161
+ finding_data["remediation"] = finding_data["remediation"].desc
162
+ elif isinstance(finding_data["remediation"], dict):
163
+ remediation_string = ""
164
+ for f, v in finding_data["remediation"].items():
165
+ remediation_string += f"{f}: {v}\n"
166
+ finding_data["remediation"] = remediation_string
167
+ elif isinstance(finding_data["remediation"], list):
168
+ finding_data["remediation"] = "\n".join(finding_data["remediation"])
169
+ return finding_data
170
+
171
+ @staticmethod
172
+ def _populate_cvs_scores(finding_obj: IntegrationFinding, vuln: Optional["Vulnerability"] = None) -> None:
173
+ """
174
+ Populates the CVSS scores for the provided IntegrationFinding object
175
+
176
+ :param IntegrationFinding finding_obj: IntegrationFinding object
177
+ :param Vulnerability vuln: OCSF Vulnerability object, defaults to None
178
+ :rtype: None
179
+ """
180
+ if vuln:
181
+ for cvs in getattr(vuln.cve, "cvss", []):
182
+ if "3" in cvs.version:
183
+ finding_obj.cvss_v3_score = cvs.base_score
184
+ elif "2" in cvs.version:
185
+ finding_obj.cvss_v2_score = cvs.base_score
186
+ else:
187
+ finding_obj.cvss_score = cvs.base_score
188
+
189
+ def _security_finding_to_regscale(
190
+ self, connector: "Vulnerabilities", finding: SecurityFinding, **_
191
+ ) -> list[IntegrationFinding]:
192
+ """
193
+ Convert OCSF SecurityFinding to RegScale IntegrationFinding
194
+
195
+ :param "Vulnerabilities" connector: Vulnerabilities connector class object
196
+ :param SecurityFinding finding: OCSF SecurityFinding to convert to an IntegrationFinding
197
+ :return: List of comparable IntegrationFinding objects
198
+ :rtype: list[IntegrationFinding]
199
+ """
200
+ findings = []
201
+
202
+ def _create_finding(resource: "ResourceDetails", vuln: Optional["Vulnerability"] = None) -> IntegrationFinding:
203
+ """
204
+ Create an IntegrationFinding object from a resource and vulnerability
205
+
206
+ :param ResourceDetails resource: OCSF ResourceDetails object
207
+ :param Optional[Vulnerability] vuln: OCSF Vulnerability object, defaults to None
208
+ :return: An IntegrationFinding object
209
+ :rtype: IntegrationFinding
210
+ """
211
+ base = vuln if vuln else finding.finding
212
+ finding_data = self._parse_finding_data(finding, vuln)
213
+ if resource.data:
214
+ dns = resource.data.get("hostname")
215
+ ip_address = resource.data.get("ipv4")
216
+ else:
217
+ dns = resource.uid if vuln else None
218
+ ip_address = None
219
+
220
+ finding_obj = IntegrationFinding(
221
+ control_labels=[],
222
+ category=f"{connector.integration_name} Vulnerability",
223
+ title=base.title,
224
+ plugin_name=connector.integration_name,
225
+ severity=Issue.assign_severity(finding.severity), # type: ignore
226
+ description=base.desc,
227
+ status=finding.status or "Open",
228
+ first_seen=self._datetime_to_str(finding_data["first_seen"]),
229
+ last_seen=self._datetime_to_str(finding_data["last_seen"]),
230
+ ip_address=ip_address,
231
+ plugin_id=finding_data["plugin_id"],
232
+ dns=dns,
233
+ severity_int=finding_data["severity"],
234
+ issue_title=base.title,
235
+ cve=finding_data["cve"],
236
+ evidence=finding.evidence,
237
+ impact=finding.impact,
238
+ asset_identifier=resource.uid,
239
+ source_report=connector.integration_name,
240
+ remediation=finding_data["remediation"],
241
+ )
242
+
243
+ self._populate_cvs_scores(finding_obj, vuln)
244
+
245
+ return finding_obj
246
+
247
+ for asset in finding.resources:
248
+ if finding.vulnerabilities:
249
+ findings.extend(_create_finding(asset, vuln) for vuln in finding.vulnerabilities)
250
+ else:
251
+ findings.append(_create_finding(asset))
252
+
253
+ return findings
254
+
255
+ def _datetime_to_str(self, date_time: Optional[datetime] = None) -> str:
256
+ """
257
+ Convert a datetime object to a string
258
+
259
+ :param Optional[datetime] date_time: The datetime object to convert, defaults to None
260
+ :return: The datetime as a string
261
+ :rtype: str
262
+ """
263
+ from regscale.core.utils.date import datetime_str
264
+
265
+ return datetime_str(date_time, self.date_format)
266
+
267
+ @staticmethod
268
+ def _map_ticket_priority(severity: str) -> Priority:
269
+ """
270
+ Map RegScale severity to OCSF priority
271
+
272
+ :param str severity: RegScale severity
273
+ :return: OCSF priority
274
+ :rtype: Priority
275
+ """
276
+ if "high" in severity.lower():
277
+ return Priority.HIGH
278
+ elif "moderate" in severity.lower():
279
+ return Priority.MEDIUM
280
+ else:
281
+ return Priority.LOW
282
+
283
+ def _determine_due_date(self, severity: str) -> str:
284
+ """
285
+ Determine the due date based on the provided severity
286
+
287
+ :param str severity: RegScale severity
288
+ :return: Due date for the issue
289
+ :rtype: str
290
+ """
291
+ from datetime import timedelta
292
+
293
+ if "high" in severity.lower():
294
+ return (datetime.now() + timedelta(days=30)).strftime(self.date_format)
295
+ elif "medium" in severity.lower():
296
+ return (datetime.now() + timedelta(days=60)).strftime(self.date_format)
297
+ else:
298
+ return (datetime.now() + timedelta(days=90)).strftime(self.date_format)
299
+
300
+ def _regscale_issue_to_ticket(self, regscale_issue: Issue, **kwargs) -> CreateTicketRequest:
301
+ """
302
+ Maps a RegScale issue to a JIRA issue
303
+
304
+ :param Issue regscale_issue: RegScale issue object
305
+ :return: Synqly CreateTicketRequest object
306
+ :rtype: CreateTicketRequest
307
+ """
308
+ description = ""
309
+ for key, value in regscale_issue.dict().items():
310
+ if key not in ["id"] and value:
311
+ description += f"{key.title()}: {value}\n"
312
+ if project := kwargs.get("default_project"):
313
+ kwargs.pop("default_project")
314
+ return engine.CreateTicketRequest(
315
+ name=regscale_issue.title,
316
+ description=f"RegScale Issue #{regscale_issue.id}:\n{description}",
317
+ summary=regscale_issue.title,
318
+ creator=kwargs.get("creator", "RegScale CLI"),
319
+ priority=self._map_ticket_priority(regscale_issue.severityLevel),
320
+ project=project,
321
+ **kwargs,
322
+ )
323
+ else:
324
+ return engine.CreateTicketRequest(
325
+ name=regscale_issue.title,
326
+ description=f"RegScale Issue #{regscale_issue.id}:\n{description}",
327
+ summary=regscale_issue.title,
328
+ creator=kwargs.get("creator", "RegScale CLI"),
329
+ priority=self._map_ticket_priority(regscale_issue.severityLevel),
330
+ **kwargs,
331
+ )
@@ -0,0 +1,72 @@
1
+ from typing import Any, Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
4
+
5
+
6
+ class Param(BaseModel):
7
+ model_config = ConfigDict(populate_by_name=True, frozen=True)
8
+
9
+ name: Optional[str] = Field("", description="The name of the parameter")
10
+ description: Optional[str] = Field("", description="The description of the parameter")
11
+ expected_type: str = Field("STRING", description="The expected type of the parameter as a string", alias="type")
12
+ optional: bool = Field(description="Whether the parameter is optional or not", alias="optional", default=False)
13
+ data_type: Optional[Any] = Field(None, description="The allowed data type of the parameter")
14
+ click_type: Optional[str] = Field(None, description="The click type of the parameter")
15
+ default: Optional[Any] = Field("None", description="The default value of the parameter")
16
+
17
+ @model_validator(mode="before")
18
+ def set_data_types(cls, values: dict) -> dict:
19
+ """
20
+ Set the data type of the parameter based on the expected type
21
+
22
+ :param values: The values of the model
23
+ :return: Updated values
24
+ :rtype: dict
25
+ """
26
+ if expected_type := values.get("type"):
27
+ values["data_type"] = cls._map_types(expected_type)
28
+ values["click_type"] = cls._map_click_types(expected_type)
29
+ return values
30
+
31
+ @classmethod
32
+ def _map_click_types(cls, type_str: str) -> Optional[str]:
33
+ """
34
+ Map the string type to the equivalent click type
35
+
36
+ :param str type_str: The data type as a string
37
+ :return: The equivalent click type, if it exists
38
+ :rtype: Optional[str]
39
+ """
40
+ click_types = {
41
+ "string": "click.STRING",
42
+ "number": "click.FLOAT",
43
+ "integer": "click.INT",
44
+ "bool": "click.BOOL",
45
+ "choice": "click.Choice",
46
+ }
47
+ return click_types.get(type_str)
48
+
49
+ @classmethod
50
+ def _map_types(cls, type_str: str) -> Any:
51
+ """
52
+ Map the javascript string type to python type
53
+
54
+ :param str type_str: The data type as a string
55
+ :return: The actual data type in python
56
+ :rtype: Any
57
+ """
58
+ data_types = {
59
+ "string": "str",
60
+ "object": "dict",
61
+ "array": "list",
62
+ "number": "float",
63
+ "integer": "int",
64
+ "boolean": "bool",
65
+ "choice": "choice",
66
+ }
67
+ if type_str in data_types:
68
+ return data_types[type_str]
69
+ try:
70
+ return eval(type_str)
71
+ except NameError:
72
+ raise ValueError(f"Invalid type: {type_str}")