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,204 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Model for Security Plan in the application"""
4
+
5
+ from typing import Optional, Union
6
+
7
+ from pydantic import ConfigDict, Field, field_validator
8
+
9
+ from regscale.core.app.api import Api
10
+ from regscale.core.app.logz import create_logger
11
+ from regscale.core.app.utils.app_utils import get_current_datetime
12
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
13
+
14
+
15
+ class SecurityPlan(RegScaleModel):
16
+ """
17
+ Security Plan model
18
+ """
19
+
20
+ _module_slug = "securityplans"
21
+
22
+ id: int = 0
23
+ uuid: str = ""
24
+ systemName: str
25
+ systemType: str = "Major Application"
26
+ defaultAssessmentDays: int = 0
27
+ planInformationSystemSecurityOfficerId: Optional[str] = None
28
+ planAuthorizingOfficialId: Optional[str] = None
29
+ systemOwnerId: Optional[str] = None # this could be userID
30
+ otherIdentifier: Optional[str] = ""
31
+ confidentiality: str = ""
32
+ integrity: str = ""
33
+ availability: str = ""
34
+ status: Optional[str] = "Operational"
35
+ description: Optional[str] = ""
36
+ dateSubmitted: Optional[str] = ""
37
+ approvalDate: Optional[str] = ""
38
+ expirationDate: Optional[str] = ""
39
+ purpose: Optional[str] = ""
40
+ conditionsOfApproval: Optional[str] = ""
41
+ environment: Optional[str] = ""
42
+ lawsAndRegulations: Optional[str] = ""
43
+ authorizationBoundary: Optional[str] = ""
44
+ networkArchitecture: Optional[str] = ""
45
+ dataFlow: Optional[str] = ""
46
+ overallCategorization: Optional[str] = ""
47
+ maturityTier: Optional[str] = ""
48
+ wizProjectId: Optional[str] = ""
49
+ serviceNowAssignmentGroup: Optional[str] = ""
50
+ jiraProject: Optional[str] = ""
51
+ tenableGroup: Optional[str] = ""
52
+ facilityId: Optional[int] = None
53
+ orgId: Optional[int] = None
54
+ parentId: int = 0
55
+ parentModule: str = ""
56
+ createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
57
+ dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
58
+ lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
59
+ dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
60
+ users: int = 0
61
+ privilegedUsers: int = 0
62
+ usersMFA: int = 0
63
+ privilegedUsersMFA: int = 0
64
+ hva: bool = False
65
+ practiceLevel: Optional[str] = ""
66
+ processLevel: Optional[str] = ""
67
+ cmmcLevel: Optional[str] = ""
68
+ cmmcStatus: Optional[str] = ""
69
+ isPublic: bool = True
70
+ executiveSummary: Optional[str] = ""
71
+ recommendations: Optional[str] = ""
72
+ bDeployGov: bool = False
73
+ bDeployHybrid: bool = False
74
+ bDeployPrivate: bool = False
75
+ bDeployPublic: bool = False
76
+ bDeployOther: bool = False
77
+ deployOtherRemarks: Optional[str] = ""
78
+ bModelIaaS: bool = False
79
+ bModelOther: bool = False
80
+ bModelPaaS: bool = False
81
+ bModelSaaS: bool = False
82
+ otherModelRemarks: Optional[str] = ""
83
+ explanationForNonOperational: Optional[str] = ""
84
+ version: Optional[str] = ""
85
+ categorizationJustification: Optional[str] = ""
86
+ internalUsers: int = 0
87
+ externalUsers: int = 0
88
+ externalUsersFuture: int = 0
89
+ internalUsersFuture: int = 0
90
+ prepOrgName: Optional[str] = ""
91
+ prepAddress: Optional[str] = ""
92
+ prepOffice: Optional[str] = ""
93
+ prepCityState: Optional[str] = ""
94
+ cspOrgName: Optional[str] = ""
95
+ cspAddress: Optional[str] = ""
96
+ cspOffice: Optional[str] = ""
97
+ cspCityState: Optional[str] = ""
98
+ authenticationLevel: Optional[str] = ""
99
+ identityAssuranceLevel: Optional[str] = ""
100
+ authenticatorAssuranceLevel: Optional[str] = ""
101
+ federationAssuranceLevel: Optional[str] = ""
102
+ fedrampAuthorizationType: Optional[str] = ""
103
+ fedrampAuthorizationLevel: Optional[str] = ""
104
+ fedrampAuthorizationStatus: Optional[str] = ""
105
+ fedrampDateSubmitted: Optional[str] = ""
106
+ fedrampDateAuthorized: Optional[str] = ""
107
+ fedrampId: Optional[str] = ""
108
+ complianceSettingsId: Optional[int] = 1
109
+ tenantsId: int = 1
110
+
111
+ @field_validator("complianceSettingsId")
112
+ def validate_regscale_version_and_compliance_settings(cls, v: int) -> Optional[int]:
113
+ """
114
+ Validate the RegScale version and if it is compatible with ComplianceSettings ID, has to be >=6.13
115
+
116
+ :param int v: ComplianceSettings ID
117
+ :return: The ComplianceSettings ID if the RegScale version is compatible, None otherwise
118
+ :rtype: Optional[int]
119
+ """
120
+ from packaging.version import Version
121
+
122
+ regscale_version = cls._get_api_handler().regscale_version
123
+
124
+ if len(regscale_version) >= 10 or Version(regscale_version) >= Version("6.13.0.0"):
125
+ return v
126
+ else:
127
+ return None
128
+
129
+ @staticmethod
130
+ def _get_additional_endpoints() -> ConfigDict:
131
+ """
132
+ Get additional endpoints for the SecurityPlan model.
133
+
134
+ :return: A dictionary of additional endpoints
135
+ :rtype: ConfigDict
136
+ """
137
+ return ConfigDict( # type: ignore
138
+ get_control_implementations="/api/controlImplementation/getAllByPlan/{plan_id}",
139
+ mega_api="/api/{module_slug}/megaAPI/{intId}",
140
+ )
141
+
142
+ @classmethod
143
+ def fetch_mega_api_data(cls, ssp_id: int) -> dict:
144
+ """
145
+ Fetch the Mega API data for the given SSP ID
146
+
147
+ :param int ssp_id: RegScale SSP ID
148
+ :return: Mega API data
149
+ :rtype: dict
150
+ """
151
+ response = cls._get_api_handler().get(
152
+ endpoint=cls.get_endpoint("mega_api").format(module_slug=cls._module_slug, intId=ssp_id)
153
+ )
154
+ if not response.raise_for_status():
155
+ return response.json()
156
+ return {}
157
+
158
+ # Legacy code
159
+ def create_new_ssp(self, api: Api, return_id: Optional[bool] = False) -> Union[int, None, "SecurityPlan"]:
160
+ """
161
+ Create a new SSP in RegScale
162
+
163
+ :param Api api: The API object to use to create the SSP in RegScale
164
+ :param Optional[bool] return_id: Return the SSP ID only
165
+ :return: The SSP or the SSP ID upon success, None otherwise.
166
+ :rtype: Union[int, None, SecurityPlan]
167
+ """
168
+ # create the ssp in RegScale
169
+ data = self.dict()
170
+ ssp_response = api.post(
171
+ f'{api.config["domain"]}/api/securityplans',
172
+ json=data,
173
+ )
174
+ if ssp_response.ok:
175
+ if return_id:
176
+ return ssp_response.json()["id"]
177
+ return SecurityPlan(**ssp_response.json())
178
+ logger = create_logger()
179
+ logger.error(f"Failed to upload SSP: {ssp_response.status_code} - {ssp_response.text}")
180
+ return None
181
+
182
+ def update_ssp(self, api: Api, return_id: Optional[bool] = False) -> Union[int, None, "SecurityPlan"]:
183
+ """
184
+ Update an SSP in RegScale
185
+
186
+ :param Api api: The API object to use to create the SSP in RegScale
187
+ :param Optional[bool] return_id: Return the SSP ID only
188
+ :return: The SSP or the SSP ID upon success, None otherwise.
189
+ :rtype: Union[int, None, SecurityPlan]
190
+ """
191
+ # create the ssp in RegScale
192
+ data = self.dict()
193
+ assert self.id is not None or self.id != 0
194
+ ssp_response = api.put(
195
+ f'{api.config["domain"]}/api/securityplans/{self.id}',
196
+ json=data,
197
+ )
198
+ if ssp_response.ok:
199
+ if return_id:
200
+ return ssp_response.json()["id"]
201
+ return SecurityPlan(**ssp_response.json())
202
+ logger = create_logger()
203
+ logger.error(f"Failed to update SSP: {ssp_response.status_code} - {ssp_response.text}")
204
+ return None
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Model for SoftwareInventory in the application"""
4
+
5
+ from typing import List, Optional, cast
6
+
7
+ from pydantic import ConfigDict, Field
8
+
9
+ from regscale.core.app.api import Api
10
+ from regscale.core.app.application import Application
11
+ from regscale.core.app.utils.app_utils import get_current_datetime
12
+ from regscale.models.regscale_models import RegScaleModel
13
+
14
+
15
+ class SoftwareInventory(RegScaleModel):
16
+ """
17
+ SoftwareInventory
18
+ """
19
+
20
+ _module_slug = "softwareInventory"
21
+ _unique_fields = [
22
+ ["name", "version", "parentHardwareAssetId"],
23
+ ]
24
+ _parent_id_field = "parentHardwareAssetId"
25
+
26
+ # UUID: Optional[str] = None
27
+ name: str
28
+ version: Optional[str] = None
29
+ function: Optional[str] = None
30
+ patchLevel: Optional[str] = None
31
+ parentHardwareAssetId: Optional[int] = None
32
+ parentSoftwareAssetId: Optional[int] = None
33
+ # parentSoftwareInventoryId: Optional[int] = None
34
+ dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
35
+ dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
36
+ createdById: str = Field(default_factory=RegScaleModel.get_user_id)
37
+ lastUpdatedById: str = Field(default_factory=RegScaleModel.get_user_id)
38
+ isPublic: bool = True
39
+ # references: Optional[List[str]] = []
40
+
41
+ @staticmethod
42
+ def _get_additional_endpoints() -> ConfigDict:
43
+ return ConfigDict(
44
+ get_all_by_parent="/api/{model_slug}/getAllByParent/{intParentID}",
45
+ batch_create="/api/{model_slug}/batchCreate",
46
+ batch_update="/api/{model_slug}/batchUpdate",
47
+ )
48
+
49
+ def __eq__(self, other: "SoftwareInventory") -> bool:
50
+ """
51
+ Override the default Equals behavior
52
+
53
+ :param SoftwareInventory other: SoftwareInventory to compare
54
+ :return: True if equal, False otherwise
55
+ :rtype: bool
56
+ """
57
+ if isinstance(other, SoftwareInventory):
58
+ return (
59
+ self.name == other.name
60
+ and self.version == other.version
61
+ and self.parentHardwareAssetId == other.parentHardwareAssetId
62
+ )
63
+ return False
64
+
65
+ def __hash__(self) -> hash:
66
+ """
67
+ Override the default hash behavior
68
+
69
+ :return: hash of the SoftwareInventory
70
+ :rtype: hash
71
+ """
72
+ return hash((self.name, self.version, self.parentHardwareAssetId))
73
+
74
+ @classmethod
75
+ def insert(cls, app: Application, obj: "SoftwareInventory") -> "SoftwareInventory":
76
+ """
77
+ Insert a new SoftwareInventory into RegScale
78
+
79
+ :param Application app: application
80
+ :param SoftwareInventory obj: SoftwareInventory to insert
81
+ :return: SoftwareInventory object
82
+ :rtype: SoftwareInventory
83
+ """
84
+ api = Api()
85
+ result = {}
86
+ res = api.post(url=app.config["domain"] + "/api/softwareinventory", json=obj.dict())
87
+ if res.status_code == 200 and res.ok:
88
+ result = SoftwareInventory(**res.json())
89
+ return result
90
+
91
+ @classmethod
92
+ def update(cls, app: Application, obj: "SoftwareInventory") -> "SoftwareInventory":
93
+ """
94
+ Update an existing SoftwareInventory in RegScale
95
+
96
+ :param Application app: application
97
+ :param SoftwareInventory obj: SoftwareInventory to update
98
+ :return: SoftwareInventory object
99
+ :rtype: SoftwareInventory
100
+ """
101
+ api = Api()
102
+ result = {}
103
+ res = api.put(
104
+ url=app.config["domain"] + f"/api/softwareinventory/{obj.id}",
105
+ json=obj.dict(),
106
+ )
107
+ if res.status_code == 200 and res.ok:
108
+ result = SoftwareInventory(**res.json())
109
+ return result
110
+
111
+ @classmethod
112
+ def fetch_by_asset(cls, app: Application, asset_id: int) -> List["SoftwareInventory"]:
113
+ """
114
+ Fetch all SoftwareInventory for a given asset
115
+
116
+ :param Application app: application
117
+ :param int asset_id: The asset id
118
+ :return: A list of SoftwareInventory objects
119
+ :rtype: List[SoftwareInventory]
120
+ """
121
+ api = Api()
122
+ result = []
123
+ res = api.get(url=app.config["domain"] + f"/api/softwareinventory/getAllByParent/{asset_id}")
124
+ if res.status_code == 200 and res.ok:
125
+ result = [SoftwareInventory(**inv) for inv in res.json()]
126
+ return result
127
+
128
+ @classmethod
129
+ def get_map(cls, plan_id: int, key_field: str = "parentId") -> dict[str, "SoftwareInventory"]:
130
+ """
131
+ Get the asset map for the asset and cache it in Redis.
132
+
133
+ :param int plan_id: Security Plan ID
134
+ :param str key_field: Key field to use, defaults to "identifier"
135
+ :return: Data Map
136
+ :rtype: dict[str, "Data"]
137
+
138
+ # TODO: Implement filter by plan_id in RegScale API
139
+ """
140
+ search_data = f"""query {{
141
+ {cls.get_module_string()}(skip: 0, take: 50) {{
142
+ items {{
143
+ {cls.build_graphql_fields()}
144
+ }}
145
+ totalCount
146
+ pageInfo {{
147
+ hasNextPage
148
+ }}
149
+ }}
150
+ }}"""
151
+ response = cls._get_api_handler().graph(query=search_data)
152
+ objects = cast(List["SoftwareInventory"], cls._handle_graph_response(response))
153
+ return_assets = {}
154
+ for obj in objects:
155
+ identifier = getattr(obj, key_field, None)
156
+ if identifier:
157
+ return_assets[identifier] = obj
158
+
159
+ return {k: v.model_dump_json() for k, v in return_assets.items()}
@@ -0,0 +1,64 @@
1
+ """StakeHolders pydantic BaseModel."""
2
+
3
+ import logging
4
+ import warnings
5
+ from typing import Optional
6
+ from urllib.parse import urljoin
7
+
8
+ from pydantic import field_validator
9
+
10
+ from regscale.core.app.api import Api
11
+ from regscale.core.app.application import Application
12
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
13
+
14
+ logger = logging.getLogger("regscale")
15
+
16
+
17
+ class StakeHolder(RegScaleModel):
18
+ """StakeHolders model"""
19
+
20
+ _module_slug = "stakeholders"
21
+
22
+ id: int = 0
23
+ parentId: int # Required
24
+ parentModule: str # Required
25
+ name: Optional[str] = ""
26
+ shortname: Optional[str] = ""
27
+ title: Optional[str] = ""
28
+ phone: Optional[str] = ""
29
+ email: Optional[str] = ""
30
+ address: Optional[str] = ""
31
+ otherID: Optional[str] = ""
32
+ notes: Optional[str] = ""
33
+
34
+ @classmethod
35
+ @field_validator("email", "shortname", "notes", mode="before", check_fields=True)
36
+ def convert_email_none_to_empty_str(cls, value: Optional[str]) -> str:
37
+ """
38
+ Convert a none value for email, shortname adn notes to an empty string.
39
+
40
+ :param Optional[str] value: The value for the field
41
+ :return: The email value or an empty string
42
+ :rtype: str
43
+ """
44
+ return value if value is not None else ""
45
+
46
+ def post(self, app: Application) -> Optional[dict]:
47
+ """
48
+ Post a StakeHolders to RegScale
49
+
50
+ This method is deprecated, use 'create' method instead
51
+
52
+ :param Application app: The application instance
53
+ :return: The response from the API or None
54
+ :rtype: Optional[dict]
55
+ """
56
+ warnings.warn(
57
+ "The 'post' method is deprecated, use 'create' method instead",
58
+ DeprecationWarning,
59
+ )
60
+ api = Api()
61
+ url = urljoin(app.config.get("domain", ""), "/api/stakeholders")
62
+ data = self.dict()
63
+ response = api.post(url, json=data)
64
+ return response.json() if response.ok else None