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,88 @@
1
+ """Generate a hierarchy for Airflow based on Click."""
2
+
3
+ from typing import Optional
4
+
5
+ from regscale.regscale import cli
6
+ from regscale.models.click_models import ClickCommand
7
+ from regscale.airflow.click_mixins import AirflowClickGroup
8
+
9
+ AIRFLOW_CLICK_GROUP = AirflowClickGroup.from_group(cli, prefix="regscale")
10
+ AIRFLOW_CLICK_OPERATORS = AIRFLOW_CLICK_GROUP.flatten_operator()
11
+
12
+
13
+ def iter_operators(operators: dict = AIRFLOW_CLICK_OPERATORS) -> dict:
14
+ """Iterate over the operators and create a structured dict"""
15
+
16
+ def _nested_dict(data: tuple, value: ClickCommand, result: dict = None) -> Optional[dict]:
17
+ """Create a single dict from a nested dict."""
18
+ if result is None:
19
+ result = {}
20
+ if len(data) > 1:
21
+ key = data[0]
22
+ if key not in result:
23
+ result[key] = {}
24
+ _nested_dict(data=data[1:], value=value, result=result[key])
25
+ else:
26
+ if data[0] in result:
27
+ if isinstance(result[data[0]], dict):
28
+ result[data[0]].update(_make_platform_params(value))
29
+ else:
30
+ result[data[0]] = [result[data[0]], _make_platform_params(value)]
31
+ else:
32
+ result[data[0]] = _make_platform_params(value)
33
+ return result
34
+
35
+ def _make_platform_params(command: ClickCommand) -> dict:
36
+ """Create a dict from a command of what platform would need."""
37
+ return {
38
+ "name": command.name,
39
+ "params": command.parameters,
40
+ "parameters": {**command.params},
41
+ }
42
+
43
+ new_dict = {}
44
+ for operator, op_dict in operators.items():
45
+ if "__" in operator:
46
+ operator_split = operator.split("__")
47
+ new_dict = _nested_dict(data=operator_split, value=op_dict["command"], result=new_dict)
48
+ else:
49
+ if operator in new_dict:
50
+ if isinstance(new_dict[operator], dict):
51
+ new_dict[operator].update(_make_platform_params(op_dict["command"]))
52
+ else:
53
+ new_dict[operator] = [
54
+ new_dict[operator],
55
+ _make_platform_params(op_dict["command"]),
56
+ ]
57
+ else:
58
+ new_dict[operator] = _make_platform_params(op_dict["command"])
59
+ return new_dict
60
+
61
+
62
+ AIRFLOW_CLI_HIERARCHY = iter_operators()
63
+
64
+
65
+ def get_command_params(cmd: str) -> list:
66
+ """Get the parameters for a command
67
+
68
+ :param str cmd: the command to get the parameters for
69
+ :return: a list of parameters
70
+ :rtype: list
71
+ """
72
+ cmd_split = cmd.split(" ")
73
+ if len(cmd_split) == 1:
74
+ return AIRFLOW_CLI_HIERARCHY[cmd_split[0]]["params"]
75
+ elif len(cmd_split) == 2:
76
+ return AIRFLOW_CLI_HIERARCHY[cmd_split[0]][cmd_split[1]]["params"]
77
+
78
+
79
+ def return_all_commands_and_params() -> dict:
80
+ """Return all commands and parameters
81
+
82
+ :return: a dict of commands and parameters
83
+ :rtype: dict
84
+ """
85
+ dct = {}
86
+ for operator in AIRFLOW_CLICK_OPERATORS:
87
+ click_name = " ".join(operator.split("__"))
88
+ dct[click_name] = {"parameters": AIRFLOW_CLICK_OPERATORS[operator]["command"].parameters}
File without changes
@@ -0,0 +1,36 @@
1
+ """Generate PythonOperators based on a click.Command."""
2
+
3
+ from typing import Union, Optional
4
+
5
+ import click
6
+ from airflow.operators.python import PythonOperator
7
+
8
+ from airflow import DAG
9
+ from regscale.airflow.tasks.click import execute_click_command
10
+ from regscale.models.click_models import ClickCommand
11
+
12
+
13
+ def generate_operator_for_command(
14
+ command: Union[click.Command, ClickCommand],
15
+ command_name: Optional[str] = None,
16
+ dag: Optional[DAG] = None,
17
+ **kwargs: dict,
18
+ ) -> PythonOperator:
19
+ """Generate a PythonOperator for a Click Command
20
+
21
+ :param Union[click.Command, ClickCommand] command: the command to generate the operator for
22
+ :param Optional[str] command_name: optional command name to specify as task_id, defaults to None
23
+ :param Optional[DAG] dag: an Optional airflow DAG to pass, defaults to None
24
+ :param dict **kwargs: additional named parameters to pass to PythonOperator
25
+ :return: a PythonOperator configured to execute the Click Command
26
+ :rtype: PythonOperator
27
+ """
28
+ if isinstance(command, click.Command):
29
+ command = ClickCommand.from_command(command)
30
+ return PythonOperator(
31
+ task_id=command_name or command.name,
32
+ python_callable=execute_click_command,
33
+ op_kwargs={"command": command.callback},
34
+ dag=dag,
35
+ **kwargs,
36
+ )
File without changes
@@ -0,0 +1,107 @@
1
+ """SQL Sensors for Airflow"""
2
+
3
+ from typing import Literal
4
+ from uuid import uuid4
5
+
6
+ from airflow.sensors.sql import SqlSensor
7
+
8
+ from regscale.airflow.sessions.sql import SQLQuery
9
+
10
+
11
+ class SqlSensorXcon(SqlSensor):
12
+ def __init__(self, step_name: str = "sql_sensor_xcon", **kwargs):
13
+ super().__init__(**kwargs)
14
+ self.step_name = step_name
15
+
16
+ def poke(self, context):
17
+ self.log.info(f"Poking: {self.sql}")
18
+ records = self._get_hook().get_first(self.sql, parameters=self.parameters)
19
+ if not records:
20
+ return False
21
+ context["task_instance"].xcom_push(key=self.step_name, value=records)
22
+ return True
23
+
24
+
25
+ def build_sql_sensor_xcon(
26
+ sql: SQLQuery,
27
+ name: str = None,
28
+ conn_id: str = "platform_db",
29
+ unique: bool = False,
30
+ mode: Literal["reschedule", "poke"] = "poke",
31
+ step_name: str = "sql_sensor_xcon",
32
+ timeout: int = 60 * 60 * 24 * 7,
33
+ poke_interval: int = 60 * 5,
34
+ **kwargs: dict,
35
+ ) -> SqlSensorXcon:
36
+ """Build a SQL Sensor that will push its results to XCom
37
+
38
+ :param SQLQuery sql: the SQL query to run
39
+ :param str name: the name of the sensor, defaults to None
40
+ :param str conn_id: the connection id to use, defaults to "platform_db"
41
+ :param bool unique: whether to make the sensor unique, defaults to False
42
+ :param Literal["reschedule", "poke"] mode: the mode of the sensor, defaults to "poke"
43
+ :param str step_name: the name of the step, defaults to "sql_sensor_xcon"
44
+ :param int timeout: the timeout of the sensor, defaults to 60 * 60 * 24 * 7
45
+ :param int poke_interval: the poke interval of the sensor, defaults to 60 * 5
46
+ :param dict kwargs: keyword arguments to pass to the sensor
47
+ :return: the SQL Sensor
48
+ :rtype: SqlSensorXcon
49
+ """
50
+ dag_run_dict = dict(zip(sql.dag_run_vars, sql.dag_run_vars))
51
+ params_dict = dict(zip(sql.params, sql.params))
52
+ if unique and name is not None:
53
+ name = f"{name}-{str(uuid4())[:8]}"
54
+
55
+ return SqlSensorXcon(
56
+ task_id=name or f"sql_sensor-{name or str(uuid4())[:8]}",
57
+ sql=sql.raw,
58
+ conn_id=conn_id,
59
+ params=params_dict or dag_run_dict,
60
+ mode=mode,
61
+ step_name=step_name,
62
+ timeout=timeout,
63
+ poke_interval=poke_interval,
64
+ **kwargs,
65
+ )
66
+
67
+
68
+ def build_sql_sensor(
69
+ sql: SQLQuery,
70
+ name: str = None,
71
+ conn_id: str = "platform_db",
72
+ unique: bool = False,
73
+ mode: Literal["reschedule", "poke"] = "poke",
74
+ timeout: int = 60 * 60 * 24 * 7,
75
+ poke_interval: int = 60 * 5,
76
+ **kwargs: dict,
77
+ ) -> SqlSensor:
78
+ """Build a SQL Sensor from a SQLQuery object
79
+
80
+ :param SQLQuery sql: the SQL query to run
81
+ :param str name: the name of the sensor, defaults to None
82
+ :param str conn_id: the connection id to use, defaults to "platform_db"
83
+ :param bool unique: whether to make the sensor unique, defaults to False
84
+ :param Literal["reschedule", "poke"] mode: the mode of the sensor, defaults to "poke"
85
+ :param int timeout: the timeout of the sensor, defaults to 60 * 60 * 24 * 7
86
+ :param int poke_interval: the poke interval of the sensor, defaults to 60 * 5
87
+ :param dict **kwargs: additional keyword arguments
88
+ :return: the SQL Sensor
89
+ :rtype: SqlSensor
90
+ """
91
+ dag_run_dict = dict(zip(sql.dag_run_vars, sql.dag_run_vars))
92
+ params_dict = dict(zip(sql.params, sql.params))
93
+ if unique and name:
94
+ name = f"{name}-{str(uuid4())[:8]}"
95
+ if unique and name is None:
96
+ name = f"sql_sensor-{str(uuid4())[:8]}"
97
+
98
+ return SqlSensor(
99
+ task_id=name,
100
+ sql=sql.raw,
101
+ conn_id=conn_id,
102
+ params=params_dict or dag_run_dict,
103
+ mode=mode,
104
+ timeout=timeout,
105
+ poke_interval=poke_interval,
106
+ **kwargs,
107
+ )
File without changes
@@ -0,0 +1,3 @@
1
+ """Import"""
2
+
3
+ from regscale.airflow.sessions.sql.queries import SQLQuery
@@ -0,0 +1,64 @@
1
+ """Provide SQL Queries to be used in Airflow DAGs related to SQL Server."""
2
+
3
+ from typing import List
4
+
5
+ from regscale.utils.string import (
6
+ replace_unknown_spaces_and_newlines,
7
+ extract_double_curly_braces_contents,
8
+ extract_dag_run_conf_key,
9
+ extract_param,
10
+ )
11
+
12
+
13
+ class SQLQuery:
14
+ """
15
+ A class to represent a SQL Query
16
+
17
+ :param str query: a SQL query
18
+ :param dict **kwargs: additional keyword arguments
19
+ """
20
+
21
+ def __init__(self, query: str = "", **kwargs: dict):
22
+ self.raw = query
23
+ self.query = replace_unknown_spaces_and_newlines(query)
24
+ self.kwargs = kwargs
25
+ self.vars: List[str] = []
26
+ self.dag_run_vars: List[str] = []
27
+ self.params: List[str] = []
28
+ self.jinja_kwargs = {}
29
+ self._populate_jinja_vars(**kwargs)
30
+
31
+ def __repr__(self) -> str:
32
+ """Return the SQLQuery object
33
+
34
+ :return: the SQLQuery object as a string
35
+ :rtype: str
36
+ """
37
+ return f"SQLQuery(query={self.query}, kwargs={self.kwargs})"
38
+
39
+ def __str__(self) -> str:
40
+ """Return the SQLQuery object
41
+
42
+ :return: the SQLQuery object as a string
43
+ :rtype: str
44
+ """
45
+ return f"{self.dag_run_vars=}\n{self.params=}\n{self.unique_vars=}"
46
+
47
+ def _populate_jinja_vars(self, **kwargs: dict):
48
+ """Populate the SQLQuery object with Jinja variables
49
+
50
+ :param dict **kwargs: keyword arguments
51
+ """
52
+ self.jinja_kwargs = kwargs
53
+ self.vars = extract_double_curly_braces_contents(self.query)
54
+ self.dag_run_vars = [extract_dag_run_conf_key(__) for __ in self.vars]
55
+ self.params = [extract_param(_) for _ in self.vars]
56
+
57
+ @property
58
+ def unique_vars(self) -> List[str]:
59
+ """Return a list of unique Jinja variables
60
+
61
+ :return: a list of unique Jinja variables as strings
62
+ :rtype: List[str]
63
+ """
64
+ return list(set(self.dag_run_vars + self.params))
@@ -0,0 +1,248 @@
1
+ """SQL Server Platform Queries."""
2
+
3
+ from regscale.airflow.sessions.sql.queries import SQLQuery
4
+
5
+
6
+ CHECK_WORKFLOW_STATUS_QUERY: str = """
7
+ SELECT
8
+ CASE
9
+ WHEN EXISTS (
10
+ SELECT 1
11
+ FROM dbo.WorkflowInstance wi
12
+ WHERE wi.id = {{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }}
13
+ AND NOT EXISTS (
14
+ SELECT 1
15
+ FROM dbo.WorkflowInstanceSteps wis
16
+ WHERE wis.WorkflowInstanceId = wi.id
17
+ AND wis.[Status] <> 'Rejected'
18
+ )
19
+ ) THEN -1
20
+ WHEN EXISTS (
21
+ SELECT 1
22
+ FROM dbo.WorkflowInstance wi
23
+ WHERE wi.id = {{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }}
24
+ AND NOT EXISTS (
25
+ SELECT 1
26
+ FROM dbo.WorkflowInstanceSteps wis
27
+ WHERE wis.WorkflowInstanceId = wi.id
28
+ AND wis.[Status] <> 'Approved'
29
+ )
30
+ ) THEN 1
31
+ WHEN EXISTS(
32
+ SELECT 1
33
+ FROM dbo.WorkflowInstance wi
34
+ WHERE wi.id = {{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }}
35
+ AND NOT EXISTS (
36
+ SELECT 1
37
+ FROM dbo.WorkflowInstanceSteps wis
38
+ WHERE wis.WorkflowInstanceId = wi.id
39
+ AND wis.[Status] <> 'Pending'
40
+ ) THEN 0
41
+ ELSE NULL
42
+ END AS OverallStatus;
43
+ """
44
+
45
+ NEW_CHECK_WORKFLOW_STATUS_QUERY: str = """
46
+ declare @workflowInstanceId int = {{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }}
47
+ declare @workflowStepId int = -1
48
+ ;WITH orderedWorkFlowSteps AS
49
+ (
50
+ SELECT
51
+ id, ROW_NUMBER() OVER(ORDER BY [Order] DESC) AS 'RowNum'
52
+ FROM WorkflowInstanceSteps where WorkflowInstanceId = @workflowInstanceId
53
+ )
54
+ SELECT @workflowStepId = id
55
+ FROM orderedWorkFlowSteps
56
+ WHERE RowNum = 2
57
+ SELECT
58
+ case
59
+ when exists
60
+ (select wis.id from dbo.WorkflowInstanceSteps wis
61
+ where wis.Id = @workflowStepId and wis.WorkflowInstanceId = @workflowInstanceId and wis.[Status] = 'Rejected')
62
+ then -1
63
+ when exists
64
+ (select wis.id from dbo.WorkflowInstanceSteps wis
65
+ where wis.Id = @workflowStepId and wis.WorkflowInstanceId = @workflowInstanceId and wis.[Status] = 'Approved')
66
+ then 1
67
+ when exists
68
+ (select wis.id from dbo.WorkflowInstanceSteps wis
69
+ where wis.Id = @workflowStepId and wis.WorkflowInstanceId = @workflowInstanceId and wis.[Status] = 'Pending')
70
+ then 0
71
+ else
72
+ null
73
+ end as OverallStatus;
74
+ """
75
+
76
+ NEWER_CHECK_WORKFLOW_STATUS_QUERY: str = """
77
+ declare @workflowInstanceId int = {{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }}
78
+ ;select * from WorkflowInstanceSteps
79
+ where WorkflowInstanceId = @workflowInstanceId and [Order] not in (0, 1000) order by [order] -- this is for validating results only
80
+ select top 1
81
+ case when wis.status = 'Rejected' then -1
82
+ when wis.status = 'Approved' then 1
83
+ when wis.status = 'Pending' then 0
84
+ else null
85
+ end as OverallStatus,
86
+ *
87
+ from WorkflowInstanceSteps wis
88
+ where wis.WorkflowInstanceId = @workflowInstanceId
89
+ and status in ('Rejected', 'Approved', 'Pending' )
90
+ order by [Order] DESC;
91
+ """
92
+
93
+ CHECK_IF_COMPLETED_QUERY: str = """
94
+ DECLARE @workflowInstanceId INT = '{{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }}';
95
+ WITH OrderedSteps AS (
96
+ SELECT
97
+ wis.*,
98
+ LEAD(wis.[Order]) OVER (ORDER BY wis.[Order] DESC) AS NextOrder,
99
+ LEAD(wis.[Status]) OVER (ORDER BY wis.[Order] DESC) AS NextStatus
100
+ FROM WorkflowInstanceSteps wis
101
+ WHERE wis.WorkflowInstanceId = @workflowInstanceId
102
+ )
103
+ SELECT
104
+ CASE
105
+ WHEN [Order] = 1000 AND NextStatus = 'Approved' THEN 1
106
+ ELSE NULL
107
+ END AS Result
108
+ FROM OrderedSteps
109
+ WHERE [Order] = 1000;
110
+ """
111
+
112
+ WATCH_WORFKLOW_QUERY: str = """
113
+ DECLARE @workflowInstanceId INT = {{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }};
114
+ WITH OrderedSteps AS (
115
+ SELECT
116
+ wis.*,
117
+ LEAD(wis.[Order]) OVER (ORDER BY wis.[Order] DESC) AS NextOrder,
118
+ ROW_NUMBER() OVER (ORDER BY wis.[Order] DESC) AS Rn
119
+ FROM WorkflowInstanceSteps wis
120
+ WHERE wis.WorkflowInstanceId = @workflowInstanceId
121
+ AND status IN ('Rejected', 'Approved', 'Pending')
122
+ )
123
+ SELECT TOP 1
124
+ CASE
125
+ WHEN NextOrder = 1000 THEN 1
126
+ ELSE 0
127
+ END AS Result,
128
+ wis.*
129
+ FROM OrderedSteps wis
130
+ WHERE Rn = 1;
131
+ """
132
+
133
+ GET_WORKFLOW_STEPS_QUERY: str = """
134
+ SELECT COUNT(*) as Steps
135
+ FROM WorkflowInstanceSteps as wis
136
+ WHERE wis.WorkflowInstanceId = {{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }}
137
+ GROUP BY WorkflowInstanceId;
138
+ """
139
+
140
+ BETTER_GET_WORKFLOW_STEPS_QUERY: str = """
141
+ declare @workflowInstanceId int = {{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }}
142
+ ;select
143
+ stepCount.Steps,
144
+ FROM
145
+ (
146
+ SELECT
147
+ @workflowInstanceId WorkflowinstanceId) as t1
148
+ left JOIN (
149
+ SELECT
150
+ @workflowInstanceId ID,
151
+ COUNT(*) as Steps
152
+ FROM
153
+ WorkflowInstanceSteps as wis
154
+ WHERE
155
+ wis.WorkflowInstanceId = @workflowInstanceId
156
+ group by
157
+ WorkflowInstanceId) as stepCount on
158
+ t1.workflowInstanceId = stepCount.ID
159
+ LEFT JOIN (
160
+ select
161
+ top 1
162
+ wis.WorkflowinstanceId,
163
+ case
164
+ when wis.status = 'Rejected' then -1
165
+ when wis.status = 'Approved' then 1
166
+ when wis.status = 'Pending' then 0
167
+ else null
168
+ end as OverallStatus
169
+ from
170
+ WorkflowInstanceSteps as wis
171
+ where
172
+ wis.WorkflowInstanceId = @workflowInstanceId
173
+ and status in ('Rejected', 'Approved', 'Pending' )
174
+ order by
175
+ [Order] DESC) as status on
176
+ t1.WorkflowinstanceId = status.WorkflowinstanceId
177
+ """
178
+
179
+ GET_STATUS_WORKFLOW_QUERY: str = """
180
+ declare @workflowInstanceId int = {{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }};
181
+ select
182
+ t1.WorkflowinstanceId,
183
+ stepCount.Steps,
184
+ status.OverallStatus
185
+ FROM
186
+ (
187
+ SELECT
188
+ @workflowInstanceId WorkflowinstanceId) as t1
189
+ left JOIN (
190
+ SELECT
191
+ @workflowInstanceId ID,
192
+ COUNT(*) as Steps
193
+ FROM
194
+ WorkflowInstanceSteps as wis
195
+ WHERE
196
+ wis.WorkflowInstanceId = @workflowInstanceId
197
+ group by
198
+ WorkflowInstanceId) as stepCount on
199
+ t1.workflowInstanceId = stepCount.ID
200
+ LEFT JOIN (
201
+ select
202
+ top 1
203
+ wis.WorkflowinstanceId,
204
+ case
205
+ when wis.status = 'Rejected' then -1
206
+ when wis.status = 'Approved' then 1
207
+ when wis.status = 'Pending' then 0
208
+ else null
209
+ end as OverallStatus
210
+ from
211
+ WorkflowInstanceSteps as wis
212
+ where
213
+ wis.WorkflowInstanceId = @workflowInstanceId
214
+ and status in ('Rejected', 'Approved', 'Pending' )
215
+ order by
216
+ [Order] DESC) as status on
217
+ t1.WorkflowinstanceId = status.WorkflowinstanceId;
218
+ """
219
+
220
+ GET_STEPS_QUERY: str = """
221
+ declare @workflowInstanceId int = {{ dag_run.conf['workflow_id'] if dag_run and dag_run.conf and 'workflow_id' in dag_run.conf else params.workflow_id }};
222
+ select
223
+ stepCount.Steps
224
+ FROM
225
+ (
226
+ SELECT
227
+ @workflowInstanceId WorkflowinstanceId) as t1
228
+ left JOIN (
229
+ SELECT
230
+ @workflowInstanceId ID,
231
+ COUNT(*) as Steps
232
+ FROM
233
+ WorkflowInstanceSteps as wis
234
+ WHERE
235
+ wis.WorkflowInstanceId = @workflowInstanceId
236
+ group by
237
+ WorkflowInstanceId) as stepCount on
238
+ t1.workflowInstanceId = stepCount.ID;
239
+ """
240
+
241
+ NEW_WORKFLOW_SQL_QUERY: SQLQuery = SQLQuery(query=NEWER_CHECK_WORKFLOW_STATUS_QUERY)
242
+ WORKFLOW_SQL_QUERY: SQLQuery = SQLQuery(query=NEW_CHECK_WORKFLOW_STATUS_QUERY)
243
+ CHECK_IF_COMPLETED_SQL_QUERY: SQLQuery = SQLQuery(query=CHECK_IF_COMPLETED_QUERY)
244
+ WATCH_WORKFLOW_SQL_QUERY: SQLQuery = SQLQuery(query=WATCH_WORFKLOW_QUERY)
245
+ GET_WORKFLOW_STEPS_SQL_QUERY: SQLQuery = SQLQuery(query=GET_WORKFLOW_STEPS_QUERY)
246
+ BETTER_GET_WORFKLOW_STEPS_SQL_QUERY: SQLQuery = SQLQuery(query=BETTER_GET_WORKFLOW_STEPS_QUERY)
247
+ GET_STATUS_WORKFLOW_SQL_QUERY: SQLQuery = SQLQuery(query=GET_STATUS_WORKFLOW_QUERY)
248
+ GET_STEPS_SQL_QUERY: SQLQuery = SQLQuery(query=GET_STEPS_QUERY)
File without changes
@@ -0,0 +1,22 @@
1
+ """Provide information related to branches in python."""
2
+
3
+
4
+ def tri_branch_func(pull_from: str, negative_task: str, neutral_task: str, positive_task: str, **kwargs: dict) -> str:
5
+ """Return the branch name
6
+
7
+ :param str pull_from: the task_id to pull from
8
+ :param str negative_task: the task_id to go to if the pull_from task returns -1
9
+ :param str neutral_task: the task_id to go to if the pull_from task returns 0
10
+ :param str positive_task: the task_id to go to if the pull_from task returns 1
11
+ :param dict **kwargs: additional keyword arguments
12
+ :return: the task_id to go to
13
+ :rtype: str
14
+ """
15
+ ti = kwargs["ti"]
16
+ var = ti.xcom_pull(task_ids=pull_from)
17
+ if var == -1:
18
+ return negative_task
19
+ elif var == 0:
20
+ return neutral_task
21
+ else:
22
+ return positive_task