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,190 @@
1
+ import logging
2
+ from typing import Optional, List, Dict
3
+
4
+ from pydantic import ConfigDict, Field
5
+
6
+ from regscale.core.app.utils.app_utils import get_current_datetime
7
+ from regscale.models.regscale_models.search import Search
8
+ from regscale.models.regscale_models import Asset
9
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
10
+ from regscale.models.regscale_models.regscale_model import T
11
+ from regscale.models.regscale_models.mixins.parent_cache import PlanCacheMixin
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class AssetMapping(RegScaleModel, PlanCacheMixin["AssetMapping"]):
17
+ """
18
+ AssetMapping model class.
19
+ """
20
+
21
+ _module_slug = "assetmapping"
22
+ _unique_fields = [
23
+ ["componentId", "assetId"],
24
+ ]
25
+ _parent_id_field = "componentId"
26
+
27
+ # New class attributes
28
+ _graph_query_name = "assetMappings"
29
+ _graph_plan_id_path = "component.securityPlansId"
30
+
31
+ id: Optional[int] = 0
32
+ uuid: Optional[str] = None
33
+ assetId: int
34
+ componentId: int
35
+ createdById: Optional[str] = None
36
+ dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
37
+ lastUpdatedById: Optional[str] = None
38
+ isPublic: Optional[bool] = True
39
+ dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
40
+ tenantsId: Optional[int] = 1
41
+
42
+ @staticmethod
43
+ def get_assets(component_id: int) -> List[T]:
44
+ """
45
+ Get assets for a given component ID.
46
+
47
+ :param int component_id: The ID of the component
48
+ :return: A list of assets
49
+ :rtype: List[T]
50
+ """
51
+ asset_mappings = AssetMapping.find_mappings(component_id=component_id)
52
+ assets = []
53
+ for asset_mapping in asset_mappings:
54
+ assets.append(Asset.get_object(object_id=asset_mapping.assetId))
55
+ return assets
56
+
57
+ @staticmethod
58
+ def _get_additional_endpoints() -> ConfigDict:
59
+ """
60
+ Get additional endpoints for the AssetMapping model.
61
+
62
+ :return: A dictionary of additional endpoints
63
+ :rtype: ConfigDict
64
+ """
65
+ return ConfigDict(
66
+ get_all_by_parent="/api/{model_slug}/getMappingsAsComponents/{intParentID}",
67
+ filter_asset_mappings="/api/{model_slug}/filterAssetMappings/{intAsset}/{intComp}/{strSearch}/{intPage}/{intPageSize}",
68
+ find_mappings="/api/{model_slug}/findMappings/{intId}",
69
+ get_mappings_as_components="/api/{model_slug}/getMappingsAsComponents/{intId}",
70
+ get_mappings_as_assets="/api/{model_slug}/getMappingsAsAssets/{intId}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
71
+ )
72
+
73
+ @classmethod
74
+ def cast_list_object(
75
+ cls,
76
+ item: Dict,
77
+ parent_id: Optional[int] = None,
78
+ parent_module: Optional[str] = None,
79
+ ) -> "AssetMapping":
80
+ """
81
+ Cast list of items to class instances.
82
+
83
+ :param Dict item: item to cast
84
+ :param Optional[int] parent_id: Parent ID, defaults to None
85
+ :param Optional[str] parent_module: Parent module, defaults to None
86
+ :return: Class instance created from the item
87
+ :rtype: "AssetMapping"
88
+ """
89
+ item["assetId"] = parent_id or item.get("assetId")
90
+ return cls(**item)
91
+
92
+ @classmethod
93
+ def get_all_by_parent(
94
+ cls,
95
+ parent_id: int,
96
+ parent_module: Optional[str] = None,
97
+ search: Optional[Search] = None,
98
+ ) -> List[T]:
99
+ """
100
+ Retrieves all asset mappings for a given parent ID and ONLY Components.
101
+
102
+ :param int parent_id: The ID of the parent
103
+ :param Optional[str] parent_module: The module of the parent
104
+ :param Optional[Search] search: The search object, defaults to None
105
+ :return: A list of asset mappings
106
+ :rtype: List[T]
107
+ :returns: A list of asset mappings for the given parent ID
108
+ """
109
+ return cls.find_mappings(parent_id)
110
+
111
+ @classmethod
112
+ def find_mappings(cls, component_id: int) -> List[T]:
113
+ """
114
+ Retrieves all component mappings for a given component ID.
115
+
116
+ :param int component_id: The ID of the component
117
+ :return: A list of component mappings
118
+ :rtype: List[T]
119
+ """
120
+ cache_key = f"{component_id}:{cls.__name__}"
121
+
122
+ # Get the lock for this cache_key
123
+ lock = cls._get_lock(cache_key)
124
+
125
+ with lock:
126
+ # Check the cache
127
+ cached_mappings = cls._parent_cache.get(cache_key)
128
+ if cached_mappings is not None:
129
+ return cached_mappings
130
+
131
+ # Not cached, make the API call
132
+ response = cls._get_api_handler().get(
133
+ endpoint=cls.get_endpoint("find_mappings").format(model_slug=cls.get_module_slug(), intId=component_id)
134
+ )
135
+ mappings = cls._handle_list_response(response)
136
+
137
+ # Cache the mappings
138
+ cls.cache_list_objects(cache_key=cache_key, objects=mappings)
139
+
140
+ return mappings
141
+
142
+ @classmethod
143
+ def get_mappings_as_components(cls, asset_id: int) -> Optional[List[T]]:
144
+ """
145
+ Retrieves all component mappings for a given asset ID.
146
+
147
+ :param int asset_id: The ID of the asset
148
+ :return: A list of component mappings or None
149
+ :rtype: Optional[List[T]]
150
+ """
151
+ response = cls._get_api_handler().get(
152
+ endpoint=cls.get_endpoint("get_mappings_as_components").format(
153
+ model_slug=cls.get_module_slug(), intId=asset_id
154
+ )
155
+ )
156
+ if not response or response.status_code in [204, 404]:
157
+ return None
158
+ if response.ok:
159
+ return [cls(**item) for item in response.json()]
160
+ return None
161
+
162
+ def get_mappings_as_assets(
163
+ self, component_id: int, sort_by: str, direction: str, page: int, page_size: int
164
+ ) -> Optional[List["AssetMapping"]]:
165
+ """
166
+ Retrieves all asset mappings for a given component ID.
167
+
168
+ :param int component_id: The ID of the component
169
+ :param str sort_by: The field to sort by
170
+ :param str direction: The direction of sorting ('asc' or 'desc')
171
+ :param int page: The page number for pagination
172
+ :param int page_size: The number of items per page
173
+ :return: A list of asset mappings or None
174
+ :rtype: Optional[List[AssetMapping]]
175
+ """
176
+ response = self._get_api_handler().get(
177
+ endpoint=self.get_endpoint("get_mappings_as_assets").format(
178
+ model_slug=self._module_slug,
179
+ intId=component_id,
180
+ strSortBy=sort_by,
181
+ strDirection=direction,
182
+ intPage=page,
183
+ intPageSize=page_size,
184
+ )
185
+ )
186
+ if not response or response.status_code in [204, 404]:
187
+ return None
188
+ if response.ok:
189
+ return [self.__class__(**item) for item in response.json()]
190
+ return None
@@ -0,0 +1,42 @@
1
+ from enum import Enum
2
+ from typing import Optional
3
+
4
+ from pydantic import Field
5
+
6
+ from regscale.core.app.utils.app_utils import get_current_datetime
7
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
8
+
9
+
10
+ class CaseStatus(str, Enum):
11
+ """
12
+ Enum for the CaseStatus field in the Case model.
13
+ """
14
+
15
+ in_progress = "In Progress"
16
+ closed = "Closed"
17
+ pending = "Pending"
18
+ resolved = "Resolved"
19
+ complete = "Complete"
20
+ cancelled = "Cancelled"
21
+ on_hold = "On Hold"
22
+
23
+
24
+ class Case(RegScaleModel):
25
+ _module_slug = "cases"
26
+ _module_id = 28
27
+
28
+ id: Optional[int] = None
29
+ title: str
30
+ uuid: Optional[str] = None
31
+ description: Optional[str] = None
32
+ status: str = CaseStatus.pending
33
+ caseNumber: Optional[str] = None
34
+ caseWorkerId: str = Field(default_factory=RegScaleModel.get_user_id)
35
+ dateReported: str = Field(default_factory=get_current_datetime)
36
+ dateResolved: Optional[str] = None
37
+ notes: Optional[str] = None
38
+ reportedBy: str = Field(default_factory=RegScaleModel.get_user_id)
39
+ facilityId: Optional[int] = None
40
+ orgId: Optional[int] = None
41
+ parentId: Optional[int] = None
42
+ parentModule: Optional[str] = None
@@ -0,0 +1,261 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """Model for Catalog in the application"""
4
+ from __future__ import annotations
5
+
6
+ import io
7
+ import json
8
+ import warnings
9
+ from typing import List, Optional, Union
10
+ from urllib.parse import urljoin
11
+
12
+ from pydantic import ConfigDict
13
+ from requests import Response
14
+
15
+ from regscale.core.app.api import Api
16
+ from regscale.core.app.application import Application
17
+ from regscale.core.app.utils.api_handler import APIRetrieveError
18
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
19
+ from regscale.models.regscale_models.security_control import SecurityControl
20
+
21
+
22
+ class Catalog(RegScaleModel):
23
+ """Catalog class"""
24
+
25
+ _module_slug = "catalogues"
26
+
27
+ id: int = 0
28
+ abstract: Optional[str] = None
29
+ datePublished: Optional[str] = None
30
+ description: Optional[str] = None
31
+ keywords: Optional[str] = None
32
+ lastRevisionDate: Optional[str] = None
33
+ title: str = ""
34
+ url: Optional[str] = None
35
+ tenantsId: Optional[int] = None
36
+ uuid: Optional[str] = None
37
+ createdById: Optional[str] = None
38
+ dateCreated: Optional[str] = None
39
+ dateLastUpdated: Optional[str] = None
40
+ lastUpdatedById: Optional[str] = None
41
+ master: bool = False
42
+ sourceOscalURL: Optional[str] = None
43
+ archived: bool = False
44
+ isPublic: bool = True
45
+ securityControls: List[SecurityControl] = []
46
+
47
+ @staticmethod
48
+ def _get_additional_endpoints() -> ConfigDict:
49
+ """
50
+ Get additional endpoints for the Catalogues model
51
+
52
+ :return: A dictionary of additional endpoints
53
+ :rtype: ConfigDict
54
+ """
55
+ return ConfigDict( # type: ignore
56
+ get_count="/api/{model_slug}/getCount",
57
+ get_list="/api/{model_slug}/getList",
58
+ get_catalog_with_all_details="/api/{model_slug}/getCatalogWithAllDetails/{intID}",
59
+ filter_catalogues="/api/{model_slug}/filterCatalogues",
60
+ graph="/api/{model_slug}/graph",
61
+ convert_mappings="/api/{model_slug}/convertMappings/{intID}",
62
+ find_by_guid="/api/{model_slug}/findByGUID/{strID}",
63
+ get_titles="/api/{model_slug}/getTitles",
64
+ get_nist="/api/{model_slug}/getNIST",
65
+ get_updatable="/api/{model_slug}/getUpdatableCatalogs",
66
+ compare_and_update="/api/{model_slug}/compareAndUpdate/{intID}",
67
+ update_regscale_catalog="/api/{model_slug}/updateRegScaleCatalog/{intID}",
68
+ get_update_report_for_catalog="/api/{model_slug}/getUpdateReportForCatalog/{intID}",
69
+ )
70
+
71
+ @classmethod
72
+ def get_list(cls) -> List["Catalog"]:
73
+ """
74
+ Use the get_list method instead.
75
+
76
+ Get all catalogs from database
77
+
78
+ :return: list of catalogs
79
+ :rtype: List["Catalog"]
80
+ """
81
+ return cls._handle_list_response(cls._get_api_handler().get(cls.get_endpoint("get_list")))
82
+
83
+ def insert_catalog(self, app: Application) -> "Catalog": # noqa
84
+ """
85
+ DEPRECATED: This method is deprecated and will be removed in a future version.
86
+ Use the create method instead.
87
+
88
+ Insert catalog into database
89
+
90
+ :param Application app: Application
91
+ :return: Newly created catalog object
92
+ :rtype: Catalog
93
+ """
94
+ warnings.warn(
95
+ "insert_catalog is deprecated and will be removed in a future version. Use create method instead.",
96
+ DeprecationWarning,
97
+ )
98
+ # Convert the model to a dictionary
99
+ return self.create()
100
+
101
+ @staticmethod
102
+ def get_catalogs(app: Application) -> list:
103
+ """
104
+ DEPRECATED: This method is deprecated and will be removed in a future version.
105
+ Use the get_list method instead.
106
+
107
+ Get all catalogs from database
108
+
109
+ :param Application app: Application
110
+ :raises APIRetrieveError: API request failed
111
+ :return: list of catalogs
112
+ :rtype: list
113
+ """
114
+ warnings.warn(
115
+ "get_catalogs is deprecated and will be removed in a future version. Use get_list method instead.",
116
+ DeprecationWarning,
117
+ )
118
+ api = Api()
119
+ api_url = urljoin(app.config["domain"], "/api/catalogues")
120
+ response = api.get(api_url)
121
+ if not response.ok:
122
+ api.logger.debug(
123
+ f"API request failed with status: {response.status_code}: {response.reason} {response.text}"
124
+ )
125
+ raise APIRetrieveError(f"API request failed with status {response.status_code}")
126
+ return response.json()
127
+
128
+ @classmethod
129
+ def get_with_all_details(cls, catalog_id: int) -> Optional[dict]:
130
+ """
131
+ Retrieves a catalog with all details by its ID.
132
+
133
+ :param int catalog_id: The ID of the catalog
134
+ :return: The response from the API or None
135
+ :rtype: Optional[dict]
136
+ """
137
+ endpoint = cls.get_endpoint("get_catalog_with_all_details").format(
138
+ model_slug=cls.get_module_slug(), intID=catalog_id
139
+ )
140
+ response = cls._get_api_handler().get(endpoint)
141
+
142
+ if response and response.ok and response.status_code not in [204, 404]:
143
+ return response.json()
144
+ return {}
145
+
146
+ @classmethod
147
+ def get_update_report_for_catalog(
148
+ cls,
149
+ catalog_id: int,
150
+ ) -> Response:
151
+ """ """
152
+ endpoint = cls.get_endpoint("get_update_report_for_catalog").format(
153
+ model_slug=cls.get_module_slug(),
154
+ intID=catalog_id,
155
+ )
156
+ response = cls._get_api_handler().get(endpoint)
157
+
158
+ return response
159
+
160
+ @classmethod
161
+ def get_updatable_catalogs(cls) -> Optional[list]:
162
+ """
163
+ Get updatable catalogues
164
+
165
+ :return: List of updatable catalogues
166
+ :rtype: Optional[list]
167
+ """
168
+
169
+ endpoint = cls.get_endpoint("get_updatable").format(model_slug=cls.get_module_slug())
170
+ response = cls._get_api_handler().get(endpoint)
171
+ if (
172
+ response
173
+ and response.ok
174
+ and response.status_code
175
+ not in [
176
+ 204,
177
+ 404,
178
+ ]
179
+ ):
180
+ return response.json()
181
+ return None
182
+
183
+ @classmethod
184
+ def update_regscale_catalog(
185
+ cls,
186
+ catalog_id: int,
187
+ ) -> Union[Response | list]:
188
+ """
189
+ Update a regscale catalog
190
+
191
+ :param int catalog_id: The ID of the catalog
192
+ :return: A Response object
193
+ :rtype: Union[Response | list]
194
+ """
195
+
196
+ endpoint = cls.get_endpoint("update_regscale_catalog").format(
197
+ model_slug=cls.get_module_slug(),
198
+ intID=catalog_id,
199
+ )
200
+ response = cls._get_api_handler().put(endpoint=endpoint) # data is optional here, not needed for this.
201
+ if (
202
+ response
203
+ and response.ok
204
+ and response.status_code
205
+ not in [
206
+ 204,
207
+ 404,
208
+ ]
209
+ ):
210
+ return response.json()
211
+ return response
212
+
213
+ @classmethod
214
+ def compare_and_update(
215
+ cls,
216
+ new_catalog: dict,
217
+ catalog_id: int,
218
+ format: str = "json",
219
+ structure: str = "flatReport",
220
+ apply_updates: bool = False,
221
+ ) -> Response:
222
+ """
223
+ Get updatable catalogues
224
+
225
+ :param dict new_catalog: The new catalog to compare
226
+ :param int catalog_id: The ID of the catalog
227
+ :param str format: The format of the catalog
228
+ :param str structure: The structure of the catalog
229
+ :param bool apply_updates: Whether to apply updates
230
+ :return: List of updatable catalogues
231
+ :rtype: Response
232
+ """
233
+ bytes_object = json.dumps(new_catalog).encode("utf-8")
234
+ files = {"newCatalogFile": io.BytesIO(bytes_object)}
235
+ # convert files to bytes like object
236
+ endpoint = cls.get_endpoint("compare_and_update").format(
237
+ model_slug=cls.get_module_slug(),
238
+ intID=catalog_id,
239
+ format=format,
240
+ structure=structure,
241
+ apply_updates=apply_updates,
242
+ )
243
+ params = {
244
+ "format": format.lower(),
245
+ "structure": structure,
246
+ "applyUpdates": apply_updates,
247
+ }
248
+ response = cls._get_api_handler().post(endpoint=endpoint, files=files, params=params)
249
+
250
+ if (
251
+ response
252
+ and response.ok
253
+ and response.status_code
254
+ not in [
255
+ 204,
256
+ 404,
257
+ ]
258
+ ):
259
+ return response
260
+ cls.log_response_error(response, suppress_error=True)
261
+ return response
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Model for Control Parameter in the application"""
4
+ from typing import Optional
5
+
6
+ from pydantic import ConfigDict
7
+
8
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
9
+
10
+
11
+ class CCI(RegScaleModel):
12
+ """
13
+ CCI class
14
+ """
15
+
16
+ _module_slug = "cci"
17
+ _unique_fields = [
18
+ ["parameterId", "securityControlId"],
19
+ ]
20
+
21
+ id: Optional[int] = 0
22
+ uuid: Optional[str] = None
23
+ name: Optional[str] = None
24
+ description: Optional[str] = None
25
+ controlType: Optional[str] = None
26
+ publishDate: Optional[str] = None
27
+ securityControlId: Optional[int] = None
28
+ archived: bool = False
29
+ createdById: Optional[str] = None
30
+ dateCreated: Optional[str] = None
31
+ lastUpdatedById: Optional[str] = None
32
+ dateLastUpdated: Optional[str] = None
33
+ tenantsId: Optional[int] = None
34
+ isPublic: bool = True
35
+
36
+ @staticmethod
37
+ def _get_additional_endpoints() -> ConfigDict:
38
+ """
39
+ Get additional endpoints for the ControlParameter
40
+
41
+ :return: Additional endpoints for the ControlParameter
42
+ :rtype: ConfigDict
43
+ """
44
+ return ConfigDict( # type: ignore
45
+ get_all_by_parent="/api/{model_slug}/getByControl/{intParentID}",
46
+ )
@@ -0,0 +1,167 @@
1
+ """
2
+ This module contains the Change model for RegScale.
3
+ """
4
+
5
+ import logging
6
+ from enum import Enum
7
+ from typing import Optional, List, Dict
8
+
9
+ from pydantic import ConfigDict, Field
10
+
11
+ from regscale.core.app.utils.app_utils import get_current_datetime
12
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class ChangeType(str, Enum):
18
+ """
19
+ Enum for the ChangeType field in the Change model.
20
+ """
21
+
22
+ emergency = "Emergency"
23
+ normal = "Normal"
24
+ standard = "Standard"
25
+
26
+
27
+ class ChangePriority(str, Enum):
28
+ """
29
+ Enum for the ChangePriority field in the Change model.
30
+ """
31
+
32
+ critical = "Critical"
33
+ low = "Low"
34
+ moderate = "Moderate"
35
+ high = "High"
36
+ security = "Security"
37
+
38
+
39
+ class ChangeStatus(str, Enum):
40
+ """
41
+ Enum for the ChangeStatus field in the Change model.
42
+ """
43
+
44
+ draft = "Draft"
45
+ assess = "Assess"
46
+ pending_approval = "Pending Approval"
47
+ approved = "Approved"
48
+ schedule = "Schedule"
49
+ implement = "Implement"
50
+ review = "Review"
51
+ complete = "Complete"
52
+ cancelled = "Cancelled"
53
+
54
+
55
+ class ChangeOutageRequired(str, Enum):
56
+ """
57
+ Enum for the ChangeOutageRequired field in the Change model.
58
+ """
59
+
60
+ yes = "Yes"
61
+ no = "No"
62
+
63
+
64
+ class Change(RegScaleModel):
65
+ """
66
+ A class to represent the Change model in RegScale.
67
+ """
68
+
69
+ _module_id = 31
70
+ _module_slug = "changes"
71
+ _parent_id_field = "parentId"
72
+
73
+ id: Optional[int] = 0
74
+ isPublic: bool = True
75
+ uuid: Optional[str] = None
76
+ title: str
77
+ changeReason: str
78
+ description: Optional[str] = None
79
+ changeOwnerId: str = Field(default_factory=RegScaleModel.get_user_id)
80
+ dateRequested: str = Field(default_factory=get_current_datetime)
81
+ startChangeWindow: Optional[str] = None
82
+ endChangeWindow: Optional[str] = None
83
+ outageRequired: str = ChangeOutageRequired.no.value
84
+ outageSummary: Optional[str] = None
85
+ status: str = ChangeStatus.draft.value
86
+ dateChangeApproved: Optional[str] = None
87
+ dateWorkCompleted: Optional[str] = None
88
+ changeType: str = ChangeType.standard.value
89
+ priority: str = ChangePriority.moderate.value
90
+ securityImpactAssessment: Optional[str] = None
91
+ changePlan: Optional[str] = None
92
+ riskAssessment: Optional[str] = None
93
+ rollbackPlan: Optional[str] = None
94
+ communicationsPlan: Optional[str] = None
95
+ notes: Optional[str] = None
96
+ leadTesterId: Optional[str] = None
97
+ testPlan: Optional[str] = None
98
+ testResults: Optional[str] = None
99
+ dateTested: Optional[str] = None
100
+ facilityId: Optional[int] = None
101
+ orgId: Optional[int] = None
102
+ parentId: Optional[int] = None
103
+ parentModule: Optional[str] = None
104
+ dateLastUpdated: str = Field(default_factory=get_current_datetime)
105
+
106
+ # now create the _get_additional_endpoints method from this list of endpoints
107
+ @staticmethod
108
+ def _get_additional_endpoints() -> ConfigDict:
109
+ """
110
+ Get additional endpoints for the Changes model.
111
+
112
+ :return: A dictionary of additional endpoints
113
+ :rtype: ConfigDict
114
+ """
115
+ return ConfigDict(
116
+ get_count="/api/{model_slug}/getCount",
117
+ schedule="/api/{model_slug}/schedule/{year}/{strDateField}",
118
+ report="/api/{model_slug}/report/{strReport}",
119
+ filter_changes="/api/{model_slug}/filterChanges",
120
+ query_by_custom_field="/api/{model_slug}/queryByCustomField/{strFieldName}/{strValue}",
121
+ )
122
+
123
+ @classmethod
124
+ def filter_change(cls, payload: Dict) -> List["Change"]:
125
+ """
126
+ Filter change based on query parameters.
127
+
128
+ :param dict payload: Query parameters
129
+ :return: A list of changes
130
+ """
131
+ response = cls._get_api_handler().post(
132
+ endpoint=cls.get_endpoint("filter_changes").format(model_slug=cls._module_slug), data=payload
133
+ )
134
+ if response and response.ok:
135
+ return [cls(**ci) for ci in response.json().get("items", [])]
136
+ return []
137
+
138
+ @staticmethod
139
+ def fetch_all_changes() -> List["Change"]:
140
+ """
141
+ Fetch all changes in RegScale
142
+
143
+ :return: List of Changes from RegScale
144
+ :rtype: List[Change]
145
+ """
146
+ from regscale.core.app.api import Api
147
+ from requests import JSONDecodeError
148
+
149
+ api = Api()
150
+ body = f"""
151
+ query {{
152
+ changes(take: 50, skip: 0) {{
153
+ items {{
154
+ {Change.build_graphql_fields()}
155
+ }}
156
+ pageInfo {{
157
+ hasNextPage
158
+ }}
159
+ ,totalCount}}
160
+ }}"""
161
+ try:
162
+ api.logger.info("Retrieving all changes from RegScale...")
163
+ existing_changes = api.graph(query=body)["changes"]["items"]
164
+ api.logger.info("Retrieved %i change(s) from RegScale.", len(existing_changes))
165
+ except (JSONDecodeError, KeyError):
166
+ existing_changes = []
167
+ return [Change(**change) for change in existing_changes]