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,346 @@
1
+ from typing import Optional
2
+ from unittest.mock import Mock, patch
3
+
4
+ import pytest
5
+
6
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
7
+
8
+
9
+ class TestModel(RegScaleModel):
10
+ _unique_fields = [["name"]]
11
+ _parent_id_field = "parentId"
12
+ id: Optional[int] = None
13
+ name: str
14
+ value: int
15
+ parentId: int
16
+ parentModule: str = "test_module"
17
+
18
+
19
+ class TestModelMultipleUnique(RegScaleModel):
20
+ _unique_fields = [["field1", "field2"], ["field3"]]
21
+ _parent_id_field = "parentId"
22
+ id: Optional[int] = None
23
+ field1: Optional[str] = None
24
+ field2: Optional[str] = None
25
+ field3: Optional[str] = None
26
+ parentId: int
27
+ parentModule: str = "test_module"
28
+
29
+
30
+ @pytest.fixture
31
+ def mock_api_handler():
32
+ with patch("regscale.models.regscale_models.regscale_model.APIHandler") as mock:
33
+ yield mock
34
+
35
+
36
+ @pytest.fixture
37
+ def mocked_model():
38
+ with patch.object(TestModel, "get_cached_object") as mock_get_cached, patch.object(
39
+ TestModel, "cache_object"
40
+ ) as mock_cache, patch.object(TestModel, "create") as mock_create, patch.object(
41
+ TestModel, "_perform_save"
42
+ ) as mock_perform_save:
43
+ yield TestModel(name="test", value=1, parentId=1), {
44
+ "get_cached": mock_get_cached,
45
+ "cache": mock_cache,
46
+ "create": mock_create,
47
+ "perform_save": mock_perform_save,
48
+ }
49
+
50
+
51
+ def test_create_new_instance(mocked_model):
52
+ model, mocks = mocked_model
53
+ mocks["get_cached"].return_value = None
54
+ mocks["create"].return_value = TestModel(id=1, name="test", value=1, parentId=1)
55
+
56
+ result = model.create_or_update()
57
+
58
+ assert result.id == 1
59
+ mocks["create"].assert_called_once()
60
+ mocks["perform_save"].assert_not_called()
61
+
62
+
63
+ def test_update_existing_instance(mocked_model):
64
+ model, mocks = mocked_model
65
+ cached_instance = TestModel(id=2, name="test", value=2, parentId=1)
66
+ mocks["get_cached"].return_value = cached_instance
67
+ model.value = 3 # This change should trigger an update
68
+ mocks["perform_save"].return_value = TestModel(id=2, name="test", value=3, parentId=1)
69
+
70
+ result = model.create_or_update()
71
+
72
+ assert model._original_data == {
73
+ "id": 2,
74
+ "name": "test",
75
+ "value": 2,
76
+ "parentId": 1,
77
+ "parentModule": "test_module",
78
+ }, "Original data should be set to cached instance data"
79
+ assert result.id == 2
80
+ assert result.value == 3
81
+ mocks["perform_save"].assert_called_once()
82
+ assert model._original_data == {
83
+ "id": 2,
84
+ "name": "test",
85
+ "value": 2,
86
+ "parentId": 1,
87
+ "parentModule": "test_module",
88
+ }, "Original data should not change after save"
89
+
90
+
91
+ def test_no_update_when_no_changes(mocked_model):
92
+ model, mocks = mocked_model
93
+ cached_instance = TestModel(id=3, name="test", value=1, parentId=1)
94
+ mocks["get_cached"].return_value = cached_instance
95
+
96
+ result = model.create_or_update()
97
+
98
+ mocks["get_cached"].assert_called_once()
99
+ mocks["perform_save"].assert_not_called()
100
+
101
+ assert result == cached_instance, "Should return the cached instance without changes"
102
+ assert model._original_data == cached_instance.dict(
103
+ exclude_unset=True
104
+ ), "Original data should be set to cached instance data"
105
+
106
+ print(f"Result: {result}")
107
+ print(f"Cached instance: {cached_instance}")
108
+ print(f"Model _original_data: {model._original_data}")
109
+
110
+
111
+ @pytest.mark.parametrize(
112
+ "initial_value,new_value,expected_calls",
113
+ [
114
+ (1, 2, 1), # Different value, should update
115
+ (1, 1, 0), # Same value, should not update
116
+ ],
117
+ )
118
+ def test_update_behavior(mocked_model, initial_value, new_value, expected_calls):
119
+ model, mocks = mocked_model
120
+ cached_instance = TestModel(id=1, name="test", value=initial_value, parentId=1)
121
+ mocks["get_cached"].return_value = cached_instance
122
+ model.value = new_value
123
+ mocks["perform_save"].return_value = TestModel(id=1, name="test", value=new_value, parentId=1)
124
+
125
+ model.create_or_update()
126
+
127
+ assert mocks["perform_save"].call_count == expected_calls
128
+
129
+
130
+ class TestFindByUnique:
131
+ @pytest.fixture
132
+ def mock_get_all_by_parent(self):
133
+ with patch.object(TestModel, "get_all_by_parent") as mock:
134
+ yield mock
135
+
136
+ def test_find_by_unique_single_field_match(self, mock_get_all_by_parent):
137
+ """Test finding an instance with a single unique field match"""
138
+ instance = TestModel(name="test", value=1, parentId=1)
139
+ existing = TestModel(id=1, name="test", value=2, parentId=1)
140
+ mock_get_all_by_parent.return_value = [existing]
141
+
142
+ result = instance.find_by_unique()
143
+
144
+ assert result == existing
145
+ mock_get_all_by_parent.assert_called_once_with(parent_id=1, parent_module="test_module")
146
+
147
+ def test_find_by_unique_case_insensitive(self, mock_get_all_by_parent):
148
+ """Test case-insensitive matching"""
149
+ instance = TestModel(name="Test", value=1, parentId=1)
150
+ existing = TestModel(id=1, name="test", value=2, parentId=1)
151
+ mock_get_all_by_parent.return_value = [existing]
152
+
153
+ result = instance.find_by_unique()
154
+
155
+ assert result == existing
156
+
157
+ def test_find_by_unique_no_match(self, mock_get_all_by_parent):
158
+ """Test when no match is found"""
159
+ instance = TestModel(name="test1", value=1, parentId=1)
160
+ existing = TestModel(id=1, name="test2", value=2, parentId=1)
161
+ mock_get_all_by_parent.return_value = [existing]
162
+
163
+ result = instance.find_by_unique()
164
+
165
+ assert result is None
166
+
167
+ def test_find_by_unique_no_unique_fields(self):
168
+ """Test when no unique fields are defined"""
169
+
170
+ class NoUniqueModel(RegScaleModel):
171
+ _unique_fields = []
172
+ name: str
173
+
174
+ instance = NoUniqueModel(name="test")
175
+
176
+ with pytest.raises(NotImplementedError):
177
+ instance.find_by_unique()
178
+
179
+ def test_find_by_unique_no_parent_id(self):
180
+ """Test when parent ID is missing"""
181
+ instance = TestModel(name="test", value=1) # No parentId
182
+
183
+ with pytest.raises(ValueError):
184
+ instance.find_by_unique()
185
+
186
+
187
+ class TestMultipleUniqueFields:
188
+ @pytest.fixture
189
+ def mock_get_all_by_parent(self):
190
+ with patch.object(TestModelMultipleUnique, "get_all_by_parent") as mock:
191
+ yield mock
192
+
193
+ def test_find_by_unique_first_set_match(self, mock_get_all_by_parent):
194
+ """Test matching on first set of unique fields"""
195
+ instance = TestModelMultipleUnique(
196
+ field1="test1",
197
+ field2="test2",
198
+ field3="different", # Different value doesn't matter for first set match
199
+ parentId=1,
200
+ )
201
+ existing = TestModelMultipleUnique(
202
+ id=1,
203
+ field1="test1",
204
+ field2="test2",
205
+ field3="also_different", # Different value doesn't matter for first set match
206
+ parentId=1,
207
+ )
208
+ mock_get_all_by_parent.return_value = [existing]
209
+
210
+ result = instance.find_by_unique()
211
+
212
+ # Should match because first set of unique fields matches
213
+ assert result == existing
214
+
215
+ def test_find_by_unique_second_set_match(self, mock_get_all_by_parent):
216
+ """Test matching on second set of unique fields"""
217
+ instance = TestModelMultipleUnique(
218
+ field1="different1", field2="different2", field3="test3", parentId=1 # Matches on second set
219
+ )
220
+ existing = TestModelMultipleUnique(
221
+ id=1, field1="test1", field2="test2", field3="test3", parentId=1 # Matches on second set
222
+ )
223
+ mock_get_all_by_parent.return_value = [existing]
224
+
225
+ result = instance.find_by_unique()
226
+
227
+ # Should match because second set of unique fields matches
228
+ assert result == existing
229
+
230
+ def test_find_by_unique_no_match(self, mock_get_all_by_parent):
231
+ """Test when no unique field sets match"""
232
+ instance = TestModelMultipleUnique(field1="different1", field2="different2", field3="different3", parentId=1)
233
+ existing = TestModelMultipleUnique(id=1, field1="test1", field2="test2", field3="test3", parentId=1)
234
+ mock_get_all_by_parent.return_value = [existing]
235
+
236
+ result = instance.find_by_unique()
237
+
238
+ # Should not match because no unique field sets match
239
+ assert result is None
240
+
241
+ def test_find_by_unique_with_none_values(self, mock_get_all_by_parent):
242
+ """Test handling of None values in multiple unique fields"""
243
+ instance = TestModelMultipleUnique(
244
+ field1="test1", field2=None, field3="different3", parentId=1 # None in first set # Different in second set
245
+ )
246
+ existing = TestModelMultipleUnique(
247
+ id=1, field1="test1", field2=None, field3="test3", parentId=1 # None in first set
248
+ )
249
+ mock_get_all_by_parent.return_value = [existing]
250
+
251
+ result = instance.find_by_unique()
252
+
253
+ # Should not match because first set has None values and second set doesn't match
254
+ assert result is None
255
+
256
+
257
+ class TestCaching:
258
+ def test_cache_hit(self, mocked_model):
259
+ """Test when object is found in cache"""
260
+ model, mocks = mocked_model
261
+ cached = TestModel(id=1, name="test", value=1, parentId=1)
262
+ mocks["get_cached"].return_value = cached
263
+
264
+ result = model.find_by_unique()
265
+
266
+ assert result == cached
267
+ mocks["get_cached"].assert_called_once()
268
+
269
+ def test_cache_update_after_save(self, mocked_model):
270
+ """Test that cache is updated after saving"""
271
+ model, mocks = mocked_model
272
+ updated = TestModel(id=1, name="test", value=2, parentId=1)
273
+ mocks["perform_save"].return_value = updated
274
+
275
+ model.value = 2
276
+ model.create_or_update()
277
+
278
+ mocks["cache"].assert_called_with(updated)
279
+
280
+
281
+ class TestErrorHandling:
282
+ @pytest.fixture
283
+ def mock_get_all_by_parent(self):
284
+ with patch.object(TestModel, "get_all_by_parent") as mock:
285
+ yield mock
286
+
287
+ def test_create_or_update_with_api_error(self, mocked_model):
288
+ """Test handling of API errors during create/update"""
289
+ model, mocks = mocked_model
290
+ mocks["get_cached"].return_value = None
291
+ mocks["create"].side_effect = Exception("API Error")
292
+
293
+ with pytest.raises(Exception) as exc_info:
294
+ model.create_or_update()
295
+
296
+ assert str(exc_info.value) == "API Error"
297
+
298
+ @pytest.mark.parametrize("attribute_error_field", ["name", "value", "non_existent_field"])
299
+ def test_find_by_unique_attribute_error(self, attribute_error_field, mocker):
300
+ """Test handling of AttributeError during find_by_unique"""
301
+ # Use mocker fixture instead of manual patch
302
+ mock_get_all_by_parent = mocker.patch.object(TestModel, "get_all_by_parent")
303
+
304
+ instance = TestModel(name="test", value=1, parentId=1)
305
+
306
+ # Create a mock instance that will raise AttributeError for the specified field
307
+ class MockTestModel(TestModel):
308
+ def __getattr__(self, name):
309
+ if name == attribute_error_field:
310
+ raise AttributeError(f"Mock object has no attribute '{name}'")
311
+ return super().__getattr__(name)
312
+
313
+ mock_instance = MockTestModel(name="test_value", value=1, parentId=1)
314
+ mock_get_all_by_parent.return_value = [mock_instance]
315
+
316
+ # Should not raise AttributeError
317
+ result = instance.find_by_unique()
318
+ assert result is None
319
+
320
+
321
+ class TestConcurrency:
322
+ def test_concurrent_cache_access(self):
323
+ """Test concurrent access to cache"""
324
+ import threading
325
+ import time
326
+
327
+ model = TestModel(name="test", value=1, parentId=1)
328
+ cache_key = model._get_cache_key(model)
329
+
330
+ def cache_operation():
331
+ with model._get_lock(cache_key):
332
+ time.sleep(0.1) # Simulate some work
333
+ model.cache_object(model)
334
+
335
+ threads = [threading.Thread(target=cache_operation) for _ in range(5)]
336
+ for t in threads:
337
+ t.start()
338
+ for t in threads:
339
+ t.join()
340
+
341
+ # Verify that cache operations completed without errors
342
+ assert model.get_cached_object(cache_key) is not None
343
+
344
+
345
+ if __name__ == "__main__":
346
+ pytest.main()
@@ -0,0 +1,32 @@
1
+ from regscale.core.app.utils.report_utils import ReportGenerator
2
+ from regscale.models import Asset
3
+ from tests.fixtures.test_fixture import CLITestFixture
4
+
5
+
6
+ class TestImport(CLITestFixture):
7
+ """
8
+ Test for Report Generator
9
+ """
10
+
11
+ def test_basic_report(self):
12
+ """
13
+ Test the basic report
14
+ """
15
+ assets = Asset.get_all_by_parent(3, "securityplans")
16
+ ReportGenerator(assets)
17
+
18
+ def test_advanced_report(self):
19
+ """
20
+ Test the advanced report
21
+ """
22
+ assets = Asset.get_all_by_parent(3, "securityplans")
23
+ ReportGenerator(objects=assets, to_file=True, report_name="test_report")
24
+
25
+ def test_save_to_regscale(self):
26
+ """
27
+ Test saving the report to Regscale
28
+ """
29
+ assets = Asset.get_all_by_parent(3, "securityplans")
30
+ ReportGenerator(
31
+ objects=assets, to_file=True, report_name="test_report", regscale_id=3, regscale_module="securityplans"
32
+ )
@@ -0,0 +1,118 @@
1
+ import json
2
+ from random import randint
3
+ from unittest.mock import patch
4
+
5
+ import pytest
6
+ from lxml import etree
7
+
8
+ from regscale.integrations.commercial.nessus.nessus_utils import (
9
+ cpe_xml_to_dict,
10
+ get_cpe_file,
11
+ lookup_cpe_item_by_name,
12
+ lookup_kev,
13
+ )
14
+ from regscale.integrations.public.cisa import pull_cisa_kev
15
+ from regscale.models.integration_models.tenable_models.models import TenableIOAsset
16
+
17
+
18
+ @pytest.fixture
19
+ def sync_vuln_result():
20
+ dat = {
21
+ "asset": {
22
+ "device_type": "general-purpose",
23
+ "hostname": "WIN-HJFQ8SOFVCP",
24
+ "uuid": "ef2eed0a-29b3-45a2-af6a-3d12141d1a71",
25
+ "ipv4": "10.40.16.200",
26
+ "netbios_name": "WIN-HJFQ8SOFVCP",
27
+ "operating_system": ["Microsoft Windows"],
28
+ "network_id": "32df72f3-5914-4c54-8e28-26a924c8c6ca",
29
+ "tracked": True,
30
+ },
31
+ "output": "\nAn SMB server is running on this port.\n",
32
+ "plugin": {
33
+ "bid": [11011],
34
+ "checks_for_default_account": False,
35
+ "checks_for_malware": False,
36
+ "description": "The remote service understands the CIFS (Common Internet File System) or "
37
+ "Server Message Block (SMB) protocol, used to provide shared access to files, "
38
+ "printers, etc between nodes on a network.",
39
+ "exploited_by_malware": False,
40
+ "exploited_by_nessus": False,
41
+ "family": "Windows",
42
+ "family_id": 7,
43
+ "id": 11011,
44
+ "in_the_news": False,
45
+ "name": "Microsoft Windows SMB Service Detection",
46
+ "modification_date": "2021-02-11T00:00:00Z",
47
+ "publication_date": "2002-06-05T00:00:00Z",
48
+ "risk_factor": "info",
49
+ "synopsis": "A file / print sharing service is listening on the remote host.",
50
+ "type": "REMOTE",
51
+ "unsupported_by_vendor": False,
52
+ "version": "1.43",
53
+ },
54
+ "port": {"port": 139, "protocol": "TCP", "service": "smb"},
55
+ "scan": {
56
+ "schedule_uuid": "template-0962c046-6816-1fa3-a5c4-ab987819db38a7aa1358e9a1e7eb",
57
+ "started_at": "2023-11-05T04:05:03.266Z",
58
+ "uuid": "0ec1bf66-28e1-4e19-9894-60a19556c1d9",
59
+ },
60
+ "severity": "info",
61
+ "severity_id": 0,
62
+ "severity_default_id": 0,
63
+ "severity_modification_type": "NONE",
64
+ "first_found": "2022-09-18T10:44:50.586Z",
65
+ "last_found": "2023-11-05T07:21:39.476Z",
66
+ "state": "OPEN",
67
+ "indexed": "2023-11-05T07:22:28.474691Z",
68
+ }
69
+ result = NessusReport(**dat)
70
+ return iter([result])
71
+
72
+
73
+ @pytest.fixture
74
+ def cpe_items():
75
+ cpe_root = etree.parse(get_cpe_file())
76
+ dat = cpe_xml_to_dict(cpe_root)
77
+ return dat
78
+
79
+
80
+ @pytest.fixture
81
+ def new_assets():
82
+ with open("./tests/test_data/ten_assets.json", "r") as f:
83
+ dat = json.load(f)
84
+ assets = [TenableIOAsset(**a) for a in dat]
85
+ return assets
86
+
87
+
88
+ @patch("regscale.core.app.application.Application")
89
+ @patch("regscale.models.integration_models.tenable_models.models.TenableIOAsset.sync_to_regscale")
90
+ def test_fetch_assets(mock_app, new_assets):
91
+ # Call the fetch_assets function
92
+ assets = new_assets
93
+ app = mock_app
94
+ with patch.object(TenableIOAsset, "sync_to_regscale") as mock_sync:
95
+ mock_sync(app=app, assets=assets, ssp_id=2)
96
+
97
+ # Check that the sync_to_regscale method was called with the correct arguments
98
+ mock_sync.assert_called_once_with(app=app, assets=assets, ssp_id=2)
99
+
100
+
101
+ def test_kev_lookup():
102
+ cve = "CVE-1234-3456"
103
+ data = pull_cisa_kev()
104
+ avail = [dat["cveID"] for dat in data["vulnerabilities"]]
105
+ index = randint(0, len(avail))
106
+ assert lookup_kev(cve, data)[0] is None
107
+ assert lookup_kev(avail[index], data)[0]
108
+
109
+
110
+ def test_cpe_lookup(cpe_items):
111
+ name = "cpe:/a:gobalsky:vega:0.49.4"
112
+ lookup_cpe_item_by_name(name, cpe_items)
113
+
114
+
115
+ @pytest.mark.skip("This test needs to be updated for the new tenable rewrite.")
116
+ def test_sync_vulns_data(sync_vuln_result):
117
+ vulns = sync_vuln_result
118
+ assert vulns
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Tests for the User model"""
4
+
5
+ import unittest
6
+ from unittest.mock import patch, MagicMock
7
+
8
+ from regscale.models.regscale_models.user import User
9
+
10
+
11
+ class TestUser(unittest.TestCase):
12
+ """Test cases for the User model"""
13
+
14
+ def setUp(self):
15
+ """Set up test cases"""
16
+ self.test_user_data = {
17
+ "userName": "testuser",
18
+ "email": "test@example.com",
19
+ "firstName": "Test",
20
+ "lastName": "User",
21
+ "homePageUrl": "/custom-dashboard",
22
+ }
23
+
24
+ @patch("regscale.models.regscale_models.user.User._get_api_handler")
25
+ def test_homepage_url_below_min_version(self, mock_api_handler):
26
+ """Test homePageUrl is None when version < 6.14.0.0"""
27
+ # Setup mock
28
+ mock_handler = MagicMock()
29
+ mock_handler.regscale_version = "6.11.0.0"
30
+ mock_api_handler.return_value = mock_handler
31
+
32
+ # Create user instance
33
+ user = User(**self.test_user_data)
34
+
35
+ # Verify homePageUrl is None for version < 6.14.0.0
36
+ self.assertIsNone(user.homePageUrl)
37
+ # Verify the underlying field still has the value
38
+ self.assertEqual(user.homePageUrl_, "/custom-dashboard")
39
+
40
+ @patch("regscale.models.regscale_models.user.User._get_api_handler")
41
+ def test_homepage_url_at_min_version(self, mock_api_handler):
42
+ """Test homePageUrl is accessible when version = 6.14.0.0"""
43
+ # Setup mock
44
+ mock_handler = MagicMock()
45
+ mock_handler.regscale_version = "6.14.0.0"
46
+ mock_api_handler.return_value = mock_handler
47
+
48
+ # Create user instance
49
+ user = User(**self.test_user_data)
50
+
51
+ # Verify homePageUrl is accessible for version = 6.14.0.0
52
+ self.assertEqual(user.homePageUrl, "/custom-dashboard")
53
+
54
+ @patch("regscale.models.regscale_models.user.User._get_api_handler")
55
+ def test_homepage_url_above_min_version(self, mock_api_handler):
56
+ """Test homePageUrl is accessible when version > 6.14.0.0"""
57
+ # Setup mock
58
+ mock_handler = MagicMock()
59
+ mock_handler.regscale_version = "6.14.0.1"
60
+ mock_api_handler.return_value = mock_handler
61
+
62
+ # Create user instance
63
+ user = User(**self.test_user_data)
64
+
65
+ # Verify homePageUrl is accessible for version > 6.14.0.0
66
+ self.assertEqual(user.homePageUrl, "/custom-dashboard")
67
+
68
+ @patch("regscale.models.regscale_models.user.User._get_api_handler")
69
+ def test_homepage_url_setter(self, mock_api_handler):
70
+ """Test homePageUrl setter works correctly"""
71
+ # Setup mock
72
+ mock_handler = MagicMock()
73
+ mock_handler.regscale_version = "6.14.0.1"
74
+ mock_api_handler.return_value = mock_handler
75
+
76
+ # Create user instance
77
+ user = User(**self.test_user_data)
78
+
79
+ # Test setting a new value
80
+ new_url = "/new-dashboard"
81
+ user.homePageUrl = new_url
82
+
83
+ # Verify both the property and underlying field are updated
84
+ self.assertEqual(user.homePageUrl, new_url)
85
+ self.assertEqual(user.homePageUrl_, new_url)
86
+
87
+ @patch("regscale.models.regscale_models.user.User._get_api_handler")
88
+ def test_homepage_url_default_value(self, mock_api_handler):
89
+ """Test homePageUrl default value behavior"""
90
+ # Setup mock
91
+ mock_handler = MagicMock()
92
+ mock_handler.regscale_version = "6.14.0.0"
93
+ mock_api_handler.return_value = mock_handler
94
+
95
+ # Create user instance without specifying homePageUrl
96
+ user = User(userName="testuser", email="test@example.com")
97
+
98
+ # Verify default value is set correctly
99
+ self.assertEqual(user.homePageUrl, "/workbench")
100
+ self.assertEqual(user.homePageUrl_, "/workbench")
101
+
102
+ @patch("regscale.models.regscale_models.user.User._get_api_handler")
103
+ def test_homepage_url_none_value(self, mock_api_handler):
104
+ """Test homePageUrl with None value"""
105
+ # Setup mock
106
+ mock_handler = MagicMock()
107
+ mock_handler.regscale_version = "6.14.0.0"
108
+ mock_api_handler.return_value = mock_handler
109
+
110
+ # Create test data with None homePageUrl
111
+ test_data = self.test_user_data.copy()
112
+ test_data["homePageUrl"] = None
113
+ user = User(**test_data)
114
+
115
+ # Verify None value is handled correctly
116
+ self.assertIsNone(user.homePageUrl)
117
+ self.assertIsNone(user.homePageUrl_)
118
+
119
+
120
+ if __name__ == "__main__":
121
+ unittest.main()
@@ -0,0 +1,19 @@
1
+ import pytest
2
+ from unittest.mock import patch
3
+ from click.testing import CliRunner
4
+
5
+
6
+ def test_about_no_variable_fetch():
7
+ """
8
+ Test that the about command runs successfully without fetching any variables
9
+ """
10
+ with patch("regscale.core.app.utils.variables.RsVariablesMeta.fetch_config_value") as mock_fetch:
11
+ # Import after patching to ensure the mock takes effect
12
+ from regscale.regscale import cli
13
+
14
+ runner = CliRunner()
15
+ result = runner.invoke(cli, ["about"])
16
+
17
+ assert result.exit_code == 0
18
+ assert "RegScale CLI Version:" in result.output
19
+ mock_fetch.assert_not_called()