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
File without changes
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """RegScale Azure Integrations"""
4
+ import os
5
+ import msal
6
+ from regscale.core.app.application import Application
7
+
8
+
9
+ def get_token(app: Application) -> str:
10
+ """
11
+ Fetch Azure AD Token
12
+
13
+ :param Application app: The application
14
+ :rtype: str
15
+ """
16
+
17
+ scope = ["https://graph.microsoft.com/.default"]
18
+ try:
19
+ azure_tenant_id = os.environ["AZURE_TENANT_ID"]
20
+ client_id = os.environ["AZURE_CLIENT_ID"]
21
+ client_secret = os.environ["AZURE_CLIENT_SECRET"]
22
+ except KeyError:
23
+ # Azure environment is not set, use init.yaml
24
+ client_id = app.config["azureCloudClientId"]
25
+ client_secret = app.config["azureCloudSecret"]
26
+ azure_tenant_id = app.config["azureCloudTenantId"]
27
+ authority = f"https://login.microsoftonline.com/{azure_tenant_id}"
28
+ client = msal.ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)
29
+ token_result = client.acquire_token_for_client(scopes=scope)
30
+ token = token_result["access_token"]
31
+
32
+ return token
@@ -0,0 +1,488 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """RegScale Azure InTune Integration"""
4
+ import json
5
+ import logging
6
+ import re
7
+ from datetime import datetime, timedelta
8
+ from time import sleep
9
+ from typing import Iterator, Optional
10
+
11
+ import click
12
+ import requests
13
+ import rich.progress
14
+
15
+ from regscale.core.app.api import Api
16
+ from regscale.core.app.application import Application
17
+ from regscale.core.app.utils.api_handler import APIHandler
18
+ from regscale.core.app.utils.app_utils import create_progress_object, error_and_exit
19
+ from regscale.core.app.utils.regscale_utils import verify_provided_module
20
+ from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding
21
+ from regscale.models import Asset, Sbom, regscale_id, regscale_models, regscale_module
22
+ from regscale.models.integration_models.sbom.cyclone_dx import CycloneDXJsonGenerator
23
+ from regscale.validation.record import validate_regscale_object
24
+
25
+
26
+ @click.group()
27
+ def intune():
28
+ """Microsoft Azure InTune Integrations"""
29
+
30
+
31
+ @intune.command(name="sync_intune")
32
+ @regscale_id()
33
+ @regscale_module()
34
+ def sync_intune(regscale_id: int, regscale_module: str):
35
+ """Sync Intune Alerts with RegScale Assets."""
36
+
37
+ from regscale.integrations.commercial.azure.scanner import IntuneIntegration
38
+
39
+ verify_provided_module(regscale_module)
40
+ try:
41
+ assert validate_regscale_object(parent_id=regscale_id, parent_module=regscale_module)
42
+ except AssertionError:
43
+ error_and_exit(
44
+ "This RegScale object does not exist. Please check your RegScale Parent ID \
45
+ and Module."
46
+ )
47
+ access_token = get_access_token(config=Application().config)
48
+ api = Api()
49
+
50
+ with create_progress_object() as device_progress:
51
+ device_task = device_progress.add_task("[#f68d1f]Fetching Device List...", total=1)
52
+ software_task = device_progress.add_task("[#1f96f6]Updating Software List...")
53
+ devices = get_device_list(api=api, access_token=access_token, device_progress=device_progress, task=device_task)
54
+ device_progress.update(task_id=software_task, total=len(devices))
55
+ for dev in devices:
56
+ full_data = get_device_data_by_device(api=api, access_token=access_token, device_id=dev.get("id"))
57
+ detected_apps = full_data.get("detectedApps")
58
+ if detected_apps:
59
+ dev["detectedApps"] = detected_apps
60
+ device_progress.update(task_id=software_task, advance=1)
61
+
62
+ if devices:
63
+ in_scan = IntuneIntegration(plan_id=regscale_id)
64
+ in_scan.sync_assets(
65
+ plan_id=regscale_id,
66
+ asset_num=len(devices),
67
+ integration_assets=fetch_intune_assets(
68
+ regscale_parent_id=regscale_id,
69
+ regscale_module=regscale_module,
70
+ devices=devices,
71
+ access_token=access_token,
72
+ ),
73
+ )
74
+ in_scan.sync_findings(
75
+ plan_id=regscale_id,
76
+ integration_findings=fetch_intune_findings(devices=devices),
77
+ )
78
+ else:
79
+ click.echo("No devices found.")
80
+
81
+ update_sbom(devices=devices, parent_id=regscale_id, parent_module=regscale_module)
82
+
83
+
84
+ def check_if_phone(device: dict) -> Optional[str]:
85
+ """
86
+ Check if the device is a phone or tablet
87
+
88
+ :param dict device: The device dictionary
89
+ :return: The device type
90
+ :rtype: Optional[str]
91
+ """
92
+
93
+ if "iphone" in device["operatingSystem"].lower():
94
+ return "Phone"
95
+ if "android" in device["operatingSystem"].lower():
96
+ return "Phone"
97
+ if "ipad" in device["operatingSystem"].lower():
98
+ return "Tablet"
99
+ return None
100
+
101
+
102
+ def determine_asset_type(device: dict) -> str:
103
+ """
104
+ Determine the asset type
105
+
106
+ :param dict device: The device dictionary
107
+ :return: The asset type
108
+ :rtype: str
109
+ """
110
+ asset_type = check_if_phone(device)
111
+ if not asset_type:
112
+ if device.get("operatingSystem", "").lower() in ["macmdm", "windows", "linux", "macOS"]:
113
+ if device.get("model") and "vm" in device.get("model", "").lower():
114
+ asset_type = "Virtual Machine"
115
+ else:
116
+ asset_type = "Laptop"
117
+ else:
118
+ asset_type = "Virtual Machine"
119
+ return asset_type
120
+
121
+
122
+ def fetch_intune_assets(
123
+ regscale_parent_id: int,
124
+ regscale_module: str,
125
+ devices: list[dict],
126
+ access_token: str,
127
+ ) -> Iterator[IntegrationAsset]:
128
+ """
129
+ Fetch InTune Assets
130
+
131
+ :param int regscale_parent_id: RegScale Parent ID
132
+ :param str regscale_module: RegScale Module
133
+ :param list[dict] devices: The list of devices
134
+ :param str access_token: The access token
135
+ :yields: IntegrationAsset
136
+ :rtype: Iterator[IntegrationAsset]
137
+ """
138
+ api = Api()
139
+ logger = logging.getLogger("regscale")
140
+ config = api.config
141
+
142
+ context = {
143
+ "regscale_parent_id": regscale_parent_id,
144
+ "regscale_module": regscale_module,
145
+ "api": api,
146
+ "access_token": access_token,
147
+ "config": config,
148
+ "logger": logger,
149
+ }
150
+
151
+ for device in devices:
152
+ try:
153
+ asset = create_asset(device=device, context=context)
154
+ if asset:
155
+ yield asset
156
+ except Exception as e:
157
+ logger.error(f"Error creating asset for device {device.get('deviceName')}: {e}")
158
+
159
+
160
+ def fetch_intune_findings(devices: list[dict]) -> Iterator[IntegrationFinding]:
161
+ """
162
+ Fetch InTune Assets
163
+
164
+ :param list[dict] devices: The list of devices
165
+ :yields: IntegrationAsset
166
+ :rtype: Iterator[IntegrationFinding]
167
+ """
168
+ logger = logging.getLogger("regscale")
169
+
170
+ for device in devices:
171
+ try:
172
+ if asset := create_finding(device=device):
173
+ yield asset
174
+ except Exception as e:
175
+ logger.error(f"Error creating asset for device {device.get('deviceName')}: {e}")
176
+
177
+
178
+ def create_finding(device: dict) -> Optional[IntegrationFinding]:
179
+ """
180
+ Create an asset from the device dictionary
181
+
182
+ :param dict device: The device dictionary
183
+ :return: The finding
184
+ :rtype: Optional[IntegrationFinding]
185
+ """
186
+
187
+ compliance = device.get("complianceState") == "compliant"
188
+ if not compliance:
189
+ # Create a finding
190
+ control_labels = []
191
+ title = ""
192
+ category = ""
193
+ plugin_name = "Intune compliance"
194
+ severity = regscale_models.IssueSeverity.High
195
+ description = "Intune Compliance Failure"
196
+ status = regscale_models.IssueStatus.Open
197
+ asset_id = device.get("azureADDeviceId")
198
+ return IntegrationFinding(
199
+ control_labels=control_labels,
200
+ title=title,
201
+ category=category,
202
+ plugin_name=plugin_name,
203
+ severity=severity,
204
+ description=description,
205
+ status=status,
206
+ asset_identifier=asset_id,
207
+ )
208
+ return None
209
+
210
+
211
+ def create_asset(device: dict, context: dict) -> Optional[IntegrationAsset]:
212
+ """
213
+ Create an asset from the device dictionary
214
+
215
+ :param dict device: The device dictionary
216
+ :param dict context: The context dictionary containing regscale_parent_id, regscale_module, config, and logger
217
+ :return: The asset
218
+ :rtype: Optional[IntegrationAsset]
219
+ """
220
+ regscale_parent_id = context["regscale_parent_id"]
221
+ regscale_module = context["regscale_module"]
222
+ config = context["config"]
223
+ logger = context["logger"]
224
+
225
+ software_list = [
226
+ {"name": app.get("displayName"), "version": app.get("version")} for app in device.get("detectedApps", [])
227
+ ]
228
+
229
+ compliance = device.get("complianceState") == "compliant"
230
+ if device.get("lastSyncDateTime"):
231
+ last_sign_in = datetime.strptime(device["lastSyncDateTime"], "%Y-%m-%dT%H:%M:%SZ")
232
+ status = "Active (On-Network)" if determine_if_recent(last_sign_in) or compliance else "Off-Network"
233
+ else:
234
+ status = "Off-Network"
235
+ asset_type = determine_asset_type(device)
236
+ ips = device.get("hardwareInformation", {}).get("wiredIPv4Addresses", [])
237
+
238
+ try:
239
+ return IntegrationAsset(
240
+ name=device.get("deviceName"),
241
+ other_tracking_number=device.get("azureADDeviceId"),
242
+ azure_identifier=device.get("azureADDeviceId"),
243
+ identifier=device.get("azureADDeviceId"),
244
+ parent_id=regscale_parent_id,
245
+ parent_module=regscale_module,
246
+ manufacturer=device.get("manufacturer"),
247
+ model=device["model"],
248
+ operating_system=device.get("operatingSystem"),
249
+ asset_owner_id=config["userId"],
250
+ asset_type=asset_type if asset_type else "Other",
251
+ asset_category=regscale_models.AssetCategory.Hardware,
252
+ status=status,
253
+ notes=f"<p>isCompliant: <strong>{compliance}</strong><br>isEncrypted: "
254
+ + f"<strong>{device['isEncrypted']}</strong><br>isRooted: <strong>"
255
+ + f"{device['jailBroken']}</strong><br>lastSyncDateTime: <strong>"
256
+ + f"{device['lastSyncDateTime']}</strong>",
257
+ mac_address=convert_str_to_mac(device.get("wiFiMacAddress") or device.get("ethernetMacAddress")),
258
+ serial_number=device.get("serialNumber") or device.get("hardwareInformation", {}).get("serialNumber"),
259
+ os_version=device.get("osVersion"),
260
+ software_inventory=software_list,
261
+ ip_address=", ".join(ips),
262
+ )
263
+ except KeyError as e:
264
+ logger.error(f"Error creating asset: {e}")
265
+ return None
266
+
267
+
268
+ def get_access_token(config: dict) -> str:
269
+ """
270
+ Authenticate and return an access token.
271
+
272
+ :param dict config: The configuration dictionary
273
+ :return: The access token
274
+ :rtype: str
275
+ """
276
+ import msal
277
+
278
+ authority = f"https://login.microsoftonline.com/{config.get('azureCloudTenantId')}"
279
+ scope = ["https://graph.microsoft.com/.default"]
280
+
281
+ app = msal.ConfidentialClientApplication(
282
+ client_id=config.get("azureCloudClientId"),
283
+ client_credential=config.get("azureCloudSecret"),
284
+ authority=authority,
285
+ )
286
+ result = app.acquire_token_for_client(scopes=scope)
287
+
288
+ if "access_token" in result:
289
+ return result["access_token"]
290
+
291
+ error_and_exit(f"Error acquiring token: {result.get('error')}")
292
+
293
+
294
+ def get_device_list(
295
+ api: Api, access_token: str, device_progress: rich.progress.Progress, task: rich.progress.TaskID
296
+ ) -> list[dict]:
297
+ """
298
+ Retrieve device data from Microsoft Intune.
299
+
300
+ :param Api api: The API object
301
+ :param str access_token: The access token
302
+ :param rich.progress.Progress job_progress: The job progress object
303
+ :param rich.progress.TaskID task: The task ID
304
+ :return: The device data
305
+ :rtype: list[dict]
306
+ """
307
+ url = "https://graph.microsoft.com/beta/deviceManagement/managedDevices?$expand=detectedApps"
308
+ headers = {"Authorization": f"Bearer {access_token}"}
309
+ devices = []
310
+
311
+ # Pagination to retrieve all devices
312
+ while url:
313
+ response = backoff_retry(api=api, url=url, headers=headers)
314
+ count = response.json().get("@odata.count")
315
+ if count:
316
+ device_progress.update(task_id=task, total=count)
317
+ if response.status_code == 200:
318
+ data = response.json()
319
+ devices.extend(data["value"])
320
+ device_progress.update(task_id=task, advance=len(response.json().get("value", [])))
321
+ url = data.get("@odata.nextLink") # Check for pagination
322
+ else:
323
+ error_and_exit(f"Error retrieving device data: {response.status_code}\n{response.text}")
324
+
325
+ return devices
326
+
327
+
328
+ def get_device_data_by_device(api: Api, access_token: str, device_id: str) -> dict:
329
+ """
330
+ Retrieve device data from Microsoft Intune.
331
+
332
+ :param Api api: The API object
333
+ :param str access_token: The access token
334
+ :param str device_id: The device ID
335
+ :return: The device data
336
+ :rtype: dict
337
+ """
338
+ url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{device_id}?$expand=detectedApps"
339
+ headers = {"Authorization": f"Bearer {access_token}"}
340
+
341
+ # Pagination to retrieve all devices
342
+ response = backoff_retry(api=api, url=url, headers=headers)
343
+ data = {}
344
+ if response.status_code == 200:
345
+ data = response.json()
346
+ else:
347
+ error_and_exit(f"Error retrieving device data: {response.status_code}\n{response.text}")
348
+ return data
349
+
350
+
351
+ def update_sbom_for_device(args: tuple):
352
+ """
353
+ Update the SBOM for a device
354
+
355
+ :args: tuple containing the asset ID, device dictionary, progress object, and task ID
356
+ :rtype: None
357
+ :return: None
358
+ """
359
+ regscale_version, fix_version, asset_id, device, progress_object, progress_task, logger = args
360
+ components = []
361
+ generator = CycloneDXJsonGenerator(device=device, logger=logger)
362
+ for app in device.get("detectedApps", []):
363
+ display_name = app.get("displayName")
364
+ version = app.get("version") or "Unknown"
365
+ app_type = "application"
366
+ if display_name:
367
+ component = {
368
+ "type": app_type,
369
+ "name": display_name,
370
+ "version": version,
371
+ }
372
+ components.append(component)
373
+ sbom = Sbom(
374
+ tool=device.get("deviceName"),
375
+ parentId=asset_id,
376
+ parentModule="assets",
377
+ name=device.get("deviceName"),
378
+ standardVersion=device.get("osVersion"),
379
+ results=json.dumps(generator.generate_sbom(components=components)),
380
+ sbomStandard="CycloneDX",
381
+ )
382
+ if regscale_version >= fix_version:
383
+ sbom.create_or_update()
384
+ else:
385
+ # Create if not exist
386
+ sbom.get_or_create()
387
+
388
+ # sbom.create_or_update()
389
+ progress_object.update(task_id=progress_task, advance=len(device.get("detectedApps", [])))
390
+
391
+
392
+ def update_sbom(devices: list[dict], parent_id: int, parent_module: str):
393
+ """
394
+ Update the SBOM for devices
395
+
396
+ :param list[dict] devices: The list of devices
397
+ :param int parent_id: The parent ID
398
+ :param str parent_module: The parent module
399
+ :rtype: None
400
+ :return: None
401
+ """
402
+ app = Application()
403
+ existing_assets = Asset.get_all_by_parent(parent_id=parent_id, parent_module=parent_module)
404
+ regscale_version = APIHandler().regscale_version
405
+ fix_version = "6.9.0.4"
406
+ if not re.match(r"^\d+\.\d+(\.\d+){0,2}$", regscale_version) or regscale_version < fix_version:
407
+ app.logger.warning(
408
+ "SBOM functionality is limited and unable to update SBOM, please update to the latest "
409
+ "RegScale version to resolve."
410
+ )
411
+ return
412
+
413
+ with create_progress_object() as sbom_progress:
414
+ total_applications = sum(len(device.get("detectedApps", [])) for device in devices)
415
+ sbom_task = sbom_progress.add_task("[#00ff00]Updating SBOM(s) in RegScale...", total=total_applications)
416
+ for device in devices:
417
+ matching_asset: Optional[Asset] = next(
418
+ (asset for asset in existing_assets if asset.azureIdentifier == device.get("azureADDeviceId")), None
419
+ )
420
+ if matching_asset:
421
+ app.thread_manager.submit_task(
422
+ func=update_sbom_for_device,
423
+ args=(
424
+ regscale_version,
425
+ fix_version,
426
+ matching_asset.id,
427
+ device,
428
+ sbom_progress,
429
+ sbom_task,
430
+ app.logger,
431
+ ),
432
+ )
433
+ _ = app.thread_manager.execute_and_verify()
434
+
435
+
436
+ def determine_if_recent(date: datetime, days: int = 7) -> bool:
437
+ """
438
+ Determine if a date is recent
439
+
440
+ :param datetime date: The date to check
441
+ :param int days: The number of days to consider recent
442
+ :return: True if the date is recent, False otherwise
443
+ :rtype: bool
444
+ """
445
+ # Using three days ago as the threshold
446
+ days_ago = datetime.now() - timedelta(days=days)
447
+ return date >= days_ago
448
+
449
+
450
+ def convert_str_to_mac(mac: str):
451
+ """
452
+ Convert a string to a MAC address
453
+
454
+ :param str mac: The MAC address string
455
+ :return: The MAC address
456
+ :rtype: str
457
+ """
458
+ if mac:
459
+ mac = mac.replace(":", "").replace("-", "").replace(".", "").replace(" ", "").upper()
460
+ return ":".join(mac[i : i + 2] for i in range(0, 12, 2))
461
+ return None
462
+
463
+
464
+ def backoff_retry(api: Api, url: str, headers: dict, max_retries: int = 5, backoff_factor: int = 2):
465
+ """
466
+ Perform a GET request with exponential backoff retry on HTTP 429.
467
+
468
+ :param Api api: The API object
469
+ :param str url: The URL to request
470
+ :param dict headers: The request headers
471
+ :param int max_retries: The maximum number of retries
472
+ :param int backoff_factor: The backoff factor (multiplier for the delay)
473
+ :return: The response object
474
+ :rtype: requests.Response
475
+ """
476
+ retries = 0
477
+ response = requests.Response()
478
+ while retries < max_retries:
479
+ response = api.get(url, headers=headers)
480
+ if response.status_code == 429:
481
+ retries += 1
482
+ sleep_time = backoff_factor**retries
483
+ print(f"Rate limited. Retrying in {sleep_time} seconds...")
484
+ sleep(sleep_time)
485
+ else:
486
+ return response
487
+ response.raise_for_status()
488
+ return response
@@ -0,0 +1,49 @@
1
+ """
2
+ Intune Integration
3
+ """
4
+
5
+ import logging
6
+ from typing import Any, Dict, Iterator
7
+
8
+ from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding, ScannerIntegration
9
+ from regscale.models import regscale_models
10
+
11
+ logger = logging.getLogger("regscale")
12
+
13
+
14
+ class IntuneIntegration(ScannerIntegration):
15
+ """Integration class for Intune Device Manager."""
16
+
17
+ title: str = "Intune"
18
+ asset_identifier_field: str = "azureIdentifier"
19
+ finding_severity_map: Dict[str, regscale_models.IssueSeverity] = {
20
+ "critical": regscale_models.IssueSeverity.Critical,
21
+ "high": regscale_models.IssueSeverity.High,
22
+ "medium": regscale_models.IssueSeverity.Moderate,
23
+ "low": regscale_models.IssueSeverity.Low,
24
+ }
25
+
26
+ def fetch_assets(self, *args: Any, **kwargs: Any) -> Iterator[IntegrationAsset]:
27
+ """
28
+ Fetches assets from Intune integration
29
+
30
+ :param Tuple args: Additional arguments
31
+ :param dict kwargs: Additional keyword arguments
32
+ :yields: Iterator[IntegrationAsset]
33
+ """
34
+ if asset_num := kwargs.get("asset_num"):
35
+ self.num_assets_to_process = asset_num
36
+ integration_assets = kwargs.get("integration_assets")
37
+ yield from integration_assets
38
+
39
+ def fetch_findings(self, *args: Any, **kwargs: dict) -> Iterator[IntegrationFinding]:
40
+ """
41
+ Fetches findings from the Intune integration
42
+
43
+ :param Tuple args: Additional arguments
44
+ :param dict kwargs: Additional keyword arguments
45
+ :yields: Iterator[IntegrationFinding]
46
+
47
+ """
48
+ integration_findings = kwargs.get("integration_findings")
49
+ yield from integration_findings
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Burp Scanner RegScale integration"""
4
+ from pathlib import Path
5
+
6
+ import click
7
+
8
+ from regscale.core.app.application import Application
9
+ from regscale.core.app.logz import create_logger
10
+ from regscale.models.integration_models.burp import Burp
11
+ from regscale.models.integration_models.flat_file_importer import FlatFileIntegration
12
+
13
+ logger = create_logger(__name__)
14
+
15
+
16
+ # Create group to handle Burp .xml file processing
17
+ @click.group()
18
+ def burp():
19
+ """Performs actions on Burp Scanner artifacts."""
20
+
21
+
22
+ @burp.command(name="import_burp")
23
+ @click.option(
24
+ "--folder_path",
25
+ help="File path to the folder containing Burp files to process to RegScale.",
26
+ prompt="File path for Burp files",
27
+ type=click.Path(exists=True, dir_okay=True, resolve_path=True),
28
+ )
29
+ @click.option(
30
+ "--regscale_ssp_id",
31
+ type=click.INT,
32
+ help="The ID number from RegScale of the System Security Plan.",
33
+ prompt="Enter RegScale System Security Plan ID",
34
+ required=True,
35
+ )
36
+ @click.option(
37
+ "--scan_date",
38
+ type=click.DateTime(formats=["%Y-%m-%d"]),
39
+ help="The the scan date of the file.",
40
+ required=False,
41
+ )
42
+ @click.option(
43
+ "--upload_file",
44
+ "--upload",
45
+ type=click.BOOL,
46
+ help="Whether to upload the file to RegScale after processing. Default is True.",
47
+ default=True,
48
+ required=False,
49
+ )
50
+ def import_burp(
51
+ folder_path: click.Path, regscale_ssp_id: click.INT, scan_date: click.DateTime, upload_file: click.BOOL
52
+ ):
53
+ """
54
+ Import Burp scans, vulnerabilities and assets to RegScale from burp files
55
+
56
+ """
57
+ app = Application()
58
+ if len(list(Path(folder_path).glob("*.xml"))) == 0:
59
+ logger.warning("No Burp files found in the specified folder.")
60
+ return
61
+ for file in Path(folder_path).glob("*.xml"):
62
+ burp = Burp(app, file, parentId=regscale_ssp_id, parentModule="securityplans")
63
+ flat_int = FlatFileIntegration(plan_id=regscale_ssp_id)
64
+ flat_int.num_findings_to_process = burp.num_findings
65
+ flat_int.num_assets_to_process = burp.num_assets
66
+ flat_int.sync_assets(
67
+ plan_id=regscale_ssp_id,
68
+ integration_assets=burp.integration_assets,
69
+ title="Burp Suite",
70
+ )
71
+ flat_int.sync_findings(
72
+ plan_id=regscale_ssp_id,
73
+ integration_findings=burp.integration_findings,
74
+ title="Burp Suite",
75
+ enable_finding_date_update=True,
76
+ scan_date=scan_date,
77
+ )
78
+ burp.move_files(upload_file=upload_file)