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,169 @@
1
+ """
2
+ This module contains the Group model class that represents a group in the RegScale application.
3
+ """
4
+
5
+ import logging
6
+ from typing import Optional, List, Tuple, cast
7
+
8
+ from pydantic import ConfigDict, Field
9
+
10
+ from regscale.core.app.utils.app_utils import get_current_datetime
11
+ from regscale.models import RegScaleModel, User, T, deprecated
12
+ from regscale.models.regscale_models.user_group import UserGroup
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class Group(RegScaleModel):
18
+ _module_slug = "groups"
19
+
20
+ id: Optional[int] = None
21
+ name: Optional[str] = None
22
+ userGroups: Optional[List[UserGroup]] = None
23
+ activated: Optional[bool] = True
24
+ createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
25
+ dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
26
+ lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
27
+ isPublic: Optional[bool] = True
28
+ dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
29
+ tenantsId: Optional[int] = 1
30
+
31
+ @staticmethod
32
+ def _get_additional_endpoints() -> ConfigDict:
33
+ """
34
+ Get additional endpoints for the Group model.
35
+
36
+ :return: A dictionary of additional endpoints
37
+ :rtype: ConfigDict
38
+ """
39
+ return ConfigDict(
40
+ get_groups="/api/{model_slug}",
41
+ change_group_status="/api/{model_slug}/changeGroupStatus/{id}/{strActivated}",
42
+ find_groups_by_user="/api/{model_slug}/findGroupsByUser/{strUser}",
43
+ filter_groups="/api/{model_slug}/filterGroups/{strName}/{strActivated}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
44
+ find_users_by_group="/api/{model_slug}/findUsersByGroup/{intGroupId}",
45
+ )
46
+
47
+ @classmethod
48
+ @deprecated("Use UserGroup.get_users_by_group instead")
49
+ def get_users_in_group(cls, name: str) -> Tuple[List[User], int]:
50
+ """
51
+ Get a list of users in a group.
52
+
53
+ :param str name: The name of the group
54
+ :return: A list of users
55
+ :rtype: Tuple[List[User], int]
56
+ """
57
+ group_list_resp = cls._get_api_handler().get(
58
+ endpoint=cls.get_endpoint("get_groups").format(model_slug=cls._module_slug)
59
+ )
60
+ group_id = 0
61
+ if group_list_resp and group_list_resp.ok:
62
+ group_list = group_list_resp.json()
63
+ for group in group_list:
64
+ if group.get("name") == name:
65
+ group_id = group.get("id")
66
+ break
67
+
68
+ response = cls._get_api_handler().get(
69
+ endpoint=cls.get_endpoint("find_users_by_group").format(model_slug=cls._module_slug, intGroupId=group_id)
70
+ )
71
+ if response and response.ok:
72
+ users = [User(**user) for user in response.json()]
73
+ for user in users:
74
+ # add delegates to users list
75
+ users.extend(user.get_delegates(user.id))
76
+ return users, group_id
77
+ else:
78
+ logger.error(f"Failed to get users in group {name}")
79
+ return [], group_id
80
+
81
+ @classmethod
82
+ def get_group_by_name(cls, name: str) -> Optional["Group"]:
83
+ """
84
+ Get a group by name
85
+ :param name: The name of the group
86
+ :return: The group
87
+ :rtype: Optional[Group]
88
+ """
89
+ response = cls._get_api_handler().get(
90
+ endpoint=cls.get_endpoint("get_groups").format(model_slug=cls._module_slug)
91
+ )
92
+ if response and response.ok:
93
+ group_list = response.json()
94
+ for group in group_list:
95
+ if group.get("name") == name:
96
+ return cls(**group)
97
+ else:
98
+ cls.log_response_error(response=response)
99
+ return None
100
+
101
+ @classmethod
102
+ def get_group_list(cls) -> List["Group"]:
103
+ """
104
+ Get a list of groups
105
+ :return: A list of groups
106
+ :rtype: List[Group]
107
+ """
108
+ response = cls._get_api_handler().get(
109
+ endpoint=cls.get_endpoint("get_groups").format(model_slug=cls._module_slug)
110
+ )
111
+ return cast(List[T], cls._handle_list_response(response))
112
+
113
+ @classmethod
114
+ def find_groups_by_user(cls, user: str) -> List["Group"]:
115
+ """
116
+ Find groups by user
117
+ :param user: The user ID
118
+ :return: A list of groups
119
+ :rtype: List[Group]
120
+ """
121
+ response = cls._get_api_handler().get(
122
+ endpoint=cls.get_endpoint("find_groups_by_user").format(model_slug=cls._module_slug, strUser=user)
123
+ )
124
+ return cast(List[T], cls._handle_list_response(response))
125
+
126
+ @classmethod
127
+ def filter_groups(
128
+ cls, name: str, activated: str, sort_by: str, direction: str, page: int, page_size: int
129
+ ) -> List["Group"]:
130
+ """
131
+ Filter groups
132
+ :param name: The name of the group
133
+ :param activated: The activation status
134
+ :param sort_by: The field to sort by
135
+ :param direction: The sort direction
136
+ :param page: The page number
137
+ :param page_size: The page size
138
+ :return: A list of groups
139
+ :rtype: List[Group]
140
+ """
141
+ response = cls._get_api_handler().get(
142
+ endpoint=cls.get_endpoint("filter_groups").format(
143
+ model_slug=cls._module_slug,
144
+ strName=name,
145
+ strActivated=activated,
146
+ strSortBy=sort_by,
147
+ strDirection=direction,
148
+ intPage=page,
149
+ intPageSize=page_size,
150
+ )
151
+ )
152
+ return cast(List[T], cls._handle_list_response(response))
153
+
154
+ @classmethod
155
+ def find_users_by_group(cls, group_id: int) -> List[User]:
156
+ """
157
+ Find users by group
158
+ :param group_id: The group ID
159
+ :return: A list of users
160
+ :rtype: List[User]
161
+ """
162
+ response = cls._get_api_handler().get(
163
+ endpoint=cls.get_endpoint("find_users_by_group").format(model_slug=cls._module_slug, intGroupId=group_id)
164
+ )
165
+ if response and response.ok:
166
+ return [User(**o) for o in response.json()]
167
+ else:
168
+ cls.log_response_error(response=response)
169
+ return []
@@ -0,0 +1,335 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Dataclass for Implementation Objective in the application"""
4
+ import logging
5
+ import uuid
6
+ from dataclasses import asdict
7
+ from enum import Enum
8
+ from logging import Logger
9
+ from typing import Any, Optional, Union, Dict
10
+
11
+ import requests
12
+ from pydantic import Field, 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.logz import create_logger
18
+ from regscale.core.app.utils.app_utils import get_current_datetime
19
+ from regscale.models.regscale_models.regscale_model import RegScaleModel
20
+
21
+
22
+ logger = logging.getLogger("regscale")
23
+
24
+
25
+ class ImplementationStatus(str, Enum):
26
+ """
27
+ Implementation Status
28
+ :param Enum: Enum
29
+ """
30
+
31
+ FULLY_IMPLEMENTED = "Fully Implemented"
32
+ PARTIALLY_IMPLEMENTED = "Partially Implemented"
33
+ NOT_IMPLEMENTED = "Not Implemented"
34
+
35
+
36
+ class ImplementationObjectiveResponsibility(str, Enum):
37
+ """
38
+ Responsibility Enum
39
+ :param Enum: Enum
40
+ """
41
+
42
+ PROVIDER = "Provider"
43
+ PROVIDER_SYSTEM_SPECIFIC = "Provider (System Specific)"
44
+ HYBRID = "Hybrid"
45
+ CUSTOMER = "Customer"
46
+ CUSTOMER_CONFIGURED = "Customer Configured"
47
+ SHARED = "Shared"
48
+ INHERITED = "Inherited"
49
+ NOT_APPLICABLE = "Not Applicable"
50
+
51
+
52
+ class ImplementationObjective(RegScaleModel):
53
+ """
54
+ RegScale Implementation Objective
55
+ Represents a row in the ImplementationObjectives table in the database.
56
+
57
+ Relationships:
58
+ - ImplementationId -> ControlImplementation (1:1)
59
+ - ObjectiveId -> ControlObjective (0..1:1) [optional]
60
+ - OptionId -> ImplementationOption (1:1)
61
+ - SecurityControlId -> SecurityControls (0..1:1) [optional]
62
+ - CreatedBy, LastUpdatedBy -> AspNetUsers (1:1) [FKs]
63
+ - TenantsId -> Tenants (1:1) [inherited]
64
+ - AuthorizationId -> LeveragedAuthorizations (0..1:1) [optional]
65
+ """
66
+
67
+ _module_slug = "implementationObjectives"
68
+ _get_objects_for_list = True # TODO: Fix API to return securityControlId
69
+ _unique_fields = [
70
+ ["implementationId", "objectiveId"],
71
+ ]
72
+ _parent_id_field = "implementationId"
73
+
74
+ id: int = 0
75
+ securityControlId: int
76
+ uuid: str = Field(default_factory=lambda: str(uuid.uuid4())) # Required
77
+ notes: Optional[str] = None
78
+ implementationId: int # Required, FK to ControlImplementation
79
+ optionId: Optional[int] = None # no longer Required, FK to ImplementationOption
80
+ inherited: Optional[bool] = False
81
+ status: Optional[Union[str, ImplementationStatus]] = ImplementationStatus.NOT_IMPLEMENTED # Not Required
82
+ objectiveId: Optional[int] = None # Optional, FK to ControlObjective
83
+ createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
84
+ lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
85
+ # statement Should be required, represents the implementation statement
86
+ statement: Optional[str] = None
87
+ dateLastAssessed: str = Field(default_factory=get_current_datetime) # Required
88
+ dateCreated: str = Field(default_factory=get_current_datetime) # Required
89
+ dateLastUpdated: str = Field(default_factory=get_current_datetime) # Required
90
+ isPublic: bool = True # Required
91
+ parentObjectiveId: Optional[int] = None
92
+ authorizationId: Optional[int] = None
93
+ responsibility: Optional[str] = None
94
+ cloudResponsibility: Optional[str] = None
95
+ customerResponsibility: Optional[str] = None
96
+
97
+ def __init__(self, **data: Any):
98
+ # returned by bad api values for securityControlId corrected with validator
99
+ # Map 'controlId' to 'securityControlId' internally
100
+ if "controlId" in data:
101
+ data["securityControlId"] = data.pop("controlId")
102
+ super().__init__(**data)
103
+
104
+ @staticmethod
105
+ def _get_additional_endpoints() -> ConfigDict:
106
+ """
107
+ Get additional endpoints for the ImplementationObjectives model, using {model_slug} as a placeholder for the model slug.
108
+
109
+ :return: Additional endpoints for the ImplementationObjective
110
+ :rtype: ConfigDict
111
+ """
112
+ return ConfigDict( # type: ignore
113
+ get_all_by_parent="/api/{model_slug}/getByControl/{intParentID}",
114
+ get_by_control="/api/{model_slug}/getByControl/{intControl}",
115
+ get_assessment="/api/{model_slug}/getAssessment/{intControl}/{intObjective}",
116
+ batch_create="/api/{model_slug}/batchCreate",
117
+ merge="/api/{model_slug}/merge/{implementationID}/{securityControlID}",
118
+ )
119
+
120
+ @classmethod
121
+ def merge_objectives(cls, implementationId: int, securityControlId: int) -> Dict:
122
+ """
123
+ Merge objectives for a given implementation and security control
124
+
125
+ :param int implementationId: Implementation ID
126
+ :param int securityControlId: Security Control ID
127
+ :return: Merged objectives
128
+ :rtype: Dict
129
+ """
130
+
131
+ response = cls._get_api_handler().get(
132
+ endpoint=cls.get_endpoint("merge").format(
133
+ implementationID=implementationId, securityControlID=securityControlId
134
+ )
135
+ )
136
+ if response and response.ok:
137
+ return response.json()
138
+
139
+ # pydantic provides __eq__ method
140
+ def __eq__(self, other: "ImplementationObjective") -> bool:
141
+ """
142
+ Check if two ImplementationObjective objects are equal
143
+
144
+ :param ImplementationObjective other: ImplementationObjective object to compare to
145
+ :return: True if equal, False if not equal
146
+ :rtype: bool
147
+ """
148
+ if isinstance(other, ImplementationObjective):
149
+ return (
150
+ getattr(self, "notes", None) == getattr(other, "notes", None)
151
+ and getattr(self, "implementationId", None) == getattr(other, "implementationId", None)
152
+ and getattr(self, "objectiveId", None) == getattr(other, "objectiveId", None)
153
+ and getattr(self, "optionId", None) == getattr(other, "optionId", None)
154
+ and getattr(self, "statement", None) == getattr(other, "statement", None)
155
+ )
156
+ return False
157
+
158
+ def __hash__(self) -> hash:
159
+ """
160
+ Hash a ImplementationObjective object
161
+
162
+ :return: Hash of ImplementationObjective object
163
+ :rtype: hash
164
+ """
165
+ return hash((self.implementationId, self.objectiveId))
166
+
167
+ @classmethod
168
+ def get_by_control(
169
+ cls,
170
+ implementation_id: int,
171
+ ) -> list["ImplementationObjective"]:
172
+ """
173
+ Get a list of implementation options by control id and security plan id
174
+
175
+ :param int implementation_id: Implementation Control ID
176
+ :return: A list of implementation options
177
+ :rtype: list[ImplementationObjective]
178
+ """
179
+ response = cls._get_api_handler().get(
180
+ endpoint=cls.get_endpoint("get_by_control").format(intControl=implementation_id),
181
+ )
182
+ if response and response.ok:
183
+ return [cls(**obj) for obj in response.json()]
184
+ return []
185
+
186
+ @property
187
+ def logger(self) -> Logger:
188
+ """
189
+ Logger implementation for a dataclass
190
+
191
+ :return: logger object
192
+ :rtype: Logger
193
+ """
194
+ logger = create_logger()
195
+ return logger
196
+
197
+ @staticmethod
198
+ def fetch_by_security_control(
199
+ app: Application,
200
+ security_control_id: int,
201
+ ) -> list["ImplementationObjective"]:
202
+ """
203
+ Fetch list of all implementation objectives in RegScale via API
204
+
205
+ :param Application app: Application Instance
206
+ :param int security_control_id: Security Control ID # in RegScale
207
+ :return: List of security controls from RegScale
208
+ :rtype: list[ImplementationObjective]
209
+ """
210
+ api = Api()
211
+ logger = create_logger()
212
+ query = """
213
+ query {
214
+ implementationObjectives (
215
+ take: 50,
216
+ skip: 0,
217
+ where: { securityControlId: {eq: placeholder }, })
218
+ {
219
+ items {
220
+ id,
221
+ uuid,
222
+ notes,
223
+ optionId,
224
+ implementationId,
225
+ securityControlId,
226
+ objectiveId,
227
+ status
228
+ }
229
+ totalCount
230
+ pageInfo {
231
+ hasNextPage
232
+ }
233
+ }
234
+ }
235
+ """.replace(
236
+ "placeholder", str(security_control_id)
237
+ )
238
+ results = []
239
+ data = api.graph(query=query)
240
+ if "implementationObjectives" in data.keys():
241
+ try:
242
+ results.extend(data["implementationObjectives"]["items"])
243
+ except requests.exceptions.JSONDecodeError:
244
+ logger.warning(
245
+ "Unable to find control implementation objectives for control %i.",
246
+ security_control_id,
247
+ )
248
+ return [ImplementationObjective(**obj) for obj in results]
249
+
250
+ @staticmethod
251
+ def update_objective(
252
+ app: Application,
253
+ obj: Any,
254
+ ) -> Response:
255
+ """
256
+ Update a single implementation objective
257
+
258
+ :param Application app: Application Instance
259
+ :param Any obj: Implementation Objective
260
+ :return: Response from RegScale API
261
+ :rtype: Response
262
+ """
263
+ if isinstance(obj, ImplementationObjective):
264
+ obj = asdict(obj)
265
+ api = Api(retry=10)
266
+ return api.put(
267
+ url=app.config["domain"] + f"/api/implementationObjectives/{obj['id']}",
268
+ json=obj,
269
+ )
270
+
271
+ @staticmethod
272
+ def insert_objective(
273
+ app: Application,
274
+ obj: Any,
275
+ ) -> Response:
276
+ """
277
+ Update a single implementation objective
278
+
279
+ :param Application app: Application Instance
280
+ :param Any obj: Implementation Objective
281
+ :return: Response from RegScale API
282
+ :rtype: Response
283
+ """
284
+ if isinstance(obj, ImplementationObjective):
285
+ obj = asdict(obj)
286
+ api = Api(retry=10)
287
+ res = api.post(url=app.config["domain"] + "/api/implementationObjectives", json=obj)
288
+ return res
289
+
290
+ @classmethod
291
+ def fetch_implementation_objectives(
292
+ cls, app: Application, control_id: int, query_type: Optional[str] = "implementation"
293
+ ) -> list[dict]:
294
+ """
295
+ Fetch list of implementation objectives by control id
296
+
297
+ :param Application app: Application Instance
298
+ :param int control_id: Implementation Control ID
299
+ :param Optional[str] query_type: Query Type for GraphQL query
300
+ :return: A list of Implementation Objectives as a dictionary
301
+ :rtype: list[dict]
302
+ """
303
+ graph_query = """
304
+ query {
305
+ implementationObjectives (skip: 0, take: 50, where: {securityControlId: {eq: placeholder}}) {
306
+ items {
307
+ id
308
+ notes
309
+ optionId
310
+ objectiveId
311
+ implementationId
312
+ securityControlId
313
+ status
314
+ }
315
+ totalCount
316
+ pageInfo {
317
+ hasNextPage
318
+ }
319
+ }
320
+ }
321
+ """.replace(
322
+ "placeholder", str(control_id)
323
+ )
324
+ results: list[Any] = []
325
+ api = Api()
326
+ if query_type != "implementation":
327
+ results = cls._get_api_handler().graph(graph_query)
328
+ else:
329
+ res = api.get(url=app.config["domain"] + f"/api/implementationObjectives/getByControl/{control_id}")
330
+ if res.ok:
331
+ try:
332
+ results = res.json()
333
+ except requests.exceptions.JSONDecodeError:
334
+ logger.warning("Unable to find control implementation objectives.")
335
+ return results