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,260 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """RegScale SonarCloud Integration"""
4
+
5
+ # standard python imports
6
+ import math
7
+ import sys
8
+ from typing import Optional
9
+
10
+ import click
11
+ import requests # type: ignore
12
+
13
+ from regscale.core.app.api import Api
14
+ from regscale.core.app.application import Application
15
+ from regscale.core.app.logz import create_logger
16
+ from regscale.core.app.utils.app_utils import (
17
+ get_current_datetime,
18
+ days_between,
19
+ )
20
+ from regscale.models import regscale_id, regscale_module
21
+ from regscale.models.regscale_models.assessment import Assessment
22
+ from regscale.models.regscale_models.issue import Issue
23
+
24
+ # create logger function to log to the console
25
+ logger = create_logger()
26
+
27
+
28
+ def get_sonarcloud_results(config: dict) -> list[list[dict]]:
29
+ """
30
+ Retrieve Sonarcloud Results from the Sonarcloud.io API
31
+ :param dict config: RegScale CLI configuration
32
+ :return: json response data from API GET request
33
+ :rtype: list[list[dict]]
34
+ """
35
+ # api endpoint
36
+ url = "https://sonarcloud.io/api/issues/search"
37
+ # SONAR_TOKEN from Sonarcloud
38
+ token = config["sonarToken"]
39
+ # arguments to pass to the API call
40
+ query = {
41
+ "organization": "regscale",
42
+ "projects": "RegScale_regscale",
43
+ "branch": "main",
44
+ "projectKey": "RegScale_regscale",
45
+ "statuses": "OPEN, CONFIRMED, REOPENED",
46
+ "createdInLast": "1m",
47
+ "ps": 500,
48
+ }
49
+ # GET request pulls in data to check results size
50
+ r = requests.get(url, auth=(str(token), ""), params=query)
51
+ # if the status code does not equal 200
52
+ if r and not r.ok:
53
+ # exit the script gracefully
54
+ sys.exit("Sonarcloud API call failed please check the configuration")
55
+ # pull in response data to a dictionary
56
+ data = r.json()
57
+ # find the total results number
58
+ total = data["paging"]["total"]
59
+ # find the number of results in each result page
60
+ size = data["paging"]["pageSize"]
61
+ # calculate the number of pages to iterate through sequentially
62
+ pages = math.ceil(total / size)
63
+ # create an empty list to hold multiple pages of data
64
+ complete = []
65
+ # loop through each page number
66
+ for i in range(1, pages + 1, 1):
67
+ # parameters to pass to the API call
68
+ filters = {
69
+ "organization": "regscale",
70
+ "projects": "RegScale_regscale",
71
+ "branch": "main",
72
+ "projectKey": "RegScale_regscale",
73
+ "statuses": "OPEN, CONFIRMED, REOPENED",
74
+ "createdInLast": "1m",
75
+ "ps": 500,
76
+ "p": f"{i}",
77
+ }
78
+ # for each page make a GET request to pull in the data
79
+ r = requests.get(url, auth=(str(token), ""), params=filters)
80
+ # pull in response data to a dictionary
81
+ data = r.json()
82
+ # extract only the issues from the data
83
+ issues = data["issues"]
84
+ # add each page to the total results page
85
+ complete.append(issues)
86
+ # return the list of json response objects for use
87
+ return complete
88
+
89
+
90
+ def build_data(api: Api) -> list[dict]:
91
+ """
92
+ Build vulnerability alert data list
93
+ :param Api api: API object
94
+ :return: vulnerability data list
95
+ :rtype: list[dict]
96
+ """
97
+ # execute GET request
98
+ data = get_sonarcloud_results(config=api.config)
99
+ # create empty list to hold json response dicts
100
+ vulnerability_data_list = []
101
+ # loop through the lists in API response data
102
+ for result in data:
103
+ # loop through the list of dicts in the API response data
104
+ for i, issue in enumerate(result):
105
+ # format datetime stamp to use with days_between function
106
+ create_date = issue["creationDate"][0:19] + "Z"
107
+ # build vulnerability list
108
+ vulnerability_data_list.append(
109
+ {
110
+ "key": issue["key"],
111
+ "severity": issue["severity"],
112
+ "component": issue["component"],
113
+ "status": issue["status"],
114
+ "message": issue["message"],
115
+ "creationDate": issue["creationDate"][0:19],
116
+ "updateDate": issue["updateDate"][0:19],
117
+ "type": issue["type"],
118
+ "days_elapsed": days_between(vuln_time=create_date),
119
+ }
120
+ )
121
+ return vulnerability_data_list
122
+
123
+
124
+ def build_dataframes(api: Api) -> str:
125
+ """
126
+ Build pandas dataframes from vulnerability alert data list
127
+
128
+ :param Api api: API object
129
+ :return: dataframe as an HTML table
130
+ :rtype: str
131
+ """
132
+ import pandas as pd # Optimize import performance
133
+
134
+ # create vulnerability data list
135
+ vuln_data_list = build_data(api=api)
136
+
137
+ # for vulnerability in vuln_data_list:
138
+ df = pd.DataFrame(vuln_data_list)
139
+ # sort dataframe by severity
140
+ df.sort_values(by=["severity"], inplace=True)
141
+ # reset and drop the index
142
+ df.reset_index(drop=True, inplace=True)
143
+ # convert the dataframe to an html table
144
+ output = df.to_html(header=True, index=False, justify="center", border=1)
145
+ return output
146
+
147
+
148
+ def create_alert_assessment(
149
+ api: Api, parent_id: Optional[int] = None, parent_module: Optional[str] = None
150
+ ) -> Optional[int]:
151
+ """
152
+ Create Assessment containing SonarCloud alerts
153
+ :param Api api: API object
154
+ :param Optional[int] parent_id: Parent ID of the assessment, defaults to None
155
+ :param Optional[str] parent_module: Parent module of the assessment, defaults to None
156
+ :return: New Assessment ID, if created
157
+ :rtype: Optional[int]
158
+ """
159
+ # create the assessment report HTML table
160
+ df_output = build_dataframes(api)
161
+ # build assessment model data
162
+ assessment_data = Assessment(
163
+ leadAssessorId=api.config["userId"],
164
+ title="SonarCloud Code Scan Assessment",
165
+ assessmentType="Control Testing",
166
+ plannedStart=get_current_datetime(),
167
+ plannedFinish=get_current_datetime(),
168
+ assessmentReport=df_output,
169
+ assessmentPlan="Complete the child issues created by the SonarCloud code scan results that were retrieved by the API. The assessment will fail if any high severity vulnerabilities has a days_elapsed value greater than or equal to 10 days.",
170
+ createdById=api.config["userId"],
171
+ dateCreated=get_current_datetime(),
172
+ lastUpdatedById=api.config["userId"],
173
+ dateLastUpdated=get_current_datetime(),
174
+ status="In Progress",
175
+ )
176
+ if parent_id and parent_module:
177
+ assessment_data.parentId = parent_id
178
+ assessment_data.parentModule = parent_module
179
+ # create vulnerability data list
180
+ vuln_data_list = build_data(api)
181
+ # if assessmentResult is changed to Pass / Fail then status has to be
182
+ # changed to complete and a completion date has to be passed
183
+ for vulnerability in vuln_data_list:
184
+ if vulnerability["severity"] == "CRITICAL" and vulnerability["days_elapsed"] >= 10:
185
+ assessment_data.status = "Complete"
186
+ assessment_data.actualFinish = get_current_datetime()
187
+ assessment_data.assessmentResult = "Fail"
188
+
189
+ # create a new assessment in RegScale
190
+ if new_assessment := assessment_data.create():
191
+ # log assessment creation result
192
+ api.logger.info("Assessment was created successfully")
193
+ return new_assessment.id
194
+ else:
195
+ api.logger.info("Assessment was not created")
196
+ return None
197
+
198
+
199
+ def create_alert_issues(parent_id: Optional[int] = None, parent_module: Optional[str] = None) -> None:
200
+ """
201
+ Create child issues from the alert assessment
202
+ :param Optional[int] parent_id: Parent ID record to associate the assessment to, defaults to None
203
+ :param Optional[str] parent_module: Parent module to associate the assessment to, defaults to None
204
+ :rtype: None
205
+ """
206
+ # set environment and application configuration
207
+ app = Application()
208
+ api = Api()
209
+ # execute POST request and return new assessment ID
210
+ assessment_id = create_alert_assessment(api=api, parent_id=parent_id, parent_module=parent_module)
211
+
212
+ # create vulnerability data list
213
+ vuln_data_list = build_data(api)
214
+ # loop through each vulnerability alert in the list
215
+ for vulnerability in vuln_data_list:
216
+ # create issue model
217
+ issue_data = Issue(
218
+ title="Sonarcloud Code Scan", # Required
219
+ dateCreated=get_current_datetime("%Y-%m-%dT%H:%M:%S"),
220
+ description=vulnerability["message"],
221
+ severityLevel=Issue.assign_severity(vulnerability["severity"]), # Required
222
+ issueOwnerId=app.config["userId"], # Required
223
+ dueDate=get_current_datetime(),
224
+ identification="Code scan assessment",
225
+ status="Open",
226
+ assessmentId=assessment_id,
227
+ createdBy=app.config["userId"],
228
+ lastUpdatedById=app.config["userId"],
229
+ dateLastUpdated=get_current_datetime(),
230
+ parentId=assessment_id,
231
+ parentModule="assessments",
232
+ )
233
+ # create assessment child issue via POST
234
+ iss = api.post(
235
+ f'{app.config["domain"]}/api/issues',
236
+ json=issue_data.dict(),
237
+ )
238
+ # log issue creation result
239
+ if iss.ok:
240
+ logger.info("Issue created successfully.")
241
+ else:
242
+ logger.info("Issue was not created.")
243
+
244
+
245
+ @click.group()
246
+ def sonarcloud() -> None:
247
+ """
248
+ Create an assessment and child issues in RegScale from SonarCloud alerts.
249
+ """
250
+ pass
251
+
252
+
253
+ @sonarcloud.command(name="sync_alerts")
254
+ @regscale_id(required=False, default=None)
255
+ @regscale_module(required=False, default=None)
256
+ def create_alerts(regscale_id: Optional[int] = None, regscale_module: Optional[str] = None) -> None:
257
+ """
258
+ Create a child assessment and child issues in RegScale from SonarCloud alerts.
259
+ """
260
+ create_alert_issues(regscale_id, regscale_module)
@@ -0,0 +1,369 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """SQL Server integration for the CLI that allows for executing SQL queries"""
4
+ import os
5
+ from datetime import datetime, timedelta
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+ import click
10
+
11
+ from regscale.core.app.api import Api
12
+ from regscale.core.app.application import Application
13
+ from regscale.core.app.internal.workflow import create_regscale_workflow_from_template
14
+ from regscale.core.app.logz import create_logger
15
+ from regscale.core.app.utils.app_utils import (
16
+ check_file_path,
17
+ check_license,
18
+ create_progress_object,
19
+ get_current_datetime,
20
+ )
21
+ from regscale.core.app.utils.regscale_utils import (
22
+ verify_provided_module,
23
+ )
24
+ from regscale.models.app_models.click import regscale_id, regscale_module
25
+ from regscale.models.regscale_models import Assessment, File
26
+
27
+ job_progress = create_progress_object()
28
+ logger = create_logger()
29
+ # SQL query
30
+ sql_query = """
31
+ SELECT p.name AS [LoginName], r.name AS [RoleName]
32
+ FROM sys.server_principals r
33
+ JOIN sys.server_role_members m ON r.principal_id = m.role_principal_id
34
+ JOIN sys.server_principals p ON p.principal_id = m.member_principal_id
35
+ WHERE r.type = 'R' AND r.name
36
+ IN (N'sysadmin', N'db_owner', N'securityadmin')
37
+ and p.is_disabled = 0
38
+ ORDER BY p.name;
39
+ """
40
+
41
+
42
+ @click.group()
43
+ def sqlserver():
44
+ """sqlserver integration to pull admin users \
45
+ report via trusted connection."""
46
+
47
+
48
+ @sqlserver.command("admins_report")
49
+ @click.option(
50
+ "--workflow_template_id",
51
+ "-w",
52
+ type=click.INT,
53
+ help="Regscale workflow template ID",
54
+ required=True,
55
+ prompt=True,
56
+ )
57
+ @click.option(
58
+ "--output_dir",
59
+ "-o",
60
+ help="Output directory to save the report. Defaults to sqlserver_reports",
61
+ type=click.Path(exists=False, file_okay=False, dir_okay=True, writable=True),
62
+ default=Path("sqlserver_reports"),
63
+ prompt=False,
64
+ )
65
+ @click.option(
66
+ "--query_file",
67
+ "-q",
68
+ help="Path to a SQL query file.",
69
+ type=click.Path(exists=True, file_okay=True, dir_okay=False, readable=True),
70
+ )
71
+ @click.option(
72
+ "--server",
73
+ "-s",
74
+ required=True,
75
+ default=os.getenv("sqlServer"),
76
+ help="SQL Server host.",
77
+ )
78
+ @click.option(
79
+ "--database",
80
+ "-d",
81
+ required=True,
82
+ default=os.getenv("sqlServerDbName"),
83
+ help="Database name.",
84
+ )
85
+ @click.option(
86
+ "--port",
87
+ "-p",
88
+ required=True,
89
+ default=os.getenv("sqlServerPort"),
90
+ help="Database Port number.",
91
+ )
92
+ @click.option("--username", "-u", default=os.getenv("sqlServerUser"), help="Username.")
93
+ @click.option("--password", "-pwd", default=os.getenv("sqlServerPassword"), help="Password.")
94
+ @regscale_id()
95
+ @regscale_module()
96
+ @click.option(
97
+ "--output_file",
98
+ "-f",
99
+ help=f"Desired output file name. Defaults to RegScale_CLI_SQL_Report_{datetime.now().strftime('%Y%m%d')}",
100
+ type=click.STRING,
101
+ default=f"RegScale_CLI_SQL_Report_{datetime.now().strftime('%Y%m%d')}",
102
+ prompt=False,
103
+ )
104
+ def generate_report(
105
+ workflow_template_id: int,
106
+ output_dir: str,
107
+ output_file: str,
108
+ server: str,
109
+ database: str,
110
+ port: int,
111
+ username: str,
112
+ password: str,
113
+ regscale_id: int,
114
+ regscale_module: str,
115
+ query_file: Path,
116
+ ) -> None:
117
+ """Execute SQL query and save the data as a .csv report."""
118
+ generate_and_save_report(
119
+ workflow_template_id,
120
+ output_dir,
121
+ query_file,
122
+ server,
123
+ database,
124
+ port,
125
+ username,
126
+ password,
127
+ regscale_id,
128
+ regscale_module,
129
+ output_file,
130
+ )
131
+
132
+
133
+ def generate_and_save_report(
134
+ workflow_template_id: int,
135
+ output_dir: str,
136
+ query_file: Path,
137
+ server: str,
138
+ database: str,
139
+ port: int,
140
+ username: str,
141
+ password: str,
142
+ regscale_id: int,
143
+ regscale_module: str,
144
+ output_file: str = f"RegScale_CLI_SQL_Report_{datetime.now().strftime('%Y%m%d')}",
145
+ ) -> None:
146
+ """
147
+ :param int workflow_template_id: RegScale workflow template ID
148
+ :param str output_dir: Output directory
149
+ :param Path query_file: SQL query file
150
+ :param str server: SQL Server name
151
+ :param str database: Database name
152
+ :param int port: Port number
153
+ :param str username: Username
154
+ :param str password: Password
155
+ :param int regscale_id: RegScale module Id
156
+ :param str regscale_module: RegScale module name
157
+ :param str output_file: Output file name, defaults to RegScale_CLI_SQL_Report_{datetime.now().strftime('%Y%m%d')}
158
+ :rtype: None
159
+ """
160
+ import pandas as pd # Optimize import performance
161
+
162
+ app = check_license()
163
+
164
+ # see if provided RegScale Module is an accepted option
165
+ verify_provided_module(regscale_module)
166
+
167
+ # Build the connection string
168
+ conn_str = build_connection_string(server, database, port, username, password)
169
+ import pyodbc
170
+
171
+ with pyodbc.connect(conn_str) as cnxn:
172
+ cursor = cnxn.cursor()
173
+ if query_file:
174
+ sql_query = _get_query_from_file(query_file)
175
+ cursor.execute(sql_query)
176
+ rows = cursor.fetchall()
177
+ # Create a DataFrame from the rows
178
+ df = pd.DataFrame.from_records(rows, columns=[column[0] for column in cursor.description])
179
+
180
+ if not df.empty:
181
+ # Convert the DataFrame to an HTML table
182
+ report = df.to_html(index=False)
183
+
184
+ # Save the DataFrame to a CSV file
185
+ new_file = f"{output_file}.csv"
186
+ # Specify the directory where you want to save the CSV file
187
+
188
+ # Create the directory if it does not exist
189
+ check_file_path(output_dir)
190
+
191
+ full_path = output_dir / new_file
192
+ # Save the DataFrame to a CSV file in the specified directory
193
+ df.to_csv(full_path, index=False)
194
+ title = f"Sql Server Report assessment {regscale_module.title()}-{regscale_id}"
195
+ description = f"Sql Server Report assessment {regscale_module.title()}-{regscale_id}"
196
+ new_assessment_id = create_and_save_assessment(
197
+ report,
198
+ [full_path],
199
+ regscale_id,
200
+ regscale_module,
201
+ title=title,
202
+ description=description,
203
+ app=app,
204
+ )
205
+ logger.debug(f"New assessment created here is the id: {new_assessment_id}")
206
+ if new_assessment_id and workflow_template_id:
207
+ create_regscale_workflow_from_template(
208
+ new_assessment_id,
209
+ template_id=workflow_template_id,
210
+ )
211
+ else:
212
+ logger.info(f"No data found for query: {sql_query}.")
213
+
214
+
215
+ def _get_query_from_file(file_path: str) -> str:
216
+ """
217
+ Get the SQL query from a file.
218
+ :param str file_path: Path to SQL query file
219
+ :return: SQL query
220
+ :rtype: str
221
+ """
222
+ with open(file_path, "r") as file:
223
+ query = file.read()
224
+ return query
225
+
226
+
227
+ def build_connection_string(
228
+ server: str,
229
+ database: str,
230
+ port: int,
231
+ username: Optional[str],
232
+ password: Optional[str],
233
+ ) -> str:
234
+ """
235
+ Build the connection string for the SQL Server.
236
+ :param str server: SQL Server name
237
+ :param str database: Database name
238
+ :param int port: Port number for the SQL Server
239
+ :param Optional[str] username: Database Username optional
240
+ :param Optional[str] password: Database Password optional
241
+ :return: Connection string
242
+ :rtype: str
243
+ """
244
+ if username and password:
245
+ conn_str = (
246
+ r"DRIVER={ODBC Driver 17 for SQL Server};"
247
+ r"SERVER=" + server + ";"
248
+ r"DATABASE=" + database + ";"
249
+ r"PORT=" + str(port) + ";"
250
+ r"UID=" + username + ";"
251
+ r"PWD=" + password + ";"
252
+ r"TrustServerCertificate=yes;"
253
+ r"TIMEOUT=30;"
254
+ # Set the login timeout to 30 seconds
255
+ )
256
+ else:
257
+ conn_str = (
258
+ r"DRIVER={ODBC Driver 17 for SQL Server};"
259
+ r"SERVER=" + server + ";"
260
+ r"DATABASE=" + database + ";"
261
+ r"PORT=" + str(port) + ";"
262
+ r"Trusted_Connection=yes;"
263
+ )
264
+ return conn_str
265
+
266
+
267
+ def calculate_finish_date(current_date: datetime, days: int) -> str:
268
+ """
269
+ Calculate finish date for Assessment by adding days to current date
270
+ :param datetime current_date: Date to start with
271
+ :param int days: # of days to add to current date
272
+ :return: String representation of finish date
273
+ :rtype: str
274
+ """
275
+ return (current_date + timedelta(days=days)).strftime("%Y-%m-%dT%H:%M:%S")
276
+
277
+
278
+ def create_assessment_object(
279
+ app: Application,
280
+ report: str,
281
+ regscale_id: int,
282
+ regscale_module: str,
283
+ title: str,
284
+ description: str,
285
+ ) -> Assessment:
286
+ """
287
+ Create a RegScale assessment object
288
+ :param Application app: Application object
289
+ :param str report: Assessment report
290
+ :param int regscale_id: RegScale ID
291
+ :param str regscale_module: RegScale module
292
+ :param str title: Assessment title
293
+ :param str description: Assessment description
294
+ :return: Assessment object
295
+ :rtype: Assessment
296
+ """
297
+ finish_date = calculate_finish_date(datetime.now(), app.config["assessmentDays"])
298
+ status = "Scheduled"
299
+ new_assessment = Assessment(
300
+ leadAssessorId=app.config["userId"],
301
+ title=title,
302
+ assessmentType="Control Testing",
303
+ plannedStart=get_current_datetime(),
304
+ plannedFinish=finish_date,
305
+ assessmentReport=report,
306
+ assessmentPlan=description,
307
+ createdById=app.config["userId"],
308
+ dateCreated=get_current_datetime(),
309
+ lastUpdatedById=app.config["userId"],
310
+ dateLastUpdated=get_current_datetime(),
311
+ parentModule=regscale_module,
312
+ parentId=regscale_id,
313
+ status=status,
314
+ )
315
+
316
+ new_assessment.actualFinish = "true"
317
+ new_assessment.assessmentResult = "Pass"
318
+ return new_assessment
319
+
320
+
321
+ def upload_files_to_assessment(api: Api, assessment_id: int, files: list) -> None:
322
+ """
323
+ Upload files to the new RegScale Assessment
324
+ :param Api api: Api object
325
+ :param int assessment_id: RegScale assessment id
326
+ :param list files: List of files to upload to RegScale assessment
327
+ :rtype: None
328
+ """
329
+ upload_files = job_progress.add_task("[#0866b4]Uploading files to the new RegScale Assessment...", total=len(files))
330
+ for new_file in files:
331
+ new_file_upload = File.upload_file_to_regscale(
332
+ file_name=new_file,
333
+ parent_id=assessment_id,
334
+ parent_module="assessments",
335
+ api=api,
336
+ )
337
+ if new_file_upload:
338
+ job_progress.update(upload_files, advance=1)
339
+
340
+
341
+ def create_and_save_assessment(
342
+ report: str,
343
+ files: list,
344
+ regscale_id: int,
345
+ regscale_module: str,
346
+ title: str,
347
+ description: str,
348
+ app: Application,
349
+ ) -> int:
350
+ """
351
+ Create a new RegScale Assessment and upload the report and files to it
352
+ :param str report: Report to upload to assessment
353
+ :param list files: List of files to upload to assessment
354
+ :param int regscale_id: RegScale id
355
+ :param str regscale_module: RegScale module
356
+ :param str title: Assessment title
357
+ :param str description: Assessment description
358
+ :param Application app: Application object
359
+ :return:RegScale assessment id
360
+ :rtype: int
361
+ """
362
+ api = Api()
363
+ new_assessment = create_assessment_object(app, report, regscale_id, regscale_module, title, description)
364
+ create_assessment = job_progress.add_task("[#21a5bb]Creating assessment in RegScale...", total=1)
365
+ if new_assessment_id := new_assessment.insert_assessment(app=app).id:
366
+ logger.info(f"created new RegScale Assessment with id of {new_assessment_id}")
367
+ job_progress.update(create_assessment, advance=1)
368
+ upload_files_to_assessment(api, new_assessment_id, files)
369
+ return new_assessment_id
@@ -0,0 +1,38 @@
1
+ """STIG Mapper commands."""
2
+
3
+ import logging
4
+
5
+ import click
6
+
7
+ from regscale.models import regscale_id, regscale_module, Asset
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ @click.group(name="stig_mapper")
13
+ def stig_mapper():
14
+ """Map data from STIGs to RegScale."""
15
+
16
+
17
+ @stig_mapper.command(name="run")
18
+ @click.option(
19
+ "--json-file", help="Path to the JSON file with mapping rules", required=True, type=click.Path(exists=True)
20
+ )
21
+ @regscale_id()
22
+ @regscale_module()
23
+ def run(json_file: str, regscale_id: int, regscale_module: str):
24
+ """
25
+ Map STIGs from a .json file to assets in RegScale.
26
+ """
27
+ from regscale.integrations.commercial.stig_mapper_integration.mapping_engine import StigMappingEngine as STIGMapper
28
+ from os import path
29
+
30
+ if not path.exists(json_file):
31
+ logger.error(f"File {json_file} does not exist.")
32
+ return
33
+ stig_mapper = STIGMapper(json_file)
34
+ assets = Asset.get_all_by_parent(parent_id=regscale_id, parent_module=regscale_module)
35
+ asset_mappings = []
36
+ for asset in assets:
37
+ asset_mappings.append(stig_mapper.map_associated_stigs_to_asset(asset=asset, ssp_id=regscale_id))
38
+ logger.info(f"Created {len(asset_mappings)} new asset mappings")