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,231 @@
1
+ """
2
+ Module for processing Trivy scan results and loading them into RegScale as assets, issues, and vulnerabilities.
3
+ """
4
+
5
+ import logging
6
+ import traceback
7
+ from typing import Any, Dict, Iterator, List, Optional
8
+
9
+ from regscale.core.app.utils.parser_utils import safe_datetime_str
10
+ from regscale.exceptions import ValidationException
11
+ from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding
12
+ from regscale.models import ImportValidater
13
+ from regscale.models.integration_models.flat_file_importer import FlatFileImporter
14
+ from regscale.models.regscale_models import AssetStatus, IssueSeverity, IssueStatus
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class TrivyImport(FlatFileImporter):
20
+ """Class for handling Trivy scanner integration."""
21
+
22
+ asset_identifier_field = "otherTrackingNumber"
23
+ finding_severity_map = {
24
+ "CRITICAL": IssueSeverity.Critical.value,
25
+ "HIGH": IssueSeverity.High.value,
26
+ "MEDIUM": IssueSeverity.Moderate.value,
27
+ "LOW": IssueSeverity.Low.value,
28
+ "UNKNOWN": IssueSeverity.High.value,
29
+ "NEGLIGIBLE": IssueSeverity.High.value,
30
+ }
31
+ identifier: Optional[str] = None
32
+
33
+ def __init__(self, **kwargs: Any):
34
+ self.name = kwargs.get("name", "Trivy")
35
+ self.identifier = None
36
+ self.required_headers = [
37
+ "Metadata",
38
+ ]
39
+ self.mapping_file = kwargs.get("mappings_path")
40
+ self.disable_mapping = kwargs.get("disable_mapping")
41
+ self.validater = ImportValidater(
42
+ self.required_headers,
43
+ kwargs.get("file_path"),
44
+ self.mapping_file,
45
+ self.disable_mapping,
46
+ )
47
+ self.headers = self.validater.parsed_headers
48
+ self.mapping = self.validater.mapping
49
+ if kwargs.get("scan_date"):
50
+ self.scan_date = kwargs.pop("scan_date")
51
+ else:
52
+ self.scan_date = safe_datetime_str(self.validater.data.get("CreatedAt"))
53
+ # even if a user doesn't specify a scan_date, we want to remove it from the kwargs and use the scan_date from
54
+ # the attributes after the scan_date is set in the previous logic
55
+ if "scan_date" in kwargs:
56
+ kwargs.pop("scan_date")
57
+ if "sha256-" in kwargs["file_name"]:
58
+ logger.debug("found sha256 in file name %s", kwargs["file_name"])
59
+ self.identifier = "sha256-" + kwargs["file_name"].split("sha256-")[1].split(".json")[0]
60
+ else:
61
+ logger.debug("using imageID for identifier")
62
+ self.identifier = self.mapping.get_value(self.validater.data, "Metadata", {}).get("ImageID")
63
+ logger.debug("self.identifier: %s", self.identifier)
64
+ self.integration_name = self.identifier
65
+ self.other_tracking_number = self.mapping.get_value(self.validater.data, "ArtifactName", self.identifier)
66
+ self.notes = f"{kwargs['file_name']}"
67
+ vuln_count = 0
68
+ for item in self.mapping.get_value(self.validater.data, "Results", []):
69
+ vuln_count += len(item.get("Vulnerabilities", []))
70
+ super().__init__(
71
+ logger=logger,
72
+ headers=self.headers,
73
+ extra_headers_allowed=True,
74
+ finding_severity_map=self.finding_severity_map,
75
+ vuln_func=self.create_vuln,
76
+ asset_func=self.create_asset,
77
+ scan_date=self.scan_date,
78
+ asset_identifier_field=self.asset_identifier_field,
79
+ vuln_count=vuln_count,
80
+ asset_count=1,
81
+ **kwargs,
82
+ )
83
+
84
+ def parse_asset(self, **kwargs) -> IntegrationAsset:
85
+ """
86
+ Parse assets from Trivy scan data.
87
+
88
+ :return: Integration asset
89
+ :rtype: IntegrationAsset
90
+ """
91
+ os_data = kwargs.pop("os_data")
92
+ return IntegrationAsset(
93
+ identifier=self.identifier,
94
+ name=self.integration_name,
95
+ ip_address="0.0.0.0",
96
+ cpu=0,
97
+ ram=0,
98
+ status=AssetStatus.Active.value,
99
+ asset_type="Other",
100
+ asset_category="Software",
101
+ operating_system=f"{os_data.get('Family', '')} {os_data.get('Name', '')}",
102
+ notes=self.notes,
103
+ other_tracking_number=self.other_tracking_number,
104
+ )
105
+
106
+ def create_asset(self, *args, **kwargs) -> Iterator[IntegrationAsset]:
107
+ """
108
+ Fetches assets from the processed json files
109
+
110
+ :yields: Iterator[IntegrationAsset]
111
+ """
112
+ if assets := self.fetch_assets(**kwargs):
113
+ for asset in assets:
114
+ yield asset
115
+
116
+ def create_vuln(self, *args, **kwargs) -> Iterator[IntegrationFinding]:
117
+ """
118
+ Fetches findings from the processed json files
119
+
120
+ :return: A list of findings
121
+ :rtype: List[IntegrationFinding]
122
+ """
123
+ if findings := self.fetch_findings(**kwargs):
124
+ for finding in findings:
125
+ yield finding
126
+
127
+ def fetch_findings(self, **_) -> List[IntegrationFinding]:
128
+ """
129
+ Fetch findings from Trivy scan data.
130
+
131
+ :raises ValidationException: If there is an error fetching/parsing findings
132
+ :return: List of IntegrationFinding
133
+ :rtype: List[IntegrationFinding]
134
+ """
135
+
136
+ findings = []
137
+ try:
138
+ for item in self.mapping.get_value(self.validater.data, "Results", []):
139
+ for finding in item.get("Vulnerabilities", []):
140
+ findings.append(
141
+ IntegrationFinding(
142
+ title=finding.get("Title", finding.get("PkgName")),
143
+ description=finding.get("Description", "No description available"),
144
+ severity=(
145
+ self.process_severity(finding.get("Severity"))
146
+ if finding.get("Severity")
147
+ else IssueSeverity.NotAssigned.value
148
+ ),
149
+ status=IssueStatus.Open.value,
150
+ cvss_v3_score=self.get_cvss_score(finding),
151
+ cvss_v3_base_score=self.get_cvss_score(finding),
152
+ plugin_name=finding.get("DataSource", {}).get("Name", self.name),
153
+ plugin_id=finding.get("DataSource", {}).get("ID", self.name),
154
+ asset_identifier=self.identifier,
155
+ cve=finding.get("VulnerabilityID"),
156
+ first_seen=self.scan_date,
157
+ last_seen=self.scan_date,
158
+ scan_date=self.scan_date,
159
+ category="Software",
160
+ control_labels=[],
161
+ )
162
+ )
163
+ return findings
164
+ except Exception:
165
+ error_message = traceback.format_exc()
166
+ logger.error(f"Error fetching findings: {error_message}")
167
+ raise ValidationException(f"Error fetching findings: {error_message}")
168
+
169
+ def process_severity(self, severity: str) -> str:
170
+ """
171
+ Process the severity of a finding.
172
+
173
+ :param str severity: The severity of the finding
174
+ :return: IssueSeverity corresponding to the severity
175
+ :rtype: str
176
+ """
177
+ from regscale.core.app.application import Application
178
+
179
+ app = Application()
180
+ severity_default = app.config.get("vulnerabilityMappingDefault", IssueSeverity.NotAssigned.value)
181
+ return self.finding_severity_map.get(severity.upper(), severity_default)
182
+
183
+ @staticmethod
184
+ def process_status(status: str) -> str:
185
+ """
186
+ Process the status of a finding.
187
+
188
+ :param str status: The status of the finding
189
+ :return: The corresponding Issue status
190
+ :rtype: str
191
+ """
192
+ if status.lower() == "fixed":
193
+ return IssueStatus.Closed.value
194
+ else:
195
+ return IssueStatus.Open.value
196
+
197
+ @staticmethod
198
+ def get_cvss_score(finding: Dict) -> float:
199
+ """
200
+ Get the CVSS score from the finding data.
201
+
202
+ :param dict finding: The finding data
203
+ :return: The CVSS score
204
+ :rtype: float
205
+ """
206
+ value = 0.0
207
+ if cvs := finding.get("CVSS"):
208
+ if nvd := cvs.get("nvd"):
209
+ value = nvd.get("V3Score", 0.0)
210
+ elif redhat := cvs.get("redhat"):
211
+ value = redhat.get("V3Score", 0.0)
212
+ return value
213
+
214
+ def fetch_assets(self, **_) -> List[IntegrationAsset]:
215
+ """
216
+ Fetch assets from Trivy scan data.
217
+
218
+ :raises ValidationException: If there is an error fetching/parsing assets
219
+ :return: List of IntegrationAsset
220
+ :rtype: List[IntegrationAsset]
221
+ """
222
+ data = self.validater.data
223
+ assets: List[IntegrationAsset] = []
224
+ os_data = self.mapping.get_value(data, "Metadata", {}, warnings=False).get("OS", {})
225
+ try:
226
+ assets.append(self.parse_asset(asset=data, os_data=os_data))
227
+ return assets
228
+ except Exception:
229
+ error_message = traceback.format_exc()
230
+ logger.error(f"Error fetching assets: {error_message}")
231
+ raise ValidationException(f"Error fetching assets: {error_message}")
@@ -0,0 +1,217 @@
1
+ from typing import List, Optional
2
+
3
+ from regscale.core.app.logz import create_logger
4
+ from regscale.core.app.utils.app_utils import get_current_datetime
5
+ from regscale.models import Asset, Vulnerability, Mapping, ImportValidater
6
+ from regscale.models.integration_models.flat_file_importer import FlatFileImporter
7
+
8
+ APP_NAME = "@app_name"
9
+ VERSION = "@version"
10
+ ACCOUNT_ID = "@account_id"
11
+
12
+
13
+ class Veracode(FlatFileImporter):
14
+ def __init__(self, **kwargs):
15
+ self.name = kwargs.get("name", "Veracode")
16
+ logger = create_logger()
17
+ self.vuln_title = "PROBLEM_TITLE"
18
+ self.fmt = "%Y-%m-%d"
19
+ self.dt_format = "%Y-%m-%d %H:%M:%S"
20
+ csv_headers = [
21
+ "Source",
22
+ ]
23
+ xml_headers = [
24
+ "app_name",
25
+ ]
26
+ self.mapping_file = kwargs.get("mappings_path")
27
+ self.disable_mapping = kwargs.get("disable_mapping")
28
+ file_type = kwargs.get("file_type")
29
+ if file_type == ".xml":
30
+ self.required_headers = xml_headers
31
+ xml_tag = "detailedreport"
32
+ else:
33
+ self.required_headers = csv_headers
34
+ xml_tag = None
35
+ self.validater = ImportValidater(
36
+ self.required_headers, kwargs.get("file_path"), self.mapping_file, self.disable_mapping, xml_tag=xml_tag
37
+ )
38
+ self.headers = self.validater.parsed_headers
39
+ self.mapping = self.validater.mapping
40
+ super().__init__(
41
+ logger=logger,
42
+ headers=self.headers,
43
+ asset_func=self.create_asset,
44
+ vuln_func=self.create_vuln,
45
+ extra_headers_allowed=False,
46
+ **kwargs,
47
+ )
48
+
49
+ def create_asset(self, dat: Optional[dict] = None) -> List[Asset]:
50
+ """
51
+ Create a RegScale asset from an asset in the Veracode export file
52
+
53
+ :param Optional[dict] dat: The data from the Veracode export file
54
+ :return: List of RegScale Asset objects
55
+ :rtype: List[Asset]
56
+ """
57
+ version = None
58
+ # Veracode is a Web Application Security Scanner, so these will be software assets, scanning a
59
+ # single web application
60
+ if "detailedreport" in self.mapping.mapping.keys():
61
+ name = self.mapping.get_value(dat, "detailedreport", {}).get(APP_NAME, "")
62
+ account_id = self.mapping.get_value(dat, "detailedreport", {}).get(ACCOUNT_ID, "")
63
+ version = self.mapping.get_value(dat, "detailedreport", {}).get(VERSION, "")
64
+ else:
65
+ name = self.mapping.get_value(dat, "Source", "")
66
+ account_id = str(self.mapping.get_value(dat, "ID", ""))
67
+ asset = Asset(
68
+ **{
69
+ "id": 0,
70
+ "name": name,
71
+ "otherTrackingNumber": account_id,
72
+ "ipAddress": "0.0.0.0",
73
+ "isPublic": True,
74
+ "status": "Active (On Network)",
75
+ "assetCategory": "Software",
76
+ "bLatestScan": True,
77
+ "bAuthenticatedScan": True,
78
+ "scanningTool": self.name,
79
+ "assetOwnerId": self.config["userId"],
80
+ "assetType": "Other",
81
+ "softwareVendor": "Veracode",
82
+ "softwareName": name,
83
+ "softwareVersion": version,
84
+ "systemAdministratorId": self.config["userId"],
85
+ "parentId": self.attributes.parent_id,
86
+ "parentModule": self.attributes.parent_module,
87
+ }
88
+ )
89
+ return [asset]
90
+
91
+ def create_vuln(self, dat: Optional[dict] = None, **kwargs) -> List[Vulnerability]:
92
+ """
93
+ Create a RegScale vulnerability from a vulnerability in the Veracode export file
94
+
95
+ :param Optional[dict] dat: The data from the Veracode export file
96
+ :return: List of RegScale Vulnerability objects
97
+ :rtype: List[Vulnerability]
98
+ """
99
+ import_type = "xml" if isinstance(dat, str) else "csv"
100
+ # Veracode is a Web Application Security Scanner, so these will be software assets,
101
+ # scanning a single web application
102
+ if import_type == "xml":
103
+ name = self.mapping.get_value(dat, "detailedreport", {}).get(APP_NAME, "")
104
+ all_sev_data = self.mapping.get_value(dat, "detailedreport", {}).get("severity", [])
105
+ severity = self.severity_info(all_sev_data)[0] if all_sev_data else "low"
106
+ if severity_data := self.severity_info(all_sev_data):
107
+ if isinstance(severity_data, list) and len(severity_data) >= 2:
108
+ cwes = [
109
+ f"{c.get('cweid')} {c.get('cwename')}" for c in severity_data[1].get("cwe", [])
110
+ ] # Multiple cwes per asset in official XML
111
+ else:
112
+ cwes = []
113
+ else:
114
+ name = self.mapping.get_value(dat, "Source", "")
115
+ severity = self.mapping.get_value(dat, "Sev", "").lower()
116
+ cwes = [self.mapping.get_value(dat, "CWE ID & Name", [])] # Coalfire should flatten data for asset -> cwes
117
+
118
+ return self.process_csv_vulns(name, cwes, severity)
119
+
120
+ def process_csv_vulns(self, hostname: str, cwes: List[str], severity: str) -> List[Vulnerability]:
121
+ """
122
+ Process the CSV findings from the ECR scan
123
+
124
+ :param str hostname: The hostname
125
+ :param List[str] cwes: The CWEs
126
+ :param str severity: The severity
127
+ :return: A list of vulnerabilities
128
+ :rtype: List[Vulnerability]
129
+ """
130
+ vulns = []
131
+ for cwe in cwes:
132
+ severity = self.determine_severity(severity)
133
+ if asset := self.get_asset(hostname):
134
+ vuln = self.create_vulnerability_object(asset, hostname, cwe, severity, "")
135
+ vulns.append(vuln)
136
+ return vulns
137
+
138
+ def create_vulnerability_object(
139
+ self, asset: Asset, hostname: str, cwe: str, severity: str, description: str
140
+ ) -> Vulnerability:
141
+ """
142
+ Create a vulnerability from a row in the Veracode file
143
+
144
+ :param Asset asset: The asset
145
+ :param str hostname: The hostname
146
+ :param str cwe: The CWE
147
+ :param str severity: The severity
148
+ :param str description: The description
149
+ :return: The vulnerability
150
+ :rtype: Vulnerability
151
+ """
152
+ config = self.attributes.app.config
153
+
154
+ return Vulnerability( # type: ignore
155
+ id=0,
156
+ scanId=0,
157
+ parentId=asset.id,
158
+ parentModule="assets",
159
+ ipAddress="0.0.0.0",
160
+ lastSeen=get_current_datetime(), # No timestamp on Veracode
161
+ firstSeen=get_current_datetime(), # No timestamp on Veracode
162
+ daysOpen=None,
163
+ dns=hostname,
164
+ mitigated=None,
165
+ operatingSystem=asset.operatingSystem,
166
+ severity=severity,
167
+ plugInName=cwe,
168
+ cve="",
169
+ tenantsId=0,
170
+ title=f"{cwe} on asset {asset.name}",
171
+ description=cwe,
172
+ plugInText=description,
173
+ createdById=config["userId"],
174
+ lastUpdatedById=config["userId"],
175
+ dateCreated=get_current_datetime(),
176
+ )
177
+
178
+ def get_asset(self, hostname: str) -> Optional[Asset]:
179
+ """
180
+ Get the asset from the hostname
181
+
182
+ :param str hostname: The hostname
183
+ :return: The asset, if found
184
+ :rtype: Optional[Asset]
185
+ """
186
+ asset_match = [asset for asset in self.data["assets"] if asset.name == hostname]
187
+ return asset_match[0] if asset_match else None
188
+
189
+ def severity_info(self, severity_list: list) -> Optional[tuple]:
190
+ """
191
+ Get the severity level and category of the vulnerability
192
+
193
+ :param list severity_list: List of severity levels
194
+ :return: Severity level and category
195
+ :rtype: Optional[tuple]
196
+ """
197
+ hit = [sev for sev in severity_list if sev.get("category")]
198
+ if hit:
199
+ return (self.hit_mapping().get(hit[0].get("level"), "low"), hit[0].get("category"))
200
+ return None
201
+
202
+ @staticmethod
203
+ def hit_mapping() -> dict:
204
+ """
205
+ Mapping of severity levels
206
+
207
+ :return: Mapping of severity levels
208
+ :rtype: dict
209
+ """
210
+ return {
211
+ "5": "critical",
212
+ "4": "high",
213
+ "3": "moderate",
214
+ "2": "low",
215
+ "1": "low",
216
+ "0": "info",
217
+ }
@@ -0,0 +1,135 @@
1
+ """
2
+ Nexpose Scan information
3
+ """
4
+
5
+ from typing import List, Optional
6
+
7
+ from regscale.core.app.application import Application
8
+ from regscale.core.app.logz import create_logger
9
+ from regscale.core.app.utils.app_utils import epoch_to_datetime, get_current_datetime
10
+ from regscale.models import ImportValidater, Mapping
11
+ from regscale.models.integration_models.flat_file_importer import FlatFileImporter
12
+ from regscale.models.regscale_models.asset import Asset
13
+ from regscale.models.regscale_models.vulnerability import Vulnerability
14
+
15
+
16
+ class XRay(FlatFileImporter):
17
+ """JFrog Xray Scan information
18
+
19
+ :param str name: Name of the scan
20
+ :param Application app: RegScale Application object
21
+ :param str file_path: Path to the JSON files
22
+ :param int regscale_ssp_id: RegScale System Security Plan ID
23
+ """
24
+
25
+ def __init__(self, **kwargs):
26
+ self.name = kwargs.get("name")
27
+ regscale_ssp_id = kwargs.get("regscale_ssp_id")
28
+ self.cvss3_score = "cvss_v3_score"
29
+ self.vuln_title = "cve"
30
+ self.required_headers = [
31
+ "impacted_artifact",
32
+ ]
33
+ self.mapping_file = kwargs.get("mappings_path")
34
+ self.disable_mapping = kwargs.get("disable_mapping")
35
+ self.validater = ImportValidater(
36
+ self.required_headers, kwargs.get("file_path"), self.mapping_file, self.disable_mapping
37
+ )
38
+ self.headers = self.validater.parsed_headers
39
+ self.mapping = self.validater.mapping
40
+ logger = create_logger()
41
+ super().__init__(
42
+ logger=logger,
43
+ app=Application(),
44
+ headers=None,
45
+ parent_id=regscale_ssp_id,
46
+ parent_module="securityplans",
47
+ asset_func=self.create_asset,
48
+ vuln_func=self.create_vuln,
49
+ **kwargs,
50
+ )
51
+
52
+ def create_asset(self, dat: Optional[dict] = None) -> Optional[Asset]:
53
+ """
54
+ Create an asset from a row in the Xray JSON file
55
+
56
+ :param Optional[dict] dat: Data row from JSON file, defaults to None
57
+ :return: RegScale Asset object
58
+ :rtype: Optional[Asset]
59
+ """
60
+
61
+ if asset_name := self.mapping.get_value(dat, "impacted_artifact") if isinstance(dat, dict) else dat:
62
+ return Asset(
63
+ **{
64
+ "id": 0,
65
+ "name": asset_name,
66
+ "ipAddress": "0.0.0.0",
67
+ "isPublic": True,
68
+ "status": "Active (On Network)",
69
+ "assetCategory": "Software",
70
+ "bLatestScan": True,
71
+ "bAuthenticatedScan": True,
72
+ "scanningTool": self.name,
73
+ "assetOwnerId": self.config["userId"],
74
+ "assetType": "Other",
75
+ "fqdn": None,
76
+ "operatingSystem": "Linux",
77
+ "systemAdministratorId": self.config["userId"],
78
+ "parentId": self.attributes.parent_id,
79
+ "parentModule": self.attributes.parent_module,
80
+ }
81
+ )
82
+ return None
83
+
84
+ def create_vuln(self, dat: Optional[dict] = None, **kwargs) -> List[Vulnerability]:
85
+ """
86
+ Create a vulnerability from a row in the JFrog Xray JSON file
87
+
88
+ :param Optional[dict] dat: Data row from JSON file, defaults to None
89
+ :return: List of RegScale Vulnerability object, if any
90
+ :rtype: List[Vulnerability]
91
+ """
92
+ asset_match = [
93
+ asset for asset in self.data["assets"] if asset.name == self.mapping.get_value(dat, "impacted_artifact")
94
+ ]
95
+ asset = asset_match[0] if asset_match else None
96
+ vulns = []
97
+ for vuln in self.mapping.get_value(dat, "cves", []):
98
+ # CVE IS A VULN, A VULN IS A CVE, Finkle is Einhorn
99
+ regscale_vuln = None
100
+ severity = (
101
+ Vulnerability.determine_cvss3_severity_text(float(vuln[self.cvss3_score]))
102
+ if vuln.get(self.cvss3_score)
103
+ else "low"
104
+ )
105
+ if asset_match:
106
+ cves = [c["cve"] for c in self.mapping.get_value(dat, "cves", []) if c.get("cve")]
107
+ for cve in cves:
108
+ regscale_vuln = Vulnerability(
109
+ id=0,
110
+ scanId=0, # set later
111
+ parentId=asset.id,
112
+ parentModule="assets",
113
+ ipAddress="0.0.0.0", # No ip address available
114
+ lastSeen=self.scan_date,
115
+ firstSeen=epoch_to_datetime(self.create_epoch),
116
+ daysOpen=None,
117
+ dns=self.mapping.get_value(dat, "impacted_artifact"),
118
+ mitigated=None,
119
+ operatingSystem="Linux",
120
+ severity=severity,
121
+ plugInName=self.mapping.get_value(dat, "issue_id", "XRay"),
122
+ plugInId=int(self.mapping.get_value(dat, "issue_id", "Xray-0000")[5:]),
123
+ cve=cve,
124
+ vprScore=None,
125
+ tenantsId=0, # Need a way to figure this out programmatically
126
+ title=f"{self.mapping.get_value(dat, 'issue_id', warnings=False) or self.mapping.get_value(dat, 'summary', f'XRay Vulnerability from Import {get_current_datetime()}', warnings=False)} on asset {asset.name}",
127
+ description=self.mapping.get_value(dat, "summary"),
128
+ plugInText=vuln.get("cve"),
129
+ extra_data={
130
+ "references": self.mapping.get_value(dat, "references", "None"),
131
+ "solution": self.mapping.get_value(dat, "fixed_versions", "None"),
132
+ },
133
+ )
134
+ vulns.append(regscale_vuln)
135
+ return vulns
@@ -0,0 +1,100 @@
1
+ """Class to lock a file to prevent concurrent access to it."""
2
+
3
+ import os
4
+ import time
5
+ from types import TracebackType
6
+ from typing import Optional, Type
7
+
8
+
9
+ class FileLock:
10
+ """
11
+ Class to lock a file to prevent concurrent access to it
12
+
13
+ :param str lock_file: File to lock, defaults to "results/xdist_lock.txt"
14
+ :param bool skip_lock: Whether to skip the lock, defaults to False
15
+ """
16
+
17
+ lock_file: str
18
+ lock_scope: str
19
+ skip_lock: bool
20
+
21
+ def __init__(self, lock_file: str = "results/xdist_lock.txt", skip_lock: bool = False):
22
+ self.lock_file: str = lock_file
23
+ self.lock_scope: str = f"{os.getpid()}".ljust(10, ".")
24
+ self.skip_lock = skip_lock
25
+ lock_folder = os.path.dirname(self.lock_file)
26
+ if not os.path.isdir(lock_folder):
27
+ os.makedirs(lock_folder)
28
+
29
+ def __enter__(self) -> "FileLock":
30
+ """
31
+ Enter the context manager.
32
+
33
+ :return: The FileLock object
34
+ :rtype: FileLock
35
+ """
36
+ if not self.skip_lock:
37
+ self.acquire_lock()
38
+ return self
39
+
40
+ def __exit__(
41
+ self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]
42
+ ) -> None:
43
+ """
44
+ Exit the context manager.
45
+
46
+ :param Optional[Type[BaseException]] exc_type: The exception type
47
+ :param Optional[BaseException] exc_val: The exception value
48
+ :param Optional[TracebackType] exc_tb: The traceback
49
+ :rtype: None
50
+ """
51
+ if not self.skip_lock:
52
+ self.release_lock()
53
+
54
+ def lock_contents(self) -> str:
55
+ """
56
+ Get the contents of the lock file.
57
+
58
+ :return: Contents of the lock file as a string
59
+ :rtype: str
60
+ """
61
+ with open(self.lock_file, "r") as lockfile:
62
+ contents = lockfile.read()
63
+ return contents
64
+
65
+ def acquire_lock(self) -> None:
66
+ """
67
+ Acquire the lock.
68
+
69
+ :rtype: None
70
+ """
71
+ try:
72
+ while os.path.isfile(self.lock_file):
73
+ # Another process is holding the lock. Waiting to acquire...
74
+ time.sleep(0.1)
75
+ # Create the lock file with the pid inside
76
+ with open(self.lock_file, "w") as lockfile:
77
+ lockfile.write(f"{self.lock_scope}")
78
+ # Read the lock file to make sure the contents is ours
79
+ with open(self.lock_file, "r") as lockfile:
80
+ contents = lockfile.read()
81
+ # If the contents is not ours, race condition -> back to square one
82
+ if contents != f"{self.lock_scope}":
83
+ self.acquire_lock()
84
+ except Exception:
85
+ self.acquire_lock()
86
+
87
+ def release_lock(self) -> None:
88
+ """
89
+ Release the lock.
90
+
91
+ :rtype: None
92
+ """
93
+ if os.path.isfile(self.lock_file):
94
+ with open(self.lock_file, "r") as lockfile:
95
+ scope = str(lockfile.read().strip())
96
+
97
+ if scope == str(self.lock_scope):
98
+ os.remove(self.lock_file) # Lock released
99
+ else:
100
+ pass # Lock can only be released by {self.lock_scope}