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,332 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """RegScale Gitlab integration"""
4
+
5
+ # standard python imports
6
+ import os
7
+ import re
8
+ import sys
9
+ from urllib.parse import urljoin
10
+
11
+ import click
12
+ import markdown
13
+ import requests
14
+ from rich.progress import Progress
15
+
16
+ from regscale.core.app.internal.login import is_valid
17
+ from regscale.core.app.logz import create_logger
18
+ from regscale.core.app.utils.app_utils import (
19
+ check_license,
20
+ create_progress_object,
21
+ error_and_exit,
22
+ get_current_datetime,
23
+ )
24
+ from regscale.models import regscale_id, regscale_module
25
+ from regscale.models.regscale_models.issue import Issue
26
+ from regscale.models.regscale_models.link import Link
27
+
28
+ job_progress = create_progress_object()
29
+ logger = create_logger()
30
+
31
+
32
+ @click.group()
33
+ def gitlab():
34
+ """GitLab integration to pull issues via API."""
35
+
36
+
37
+ @gitlab.command(name="sync_issues", help="Integration to GitLab to sync issues into a module.")
38
+ @regscale_id()
39
+ @regscale_module()
40
+ @click.option("--gitlab_url", "-u", default="https://gitlab.com", help="GitLab URL", required=True)
41
+ @click.option(
42
+ "--gitlab_project_id",
43
+ "-gpid",
44
+ required=True,
45
+ help="The ID of the GitLab project to pull issues from.",
46
+ default=os.environ.get("GITLAB_PROJECT"),
47
+ )
48
+ @click.option(
49
+ "--api_token",
50
+ "-t",
51
+ required=True,
52
+ help="Your GitLab API token with API read access.",
53
+ default=os.environ.get("GITLAB_API_TOKEN"),
54
+ )
55
+ @click.option(
56
+ "--include_links",
57
+ "-l",
58
+ is_flag=True,
59
+ help="Include links from the issue description.",
60
+ default=False,
61
+ )
62
+ def sync_issues(
63
+ regscale_id: int,
64
+ regscale_module: str,
65
+ gitlab_url: str,
66
+ gitlab_project_id: int,
67
+ api_token: str,
68
+ include_links: bool,
69
+ ):
70
+ """Sync issues from a GitLab project into a RegScale record."""
71
+ run_sync_issues(
72
+ regscale_id=regscale_id,
73
+ regscale_module=regscale_module,
74
+ gitlab_url=gitlab_url,
75
+ gitlab_project_id=gitlab_project_id,
76
+ api_token=api_token,
77
+ include_links=include_links,
78
+ )
79
+
80
+
81
+ def run_sync_issues(
82
+ regscale_id: int,
83
+ regscale_module: str,
84
+ gitlab_url: str,
85
+ gitlab_project_id: int,
86
+ api_token: str,
87
+ include_links: bool,
88
+ ) -> None:
89
+ """Sync issues from a GitLab project into a module
90
+
91
+ :param int regscale_id: The RegScale ID to sync issues to
92
+ :param str regscale_module: The RegScale module to sync issues to
93
+ :param str gitlab_url: The GitLab URL to sync issues from
94
+ :param int gitlab_project_id: The GitLab project ID to sync issues from
95
+ :param str api_token: The GitLab API token to use
96
+ :param bool include_links: Whether to include links from the issue description
97
+ :rtype: None
98
+ """
99
+ app = check_license()
100
+ if not is_valid(app=app):
101
+ logger.warn("RegScale token is invalid. please login.")
102
+ sys.exit(1)
103
+
104
+ with job_progress:
105
+ gitlab_issues = get_issues_from_gitlab(gitlab_url, gitlab_project_id, api_token, job_progress)
106
+
107
+ regscale_issues = get_regscale_issues(regscale_id, regscale_module, job_progress)
108
+ logger.debug(f"Fetched {len(regscale_issues)} issues from RegScale.")
109
+
110
+ # Convert the issues to your desired format
111
+ issues = convert_issues(
112
+ gitlab_issues,
113
+ regscale_id,
114
+ regscale_module,
115
+ include_links,
116
+ job_progress,
117
+ )
118
+
119
+ # # Save or update the converted issues
120
+ save_or_update_issues(issues, regscale_issues, job_progress)
121
+
122
+
123
+ def get_regscale_issues(regscale_id: int, regscale_module: str, job_progress: Progress) -> list:
124
+ """Function to fetch issues from RegScale
125
+
126
+ :param int regscale_id: The RegScale ID to fetch issues for
127
+ :param str regscale_module: The RegScale module to fetch issues for
128
+ :param Progress job_progress: The progress object to use for updating
129
+ :return: list of regscale issues
130
+ :rtype: list
131
+ """
132
+ app = check_license()
133
+ task = job_progress.add_task("[#f8b737]Fetching issues from regscale", total=1)
134
+ if regscale_module == "securityplans":
135
+ existing_issues = Issue.fetch_issues_by_ssp(app=app, ssp_id=regscale_id)
136
+ logger.info(f"Fetched {len(existing_issues)} issues from RegScale by SSP.")
137
+ else:
138
+ existing_issues = Issue.fetch_issues_by_parent(
139
+ app=app, regscale_id=regscale_id, regscale_module=regscale_module
140
+ )
141
+ logger.info(f"Fetched {len(existing_issues)} issues from RegScale by issue parent.")
142
+ job_progress.update(task, advance=1)
143
+ return existing_issues
144
+
145
+
146
+ def save_or_update_issues(gitlab_issues: list, regscale_issues: list, job_progress: Progress) -> None:
147
+ """Function to save or update issues from GitLab to RegScale
148
+
149
+ :param list gitlab_issues: The list of GitLab issues to save or update
150
+ :param list regscale_issues: The list of RegScale issues to save or update
151
+ :param Progress job_progress: The progress object to use for updating
152
+ :rtype: None
153
+ """
154
+ app = check_license()
155
+ # figure out which issues need to be updated vs inserted
156
+ task = job_progress.add_task(
157
+ "[#f8b737]Saving issues from GitLab to RegScale...",
158
+ total=len(gitlab_issues),
159
+ )
160
+ regscale_dict = {regscale_issue.dependabotId: regscale_issue for regscale_issue in regscale_issues}
161
+
162
+ for gitlab_issue_obj in gitlab_issues:
163
+ gitlab_issue = gitlab_issue_obj.get("issue")
164
+ # if we have the issue already in the regscale dict, check and update it
165
+ if gitlab_issue.dependabotId in regscale_dict:
166
+ regscale_issue = regscale_dict.get(gitlab_issue.dependabotId)
167
+ # has it updated?
168
+ if regscale_issue.__eq__(gitlab_issue) is False:
169
+ gitlab_issue.id = regscale_issue.id
170
+ try:
171
+ Issue.update_issue(app=app, issue=gitlab_issue)
172
+ logger.info(f"Updated issue {gitlab_issue.id}")
173
+ except Exception as vex:
174
+ logger.error(vex)
175
+ existing_links = Link.fetch_links_by_parent(app, gitlab_issue.id, "issues")
176
+ for link in gitlab_issue_obj.get("links", []):
177
+ # set here for comparison purposes
178
+ link.parentID = gitlab_issue.id
179
+ if link not in existing_links:
180
+ try:
181
+ new_link = Link.insert_link(app=app, link=link)
182
+ logger.info(f"Inserted link {new_link.id}")
183
+ # Add the new link to the existing_links list
184
+ existing_links.append(new_link)
185
+ except Exception as ex:
186
+ logger.error(ex)
187
+
188
+ # insert new issue
189
+ else:
190
+ try:
191
+ issue = Issue.insert_issue(app=app, issue=gitlab_issue)
192
+ if issue is not None and issue.id is not None:
193
+ logger.info(f"Inserted issue {issue.id}")
194
+ except Exception as ex:
195
+ logger.error(ex)
196
+ for link in gitlab_issue_obj.get("links", []):
197
+ link.parentID = issue.id
198
+ try:
199
+ new_link = Link.insert_link(app=app, link=link)
200
+ except Exception as ex:
201
+ logger.error(ex)
202
+ job_progress.update(task, advance=1)
203
+
204
+
205
+ def extract_links_with_labels(text: str, parent_id: int, parent_module: str) -> list[Link]:
206
+ """Extract links from an issue description text with labels
207
+
208
+ :param str text: The issue description containing links
209
+ :param int parent_id: The parent ID associated with the parent module
210
+ :param str parent_module: The parent module associated with the parent ID
211
+ :return: A list of Link objects extracted from the text
212
+ :rtype: list[Link]
213
+ """
214
+ results = []
215
+ url_pattern = re.compile(r"https?://(?:[a-zA-Z0-9$@.&+*(),%-]|%[0-9a-fA-F]{2})+")
216
+
217
+ for line in text.split("\n"):
218
+ if ":" in line and ("Link" in line or "link" in line):
219
+ label, url = line.split(":", 1)
220
+ url = url.strip().replace("<br>", "")
221
+
222
+ if url.startswith("https:"):
223
+ url = url[6:].strip()
224
+
225
+ if url_pattern.match(url):
226
+ results.append(
227
+ Link(
228
+ title=label.replace("-", "").strip(),
229
+ url=url,
230
+ parentID=parent_id,
231
+ parentModule=parent_module,
232
+ )
233
+ )
234
+
235
+ return results
236
+
237
+
238
+ def convert_issues(
239
+ gitlab_issues: list,
240
+ regscale_id: int,
241
+ regscale_module: str,
242
+ include_links: bool,
243
+ job_progress: Progress,
244
+ ) -> list:
245
+ """
246
+ Converts issues from GitLab to regscale
247
+
248
+ :param list gitlab_issues: The list of GitLab issues to convert
249
+ :param int regscale_id: The RegScale ID to convert issues to
250
+ :param str regscale_module: The RegScale module to convert issues to
251
+ :param bool include_links: Whether to include links from the issue description
252
+ :param Progress job_progress: The progress object to use for updating
253
+ :return: list of converted issues
254
+ :rtype: list
255
+ """
256
+ app = check_license()
257
+
258
+ task = job_progress.add_task("[#f8b737]Converting issues from gitlab...", total=len(gitlab_issues))
259
+ regscale_issues = []
260
+ for issue in gitlab_issues:
261
+ status = "Open"
262
+ if issue.get("state"):
263
+ if issue.get("state") == "open":
264
+ status = "Open"
265
+ elif issue.get("state") == "closed":
266
+ status = "Closed"
267
+ severity_level = Issue.assign_severity(issue.get("weight", 0))
268
+ # Convert the issue to your desired format
269
+ converted_issue = Issue(
270
+ title=issue["title"],
271
+ description=str(markdown.markdown(issue["description"])),
272
+ severityLevel=severity_level,
273
+ issueOwnerId=app.config["userId"],
274
+ costEstimate=0,
275
+ levelOfEffort=0,
276
+ dueDate=issue["due_date"],
277
+ identification="Other",
278
+ dependabotId=str(issue["id"]),
279
+ dateCreated=issue["created_at"],
280
+ parentId=regscale_id,
281
+ parentModule=regscale_module,
282
+ status=status,
283
+ securityPlanId=regscale_id if regscale_module == "securityplans" else None,
284
+ componentId=regscale_id if regscale_module == "components" else None,
285
+ )
286
+ if converted_issue.status == "Closed":
287
+ if issue.get("closed_at"):
288
+ converted_issue.dateCompleted = issue.get("closed_at")
289
+ else:
290
+ converted_issue.dateCompleted = get_current_datetime()
291
+ # Extract the links from the description
292
+ if include_links:
293
+ links = extract_links_with_labels(issue["description"], 0, "issues")
294
+ regscale_issues.append({"issue": converted_issue, "links": links})
295
+ else:
296
+ regscale_issues.append({"issue": converted_issue, "links": []})
297
+ job_progress.update(task, advance=1)
298
+ return regscale_issues
299
+
300
+
301
+ def get_issues_from_gitlab(gitlab_url: str, gitlab_project_id: int, api_token: str, job_progress: Progress) -> list:
302
+ """Fetch issues from GitLab
303
+
304
+ :param str gitlab_url: The GitLab URL to fetch issues from
305
+ :param int gitlab_project_id: The GitLab project ID to fetch issues from
306
+ :param str api_token: The GitLab API token to use
307
+ :param Progress job_progress: The progress object to use for updating
308
+ :return: list of issues
309
+ :rtype: list
310
+ """
311
+ # Define the GitLab API URL for issues
312
+ api_call = f"/api/v4/projects/{gitlab_project_id}/issues"
313
+ url = urljoin(gitlab_url, api_call)
314
+ logger.info("Fetching issues from gitlab...")
315
+ logger.debug(f"Fetching with API token {api_token}")
316
+ # Define the headers, including your API token
317
+ headers = {"Private-Token": api_token}
318
+ # Send a GET request to the API
319
+ fetching_issues = job_progress.add_task("[#f8b737]Fetching issues from gitlab...", total=1)
320
+ response = requests.get(url, headers=headers)
321
+ job_progress.update(fetching_issues, advance=1)
322
+ issues = []
323
+ # If the request was successful
324
+ if response.ok:
325
+ # Load the issues from the response
326
+ issues = response.json()
327
+ logger.info(f"Fetched {len(issues)} issues from gitlab")
328
+ else:
329
+ logger.error(response.status_code)
330
+ logger.error(response.text)
331
+ error_and_exit(f"Failed to get issues from GitLab. Status code: {response.status_code}")
332
+ return issues
@@ -0,0 +1,165 @@
1
+ """
2
+ Module for processing Grype scan results and loading them into RegScale.
3
+ """
4
+
5
+ import logging
6
+ import traceback
7
+ from datetime import datetime
8
+ from typing import List, Optional, Union
9
+
10
+ import click
11
+ from pathlib import Path
12
+
13
+ from regscale.core.app.utils.file_utils import (
14
+ download_from_s3,
15
+ find_files,
16
+ iterate_files,
17
+ move_file,
18
+ )
19
+ from regscale.models.integration_models.flat_file_importer import FlatFileImporter
20
+ from regscale.models.integration_models.grype_import import GrypeImport
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ class GrypeProcessingError(Exception):
26
+ """Custom exception for Grype processing errors."""
27
+
28
+ pass
29
+
30
+
31
+ @click.group()
32
+ def grype():
33
+ """Performs actions from the Grype scanner integration."""
34
+ pass
35
+
36
+
37
+ @grype.command("import_scans")
38
+ @FlatFileImporter.common_scanner_options(
39
+ message="File path to the folder containing Grype .json files to process to RegScale.",
40
+ prompt="File path for Grype files",
41
+ import_name="grype",
42
+ )
43
+ @click.option("--destination", "-d", type=click.Path(exists=True, dir_okay=True), required=False)
44
+ @click.option("--file_pattern", "-p", type=str, required=False, default="grype*.json")
45
+ def import_scans(
46
+ destination: Optional[Path],
47
+ file_pattern: str,
48
+ folder_path: Path,
49
+ regscale_ssp_id: int,
50
+ scan_date: datetime,
51
+ mappings_path: Path,
52
+ disable_mapping: bool,
53
+ s3_bucket: str,
54
+ s3_prefix: str,
55
+ aws_profile: str,
56
+ upload_file: bool,
57
+ ) -> None:
58
+ """
59
+ Process Grype scan results from a folder containing Grype scan files and load into RegScale.
60
+ """
61
+ import_grype_scans(
62
+ destination=destination,
63
+ file_pattern=file_pattern,
64
+ folder_path=folder_path,
65
+ regscale_ssp_id=regscale_ssp_id,
66
+ scan_date=scan_date,
67
+ mappings_path=mappings_path,
68
+ disable_mapping=disable_mapping,
69
+ s3_bucket=s3_bucket,
70
+ s3_prefix=s3_prefix,
71
+ aws_profile=aws_profile,
72
+ upload_file=upload_file,
73
+ )
74
+
75
+
76
+ def import_grype_scans(
77
+ folder_path: Path,
78
+ regscale_ssp_id: int,
79
+ scan_date: datetime,
80
+ mappings_path: Optional[Path] = None,
81
+ disable_mapping: Optional[bool] = False,
82
+ s3_bucket: Optional[str] = None,
83
+ s3_prefix: Optional[str] = None,
84
+ aws_profile: Optional[str] = None,
85
+ destination: Optional[Path] = None,
86
+ file_pattern: Optional[str] = "grype*.json",
87
+ upload_file: Optional[bool] = True,
88
+ ) -> None:
89
+ """
90
+ Process Grype scan results from a folder container grype scan files and load into RegScale.
91
+
92
+ :param Path folder_path: Path to the Grype scan results JSON file
93
+ :param int regscale_ssp_id: RegScale SSP ID
94
+ :param datetime scan_date: The date of the scan
95
+ :param Optional[Path] mappings_path: Path to the header mapping file, default: None
96
+ :param Optional[bool] disable_mapping: Disable the header mapping, default: False
97
+ :param Optional[str] s3_bucket: S3 bucket to download scan files from, default: None
98
+ :param Optional[str] s3_prefix: Prefix (folder path) within the S3 bucket, default: None
99
+ :param Optional[str] aws_profile: AWS profile to use for S3 access, default: None
100
+ :param Optional[Path] destination: Destination folder for processed files, default: None
101
+ :param Optional[str] file_pattern: File pattern to search for in the directory, default: grype*.json
102
+ :param Optional[bool] upload_file: Whether to upload the file to RegScale after processing, default: True
103
+ :raises GrypeProcessingError: If there is an error processing the Grype results
104
+ :rtype: None
105
+ """
106
+ from regscale.exceptions import ValidationException
107
+ from regscale.core.app.application import Application
108
+
109
+ try:
110
+ if s3_bucket and s3_prefix and aws_profile:
111
+ download_from_s3(bucket=s3_bucket, prefix=s3_prefix, local_path=destination, aws_profile=aws_profile)
112
+ files = find_files(path=destination, pattern=file_pattern)
113
+ logger.info("Downloaded all Grype scan files from S3. Processing...")
114
+ elif destination and not s3_bucket:
115
+ logger.info("Moving Grype scan files to %s", destination)
116
+ stored_file_collection = find_files(path=folder_path, pattern=file_pattern)
117
+ move_all_files(stored_file_collection, destination)
118
+ files = find_files(path=destination, pattern=file_pattern)
119
+ logger.info("Done moving files")
120
+ else:
121
+ stored_file_collection = find_files(path=folder_path, pattern=file_pattern)
122
+ files = stored_file_collection
123
+ if not files:
124
+ logger.error("No Grype scan results found in the specified directory")
125
+ return
126
+
127
+ except Exception as e:
128
+ logger.error(f"Error processing Grype results: {str(e)}")
129
+ logger.error(traceback.format_exc())
130
+ raise GrypeProcessingError(f"Failed to process Grype results: {str(e)}")
131
+
132
+ for file in files:
133
+ try:
134
+ GrypeImport(
135
+ name="Grype",
136
+ app=Application(),
137
+ file_path=str(file),
138
+ file_type=file.suffix,
139
+ parent_id=regscale_ssp_id,
140
+ parent_module="securityplans",
141
+ scan_date=scan_date,
142
+ mappings_path=mappings_path,
143
+ disable_mapping=disable_mapping,
144
+ upload_file=upload_file,
145
+ file_name=file.name,
146
+ )
147
+ except ValidationException as e:
148
+ logger.error(f"Validation error on {file}: {e}")
149
+ continue
150
+ logger.info("Completed Grype processing.")
151
+
152
+
153
+ def move_all_files(file_collection: List[Union[Path, str]], destination: Union[Path, str]) -> None:
154
+ """
155
+ Move all Grype files in the current directory to a folder called 'processed'.
156
+
157
+ :param List[Union[Path, str]] file_collection: A list of file paths or S3 URIs
158
+ :param Union[Path, str] destination: The destination folder
159
+ :rtype: None
160
+ """
161
+ for file in iterate_files(file_collection):
162
+ file_path = Path(file)
163
+ new_filename = f"{file_path.stem}{file_path.suffix}"
164
+ new_file_path = Path(destination) / new_filename
165
+ move_file(file, new_file_path)
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """IBM AppScan RegScale integration"""
4
+ from datetime import datetime
5
+ from os import PathLike
6
+ from typing import Optional
7
+
8
+ import click
9
+
10
+ from regscale.models.integration_models.flat_file_importer import FlatFileImporter
11
+ from regscale.models.integration_models.ibm import AppScan
12
+
13
+
14
+ @click.group()
15
+ def ibm():
16
+ """Performs actions on IBM AppScan files."""
17
+
18
+
19
+ @ibm.command(name="import_appscan")
20
+ @FlatFileImporter.common_scanner_options(
21
+ message="File path to the folder containing IBM AppScan .csv files to process to RegScale.",
22
+ prompt="File path for IBM AppScan files",
23
+ import_name="ibm_appscan",
24
+ )
25
+ def import_appscan(
26
+ folder_path: PathLike[str],
27
+ regscale_ssp_id: int,
28
+ scan_date: datetime,
29
+ mappings_path: PathLike[str],
30
+ disable_mapping: bool,
31
+ s3_bucket: str,
32
+ s3_prefix: str,
33
+ aws_profile: str,
34
+ upload_file: bool,
35
+ ) -> None:
36
+ """
37
+ Import IBM AppScan scans, vulnerabilities and assets to RegScale from IBM AppScan files
38
+ """
39
+ import_appscan_files(
40
+ folder_path,
41
+ regscale_ssp_id,
42
+ scan_date,
43
+ mappings_path,
44
+ disable_mapping,
45
+ s3_bucket,
46
+ s3_prefix,
47
+ aws_profile,
48
+ upload_file,
49
+ )
50
+
51
+
52
+ def import_appscan_files(
53
+ folder_path: PathLike[str],
54
+ regscale_ssp_id: int,
55
+ scan_date: datetime,
56
+ mappings_path: PathLike[str],
57
+ disable_mapping: bool,
58
+ s3_bucket: str,
59
+ s3_prefix: str,
60
+ aws_profile: str,
61
+ upload_file: Optional[bool] = True,
62
+ ) -> None:
63
+ """
64
+ Import IBM AppScan scans, vulnerabilities and assets to RegScale from IBM AppScan files
65
+
66
+ :param PathLike[str] folder_path: File path to the folder containing IBM AppScan .csv files to process to RegScale
67
+ :param int regscale_ssp_id: The RegScale SSP ID
68
+ :param datetime scan_date: The date of the scan
69
+ :param PathLike[str] mappings_path: The path to the mappings file
70
+ :param bool disable_mapping: Whether to disable custom mappings
71
+ :param str s3_bucket: The S3 bucket to download the files from
72
+ :param str s3_prefix: The S3 prefix to download the files from
73
+ :param str aws_profile: The AWS profile to use for S3 access
74
+ :param Optional[bool] upload_file: Whether to upload the file to RegScale after processing, defaults to True
75
+ :rtype: None
76
+ """
77
+ FlatFileImporter.import_files(
78
+ import_type=AppScan,
79
+ import_name="IBM AppScan",
80
+ file_types=".csv",
81
+ folder_path=folder_path,
82
+ regscale_ssp_id=regscale_ssp_id,
83
+ scan_date=scan_date,
84
+ mappings_path=mappings_path,
85
+ disable_mapping=disable_mapping,
86
+ s3_bucket=s3_bucket,
87
+ s3_prefix=s3_prefix,
88
+ aws_profile=aws_profile,
89
+ upload_file=upload_file,
90
+ )