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,571 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Module to allow user to make changes to Control Implementations in an Excel spreadsheet for a user-friendly experience
5
+ """
6
+
7
+ import math
8
+ import os
9
+ import shutil
10
+ import sys
11
+ from typing import Union, Any, TYPE_CHECKING
12
+
13
+ import click
14
+ from pathlib import Path
15
+
16
+ if TYPE_CHECKING:
17
+ from regscale.core.app.api import Api
18
+
19
+
20
+ from openpyxl import Workbook, load_workbook
21
+ from openpyxl.styles import Alignment, PatternFill, Protection
22
+ from openpyxl.worksheet.datavalidation import DataValidation
23
+
24
+
25
+ from regscale.core.app.logz import create_logger
26
+ from regscale.core.app.utils.app_utils import (
27
+ check_empty_nan,
28
+ check_file_path,
29
+ error_and_exit,
30
+ get_current_datetime,
31
+ get_user_names,
32
+ )
33
+ from regscale.models.app_models.click import regscale_id, regscale_module
34
+ from regscale.models.regscale_models.control import Control
35
+ from regscale.models.regscale_models.control_implementation import ControlImplementation
36
+
37
+
38
+ ALL_IMPS = "all_implementations.xlsx"
39
+ OLD_IMPS = "old_implementations.xlsx"
40
+ DIFFS = "differences.txt"
41
+ ERROR_MSG = "Your entry is not one of the available options"
42
+ INVALID_MSG = "Invalid Entry"
43
+ PROMPT_MSG = "Please select from the list"
44
+
45
+
46
+ @click.group(name="control_editor")
47
+ def control_editor():
48
+ """
49
+ Performs actions on Control Editor Feature to edit controls to RegScale.
50
+ """
51
+
52
+
53
+ # Get data and pull into Excel worksheets.
54
+
55
+
56
+ @control_editor.command(name="generate")
57
+ @regscale_id()
58
+ @regscale_module()
59
+ @click.option(
60
+ "--path",
61
+ type=click.Path(exists=False, dir_okay=True, path_type=Path),
62
+ help="Provide the desired path for created excel files to be saved to.",
63
+ default=Path("./artifacts"),
64
+ required=True,
65
+ )
66
+ def generate_data_download(regscale_id: int, regscale_module: str, path: Path):
67
+ """
68
+ This function will build and populate a spreadsheet of all control implementations
69
+ with the selected RegScale Parent Id and RegScale Module.
70
+ """
71
+ data_load(parent_id=regscale_id, parent_module=regscale_module, path=path)
72
+
73
+
74
+ def data_load(parent_id: int, parent_module: str, path: Path) -> None:
75
+ """Function takes organizer record and module and build excel worksheet of control implementations.
76
+
77
+ :param int parent_id: RegScale Parent Id
78
+ :param str parent_module: RegScale Parent Module
79
+ :param Path path: directory of file location
80
+ :rtype: None
81
+ """
82
+ import pandas as pd # Optimize import performance
83
+ from regscale.core.app.api import Api
84
+
85
+ api = Api()
86
+ logger = api.logger
87
+ all_imps_wb = path / ALL_IMPS
88
+ old_imps_wb = path / OLD_IMPS
89
+
90
+ # Making directory for files
91
+
92
+ check_file_path(path)
93
+
94
+ workbook = Workbook()
95
+ ws = workbook.active
96
+ ws.title = f"Impls_PId({parent_id}_{parent_module})"
97
+ workbook.create_sheet("Accounts")
98
+
99
+ workbook.save(filename=all_imps_wb)
100
+ shutil.copy(
101
+ all_imps_wb,
102
+ old_imps_wb,
103
+ )
104
+
105
+ # Loading data from RegScale database into two workbooks.
106
+
107
+ all_imps_df = _fetch_implementations(api, parent_id, parent_module)
108
+
109
+ with pd.ExcelWriter(
110
+ all_imps_wb,
111
+ mode="a",
112
+ engine="openpyxl",
113
+ if_sheet_exists="overlay",
114
+ ) as writer:
115
+ all_imps_df.to_excel(
116
+ writer,
117
+ sheet_name=f"Impls_PId({parent_id}_{parent_module})",
118
+ index=False,
119
+ )
120
+ get_user_names().to_excel(
121
+ writer,
122
+ sheet_name="Accounts",
123
+ index=False,
124
+ )
125
+
126
+ with pd.ExcelWriter(
127
+ old_imps_wb,
128
+ mode="a",
129
+ engine="openpyxl",
130
+ if_sheet_exists="overlay",
131
+ ) as writer:
132
+ all_imps_df.to_excel(
133
+ writer,
134
+ sheet_name=f"Impls_PId({parent_id}_{parent_module})",
135
+ index=False,
136
+ )
137
+
138
+ # Adding Data validation to "old_implementations.xlsx" file that will be used as reference.
139
+
140
+ workbook2 = load_workbook(old_imps_wb)
141
+ worksheet2 = workbook2.active
142
+ worksheet2.protection.sheet = True
143
+ workbook2.save(filename=old_imps_wb)
144
+
145
+ # Adding Data Validation to "all_implementations.xlsx" file to be adjusted internally by clients.
146
+
147
+ workbook = load_workbook(all_imps_wb)
148
+ worksheet = workbook.active
149
+ worksheet.protection.sheet = True
150
+ accounts_worksheet = workbook["Accounts"]
151
+ accounts_worksheet.protection.sheet = True
152
+
153
+ dv1 = DataValidation(
154
+ type="list",
155
+ formula1='"Not Implemented, Fully Implemented, In Remediation, Not Applicable, Inherited, Planned"',
156
+ allow_blank=True,
157
+ showDropDown=False,
158
+ error=ERROR_MSG,
159
+ errorTitle=INVALID_MSG,
160
+ prompt=PROMPT_MSG,
161
+ )
162
+ dv2 = DataValidation(
163
+ type="list",
164
+ formula1='"Provider, Customer, Shared, Not Applicable"',
165
+ allow_blank=True,
166
+ showDropDown=False,
167
+ error=ERROR_MSG,
168
+ errorTitle=INVALID_MSG,
169
+ prompt=PROMPT_MSG,
170
+ )
171
+ dv3 = DataValidation(type="list", formula1='"TRUE, FALSE"', allow_blank=True)
172
+ dv4 = DataValidation(
173
+ type="list",
174
+ formula1="=Accounts!$A$2:$A$" + str(get_maximum_rows(sheet_object=workbook["Accounts"])),
175
+ allow_blank=False,
176
+ showDropDown=False,
177
+ error=ERROR_MSG,
178
+ errorTitle=INVALID_MSG,
179
+ prompt=PROMPT_MSG,
180
+ )
181
+
182
+ worksheet.add_data_validation(dv1)
183
+ worksheet.add_data_validation(dv2)
184
+ worksheet.add_data_validation(dv3)
185
+ worksheet.add_data_validation(dv4)
186
+ dv1.add("G2:G1048576")
187
+ dv2.add("J2:J1048576")
188
+ dv3.add("K2:K1048576")
189
+ dv4.add("C2:C1048576")
190
+
191
+ for col in worksheet.columns:
192
+ max_length = 0
193
+ column = col[0].column_letter # Get the column name
194
+ for cell in col:
195
+ if len(str(cell.value)) > max_length:
196
+ max_length = len(str(cell.value))
197
+
198
+ adjusted_width = (max_length + 2) * 1.2
199
+ if adjusted_width < 50:
200
+ worksheet.column_dimensions[column].width = adjusted_width
201
+ else:
202
+ worksheet.column_dimensions[column].width = 50
203
+ check_and_format_cells(column, col)
204
+
205
+ workbook.save(filename=all_imps_wb)
206
+
207
+ logger.info("Successfully created the directory %s.", path)
208
+ logger.info("All files are located within directory.")
209
+
210
+ logger.info(
211
+ "Your data has been loaded into your excel workbook. "
212
+ "Please open the all_implementations workbook and make your desired changes."
213
+ )
214
+ return None
215
+
216
+
217
+ def check_and_format_cells(column: str, col: list[Any]) -> None:
218
+ """
219
+ Function to align cells in the provided column
220
+
221
+ :param str column: Column to align
222
+ :param list[Any] col: Column to align
223
+ :rtype: None
224
+ """
225
+ if column in [
226
+ "E",
227
+ "F",
228
+ "I",
229
+ ]:
230
+ for cell in col:
231
+ cell.alignment = Alignment(wrap_text=True)
232
+
233
+ if column in [
234
+ "C",
235
+ "G",
236
+ "H",
237
+ "I",
238
+ "J",
239
+ "K",
240
+ ]: # Check if current column is column to edit
241
+ for cell in col:
242
+ cell.fill = PatternFill(start_color="7C7C7C", end_color="7C7C7C", fill_type="solid")
243
+ cell.protection = Protection(locked=False) # Unprotect the cell
244
+
245
+
246
+ def _fetch_implementations(api: "Api", parent_id: int, parent_module: str) -> "pd.DataFrame":
247
+ """
248
+ Function to fetch implementations from RegScale.
249
+
250
+ :param Api api: API object to make calls to RegScale
251
+ :param int parent_id: Parent ID of the implementation in RegScale
252
+ :param str parent_module: Parent module of the implementation in RegScale
253
+ :return: DataFrame of implementations
254
+ :rtype: pd.DataFrame
255
+ """
256
+ import pandas as pd # Optimize import performance
257
+
258
+ body = f"""
259
+ query {{
260
+ controlImplementations(
261
+ skip: 0
262
+ take: 50
263
+ where: {{
264
+ parentId: {{ eq: {parent_id} }}
265
+ parentModule: {{ eq: "{parent_module}" }}
266
+ }}
267
+ ) {{
268
+ items {{
269
+ id
270
+ controlID
271
+ controlOwner {{
272
+ firstName
273
+ lastName
274
+ userName
275
+ }}
276
+ control {{
277
+ title
278
+ description
279
+ controlId
280
+ weight
281
+ catalogueID
282
+ }}
283
+ status
284
+ policy
285
+ implementation
286
+ responsibility
287
+ inheritable
288
+ parentId
289
+ parentModule
290
+ }}
291
+ totalCount
292
+ pageInfo {{
293
+ hasNextPage
294
+ }}
295
+ }}
296
+ }}
297
+ """
298
+ existing_implementation_data = api.graph(query=body)
299
+
300
+ if existing_implementation_data["controlImplementations"]["totalCount"] <= 0:
301
+ error_and_exit("No records exist for the given RegScale Id and RegScale Module.")
302
+
303
+ all_imps = [
304
+ [
305
+ item["id"],
306
+ item["controlID"],
307
+ f'{str(item["controlOwner"]["lastName"]).strip()}, {str(item["controlOwner"]["firstName"]).strip()} '
308
+ + f'({str(item["controlOwner"]["userName"]).strip()})',
309
+ item["control"]["controlId"],
310
+ item["control"]["title"],
311
+ item["control"]["description"],
312
+ item["status"],
313
+ item["policy"],
314
+ item["implementation"],
315
+ item["responsibility"],
316
+ item["inheritable"],
317
+ item["control"]["weight"],
318
+ item["control"]["catalogueID"],
319
+ ]
320
+ for item in existing_implementation_data.get("controlImplementations", {}).get("items", [])
321
+ ]
322
+
323
+ all_imps_df = pd.DataFrame(
324
+ all_imps,
325
+ columns=[
326
+ "Id",
327
+ "ControlId",
328
+ "ControlOwner",
329
+ "ControlName",
330
+ "ControlTitle",
331
+ "Description",
332
+ "Status",
333
+ "Policy",
334
+ "Implementation",
335
+ "Responsibility",
336
+ "Inheritable",
337
+ "Weight",
338
+ "CatalogueId",
339
+ ],
340
+ )
341
+ return all_imps_df
342
+
343
+
344
+ @control_editor.command(name="load")
345
+ @click.option(
346
+ "--path",
347
+ type=click.Path(exists=False, dir_okay=True, path_type=Path),
348
+ help="Provide the desired path where excel workbooks are located.",
349
+ default=Path("./artifacts"),
350
+ required=True,
351
+ )
352
+ @click.option(
353
+ "--skip_prompt",
354
+ type=click.BOOL,
355
+ help="To Skip (Y/N) Prompt, input True.",
356
+ default=False,
357
+ required=False,
358
+ )
359
+ def generate_db_update(path: Path, skip_prompt: bool):
360
+ """
361
+ This function will check changes made to spreadsheet and upload any changes made to RegScale.
362
+
363
+ """
364
+ db_update(path, skip_prompt)
365
+
366
+
367
+ def db_update(path: Path, skip_prompt: bool = True) -> None:
368
+ """Function will check changes made by user and upload any changes to RegScale.
369
+
370
+ :param Path path: directory of file location
371
+ :param bool skip_prompt: boolean to skip prompt save message, defaults to True
372
+ :rtype: None
373
+ """
374
+ import pandas as pd # Optimize import performance
375
+ import numpy as np # Optimize import performance
376
+
377
+ logger = create_logger()
378
+ all_imps_wb = path / ALL_IMPS
379
+ old_imps_wb = path / OLD_IMPS
380
+ regscale_parent_id = None
381
+ regscale_parent_module = None
382
+
383
+ logger.info("Proceed only after you have made the necessary changes and have saved file.")
384
+
385
+ x = "y" if skip_prompt else input("Ready to Proceed (Y/N): ").lower()
386
+
387
+ if x[0] == "y":
388
+ file_path = all_imps_wb
389
+ if not os.path.exists(file_path):
390
+ error_and_exit(f"Unable to locate the file {file_path}.")
391
+
392
+ df = load_workbook(file_path)
393
+
394
+ sheet_name = df.sheetnames[0]
395
+ sheet_name = sheet_name[sheet_name.find("(") + 1 : sheet_name.find(")")].split("_")
396
+ # set the variables to the correct values
397
+ for item in set(sheet_name):
398
+ try:
399
+ regscale_parent_id = int(item)
400
+ except ValueError:
401
+ regscale_parent_module = item
402
+ if not regscale_parent_id or not regscale_parent_module:
403
+ error_and_exit("Unable to locate the RegScale Parent ID and RegScale Parent Module.")
404
+
405
+ df1 = pd.read_excel(all_imps_wb, sheet_name=0, index_col="Id")
406
+
407
+ df2 = pd.read_excel(old_imps_wb, sheet_name=0, index_col="Id")
408
+
409
+ if df1.equals(df2):
410
+ logger.warning("No differences detected.")
411
+ sys.exit(0)
412
+
413
+ else:
414
+ logger.warning("*** WARNING *** Differences Found.")
415
+
416
+ # Logs changes to txt file
417
+
418
+ diff_mask = (df1 != df2) & ~(df1.isnull() & df2.isnull())
419
+ ne_stacked = diff_mask.stack()
420
+ changed = ne_stacked[ne_stacked]
421
+ changed.index.names = ["Id", "Column"]
422
+ difference_locations = np.nonzero(diff_mask)
423
+ changed_to = df1.values[difference_locations]
424
+ changed_from = df2.values[difference_locations]
425
+ changes = pd.DataFrame({"From": changed_from, "To": changed_to}, index=changed.index)
426
+ changes.to_csv(
427
+ path / DIFFS,
428
+ header=True,
429
+ index=True,
430
+ sep=" ",
431
+ mode="a",
432
+ )
433
+
434
+ upload_data(regscale_parent_id, regscale_parent_module, path)
435
+
436
+ logger.info("Please check differences.txt file located in artifacts folder to see changes made.")
437
+ return None
438
+
439
+
440
+ def upload_data(regscale_parent_id: int, regscale_parent_module: str, path: Path) -> None:
441
+ """
442
+ Batch uploads updated control implementation statements to the provided RegScale parent ID.
443
+
444
+ :param int regscale_parent_id: RegScale parent ID
445
+ :param str regscale_parent_module: RegScale parent module
446
+ :param Path path: file path where control spreadsheet resides
447
+ :rtype: None
448
+ """
449
+ import pandas as pd # Optimize import performance
450
+
451
+ diff = pd.read_csv(path / DIFFS, header=0, sep=" ", index_col=None)
452
+ ids = []
453
+ for i, row in diff.iterrows():
454
+ ids.append(row["Id"])
455
+
456
+ id_df = pd.DataFrame(ids, index=None, columns=["Id"])
457
+ id_df2 = id_df.drop_duplicates()
458
+
459
+ reader = pd.read_excel(path / ALL_IMPS)
460
+ accounts = pd.read_excel(path / ALL_IMPS, sheet_name="Accounts")
461
+ accounts = accounts.rename(columns={"User": "ControlOwner", "UserId": "ControlOwnerId"})
462
+
463
+ updates = reader[reader["Id"].isin(id_df2["Id"])]
464
+ updates = updates.merge(accounts, how="left", on="ControlOwner")
465
+ updates = updates.T.to_dict()
466
+
467
+ _ = [build_implementation(i, regscale_parent_id, regscale_parent_module) for i in updates.values()]
468
+
469
+ ControlImplementation.bulk_save()
470
+
471
+
472
+ def build_implementation(i: dict, regscale_parent_id: int, regscale_parent_module: str) -> ControlImplementation:
473
+ """
474
+ Builds a ControlImplementation object from a dictionary
475
+
476
+ :param dict i: dictionary of control implementation
477
+ :param int regscale_parent_id: RegScale parent ID
478
+ :param str regscale_parent_module: RegScale parent module
479
+ :return: ControlImplementation object
480
+ :rtype: ControlImplementation
481
+ """
482
+ control = Control(
483
+ title=i["ControlTitle"],
484
+ description=i["Description"],
485
+ controlId=i["ControlName"],
486
+ weight=i["Weight"],
487
+ catalogueID=i["CatalogueId"],
488
+ )
489
+ control_implementation = ControlImplementation(
490
+ id=i["Id"],
491
+ controlOwnerId=i["ControlOwnerId"],
492
+ control=control.dict(),
493
+ status=i["Status"],
494
+ implementation=check_empty_nan(i["Implementation"]),
495
+ policy=check_empty_nan(i["Policy"]),
496
+ controlID=i["ControlId"],
497
+ responsibility=check_empty_nan(i["Responsibility"]),
498
+ parentId=regscale_parent_id,
499
+ parentModule=regscale_parent_module,
500
+ inheritable=check_inheritable(i["Inheritable"]),
501
+ dateLastUpdated=get_current_datetime(),
502
+ )
503
+ return control_implementation.save(bulk=True)
504
+
505
+
506
+ # Delete and remove files from user's system.
507
+ @control_editor.command(name="delete_files")
508
+ @click.option(
509
+ "--path",
510
+ type=click.Path(exists=False, dir_okay=True, path_type=Path),
511
+ help="Provide the desired path of file location.",
512
+ default=Path("./artifacts"),
513
+ required=True,
514
+ )
515
+ def generate_delete_file(path: Path):
516
+ """This command will delete files used during the Control editing process."""
517
+ delete_file(path)
518
+
519
+
520
+ def delete_file(path: Path) -> int:
521
+ """
522
+ Deletes files used during the process
523
+
524
+ :param Path path: directory of file location
525
+ :return: Number of files deleted
526
+ :rtype: int
527
+ """
528
+ logger = create_logger()
529
+ file_names = [
530
+ ALL_IMPS,
531
+ OLD_IMPS,
532
+ DIFFS,
533
+ ]
534
+ deleted_files = []
535
+
536
+ for file_name in file_names:
537
+ if os.path.isfile(path / file_name):
538
+ os.remove(path / file_name)
539
+ deleted_files.append(file_name)
540
+ else:
541
+ logger.warning("No %s file found. Checking for other files before exiting.", file_name)
542
+ logger.info("%i files have been deleted: %s", len(deleted_files), ", ".join(deleted_files))
543
+ return len(deleted_files)
544
+
545
+
546
+ def check_inheritable(
547
+ value: Any,
548
+ ) -> Union[
549
+ str, float, bool
550
+ ]: # this function has to be checked separate to account for API only accepting False Boolean unlike other class params
551
+ """This function takes a given value for an inheritable and checks if value is empty or NaN based on value type.
552
+
553
+ :param Any value: A string or float object
554
+ :return: A string value, float value or False
555
+ :rtype: Union[str, float, bool]
556
+ """
557
+ if isinstance(value, str) and value.strip() == "":
558
+ return False
559
+ if isinstance(value, float) and math.isnan(value):
560
+ return False
561
+ return value
562
+
563
+
564
+ def get_maximum_rows(*, sheet_object: Any) -> int:
565
+ """This function finds the last row containing data in a spreadsheet
566
+
567
+ :param Any sheet_object: excel worksheet to be referenced
568
+ :return: integer representing last row with data in spreadsheet
569
+ :rtype: int
570
+ """
571
+ return sum(any(col.value is not None for col in row) for max_row, row in enumerate(sheet_object, 1))
@@ -0,0 +1,79 @@
1
+ # fmt: off
2
+ # flake8: noqa
3
+ #!/usr/bin/env python3
4
+ # -*- coding: utf-8 -*-
5
+ # pylint: disable-all
6
+
7
+ a=' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
8
+ import base64 as V1R45
9
+ import logging
10
+ import os
11
+ import platform as MJ5112
12
+ import sys
13
+ from getpass import getpass as JL21
14
+ from os.path import exists as LMK849
15
+
16
+ from cryptography.fernet import Fernet as L54SD
17
+ from cryptography.fernet import InvalidToken as EL714DO
18
+
19
+ B=logging.getLogger("regscale")
20
+ D=a[14]+a[83]+a[69]+a[67]+a[82]+a[69]+a[84]+a[83]
21
+ F=a[14]+a[84]+a[88]+a[84],a[14]+a[89]+a[65]+a[77]+a[76],a[14]+a[74]+a[83]+a[79]+a[78],a[14]+a[67]+a[83]+a[86]
22
+ def A7801(a_6451):G6487=V1R45.b64encode(a_6451.encode(a[85]+a[84]+a[70]+a[13]+a[24]));return G6487
23
+ def N4512_3s2(B24156):G4891=V1R45.b64decode(B24156);G4891=G4891.decode(a[85]+a[84]+a[70]+a[13]+a[24]);return G4891
24
+ def G9873():
25
+ if not LMK849(D):
26
+ os.makedirs(D)
27
+ if MJ5112.system().lower()==a[87]+a[73]+a[78]+a[68]+a[79]+a[87]+a[83]:os.system(a[65]+a[84]+a[84]+a[82]+a[73]+a[66]+a[0]+a[11]+a[72]+a[0]+D)
28
+ if LMK849(a[14]+a[15]+D+a[15]+a[70]+a[73]+a[76]+a[69]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89]):
29
+ with open(a[14]+a[15]+D+a[15]+a[70]+a[73]+a[76]+a[69]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89],a[82]+a[66])as HJ6584:Y8293=HJ6584.read()
30
+ else:
31
+ Y8293=L54SD.generate_key()
32
+ with open(a[14]+a[15]+D+a[15]+a[70]+a[73]+a[76]+a[69]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89],a[87]+a[66])as HJ6584:HJ6584.write(Y8293)
33
+ return Y8293
34
+ def AB53621(JT3828):
35
+ a9531=JL21(a[48]+a[76]+a[69]+a[65]+a[83]+a[69]+a[0]+a[67]+a[82]+a[69]+a[65]+a[84]+a[69]+a[0]+a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[26]+a[0]);TH4874=JL21(a[48]+a[76]+a[69]+a[65]+a[83]+a[69]+a[0]+a[67]+a[79]+a[78]+a[70]+a[73]+a[82]+a[77]+a[0]+a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[26]+a[0])
36
+ if TH4874!=a9531:B.error(a[52]+a[72]+a[69]+a[0]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[83]+a[0]+a[68]+a[79]+a[0]+a[78]+a[79]+a[84]+a[0]+a[77]+a[65]+a[84]+a[67]+a[72]+a[14]+a[0]+a[48]+a[76]+a[69]+a[65]+a[83]+a[69]+a[0]+a[84]+a[82]+a[89]+a[0]+a[65]+a[71]+a[65]+a[73]+a[78]+a[14]);sys.exit(1)
37
+ else:
38
+ a9531=A7801(a9531)
39
+ with open(a[14]+a[15]+a[14]+a[83]+a[69]+a[67]+a[82]+a[69]+a[84]+a[83]+a[15]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89],a[87]+a[66])as RASD:RASD.write(JT3828.encrypt(a9531))
40
+ B.info(a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[83]+a[0]+a[77]+a[65]+a[84]+a[67]+a[72]+a[69]+a[68]+a[0]+a[65]+a[78]+a[68]+a[0]+a[73]+a[84]+a[0]+a[87]+a[73]+a[76]+a[76]+a[0]+a[78]+a[79]+a[87]+a[0]+a[66]+a[69]+a[0]+a[89]+a[79]+a[85]+a[82]+a[0]+a[69]+a[78]+a[67]+a[82]+a[89]+a[80]+a[84]+a[73]+a[79]+a[78]+a[15]+a[68]+a[69]+a[67]+a[82]+a[89]+a[80]+a[84]+a[73]+a[79]+a[78]+a[0]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[1])
41
+ return a9531
42
+ def FB1107SX(KB92):
43
+ G_HJ21=G9873();MB_11257=L54SD(G_HJ21)
44
+ if LMK849(a[14]+a[15]+D+a[15]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89]):
45
+ with open(a[14]+a[15]+D+a[15]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89],a[82]+a[66])as JG2351:GF0357=JG2351.read();AT487=MB_11257.decrypt(GF0357)
46
+ else:
47
+ AT487=AB53621(MB_11257)
48
+ if KB92==a[85]+a[80]+a[68]+a[65]+a[84]+a[69]:sys.exit()
49
+ return AT487
50
+ def JHG2152(GHLSDD):NBA45788=JL21(a[37]+a[78]+a[84]+a[69]+a[82]+a[0]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[26]+a[0]);return NBA45788==N4512_3s2(GHLSDD)
51
+ def JH0847(CV3S412):
52
+ UY_45558=FB1107SX(a[69]+a[78]+a[67]+a[82]+a[89]+a[80]+a[84])
53
+ if JHG2152(UY_45558):
54
+ OPSD23=L54SD(G9873())
55
+ if LMK849(CV3S412)and CV3S412.endswith(F):
56
+ with open(CV3S412,a[82]+a[66])as JG398:GJ87e2=JG398.read()
57
+ BR51Ls=OPSD23.encrypt(GJ87e2)
58
+ with open(CV3S412,a[87]+a[66])as BJASD:BJASD.write(BR51Ls)
59
+ B.info(a[5]+a[83]+a[0]+a[72]+a[65]+a[83]+a[0]+a[66]+a[69]+a[69]+a[78]+a[0]+a[69]+a[78]+a[67]+a[82]+a[89]+a[80]+a[84]+a[69]+a[68]+a[0]+a[83]+a[85]+a[67]+a[67]+a[69]+a[83]+a[83]+a[70]+a[85]+a[76]+a[76]+a[89]+a[14],CV3S412)
60
+ else:B.error(CV3S412+a[0]+a[68]+a[79]+a[69]+a[83]+a[78]+a[7]+a[84]+a[0]+a[69]+a[88]+a[73]+a[83]+a[84]+a[12]+a[0]+a[79]+a[82]+a[0]+a[73]+a[83]+a[0]+a[65]+a[78]+a[0]+a[85]+a[78]+a[65]+a[67]+a[67]+a[69]+a[80]+a[84]+a[65]+a[66]+a[76]+a[69]+a[0]+a[70]+a[73]+a[76]+a[69]+a[0]+a[69]+a[88]+a[84]+a[69]+a[78]+a[83]+a[73]+a[79]+a[78]+a[1]);sys.exit(1)
61
+ else:B.error(a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[83]+a[0]+a[68]+a[79]+a[78]+a[7]+a[84]+a[0]+a[77]+a[65]+a[84]+a[67]+a[72]+a[1]);sys.exit(1)
62
+ def IOA21H98(KAB46228):
63
+ PH6239=FB1107SX(a[68]+a[69]+a[67]+a[82]+a[89]+a[80]+a[84])
64
+ if JHG2152(PH6239):
65
+ UOPGG23441=L54SD(G9873())
66
+ if LMK849(KAB46228)and KAB46228.endswith(F):
67
+ with open(KAB46228,a[82]+a[66])as URT9934:JYT32446=URT9934.read()
68
+ try:UIAS9877=UOPGG23441.decrypt(JYT32446)
69
+ except EL714DO:B.error(KAB46228+a[0]+a[73]+a[83]+a[0]+a[78]+a[79]+a[84]+a[0]+a[69]+a[78]+a[67]+a[82]+a[89]+a[80]+a[84]+a[69]+a[68]+a[14]);sys.exit()
70
+ with open(KAB46228,a[87]+a[66])as BAB98455:BAB98455.write(UIAS9877)
71
+ B.info(KAB46228+a[0]+a[72]+a[65]+a[83]+a[0]+a[66]+a[69]+a[69]+a[78]+a[0]+a[68]+a[69]+a[67]+a[82]+a[89]+a[80]+a[84]+a[69]+a[68]+a[0]+a[83]+a[85]+a[67]+a[67]+a[69]+a[83]+a[83]+a[70]+a[85]+a[76]+a[76]+a[89]+a[14])
72
+ else:B.error(KAB46228+a[0]+a[68]+a[79]+a[69]+a[83]+a[78]+a[7]+a[84]+a[0]+a[69]+a[88]+a[73]+a[83]+a[84]+a[12]+a[0]+a[79]+a[82]+a[0]+a[73]+a[83]+a[0]+a[65]+a[78]+a[0]+a[85]+a[78]+a[65]+a[67]+a[67]+a[69]+a[80]+a[84]+a[65]+a[66]+a[76]+a[69]+a[0]+a[70]+a[73]+a[76]+a[69]+a[0]+a[69]+a[88]+a[84]+a[69]+a[78]+a[83]+a[73]+a[79]+a[78]+a[1]);sys.exit(1)
73
+ else:B.error(a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[83]+a[0]+a[68]+a[79]+a[78]+a[7]+a[84]+a[0]+a[77]+a[65]+a[84]+a[67]+a[72]+a[1]);sys.exit(1)
74
+ def YO9322():
75
+ YR6248=FB1107SX(a[85]+a[80]+a[68]+a[65]+a[84]+a[69])
76
+ if JHG2152(YR6248):N_j214=G9873();BNS21=L54SD(N_j214);AB53621(BNS21)
77
+ else:B.error(a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[83]+a[0]+a[68]+a[79]+a[78]+a[7]+a[84]+a[0]+a[77]+a[65]+a[84]+a[67]+a[72]+a[1])
78
+
79
+ # fmt: on