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,697 @@
1
+ #!/usr/bin/python
2
+ """Script to parse a .xlsx file and load the inventory into RegScale as assets"""
3
+
4
+ import os
5
+ from typing import Optional
6
+ from urllib.parse import urljoin
7
+
8
+ import click
9
+ from openpyxl import load_workbook
10
+ from openpyxl.worksheet.worksheet import Worksheet
11
+ from rich.progress import track
12
+
13
+ from regscale.core.app.logz import create_logger
14
+ from regscale.models import (
15
+ SecurityPlan,
16
+ Catalog,
17
+ ControlImplementation,
18
+ ControlImplementationStatus,
19
+ CustomField,
20
+ CustomFieldsData,
21
+ )
22
+
23
+ NOT_APPLICABLE = "Not Applicable"
24
+ logger = create_logger()
25
+
26
+
27
+ class ControlImportMeta:
28
+ def __init__(self, control_id: str, import_row: int):
29
+ self.control_id = control_id
30
+ self.import_row = import_row
31
+ self.implementation_id = 0
32
+ self.parent_id = 0
33
+
34
+
35
+ def import_emass_slcm_file(file_name: click.Path, regscale_id: int, catalogue_id: int, tenant_id: int) -> None:
36
+ """
37
+ This function imports a SLCM export created by an eMASS system.
38
+
39
+ :param click.Path file_name:
40
+ :param int regscale_id:
41
+ :param int catalogue_id:
42
+ :param int tenant_id:
43
+ :return None:
44
+ :rtype None:
45
+ """
46
+ if not verify_sp_id(regscale_id):
47
+ return logger.error("Not a valid Security Plan ID. Aborting!")
48
+ if not verify_cat_id(catalogue_id):
49
+ return logger.error("Not a valid Catalog ID. Aborting!")
50
+ if not os.path.isfile(file_name):
51
+ return logger.error("No file name/path provided to import. Aborting!")
52
+ custom_fields = check_for_custom_fields(tenant_id)
53
+ wb_obj = load_workbook(file_name)
54
+ ws = wb_obj.active
55
+ control_list = build_list_of_controls(ws)
56
+ control_list = get_or_initialize_control_implementation(control_list, regscale_id, catalogue_id)
57
+ identify_controls_to_remove(control_list, regscale_id)
58
+ for cur_control_index in track(
59
+ range(len(control_list)), description="Loading SLCM Control Implementations updates..."
60
+ ):
61
+ cur_control = control_list[cur_control_index]
62
+ process_row(ws, cur_control, regscale_id, custom_fields)
63
+
64
+
65
+ def build_list_of_controls(ws: Worksheet) -> list:
66
+ """
67
+ Builds a list of controls to import, so any missing can be created.
68
+
69
+ :param Worksheet ws:
70
+ :return list:
71
+ :rtype list:
72
+ """
73
+ control_list = []
74
+ row = 7
75
+ control_id = ws.cell(row=row, column=1).value
76
+ while control_id is not None:
77
+ control_list.append(ControlImportMeta(control_id, row))
78
+ row += 1
79
+ control_id = ws.cell(row=row, column=1).value
80
+ return control_list
81
+
82
+
83
+ def identify_controls_to_remove(control_list: list, regscale_id: int) -> None:
84
+ """
85
+ Identifies controls that are in the security plan but not in the import, and designate them for deletion.
86
+
87
+ :param list control_list:
88
+ :param int regscale_id:
89
+ :return None:
90
+ :rtype None:
91
+ """
92
+ current_implementations = get_all_current_control_implementation(regscale_id)
93
+ if current_implementations is not None:
94
+ for cur_control_index in track(
95
+ range(len(current_implementations)), description="Identifying SLCM Control Implementations to remove..."
96
+ ):
97
+ cur_implementation = current_implementations[cur_control_index]
98
+ verify_control_implementation_to_remove(cur_implementation, control_list)
99
+
100
+
101
+ def verify_control_implementation_to_remove(control: dict, control_list: list) -> None:
102
+ """
103
+ Verifies whether a control implementation is in the import, and if not, deletes it from the SP.
104
+
105
+ :param dict control:
106
+ :param list control_list:
107
+ :return None:
108
+ :rtype None:
109
+ """
110
+ control_id = control["controlName"]
111
+ if find_control_in_metadata_list(control_list, control_id) is None:
112
+ remove_control_implementation(control)
113
+
114
+
115
+ def remove_control_implementation(control: dict) -> None:
116
+ """
117
+ Deletes the control implementation from the security plan.
118
+
119
+ :param dict control:
120
+ :return None:
121
+ :rtype None:
122
+ """
123
+ from regscale.core.app.api import Api
124
+
125
+ api = Api()
126
+ control_id = control["id"]
127
+ conmon_url = urljoin(api.config["domain"], f"/api/controlImplementation/{control_id}")
128
+ conmon_response = api.delete(conmon_url)
129
+ if not conmon_response.ok:
130
+ logger.warning("Unable to delete control implementation %s", control_id)
131
+
132
+
133
+ def get_or_initialize_control_implementation(control_list: list, regscale_id: int, catalogue_id: int) -> list:
134
+ """
135
+ Retrieves all control implementations associated with the security plan.
136
+
137
+ :param list control_list:
138
+ :param int regscale_id:
139
+ :param int catalogue_id:
140
+ :return list:
141
+ :rtype list:
142
+ """
143
+ current_implementations = get_all_current_control_implementation(regscale_id)
144
+ if current_implementations is not None:
145
+ control_list = match_control_rows(control_list, current_implementations)
146
+ return create_control_implementations(control_list, regscale_id, catalogue_id)
147
+
148
+
149
+ def get_all_current_control_implementation(regscale_id: int) -> Optional[list]:
150
+ """
151
+ Retrieves the current set of control implementations associated with the security plan.
152
+
153
+ :param int regscale_id:
154
+ :return list:
155
+ :rtype list:
156
+ """
157
+ from regscale.core.app.api import Api
158
+
159
+ api = Api()
160
+ # Using the REST API as the Security Control name is dropped by the model
161
+ conmon_url = urljoin(api.config["domain"], f"/api/controlImplementation/getAllByPlan/{regscale_id}")
162
+ conmon_response = api.get(conmon_url)
163
+ if conmon_response.ok:
164
+ try:
165
+ cil_json = conmon_response.json()
166
+ if len(cil_json) > 0:
167
+ return cil_json
168
+ except Exception:
169
+ return None
170
+ return None
171
+
172
+
173
+ def create_control_implementations(control_list: list, regscale_id: int, catalogue_id: int) -> list:
174
+ """
175
+ Retrieves all security controls associated with the catalog.
176
+
177
+ :param list control_list:
178
+ :param int regscale_id:
179
+ :param int catalogue_id:
180
+ :return list:
181
+ :rtype list:
182
+ """
183
+ from regscale.core.app.api import Api
184
+
185
+ api = Api()
186
+ conmon_url = urljoin(api.config["domain"], f"/api/SecurityControls/getList/{catalogue_id}")
187
+ conmon_response = api.get(conmon_url)
188
+ if conmon_response.ok:
189
+ try:
190
+ scl_json = conmon_response.json()
191
+ if len(scl_json) > 0:
192
+ control_list = match_control_parent_rows(control_list, scl_json, regscale_id)
193
+ except Exception:
194
+ return control_list
195
+ return control_list
196
+
197
+
198
+ def match_control_parent_rows(control_list: list, sec_control_list: list, regscale_id: int) -> list:
199
+ """
200
+ Matches the control IDs from the SLCM import and the list of controls associated with the security plan.
201
+
202
+ :param list control_list:
203
+ :param list sec_control_list:
204
+ :param int regscale_id:
205
+ :param int catalogue_id:
206
+ :return list:
207
+ :rtype list:
208
+ """
209
+ rtn_list = []
210
+ for cur_control_index in track(range(len(control_list)), description="Creating missing control implementations..."):
211
+ cur_meta = control_list[cur_control_index]
212
+ if cur_meta.implementation_id == 0:
213
+ sec_ctl = find_control_in_list(sec_control_list, cur_meta.control_id, "controlId")
214
+ if sec_ctl is not None:
215
+ cur_meta.parent_id = sec_ctl["id"]
216
+ cur_meta.implementation_id = create_control_implementation(sec_ctl, regscale_id)
217
+ rtn_list.append(cur_meta)
218
+ return rtn_list
219
+
220
+
221
+ def create_control_implementation(sec_control: dict, regscale_id: int) -> int:
222
+ """
223
+ Creates a control implementation that is in the import but currently doesn't exist in the security plan.
224
+
225
+ :param sec_control:
226
+ :param regscale_id:
227
+ :return:
228
+ """
229
+ from regscale.core.app.api import Api
230
+
231
+ config = Api().config
232
+ updated_control_imp = sec_control
233
+ ctrl_imp = ControlImplementation.create_new_control_implementation(
234
+ sec_control, regscale_id, "securityplans", ControlImplementationStatus.NotImplemented, config["userId"]
235
+ )
236
+ try:
237
+ if isinstance(ctrl_imp, dict):
238
+ updated_control_imp = ctrl_imp
239
+ return save_new_control_implementation(updated_control_imp)
240
+ except Exception as ex:
241
+ logger.error(f"Unable to save new control implementation - {ex}")
242
+ return 0
243
+
244
+
245
+ def save_new_control_implementation(control_imp: dict) -> int:
246
+ """
247
+ Saves a new control implementation
248
+
249
+ :param dict control_imp:
250
+ :return int:
251
+ :rtype int:
252
+ """
253
+ from regscale.core.app.api import Api
254
+
255
+ api = Api()
256
+ # Using the REST API as the model throws errors when some non-required data elements aren't populated
257
+ conmon_url = urljoin(api.config["domain"], "/api/controlImplementation/")
258
+ conmon_response = api.post(conmon_url, json=control_imp)
259
+ if conmon_response.ok:
260
+ scl_json = conmon_response.json()
261
+ return scl_json["id"]
262
+ else:
263
+ logger.error(conmon_response)
264
+ return 0
265
+
266
+
267
+ def check_for_custom_fields(tenant_id: int) -> list:
268
+ """
269
+ Retrieves the custom fields that some SLCM values are populated into.
270
+
271
+ :param int tenant_id:
272
+ :return list:
273
+ :rtype list:
274
+ """
275
+ from regscale.core.app.api import Api
276
+
277
+ api = Api()
278
+ cfl = CustomField.get_list_by_module_id(15)
279
+ if len(cfl) == 0:
280
+ conmon_url = urljoin(api.config["domain"], f"/api/customFields/module/{tenant_id}/15")
281
+ conmon_response = api.get(conmon_url)
282
+ if conmon_response.ok:
283
+ cfl_json = conmon_response.json()
284
+ return cfl_json
285
+ else:
286
+ logger.error(conmon_response)
287
+ return []
288
+ cfl_list = []
289
+ for cur_cfl in cfl:
290
+ cur_json = cur_cfl.dict()
291
+ cfl_list.append(cur_json)
292
+ return cfl_list
293
+
294
+
295
+ def match_control_rows(control_list: list, control_imp_list: list) -> list:
296
+ """
297
+ Matches the controls in the import with those that exist in the SP.
298
+
299
+ :param list control_list:
300
+ :param list control_imp_list:
301
+ :return list:
302
+ :rtype list:
303
+ """
304
+ rtn_list = []
305
+ for cur_meta in control_list:
306
+ ctl_imp = find_control_in_list(control_imp_list, cur_meta.control_id, "controlName")
307
+ if ctl_imp is not None:
308
+ cur_meta.implementation_id = ctl_imp["id"]
309
+ cur_meta.parent_id = ctl_imp["controlID"]
310
+ rtn_list.append(cur_meta)
311
+ return rtn_list
312
+
313
+
314
+ def find_control_in_list(control_imp_list: list, control_id: str, data_field: str) -> Optional[dict]:
315
+ """
316
+ Finds the control from the import in the list of existing controls
317
+
318
+ :param list control_imp_list:
319
+ :param str control_id:
320
+ :param str data_field:
321
+ :return dict:
322
+ :rtype dict:
323
+ """
324
+ for cur_imp in control_imp_list:
325
+ if cur_imp[data_field].upper() == control_id.upper():
326
+ return cur_imp
327
+ return None
328
+
329
+
330
+ def find_control_in_metadata_list(control_imp_list: list, control_id: str) -> Optional[dict]:
331
+ """
332
+ Finds the control from the import in the list of existing controls
333
+
334
+ :param list control_imp_list:
335
+ :param str control_id:
336
+ :param str data_field:
337
+ :return dict:
338
+ :rtype dict:
339
+ """
340
+ for cur_imp in control_imp_list:
341
+ if cur_imp.control_id.upper() == control_id.upper():
342
+ return cur_imp
343
+ return None
344
+
345
+
346
+ def process_row(ws: Worksheet, control: ControlImportMeta, regscale_id: int, custom_fields: list) -> None:
347
+ """
348
+ Processes the current row in the import.
349
+
350
+ :param Worksheet ws:
351
+ :param ControlImportMeta control:
352
+ :param int regscale_id:
353
+ :param list custom_fields:
354
+ :return None:
355
+ :rtype None:
356
+ """
357
+ control_imp = get_control_implementation(control.implementation_id)
358
+ if control_imp is None:
359
+ return
360
+ # Column B (2) - Control Title - Security Control (Parent Control) Title (should be from Catalog)
361
+ # Column C (3) - Control Information - Security Control Description (should be from Catalog)
362
+ # Column D (4) - Compliance Status - Last Assessment Result
363
+ status = ws.cell(row=control.import_row, column=4).value
364
+ control_imp.lastAssessmentResult = "Fail"
365
+ if status == "Compliant":
366
+ control_imp.lastAssessmentResult = "Pass"
367
+ if status == NOT_APPLICABLE:
368
+ control_imp.status = NOT_APPLICABLE
369
+ save_control_implementation_update(control_imp)
370
+ process_implementation(ws, control, control_imp, custom_fields)
371
+ process_slcm(ws, control, control_imp, custom_fields)
372
+ process_risk_assessment(ws, control, regscale_id, control_imp)
373
+
374
+
375
+ def save_control_implementation_update(control_imp: ControlImplementation) -> None:
376
+ """
377
+ Saves the current control implementation
378
+
379
+ :param ControlImplementation control_imp:
380
+ :return None:
381
+ :rtype None:
382
+ """
383
+ from regscale.core.app.api import Api
384
+
385
+ api = Api()
386
+ try:
387
+ control_imp.save(False)
388
+ except Exception:
389
+ control_imp_payload = control_imp.dict()
390
+ conmon_url = urljoin(api.config["domain"], f"/api/controlImplementation/{control_imp.id}")
391
+ conmon_response = api.put(conmon_url, json=control_imp_payload)
392
+ if conmon_response.ok:
393
+ scl_json = conmon_response.json()
394
+ if scl_json is None:
395
+ logger.error("Could not update")
396
+ else:
397
+ logger.error(conmon_response)
398
+
399
+
400
+ def get_control_implementation(control_id: int) -> ControlImplementation:
401
+ """
402
+ Retrieves the current control implementation
403
+
404
+ :param int control_id:
405
+ :return ControlImplementation:
406
+ :rtype ControlImplementation:
407
+ """
408
+ # Using the model throws errors about missing data elements
409
+ from regscale.core.app.api import Api
410
+
411
+ api = Api()
412
+ conmon_url = urljoin(api.config["domain"], f"/api/controlImplementation/{control_id}")
413
+ conmon_response = api.get(conmon_url)
414
+ if conmon_response.ok:
415
+ try:
416
+ ctl_imp_json = conmon_response.json()
417
+ return ControlImplementation(**ctl_imp_json)
418
+ except Exception:
419
+ return None
420
+ return None
421
+
422
+
423
+ def process_implementation(
424
+ ws: Worksheet, control: ControlImportMeta, control_imp: ControlImplementation, custom_fields: list
425
+ ) -> None:
426
+ """
427
+ Processes the implementation columns in the import.
428
+
429
+ :param Worksheet ws:
430
+ :param ControlImportMeta control:
431
+ :param ControlImplementation control_imp:
432
+ :param list custom_fields:
433
+ :return None:
434
+ :rtype None:
435
+ """
436
+ # Column E (5) - Implementation Status - Control and Compliance Status
437
+ control_imp.status = slcm_status(ws.cell(row=control.import_row, column=5).value)
438
+ # Column F (6) - Common Control Provider - Responsibility - Custom Field (Common Control Provider)
439
+ # control_imp.responsibility = slcm_responsibility(ws.cell(row=control.import_row, column=6).value)
440
+ set_custom_field_data(
441
+ custom_fields, control_imp.id, "Common Control Provider", ws.cell(row=control.import_row, column=6).value
442
+ )
443
+ # Column G (7) - Security Control Designation - Responsibility
444
+ control_imp.responsibility = slcm_scdesignation(
445
+ ws.cell(row=control.import_row, column=7).value, control_imp.responsibility
446
+ )
447
+ # Column H (8) - Test Method - Control Test Plans - Ignore - Should load the default tests and CCIs
448
+ # Column I (9) - N/A Justification - Exclusion Justification
449
+ control_imp.exclusionJustification = ws.cell(row=control.import_row, column=9).value
450
+ # Column J (10) - Estimated Completion Date - Planned Implementation Date
451
+ control_imp.plannedImplementationDate = ws.cell(row=control.import_row, column=10).value
452
+ # Column K (11) - Implementation Narrative - Steps to Implement
453
+ control_imp.stepsToImplement = ws.cell(row=control.import_row, column=11).value
454
+ # Column L (12) - Responsible Entities - Customer/Cloud Implementation
455
+ entities = ws.cell(row=control.import_row, column=12).value
456
+ if control_imp.responsibility == "Customer":
457
+ control_imp.customerImplementation = entities
458
+ elif control_imp.responsibility == "Provider":
459
+ control_imp.cloudImplementation = entities
460
+ else:
461
+ control_imp.customerImplementation = entities
462
+ control_imp.cloudImplementation = entities
463
+ # Column M (13) - Application Layer - Custom Field (Application Layer)
464
+ set_custom_field_data(
465
+ custom_fields, control_imp.id, "Application Layer", ws.cell(row=control.import_row, column=13).value
466
+ )
467
+ # Column N (14) - Database Layer - Custom Field (Database Layer)
468
+ set_custom_field_data(
469
+ custom_fields, control_imp.id, "Database Layer", ws.cell(row=control.import_row, column=14).value
470
+ )
471
+ # Column O (15) - Operating System Layer - Custom Field (Operating System Layer)
472
+ set_custom_field_data(
473
+ custom_fields, control_imp.id, "Operating System Layer", ws.cell(row=control.import_row, column=15).value
474
+ )
475
+ save_control_implementation_update(control_imp)
476
+
477
+
478
+ def set_custom_field_data(custom_fields: list, control_id: int, field_name: str, field_value: str) -> None:
479
+ """
480
+ Creates a custom field data object
481
+
482
+ :param list custom_fields:
483
+ :param int control_id:
484
+ :param str field_name:
485
+ :param str field_value:
486
+ :return None:
487
+ :rtype None:
488
+ """
489
+ from regscale.core.app.api import Api
490
+
491
+ api = Api()
492
+ if (field_value is None) or (len(field_value) == 0):
493
+ return
494
+ custom_field_rec = find_custom_field(custom_fields, field_name)
495
+ if custom_field_rec is None:
496
+ return
497
+ cfdata = CustomFieldsData()
498
+ cfdata.moduleId = custom_field_rec["moduleId"]
499
+ cfdata.fieldId = custom_field_rec["id"]
500
+ cfdata.fieldName = custom_field_rec["fieldName"]
501
+ cfdata.fieldDataType = custom_field_rec["fieldDataType"]
502
+ cfdata.fieldValue = field_value
503
+ cfdata.parentId = control_id
504
+ cfdata_payload = cfdata.dict()
505
+ conmon_url = urljoin(api.config["domain"], "/api/customFieldsData/")
506
+ conmon_response = api.post(conmon_url, json=cfdata_payload)
507
+ if not conmon_response.ok:
508
+ logger.error(conmon_response)
509
+
510
+
511
+ def find_custom_field(custom_fields: list, field_name: str) -> Optional[dict]:
512
+ """
513
+ Find the appropriate custom field in the list of existing custom fields
514
+
515
+ :param list custom_fields:
516
+ :param str field_name:
517
+ :return dict:
518
+ :rtype dict:
519
+ """
520
+ for cur_custom_field in custom_fields:
521
+ if cur_custom_field["fieldName"] == field_name:
522
+ return cur_custom_field
523
+ return None
524
+
525
+
526
+ def slcm_status(status: str) -> str:
527
+ """
528
+ Convert the status from the import to the appropriate RS value
529
+
530
+ :param str status:
531
+ :return str:
532
+ :rtype str:
533
+ """
534
+ if status == "Implemented":
535
+ return "Fully Implemented"
536
+ if (status == "Not Implemented") or (status == "Planned") or (status == "Inherited"):
537
+ return status
538
+ return NOT_APPLICABLE
539
+
540
+
541
+ def slcm_responsibility(responsibility: str) -> str:
542
+ """
543
+ Convert the responsibility from the import to the appropriate RS value
544
+
545
+ :param str responsibility:
546
+ :return str:
547
+ :rtype str:
548
+ """
549
+ if responsibility == "DoD":
550
+ return "Customer"
551
+ if responsibility == "Component":
552
+ return "Provider"
553
+ if responsibility == "Enclave":
554
+ return "Shared"
555
+
556
+
557
+ def slcm_scdesignation(scdesignation: str, responsibility: str) -> str:
558
+ """
559
+ Convert the SLCM designation from the import to the appropriate RS value
560
+
561
+ :param str scdesignation:
562
+ :param str responsibility:
563
+ :return str:
564
+ :rtype str:
565
+ """
566
+ if scdesignation == "Hybrid":
567
+ return "Hybrid"
568
+ return responsibility
569
+
570
+
571
+ def process_slcm(
572
+ ws: Worksheet, control: ControlImportMeta, control_imp: ControlImplementation, custom_fields: list
573
+ ) -> None:
574
+ """
575
+ Process the SLCM columns of the import
576
+
577
+ :param Worksheet ws:
578
+ :param ControlImportMeta control:
579
+ :param ControlImplementation control_imp:
580
+ :param list custom_fields:
581
+ :return None:
582
+ :rtype None:
583
+ """
584
+ # Column Q (17) - Criticality - Ignore - Leaving blank in the export
585
+ # Column R (18) - Frequency
586
+ control_imp.assessmentFrequency = slcm_frequency_calculation(ws.cell(row=control.import_row, column=18).value)
587
+ # Column S (19) - Method - Custom Field (Method)
588
+ set_custom_field_data(custom_fields, control_imp.id, "Method", ws.cell(row=control.import_row, column=19).value)
589
+ # Column T (20) - Reporting - Ignore - Statement built based on whether control has CCI's and ConMon
590
+ # Column U (21) - Tracking - Ignore - Statement built based on whether control has CCI's
591
+ # Column V (22) - SLCM Comments - Assessments
592
+ save_control_implementation_update(control_imp)
593
+
594
+
595
+ def slcm_frequency_calculation(frequency: str) -> int:
596
+ """
597
+ Convert the SLCM frequency to a RS frequency in days.
598
+
599
+ :param str frequency:
600
+ :return int:
601
+ :rtype int:
602
+ """
603
+ if frequency == "Every Three Years":
604
+ return 365 * 3
605
+ if frequency == "Every Two Years":
606
+ return 365 * 2
607
+ if frequency == "Annually":
608
+ return 365
609
+ if frequency == "Semi-annually":
610
+ return 163
611
+ if frequency == "Quarterly":
612
+ return 90
613
+ if frequency == "Monthly":
614
+ return 30
615
+ if frequency == "Weekly":
616
+ return 7
617
+ return 1
618
+
619
+
620
+ def process_risk_assessment(
621
+ ws: Worksheet, control: ControlImportMeta, regscale_id: int, control_imp: ControlImplementation
622
+ ) -> None:
623
+ """
624
+ Process the Risk Assessment columns of the import - These are calculated values in the export,
625
+ and thus are not included in the import (at this time).
626
+
627
+ :param Worksheet ws:
628
+ :param ControlImportMeta control:
629
+ :param int regscale_id:
630
+ :param ControlImplementation control_imp:
631
+ :return None:
632
+ :rtype None:
633
+ """
634
+ # This whole section goes to Mitigations and Risks - Ignore - These don't have the key information needed to create
635
+ # Column X (24) - Severity - Risk - Consequence
636
+ # Column Y (25) - Relevance of Threat - Risk - Probability
637
+ # Column Z (26) - Likelihood - Calculated from Consequence and Probability - Leave for now
638
+ # Column AA (27) - Impact - Risk - Spread across all Risk fields
639
+ # Column AB (28) - Residual Risk Level - Calculated - Leave for now
640
+ # Column AC (29) - Vulnerability Summary - Risk - RiskStatement
641
+ # Column AD (30) - Mitigations - Risk - Mitigation
642
+ # Column AE (31) - Impact Description - Risk - ImpactDescription
643
+ # Column AF (32) - Recommendations - RiskTreatments (tied to Risk.id)
644
+ if (ws is None) or (control is None) or (regscale_id <= 0) or (control_imp is None):
645
+ logger.warning("Processing Risk Assessment - No data to import")
646
+
647
+
648
+ def verify_sp_id(regscale_id: int) -> bool:
649
+ """
650
+ Verify the provided SP ID is valid
651
+
652
+ :param int regscale_id:
653
+ :return bool:
654
+ :rtype bool:
655
+ """
656
+ from regscale.core.app.api import Api
657
+
658
+ api = Api()
659
+ sp = SecurityPlan.get_object(regscale_id)
660
+ if sp is None:
661
+ logger.warning("Model didn't return any security plan, trying again with the REST API")
662
+ conmon_url = urljoin(api.config["domain"], f"/api/securityplans/{regscale_id}")
663
+ conmon_response = api.get(conmon_url)
664
+ if conmon_response.ok:
665
+ try:
666
+ sec_plan = conmon_response.json()
667
+ if sec_plan is None:
668
+ return False
669
+ except Exception:
670
+ return False
671
+ return True
672
+
673
+
674
+ def verify_cat_id(catalogue_id: int) -> bool:
675
+ """
676
+ Verify the provided catalog ID is valid
677
+
678
+ :param int catalogue_id:
679
+ :return bool:
680
+ :rtype bool:
681
+ """
682
+ from regscale.core.app.api import Api
683
+
684
+ api = Api()
685
+ sp = Catalog.get_object(catalogue_id)
686
+ if sp is None:
687
+ logger.warning("Model didn't return any catalog, trying again with the REST API")
688
+ conmon_url = urljoin(api.config["domain"], f"/api/catalog/{catalogue_id}")
689
+ conmon_response = api.get(conmon_url)
690
+ if conmon_response.ok:
691
+ try:
692
+ sec_plan = conmon_response.json()
693
+ if sec_plan is None:
694
+ return False
695
+ except Exception:
696
+ return False
697
+ return True
File without changes