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,196 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Dataclass for a RegScale Threat"""
4
+
5
+ # standard python imports
6
+ from concurrent.futures import ThreadPoolExecutor, as_completed
7
+ from typing import Any, List, Optional, Union
8
+
9
+ from pydantic import ConfigDict, Field
10
+
11
+ from regscale.core.app.api import Api
12
+ from regscale.core.app.utils.app_utils import get_current_datetime
13
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
14
+
15
+
16
+ class Threat(RegScaleModel):
17
+ """Threat Model"""
18
+
19
+ _module_slug = "threats"
20
+ _exclude_graphql_fields = ["tenantsId"]
21
+
22
+ threatType: str # Required
23
+ status: Optional[str] = "Under Investigation" # Required
24
+ source: Optional[str] = "Open Source" # Required
25
+ title: Optional[str] = "" # Required
26
+ targetType: Optional[str] = "" # Required
27
+ threatOwnerId: Optional[str] = Field(default_factory=RegScaleModel.get_user_id) # Required
28
+ id: Optional[int] = 0
29
+ uuid: Optional[str] = None
30
+ investigationResults: Optional[str] = ""
31
+ notes: Optional[str] = ""
32
+ dateIdentified: str = Field(default_factory=get_current_datetime)
33
+ dateResolved: Optional[str] = ""
34
+ dateCreated: str = Field(default_factory=get_current_datetime)
35
+ description: Optional[str] = ""
36
+ targets: Optional[str] = ""
37
+ vulnerabilityAnalysis: Optional[str] = ""
38
+ mitigations: Optional[str] = ""
39
+ threatTypeUnintentional: Optional[bool] = True
40
+ threatTypePurposeful: Optional[bool] = True
41
+ threatTypeEnvironmental: Optional[bool] = True
42
+ threatTypeInsider: Optional[bool] = True
43
+ threatImpactConfidentiality: Optional[bool] = True
44
+ threatImpactIntegrity: Optional[bool] = True
45
+ threatImpactAvailability: Optional[bool] = True
46
+ investigated: Optional[bool] = True
47
+ exploitable: Optional[bool] = True
48
+ isPublic: Optional[bool] = True
49
+ facilityId: Optional[int] = None # This has to be None for default or else the server returns a 500 error
50
+ orgId: Optional[int] = None # This has to be None for default or else the server returns a 500 error
51
+ parentModule: Optional[str] = ""
52
+ parentId: Optional[int] = 0
53
+ tenantsId: Optional[int] = 1
54
+
55
+ @staticmethod
56
+ def _get_additional_endpoints() -> ConfigDict:
57
+ """
58
+ Get additional endpoints for the Issues model.
59
+
60
+ :return: A dictionary of additional endpoints
61
+ :rtype: ConfigDict
62
+ """
63
+ return ConfigDict(
64
+ get_count="/api/{model_slug}/count",
65
+ get_all_by_parent="/api/{model_slug}/getAllByParent/{intParentId}/{strModule}",
66
+ get_filtered_list="/api/{model_slug}/getFilteredList/{strFind}",
67
+ get_all_by_parent_module="/api/{model_slug}/getAllByParentModule/{strModule}",
68
+ graph="/api/{model_slug}/graph",
69
+ graph_by_date="/api/{model_slug}/graphByDate/{strGroupBy}/{year}",
70
+ filter_threats="/api/{model_slug}/filterThreats",
71
+ query_by_custom_field="/api/{model_slug}/queryByCustomField/{strFieldName}/{strValue}",
72
+ report="/api/{model_slug}/report/{strReport}",
73
+ schedule="/api/{model_slug}/schedule/{year}/{dvar}",
74
+ main_dashboard="/api/{model_slug}/mainDashboard/{intYear}",
75
+ main_dashboard_chart="/api/{model_slug}/mainDashboardChart/{year}",
76
+ dashboard="/api/{model_slug}/dashboard/{strGroupBy}",
77
+ dashboard_by_parent="/api/{model_slug}/dashboardByParent/{strGroupBy}/{intId}/{strModule}",
78
+ )
79
+
80
+ @staticmethod
81
+ def xstr(str_eval: Any) -> str:
82
+ """
83
+ Replaces string with None value to ""
84
+
85
+ :param Any str_eval: key to replace None value to ""
86
+ :return: Updates provided str field to ""
87
+ :rtype: str
88
+ """
89
+ return "" if str_eval is None else str_eval
90
+
91
+ @staticmethod
92
+ def bulk_insert(api: Optional[Api], threats: list[Union[dict, "Threat"]]) -> List["Threat"]:
93
+ """
94
+ Bulk insert Threats to the RegScale API
95
+
96
+ :param Optional[Api] api: RegScale API
97
+ :param list[Union[dict, Threat]] threats: List of Threats to insert
98
+ :return: List of Threat objects from RegScale API
99
+ :rtype: List[Threat]
100
+ """
101
+ if api:
102
+ import warnings
103
+
104
+ warnings.warn(
105
+ "Api parameter is deprecated and will be removed in future versions.",
106
+ DeprecationWarning,
107
+ stacklevel=2,
108
+ )
109
+
110
+ results = []
111
+ threat_objects = []
112
+ for threat in threats:
113
+ if isinstance(threat, dict):
114
+ threat_objects.append(Threat(**threat))
115
+ else:
116
+ threat_objects.append(threat)
117
+
118
+ with ThreadPoolExecutor(max_workers=30) as executor:
119
+ futures = [
120
+ executor.submit(
121
+ threat.create,
122
+ )
123
+ for threat in threat_objects
124
+ ]
125
+ for future in as_completed(futures):
126
+ results.append(future.result())
127
+ return results
128
+
129
+ @staticmethod
130
+ def bulk_update(api: Optional[Api], threats: list[Union[dict, "Threat"]]) -> List["Threat"]:
131
+ """
132
+ Bulk insert Threats to the RegScale API
133
+
134
+ :param Optional[Api] api: RegScale API
135
+ :param list[Union[dict, Threat]] threats: List of Threats to update
136
+ :return: List of Threat objects from RegScale API
137
+ :rtype: List[Threat]
138
+ """
139
+ if api:
140
+ import warnings
141
+
142
+ warnings.warn(
143
+ "Api parameter is deprecated and will be removed in future versions.",
144
+ DeprecationWarning,
145
+ stacklevel=2,
146
+ )
147
+ results = []
148
+ threat_objects = []
149
+ for threat in threats:
150
+ if isinstance(threat, dict):
151
+ threat_objects.append(Threat(**threat))
152
+ else:
153
+ threat_objects.append(threat)
154
+
155
+ # use threadpoolexecutor to speed up inserts
156
+ with ThreadPoolExecutor(max_workers=30) as executor:
157
+ futures = [
158
+ executor.submit(
159
+ threat.save,
160
+ )
161
+ for threat in threat_objects
162
+ ]
163
+ for future in as_completed(futures):
164
+ results.append(future.result())
165
+ return results
166
+
167
+ @staticmethod
168
+ def fetch_all_threats() -> List["Threat"]:
169
+ """
170
+ Find all Threats in RegScale
171
+
172
+ :return: List of Threats from RegScale
173
+ :rtype: List[Threat]
174
+ """
175
+ from json import JSONDecodeError
176
+
177
+ api = Api()
178
+ body = f"""
179
+ query {{
180
+ threats(take: 50, skip: 0) {{
181
+ items {{
182
+ {Threat.build_graphql_fields()}
183
+ }}
184
+ pageInfo {{
185
+ hasNextPage
186
+ }}
187
+ ,totalCount}}
188
+ }}
189
+ """
190
+ try:
191
+ api.logger.info("Retrieving all threats from RegScale...")
192
+ existing_threats = api.graph(query=body)["threats"]["items"]
193
+ api.logger.info("Retrieved %i threat(s) from RegScale.", len(existing_threats))
194
+ except (JSONDecodeError, KeyError):
195
+ existing_threats = []
196
+ return [Threat(**threat) for threat in existing_threats]
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Dataclass for a RegScale User"""
4
+
5
+ # standard python imports
6
+ import random
7
+ import string
8
+ from typing import cast, Optional, List
9
+
10
+ from pydantic import Field, ConfigDict, field_validator
11
+
12
+ from regscale.core.app.utils.app_utils import get_current_datetime
13
+ from .regscale_model import RegScaleModel, T
14
+
15
+
16
+ def generate_password() -> str:
17
+ """
18
+ Generates a random string that is 12-20 characters long
19
+
20
+ :return: random string 12-20 characters long
21
+ :rtype: str
22
+ """
23
+ # select a random password length between 12-20 characters
24
+ length = random.randint(12, 20)
25
+
26
+ # get all possible strings to create a password
27
+ all_string_chars = string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuation
28
+
29
+ # randomly select characters matching the random length
30
+ temp = random.sample(all_string_chars, length)
31
+ # return a string from the temp list of samples
32
+ return "".join(temp)
33
+
34
+
35
+ class User(RegScaleModel):
36
+ """User Model"""
37
+
38
+ model_config = ConfigDict(populate_by_name=True)
39
+ _module_slug = "accounts"
40
+ _unique_fields = [
41
+ ["userName", "email"],
42
+ ]
43
+ _exclude_graphql_fields = ["extra_data", "tenantsId", "password"]
44
+
45
+ userName: str = Field(alias="username")
46
+ email: Optional[str] = None
47
+ firstName: Optional[str] = None
48
+ lastName: Optional[str] = None
49
+ tenantId: int = 1
50
+ initials: Optional[str] = None
51
+ id: Optional[str] = None
52
+ password: str = Field(default_factory=generate_password)
53
+ homePageUrl: Optional[str] = "/workbench"
54
+ name: Optional[str] = None
55
+ workPhone: Optional[str] = None
56
+ mobilePhone: Optional[str] = None
57
+ avatar: Optional[bytes] = None
58
+ jobTitle: Optional[str] = None
59
+ orgId: Optional[int] = None
60
+ pictureURL: Optional[str] = None
61
+ activated: bool = False
62
+ emailNotifications: bool = True
63
+ ldapUser: bool = False
64
+ externalId: Optional[str] = None
65
+ dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
66
+ lastLogin: Optional[str] = None
67
+ readOnly: bool = True
68
+ roles: Optional[List[str]] = None
69
+
70
+ @field_validator("homePageUrl")
71
+ def validate_regscale_version_and_home_page_url(cls, v: str) -> Optional[str]:
72
+ """
73
+ Validate the RegScale version and if it is compatible with homePageUrl, has to be >=6.13
74
+
75
+ :param str v: homePageUrl value
76
+ :return: The homePageUrl if the RegScale version is compatible, None otherwise
77
+ """
78
+ from packaging.version import Version
79
+
80
+ regscale_version = cls._get_api_handler().regscale_version
81
+
82
+ if len(regscale_version) >= 10 or Version(regscale_version) >= Version("6.14.0.0"):
83
+ return v
84
+ else:
85
+ return None
86
+
87
+ @classmethod
88
+ def _get_additional_endpoints(cls) -> ConfigDict:
89
+ """
90
+ Get additional endpoints for the Accounts model, using {model_slug} as a placeholder for the model slug.
91
+
92
+ :return: A dictionary of additional endpoints
93
+ :rtype: ConfigDict
94
+ """
95
+ return ConfigDict(
96
+ get_all="/api/{model_slug}",
97
+ create_account=cls._module_slug_url,
98
+ update_account=cls._module_slug_url,
99
+ get_accounts=cls._module_slug_url,
100
+ register_questionnaire_user="/api/{model_slug}/registerQuestionnaireUser",
101
+ cache_reset="/api/{model_slug}/cacheReset",
102
+ create_ldap_accounts="/api/{model_slug}/ldap",
103
+ create_azuread_accounts="/api/{model_slug}/azureAD",
104
+ assign_role="/api/{model_slug}/assignRole",
105
+ check_role="/api/{model_slug}/checkRole/{strUserId}/{strRoleId}",
106
+ delete_role="/api/{model_slug}/deleteRole/{strUserId}/{strRoleId}",
107
+ get_my_manager="/api/{model_slug}/getMyManager",
108
+ get_manager_by_user_id="/api/{model_slug}/getManagerByUserId/{strUserId}",
109
+ list="/api/{model_slug}/getList",
110
+ get_inactive_users="/api/{model_slug}/getInactiveUsers",
111
+ get_accounts_by_tenant="/api/{model_slug}/{tenantId}",
112
+ get_accounts_by_email_flag="/api/{model_slug}/{intTenantId}/{bEmailFlag}",
113
+ get_all_by_tenant="/api/{model_slug}/getAllByTenant/{intTenantId}",
114
+ filter_users="/api/{model_slug}/filterUsers/{intTenant}/{strSearch}/{bActive}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
115
+ filter_user_roles="/api/{model_slug}/filterUserRoles/{intId}/{strRole}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
116
+ change_user_status="/api/{model_slug}/changeUserStatus/{strId}/{bStatus}",
117
+ get_user_by_username="/api/{model_slug}/getUserByUsername/{strUsername}",
118
+ get="/api/{model_slug}/find/{id}",
119
+ get_roles="/api/{model_slug}/getRoles",
120
+ get_roles_by_user="/api/{model_slug}/getRolesByUser/{strUser}",
121
+ is_delegate="/api/{model_slug}/isDelegate/{strUser}",
122
+ get_delegates="/api/{model_slug}/getDelegates/{userId}",
123
+ change_avatar="/api/{model_slug}/changeAvatar/{strUsername}",
124
+ )
125
+
126
+ @classmethod
127
+ def get_tenant_id_for_user_id(cls, user_id: str) -> Optional[int]:
128
+ """
129
+ Retrieve all users by tenant ID.
130
+
131
+ Args:
132
+ user_id: str : user id to find
133
+
134
+ Returns:
135
+ Optional[int]: optionals
136
+ """
137
+ user = cls.get_user_by_id(user_id)
138
+ return user.tenantId if user else None
139
+
140
+ @classmethod
141
+ def get_user_by_id(cls, user_id: str) -> "User":
142
+ """
143
+ Get a user by their ID
144
+
145
+ :param str user_id: The user's ID
146
+ :return: The user object
147
+ :rtype: User
148
+ """
149
+ response = cls._get_api_handler().get(
150
+ endpoint=cls.get_endpoint("get").format(model_slug=cls._module_slug, id=user_id)
151
+ )
152
+ return cls._handle_response(response)
153
+
154
+ @classmethod
155
+ def get_all(cls) -> List["User"]:
156
+ """
157
+ Get all users from RegScale
158
+
159
+ :return: List of RegScale users
160
+ :rtype: List[User]
161
+ """
162
+ response = cls._get_api_handler().get(endpoint=cls.get_endpoint("get_all"))
163
+ return cast(List[T], cls._handle_list_response(response))
164
+
165
+ def assign_role(self, role_id: str) -> bool:
166
+ """
167
+ Assign a role to a user
168
+
169
+ :return: Whether the role was assigned
170
+ :rtype: bool
171
+ """
172
+ response = self._get_api_handler().post(
173
+ data={"roleId": role_id, "userId": self.id}, endpoint=self.get_endpoint("assign_role")
174
+ )
175
+ return response.ok
@@ -0,0 +1,55 @@
1
+ """
2
+ UserGroup model for the RegScale API.
3
+ """
4
+
5
+ from typing import Optional
6
+
7
+ from pydantic import ConfigDict, Field
8
+
9
+ from regscale.core.app.utils.app_utils import get_current_datetime
10
+ from regscale.models import RegScaleModel
11
+
12
+
13
+ class UserGroup(RegScaleModel):
14
+ _module_slug = "userGroups"
15
+
16
+ id: Optional[int] = None
17
+ groupsId: int
18
+ userId: str
19
+ isPublic: Optional[bool] = True
20
+ tenantsId: Optional[int] = 1
21
+ createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
22
+ dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
23
+ lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
24
+ dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
25
+
26
+ @staticmethod
27
+ def _get_additional_endpoints() -> ConfigDict:
28
+ """
29
+ Get additional endpoints for the UserGroup model.
30
+
31
+ :return: A dictionary of additional endpoints
32
+ :rtype: ConfigDict
33
+ """
34
+ return ConfigDict(
35
+ filter_user_groups="/api/{model_slug}/filterUserGroups/{intGroupId}/{intPage}/{intPageSize}",
36
+ # Get the list of users in the specified group (GET)
37
+ get_users_by_group="/api/userGroups/getUsersByGroup/{intGroupId}",
38
+ # Get the list of groups for a given user (GET)
39
+ get_groups_by_user="/api/userGroups/getGroupsByUser/{strUserId}",
40
+ )
41
+
42
+ @classmethod
43
+ def get_users_by_group(cls, group_id: int):
44
+ """
45
+ Get the list of users in the specified group.
46
+
47
+ :param group_id: The group ID
48
+ :return: A list of users
49
+ """
50
+ response = cls._get_api_handler().get(
51
+ endpoint=cls.get_endpoint("get_users_by_group").format(intGroupId=group_id)
52
+ )
53
+ if response and response.ok:
54
+ return response.json()
55
+ return []
@@ -0,0 +1,242 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Model for Vulnerability in the application"""
4
+ from enum import Enum
5
+ from typing import List, Optional, Union
6
+ from urllib.parse import urljoin
7
+ from warnings import warn
8
+
9
+ from pydantic import ConfigDict, Field
10
+ from requests import Response
11
+
12
+ from regscale.core.app.api import Api
13
+ from regscale.core.app.application import Application
14
+ from regscale.core.app.utils.app_utils import get_current_datetime
15
+ from regscale.models import regscale_models
16
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
17
+
18
+
19
+ def deprecated(message):
20
+ def decorator(func):
21
+ def wrapper(*args, **kwargs):
22
+ warn(f"{func.__name__} is deprecated. {message}", DeprecationWarning, stacklevel=2)
23
+ return func(*args, **kwargs)
24
+
25
+ return wrapper
26
+
27
+ return decorator
28
+
29
+
30
+ class VulnerabilitySeverity(str, Enum):
31
+ """Vulnerability Severity"""
32
+
33
+ Low = "LOW"
34
+ Medium = "MEDIUM"
35
+ High = "HIGH"
36
+ Critical = "CRITICAL"
37
+
38
+
39
+ class VulnerabilityStatus(str, Enum):
40
+ """Vulnerability Status"""
41
+
42
+ Open = "OPEN"
43
+ Closed = "CLOSED"
44
+
45
+
46
+ class Vulnerability(RegScaleModel):
47
+ """Vulnerability Model"""
48
+
49
+ _module_slug = "vulnerability"
50
+ _unique_fields = [
51
+ ["plugInName", "parentId", "parentModule"],
52
+ ]
53
+
54
+ id: int = 0
55
+ createdById: str = Field(default_factory=RegScaleModel.get_user_id)
56
+ dateCreated: str = Field(default_factory=get_current_datetime)
57
+ lastUpdatedById: str = Field(default_factory=RegScaleModel.get_user_id)
58
+ dateLastUpdated: str = Field(default_factory=get_current_datetime)
59
+ uuid: Optional[str] = None
60
+ scanId: Optional[int] = None
61
+ parentId: Optional[int] = None
62
+ parentModule: Optional[str] = None
63
+ lastSeen: Optional[str] = None
64
+ firstSeen: Optional[str] = None
65
+ daysOpen: Optional[int] = None
66
+ dns: Optional[str] = None
67
+ ipAddress: Optional[str] = Field(default="")
68
+ mitigated: Optional[bool] = None
69
+ operatingSystem: Optional[str] = None
70
+ port: Optional[Union[str, int]] = None
71
+ protocol: Optional[str] = None
72
+ severity: Optional[Union[str, VulnerabilitySeverity]] = None
73
+ plugInName: Optional[str] = None
74
+ plugInId: Optional[int] = None
75
+ cve: Optional[str] = None
76
+ vprScore: Optional[Union[int, float]] = None
77
+ exploitAvailable: Optional[bool] = None
78
+ title: Optional[str] = None
79
+ cvsSv3BaseScore: Optional[Union[float, int]] = None
80
+ description: Optional[str] = None
81
+ plugInText: Optional[str] = None
82
+ tenantsId: int = Field(default=0)
83
+ isPublic: bool = Field(default=False)
84
+ dateClosed: Optional[str] = None
85
+ status: Optional[VulnerabilityStatus] = VulnerabilityStatus.Open
86
+
87
+ def __eq__(self, other) -> bool:
88
+ """
89
+ Check if two Vulnerability objects are equal is needed for comparison operations in flat file importer
90
+ :param other:
91
+ :return: True if the two objects are equal, False otherwise
92
+ :rtype: bool
93
+ """
94
+ if not isinstance(other, Vulnerability):
95
+ return False
96
+ return (
97
+ self.plugInName == other.plugInName
98
+ and self.parentId == other.parentId
99
+ and self.parentModule == other.parentModule
100
+ and self.ipAddress == other.ipAddress
101
+ and self.dns == other.dns
102
+ )
103
+
104
+ def __init__(self, **data):
105
+ # Map snake_case to camelCase before initialization
106
+ field_mappings = {
107
+ "scan_id": "scanId",
108
+ "parent_id": "parentId",
109
+ "parent_module": "parentModule",
110
+ "last_seen": "lastSeen",
111
+ "first_seen": "firstSeen",
112
+ "days_open": "daysOpen",
113
+ "ip_address": "ipAddress",
114
+ "operating_system": "operatingSystem",
115
+ "plugin_name": "plugInName",
116
+ "plugin_id": "plugInId",
117
+ "vpr_score": "vprScore",
118
+ "exploit_available": "exploitAvailable",
119
+ "cvss_v3_base_score": "cvsSv3BaseScore",
120
+ "plugin_text": "plugInText",
121
+ "tenants_id": "tenantsId",
122
+ "is_public": "isPublic",
123
+ "date_closed": "dateClosed",
124
+ }
125
+
126
+ # Convert snake_case keys to camelCase
127
+ for snake_key, camel_key in field_mappings.items():
128
+ if snake_key in data:
129
+ data[camel_key] = data.pop(snake_key)
130
+
131
+ super().__init__(**data)
132
+
133
+ @staticmethod
134
+ def _get_additional_endpoints() -> ConfigDict:
135
+ """
136
+ Get additional endpoints for the Vulnerability model, using {model_slug} as a placeholder for the model slug.
137
+
138
+ :return: A dictionary of additional endpoints
139
+ :rtype: ConfigDict
140
+ """
141
+ return ConfigDict( # type: ignore
142
+ get_count="/api/{model_slug}/getCount", # type: ignore
143
+ batch_create="/api/{model_slug}/batchCreate", # type: ignore
144
+ find_by_guid="/api/{model_slug}/findByGUID/{strGUID}", # type: ignore
145
+ drilldown="/api/{model_slug}/drilldown/{parentId}/{scanId}/{strSeverity}/{intPage}/" # type: ignore
146
+ "{intPageSize}",
147
+ lookup_cve="/api/{model_slug}/lookupCVE/{strCVE}", # type: ignore
148
+ get="/api/{model_slug}/find/{id}", # type: ignore
149
+ )
150
+
151
+ @staticmethod
152
+ def determine_cvss3_severity_text(cvss_v3_base_score: float) -> str:
153
+ """
154
+ Determine CVSS3 Severity Text from CVSS3 Base Score
155
+
156
+ :param float cvss_v3_base_score: CVSS3 Base Score
157
+ :return: CVSS3 Severity Text
158
+ :rtype: str
159
+ """
160
+ results = "low"
161
+ if 4.0 <= cvss_v3_base_score <= 6.9:
162
+ results = "medium"
163
+ elif 7.0 <= cvss_v3_base_score <= 8.9:
164
+ results = "high"
165
+ elif cvss_v3_base_score > 8.9:
166
+ results = "critical"
167
+ return results
168
+
169
+ @staticmethod
170
+ @deprecated("Use Vulnerability.get_all_by_parent() instead")
171
+ def find_vulns_by_scan(app: Application, scan_id: int) -> List["Vulnerability"]: # noqa: F841
172
+ """
173
+ Find Vulnerabilities by Scan ID
174
+
175
+ :param Application app: Application instance
176
+ :param int scan_id: Scan ID
177
+ :return: List of Vulnerabilities
178
+ :rtype: List[Vulnerability]
179
+ """
180
+ return Vulnerability.get_all_by_parent(parent_id=scan_id, parent_module=regscale_models.Scan.get_module_slug())
181
+
182
+ @classmethod
183
+ @deprecated("Use Vulnerability.create() instead")
184
+ def post_vulnerability(cls, vulnerability: "Vulnerability") -> Optional["Vulnerability"]:
185
+ """
186
+ Post a vulnerability to the API
187
+
188
+ :param Vulnerability vulnerability: The vulnerability to be posted
189
+ :return: The response from the API as a dictionary
190
+ :rtype: Optional["Vulnerability"]
191
+ """
192
+ return vulnerability.create()
193
+
194
+ @classmethod
195
+ @deprecated(
196
+ "Use Vulnerability.create() for individual vulnerabilities or Vulnerability.batch_create() for "
197
+ "multiple vulnerabilities"
198
+ )
199
+ def post_vulnerabilities(
200
+ cls,
201
+ app: Application, # noqa: F841
202
+ vulnerabilities: List["Vulnerability"],
203
+ output_to_console: Optional[bool] = True,
204
+ ) -> List[Response]:
205
+ """
206
+ Insert new vulnerabilities into RegScale
207
+
208
+ :param Application app: Application object
209
+ :param List[Vulnerability] vulnerabilities: List of Vulnerability objects
210
+ :param Optional[bool] output_to_console: Whether to output to console, defaults to True
211
+ :return: A list of Responses
212
+ :rtype List[Response]
213
+ """
214
+ responses = []
215
+
216
+ def batch_post(url: str, dat: list[dict]) -> Response:
217
+ """
218
+ Simple wrapper to post a list of JSON data to a URL
219
+
220
+ :param str url: URL to post to
221
+ :param list[dict] dat: A list of JSON data to post
222
+ :return: Response object
223
+ :rtype: Response
224
+ """
225
+ return api.post(url=url, json=dat)
226
+
227
+ api = Api()
228
+ if output_to_console and vulnerabilities:
229
+ api.logger.info("Creating %i new vulnerabilities in RegScale...", len(vulnerabilities))
230
+ # Create batches of vulnerabilities to post
231
+ batch_size = 500
232
+ batches = [vulnerabilities[i : i + batch_size] for i in range(0, len(vulnerabilities), batch_size)]
233
+ for batch in batches:
234
+ res = batch_post(
235
+ url=urljoin(api.config["domain"], cls.get_endpoint("batch_create")),
236
+ dat=[vuln.model_dump() for vuln in batch],
237
+ )
238
+ if res.ok:
239
+ responses.extend(res.json())
240
+ if len(responses):
241
+ api.logger.info("Successfully created %i new vulnerabilities in RegScale", len(responses))
242
+ return responses