regscale-cli 6.21.2.0__py3-none-any.whl → 6.28.2.1__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.
Files changed (314) hide show
  1. regscale/_version.py +1 -1
  2. regscale/airflow/hierarchy.py +2 -2
  3. regscale/core/app/api.py +5 -2
  4. regscale/core/app/application.py +36 -6
  5. regscale/core/app/internal/control_editor.py +73 -21
  6. regscale/core/app/internal/evidence.py +727 -204
  7. regscale/core/app/internal/login.py +4 -2
  8. regscale/core/app/internal/model_editor.py +219 -64
  9. regscale/core/app/utils/app_utils.py +86 -12
  10. regscale/core/app/utils/catalog_utils/common.py +1 -1
  11. regscale/core/login.py +21 -4
  12. regscale/core/utils/async_graphql_client.py +363 -0
  13. regscale/core/utils/date.py +77 -1
  14. regscale/dev/cli.py +26 -0
  15. regscale/dev/code_gen.py +109 -24
  16. regscale/dev/version.py +72 -0
  17. regscale/integrations/commercial/__init__.py +30 -2
  18. regscale/integrations/commercial/aws/audit_manager_compliance.py +3908 -0
  19. regscale/integrations/commercial/aws/cli.py +3107 -54
  20. regscale/integrations/commercial/aws/cloudtrail_control_mappings.py +333 -0
  21. regscale/integrations/commercial/aws/cloudtrail_evidence.py +501 -0
  22. regscale/integrations/commercial/aws/cloudwatch_control_mappings.py +357 -0
  23. regscale/integrations/commercial/aws/cloudwatch_evidence.py +490 -0
  24. regscale/integrations/commercial/{amazon → aws}/common.py +71 -19
  25. regscale/integrations/commercial/aws/config_compliance.py +914 -0
  26. regscale/integrations/commercial/aws/conformance_pack_mappings.py +198 -0
  27. regscale/integrations/commercial/aws/control_compliance_analyzer.py +439 -0
  28. regscale/integrations/commercial/aws/evidence_generator.py +283 -0
  29. regscale/integrations/commercial/aws/guardduty_control_mappings.py +340 -0
  30. regscale/integrations/commercial/aws/guardduty_evidence.py +1053 -0
  31. regscale/integrations/commercial/aws/iam_control_mappings.py +368 -0
  32. regscale/integrations/commercial/aws/iam_evidence.py +574 -0
  33. regscale/integrations/commercial/aws/inventory/__init__.py +338 -22
  34. regscale/integrations/commercial/aws/inventory/base.py +107 -5
  35. regscale/integrations/commercial/aws/inventory/resources/analytics.py +390 -0
  36. regscale/integrations/commercial/aws/inventory/resources/applications.py +234 -0
  37. regscale/integrations/commercial/aws/inventory/resources/audit_manager.py +513 -0
  38. regscale/integrations/commercial/aws/inventory/resources/cloudtrail.py +315 -0
  39. regscale/integrations/commercial/aws/inventory/resources/cloudtrail_logs_metadata.py +476 -0
  40. regscale/integrations/commercial/aws/inventory/resources/cloudwatch.py +191 -0
  41. regscale/integrations/commercial/aws/inventory/resources/compute.py +328 -9
  42. regscale/integrations/commercial/aws/inventory/resources/config.py +464 -0
  43. regscale/integrations/commercial/aws/inventory/resources/containers.py +74 -9
  44. regscale/integrations/commercial/aws/inventory/resources/database.py +481 -31
  45. regscale/integrations/commercial/aws/inventory/resources/developer_tools.py +253 -0
  46. regscale/integrations/commercial/aws/inventory/resources/guardduty.py +286 -0
  47. regscale/integrations/commercial/aws/inventory/resources/iam.py +470 -0
  48. regscale/integrations/commercial/aws/inventory/resources/inspector.py +476 -0
  49. regscale/integrations/commercial/aws/inventory/resources/integration.py +175 -61
  50. regscale/integrations/commercial/aws/inventory/resources/kms.py +447 -0
  51. regscale/integrations/commercial/aws/inventory/resources/machine_learning.py +358 -0
  52. regscale/integrations/commercial/aws/inventory/resources/networking.py +390 -67
  53. regscale/integrations/commercial/aws/inventory/resources/s3.py +394 -0
  54. regscale/integrations/commercial/aws/inventory/resources/security.py +268 -72
  55. regscale/integrations/commercial/aws/inventory/resources/securityhub.py +473 -0
  56. regscale/integrations/commercial/aws/inventory/resources/storage.py +288 -29
  57. regscale/integrations/commercial/aws/inventory/resources/systems_manager.py +657 -0
  58. regscale/integrations/commercial/aws/inventory/resources/vpc.py +655 -0
  59. regscale/integrations/commercial/aws/kms_control_mappings.py +288 -0
  60. regscale/integrations/commercial/aws/kms_evidence.py +879 -0
  61. regscale/integrations/commercial/aws/ocsf/__init__.py +7 -0
  62. regscale/integrations/commercial/aws/ocsf/constants.py +115 -0
  63. regscale/integrations/commercial/aws/ocsf/mapper.py +435 -0
  64. regscale/integrations/commercial/aws/org_control_mappings.py +286 -0
  65. regscale/integrations/commercial/aws/org_evidence.py +666 -0
  66. regscale/integrations/commercial/aws/s3_control_mappings.py +356 -0
  67. regscale/integrations/commercial/aws/s3_evidence.py +632 -0
  68. regscale/integrations/commercial/aws/scanner.py +1072 -205
  69. regscale/integrations/commercial/aws/security_hub.py +319 -0
  70. regscale/integrations/commercial/aws/session_manager.py +282 -0
  71. regscale/integrations/commercial/aws/ssm_control_mappings.py +291 -0
  72. regscale/integrations/commercial/aws/ssm_evidence.py +492 -0
  73. regscale/integrations/commercial/jira.py +489 -153
  74. regscale/integrations/commercial/microsoft_defender/defender.py +326 -5
  75. regscale/integrations/commercial/microsoft_defender/defender_api.py +348 -14
  76. regscale/integrations/commercial/microsoft_defender/defender_constants.py +157 -0
  77. regscale/integrations/commercial/qualys/__init__.py +167 -68
  78. regscale/integrations/commercial/qualys/scanner.py +305 -39
  79. regscale/integrations/commercial/sarif/sairf_importer.py +432 -0
  80. regscale/integrations/commercial/sarif/sarif_converter.py +67 -0
  81. regscale/integrations/commercial/sicura/api.py +79 -42
  82. regscale/integrations/commercial/sicura/commands.py +8 -2
  83. regscale/integrations/commercial/sicura/scanner.py +83 -44
  84. regscale/integrations/commercial/stigv2/ckl_parser.py +5 -5
  85. regscale/integrations/commercial/synqly/assets.py +133 -16
  86. regscale/integrations/commercial/synqly/edr.py +2 -8
  87. regscale/integrations/commercial/synqly/query_builder.py +536 -0
  88. regscale/integrations/commercial/synqly/ticketing.py +27 -0
  89. regscale/integrations/commercial/synqly/vulnerabilities.py +165 -28
  90. regscale/integrations/commercial/tenablev2/cis_parsers.py +453 -0
  91. regscale/integrations/commercial/tenablev2/cis_scanner.py +447 -0
  92. regscale/integrations/commercial/tenablev2/commands.py +146 -5
  93. regscale/integrations/commercial/tenablev2/scanner.py +1 -3
  94. regscale/integrations/commercial/tenablev2/stig_parsers.py +113 -57
  95. regscale/integrations/commercial/wizv2/WizDataMixin.py +1 -1
  96. regscale/integrations/commercial/wizv2/click.py +191 -76
  97. regscale/integrations/commercial/wizv2/compliance/__init__.py +15 -0
  98. regscale/integrations/commercial/wizv2/{policy_compliance_helpers.py → compliance/helpers.py} +78 -60
  99. regscale/integrations/commercial/wizv2/compliance_report.py +1592 -0
  100. regscale/integrations/commercial/wizv2/core/__init__.py +133 -0
  101. regscale/integrations/commercial/wizv2/{async_client.py → core/client.py} +7 -3
  102. regscale/integrations/commercial/wizv2/{constants.py → core/constants.py} +92 -89
  103. regscale/integrations/commercial/wizv2/core/file_operations.py +237 -0
  104. regscale/integrations/commercial/wizv2/fetchers/__init__.py +11 -0
  105. regscale/integrations/commercial/wizv2/{data_fetcher.py → fetchers/policy_assessment.py} +66 -9
  106. regscale/integrations/commercial/wizv2/file_cleanup.py +104 -0
  107. regscale/integrations/commercial/wizv2/issue.py +776 -28
  108. regscale/integrations/commercial/wizv2/models/__init__.py +0 -0
  109. regscale/integrations/commercial/wizv2/parsers/__init__.py +34 -0
  110. regscale/integrations/commercial/wizv2/{parsers.py → parsers/main.py} +1 -1
  111. regscale/integrations/commercial/wizv2/processors/__init__.py +11 -0
  112. regscale/integrations/commercial/wizv2/{finding_processor.py → processors/finding.py} +1 -1
  113. regscale/integrations/commercial/wizv2/reports.py +243 -0
  114. regscale/integrations/commercial/wizv2/sbom.py +1 -1
  115. regscale/integrations/commercial/wizv2/scanner.py +1031 -441
  116. regscale/integrations/commercial/wizv2/utils/__init__.py +48 -0
  117. regscale/integrations/commercial/wizv2/{utils.py → utils/main.py} +116 -61
  118. regscale/integrations/commercial/wizv2/variables.py +89 -3
  119. regscale/integrations/compliance_integration.py +1036 -151
  120. regscale/integrations/control_matcher.py +432 -0
  121. regscale/integrations/due_date_handler.py +333 -0
  122. regscale/integrations/milestone_manager.py +291 -0
  123. regscale/integrations/public/__init__.py +14 -0
  124. regscale/integrations/public/cci_importer.py +834 -0
  125. regscale/integrations/public/csam/__init__.py +0 -0
  126. regscale/integrations/public/csam/csam.py +938 -0
  127. regscale/integrations/public/csam/csam_agency_defined.py +179 -0
  128. regscale/integrations/public/csam/csam_common.py +154 -0
  129. regscale/integrations/public/csam/csam_controls.py +432 -0
  130. regscale/integrations/public/csam/csam_poam.py +124 -0
  131. regscale/integrations/public/fedramp/click.py +77 -6
  132. regscale/integrations/public/fedramp/docx_parser.py +10 -1
  133. regscale/integrations/public/fedramp/fedramp_cis_crm.py +675 -289
  134. regscale/integrations/public/fedramp/fedramp_five.py +1 -1
  135. regscale/integrations/public/fedramp/poam/scanner.py +75 -7
  136. regscale/integrations/public/fedramp/poam_export_v5.py +888 -0
  137. regscale/integrations/scanner_integration.py +1961 -430
  138. regscale/models/integration_models/CCI_List.xml +1 -0
  139. regscale/models/integration_models/aqua.py +2 -2
  140. regscale/models/integration_models/cisa_kev_data.json +805 -11
  141. regscale/models/integration_models/flat_file_importer/__init__.py +5 -8
  142. regscale/models/integration_models/nexpose.py +36 -10
  143. regscale/models/integration_models/qualys.py +3 -4
  144. regscale/models/integration_models/synqly_models/capabilities.json +1 -1
  145. regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +87 -18
  146. regscale/models/integration_models/synqly_models/filter_parser.py +332 -0
  147. regscale/models/integration_models/synqly_models/ocsf_mapper.py +124 -25
  148. regscale/models/integration_models/synqly_models/synqly_model.py +89 -16
  149. regscale/models/locking.py +12 -8
  150. regscale/models/platform.py +4 -2
  151. regscale/models/regscale_models/__init__.py +7 -0
  152. regscale/models/regscale_models/assessment.py +2 -1
  153. regscale/models/regscale_models/catalog.py +1 -1
  154. regscale/models/regscale_models/compliance_settings.py +251 -1
  155. regscale/models/regscale_models/component.py +1 -0
  156. regscale/models/regscale_models/control_implementation.py +236 -41
  157. regscale/models/regscale_models/control_objective.py +74 -5
  158. regscale/models/regscale_models/file.py +2 -0
  159. regscale/models/regscale_models/form_field_value.py +5 -3
  160. regscale/models/regscale_models/inheritance.py +44 -0
  161. regscale/models/regscale_models/issue.py +301 -102
  162. regscale/models/regscale_models/milestone.py +33 -14
  163. regscale/models/regscale_models/organization.py +3 -0
  164. regscale/models/regscale_models/regscale_model.py +310 -73
  165. regscale/models/regscale_models/security_plan.py +4 -2
  166. regscale/models/regscale_models/vulnerability.py +3 -3
  167. regscale/regscale.py +25 -4
  168. regscale/templates/__init__.py +0 -0
  169. regscale/utils/threading/threadhandler.py +20 -15
  170. regscale/validation/record.py +23 -1
  171. {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/METADATA +17 -33
  172. {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/RECORD +310 -111
  173. tests/core/__init__.py +0 -0
  174. tests/core/utils/__init__.py +0 -0
  175. tests/core/utils/test_async_graphql_client.py +472 -0
  176. tests/fixtures/test_fixture.py +13 -8
  177. tests/regscale/core/test_login.py +171 -4
  178. tests/regscale/integrations/commercial/__init__.py +0 -0
  179. tests/regscale/integrations/commercial/aws/__init__.py +0 -0
  180. tests/regscale/integrations/commercial/aws/test_audit_manager_compliance.py +1304 -0
  181. tests/regscale/integrations/commercial/aws/test_audit_manager_evidence_aggregation.py +341 -0
  182. tests/regscale/integrations/commercial/aws/test_aws_analytics_collector.py +260 -0
  183. tests/regscale/integrations/commercial/aws/test_aws_applications_collector.py +242 -0
  184. tests/regscale/integrations/commercial/aws/test_aws_audit_manager_collector.py +1155 -0
  185. tests/regscale/integrations/commercial/aws/test_aws_cloudtrail_collector.py +534 -0
  186. tests/regscale/integrations/commercial/aws/test_aws_config_collector.py +400 -0
  187. tests/regscale/integrations/commercial/aws/test_aws_developer_tools_collector.py +203 -0
  188. tests/regscale/integrations/commercial/aws/test_aws_guardduty_collector.py +315 -0
  189. tests/regscale/integrations/commercial/aws/test_aws_iam_collector.py +458 -0
  190. tests/regscale/integrations/commercial/aws/test_aws_inspector_collector.py +353 -0
  191. tests/regscale/integrations/commercial/aws/test_aws_inventory_integration.py +530 -0
  192. tests/regscale/integrations/commercial/aws/test_aws_kms_collector.py +919 -0
  193. tests/regscale/integrations/commercial/aws/test_aws_machine_learning_collector.py +237 -0
  194. tests/regscale/integrations/commercial/aws/test_aws_s3_collector.py +722 -0
  195. tests/regscale/integrations/commercial/aws/test_aws_scanner_integration.py +722 -0
  196. tests/regscale/integrations/commercial/aws/test_aws_securityhub_collector.py +792 -0
  197. tests/regscale/integrations/commercial/aws/test_aws_systems_manager_collector.py +918 -0
  198. tests/regscale/integrations/commercial/aws/test_aws_vpc_collector.py +996 -0
  199. tests/regscale/integrations/commercial/aws/test_cli_evidence.py +431 -0
  200. tests/regscale/integrations/commercial/aws/test_cloudtrail_control_mappings.py +452 -0
  201. tests/regscale/integrations/commercial/aws/test_cloudtrail_evidence.py +788 -0
  202. tests/regscale/integrations/commercial/aws/test_config_compliance.py +298 -0
  203. tests/regscale/integrations/commercial/aws/test_conformance_pack_mappings.py +200 -0
  204. tests/regscale/integrations/commercial/aws/test_control_compliance_analyzer.py +375 -0
  205. tests/regscale/integrations/commercial/aws/test_datetime_parsing.py +223 -0
  206. tests/regscale/integrations/commercial/aws/test_evidence_generator.py +386 -0
  207. tests/regscale/integrations/commercial/aws/test_guardduty_control_mappings.py +564 -0
  208. tests/regscale/integrations/commercial/aws/test_guardduty_evidence.py +1041 -0
  209. tests/regscale/integrations/commercial/aws/test_iam_control_mappings.py +718 -0
  210. tests/regscale/integrations/commercial/aws/test_iam_evidence.py +1375 -0
  211. tests/regscale/integrations/commercial/aws/test_kms_control_mappings.py +656 -0
  212. tests/regscale/integrations/commercial/aws/test_kms_evidence.py +1163 -0
  213. tests/regscale/integrations/commercial/aws/test_ocsf_mapper.py +370 -0
  214. tests/regscale/integrations/commercial/aws/test_org_control_mappings.py +546 -0
  215. tests/regscale/integrations/commercial/aws/test_org_evidence.py +1240 -0
  216. tests/regscale/integrations/commercial/aws/test_s3_control_mappings.py +672 -0
  217. tests/regscale/integrations/commercial/aws/test_s3_evidence.py +987 -0
  218. tests/regscale/integrations/commercial/aws/test_scanner_evidence.py +373 -0
  219. tests/regscale/integrations/commercial/aws/test_security_hub_config_filtering.py +539 -0
  220. tests/regscale/integrations/commercial/aws/test_session_manager.py +516 -0
  221. tests/regscale/integrations/commercial/aws/test_ssm_control_mappings.py +588 -0
  222. tests/regscale/integrations/commercial/aws/test_ssm_evidence.py +735 -0
  223. tests/regscale/integrations/commercial/conftest.py +28 -0
  224. tests/regscale/integrations/commercial/microsoft_defender/__init__.py +1 -0
  225. tests/regscale/integrations/commercial/microsoft_defender/test_defender.py +1517 -0
  226. tests/regscale/integrations/commercial/microsoft_defender/test_defender_api.py +1748 -0
  227. tests/regscale/integrations/commercial/microsoft_defender/test_defender_constants.py +327 -0
  228. tests/regscale/integrations/commercial/microsoft_defender/test_defender_scanner.py +487 -0
  229. tests/regscale/integrations/commercial/test_aws.py +3742 -0
  230. tests/regscale/integrations/commercial/test_burp.py +48 -0
  231. tests/regscale/integrations/commercial/test_crowdstrike.py +49 -0
  232. tests/regscale/integrations/commercial/test_dependabot.py +341 -0
  233. tests/regscale/integrations/commercial/test_gcp.py +1543 -0
  234. tests/regscale/integrations/commercial/test_gitlab.py +549 -0
  235. tests/regscale/integrations/commercial/test_ip_mac_address_length.py +84 -0
  236. tests/regscale/integrations/commercial/test_jira.py +2204 -0
  237. tests/regscale/integrations/commercial/test_npm_audit.py +42 -0
  238. tests/regscale/integrations/commercial/test_okta.py +1228 -0
  239. tests/regscale/integrations/commercial/test_sarif_converter.py +251 -0
  240. tests/regscale/integrations/commercial/test_sicura.py +349 -0
  241. tests/regscale/integrations/commercial/test_snow.py +423 -0
  242. tests/regscale/integrations/commercial/test_sonarcloud.py +394 -0
  243. tests/regscale/integrations/commercial/test_sqlserver.py +186 -0
  244. tests/regscale/integrations/commercial/test_stig.py +33 -0
  245. tests/regscale/integrations/commercial/test_stig_mapper.py +153 -0
  246. tests/regscale/integrations/commercial/test_stigv2.py +406 -0
  247. tests/regscale/integrations/commercial/test_wiz.py +1365 -0
  248. tests/regscale/integrations/commercial/test_wiz_inventory.py +256 -0
  249. tests/regscale/integrations/commercial/wizv2/__init__.py +339 -0
  250. tests/regscale/integrations/commercial/wizv2/compliance/__init__.py +1 -0
  251. tests/regscale/integrations/commercial/wizv2/compliance/test_helpers.py +903 -0
  252. tests/regscale/integrations/commercial/wizv2/core/__init__.py +1 -0
  253. tests/regscale/integrations/commercial/wizv2/core/test_auth.py +701 -0
  254. tests/regscale/integrations/commercial/wizv2/core/test_client.py +1037 -0
  255. tests/regscale/integrations/commercial/wizv2/core/test_file_operations.py +989 -0
  256. tests/regscale/integrations/commercial/wizv2/fetchers/__init__.py +1 -0
  257. tests/regscale/integrations/commercial/wizv2/fetchers/test_policy_assessment.py +805 -0
  258. tests/regscale/integrations/commercial/wizv2/parsers/__init__.py +1 -0
  259. tests/regscale/integrations/commercial/wizv2/parsers/test_main.py +1153 -0
  260. tests/regscale/integrations/commercial/wizv2/processors/__init__.py +1 -0
  261. tests/regscale/integrations/commercial/wizv2/processors/test_finding.py +671 -0
  262. tests/regscale/integrations/commercial/wizv2/test_WizDataMixin.py +537 -0
  263. tests/regscale/integrations/commercial/wizv2/test_click_comprehensive.py +851 -0
  264. tests/regscale/integrations/commercial/wizv2/test_compliance_report_comprehensive.py +910 -0
  265. tests/regscale/integrations/commercial/wizv2/test_compliance_report_normalization.py +138 -0
  266. tests/regscale/integrations/commercial/wizv2/test_file_cleanup.py +283 -0
  267. tests/regscale/integrations/commercial/wizv2/test_file_operations.py +260 -0
  268. tests/regscale/integrations/commercial/wizv2/test_issue.py +343 -0
  269. tests/regscale/integrations/commercial/wizv2/test_issue_comprehensive.py +1203 -0
  270. tests/regscale/integrations/commercial/wizv2/test_reports.py +497 -0
  271. tests/regscale/integrations/commercial/wizv2/test_sbom.py +643 -0
  272. tests/regscale/integrations/commercial/wizv2/test_scanner_comprehensive.py +805 -0
  273. tests/regscale/integrations/commercial/wizv2/test_wiz_click_client_id.py +165 -0
  274. tests/regscale/integrations/commercial/wizv2/test_wiz_compliance_report.py +1394 -0
  275. tests/regscale/integrations/commercial/wizv2/test_wiz_compliance_unit.py +341 -0
  276. tests/regscale/integrations/commercial/wizv2/test_wiz_control_normalization.py +138 -0
  277. tests/regscale/integrations/commercial/wizv2/test_wiz_findings_comprehensive.py +364 -0
  278. tests/regscale/integrations/commercial/wizv2/test_wiz_inventory_comprehensive.py +644 -0
  279. tests/regscale/integrations/commercial/wizv2/test_wiz_status_mapping.py +149 -0
  280. tests/regscale/integrations/commercial/wizv2/test_wizv2.py +1218 -0
  281. tests/regscale/integrations/commercial/wizv2/test_wizv2_utils.py +519 -0
  282. tests/regscale/integrations/commercial/wizv2/utils/__init__.py +1 -0
  283. tests/regscale/integrations/commercial/wizv2/utils/test_main.py +1523 -0
  284. tests/regscale/integrations/public/__init__.py +0 -0
  285. tests/regscale/integrations/public/fedramp/__init__.py +1 -0
  286. tests/regscale/integrations/public/fedramp/test_gen_asset_list.py +150 -0
  287. tests/regscale/integrations/public/fedramp/test_poam_export_v5.py +1293 -0
  288. tests/regscale/integrations/public/test_alienvault.py +220 -0
  289. tests/regscale/integrations/public/test_cci.py +1053 -0
  290. tests/regscale/integrations/public/test_cisa.py +1021 -0
  291. tests/regscale/integrations/public/test_emass.py +518 -0
  292. tests/regscale/integrations/public/test_fedramp.py +1152 -0
  293. tests/regscale/integrations/public/test_fedramp_cis_crm.py +3661 -0
  294. tests/regscale/integrations/public/test_file_uploads.py +506 -0
  295. tests/regscale/integrations/public/test_oscal.py +453 -0
  296. tests/regscale/integrations/test_compliance_status_mapping.py +406 -0
  297. tests/regscale/integrations/test_control_matcher.py +1421 -0
  298. tests/regscale/integrations/test_control_matching.py +155 -0
  299. tests/regscale/integrations/test_milestone_manager.py +408 -0
  300. tests/regscale/models/test_control_implementation.py +118 -3
  301. tests/regscale/models/test_form_field_value_integration.py +304 -0
  302. tests/regscale/models/test_issue.py +378 -1
  303. tests/regscale/models/test_module_integration.py +582 -0
  304. tests/regscale/models/test_tenable_integrations.py +811 -105
  305. regscale/integrations/commercial/wizv2/policy_compliance.py +0 -3057
  306. regscale/integrations/public/fedramp/mappings/fedramp_r4_parts.json +0 -7388
  307. regscale/integrations/public/fedramp/mappings/fedramp_r5_parts.json +0 -9605
  308. regscale/integrations/public/fedramp/parts_mapper.py +0 -107
  309. /regscale/integrations/commercial/{amazon → sarif}/__init__.py +0 -0
  310. /regscale/integrations/commercial/wizv2/{wiz_auth.py → core/auth.py} +0 -0
  311. {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/LICENSE +0 -0
  312. {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/WHEEL +0 -0
  313. {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/entry_points.txt +0 -0
  314. {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,453 @@
1
+ """Functions for parsing CIS benchmark output from Tenable"""
2
+
3
+ import logging
4
+ import re
5
+ from typing import Union, Optional
6
+
7
+ from regscale.core.app.utils.app_utils import get_current_datetime
8
+ from regscale.integrations.scanner_integration import IntegrationFinding, issue_due_date
9
+ from regscale.models import regscale_models
10
+
11
+ logger = logging.getLogger("regscale")
12
+
13
+ # Constants
14
+ _FAR_FUTURE_DATE = "2099-12-31T23:59:59Z" # Used for passed findings with no remediation needed
15
+
16
+
17
+ def parse_cis_compliance_result(compliance_data: dict, finding: IntegrationFinding) -> IntegrationFinding:
18
+ """
19
+ Parses CIS benchmark compliance data from Tenable and constructs an IntegrationFinding.
20
+
21
+ This function processes CIS benchmark compliance check results from either Tenable.io
22
+ compliance export API or Tenable Security Center analysis API, extracting key fields
23
+ and mapping them to RegScale checklist format.
24
+
25
+ :param dict compliance_data: The CIS compliance data dictionary from Tenable API
26
+ :param IntegrationFinding finding: The finding object to update with parsed data
27
+ :return: An IntegrationFinding object containing the parsed CIS compliance information
28
+ :rtype: IntegrationFinding
29
+
30
+ Example compliance_data structure (Tenable.io):
31
+ {
32
+ "check_id": "123456",
33
+ "check_name": "Ensure SSH Protocol is set to 2",
34
+ "audit_file": "CIS_AlmaLinux_OS_8_Server_v3.0.0_L1.audit",
35
+ "benchmark_name": "CIS AlmaLinux OS 8 Benchmark",
36
+ "benchmark_version": "v3.0.0",
37
+ "status": "FAILED",
38
+ "actual_value": "1",
39
+ "expected_value": "2",
40
+ "check_info": "Description of the check...",
41
+ "solution": "Edit /etc/ssh/sshd_config...",
42
+ "reference": "800-53|AC-17,CSCv7|9.2",
43
+ "see_also": "https://workbench.cisecurity.org/benchmarks/123",
44
+ "asset": {
45
+ "uuid": "abc-123-def",
46
+ "id": "456"
47
+ }
48
+ }
49
+ """
50
+
51
+ # Extract basic CIS benchmark information
52
+ check_id = compliance_data.get("check_id", "")
53
+ check_name = compliance_data.get("check_name", "")
54
+ audit_file = compliance_data.get("audit_file", "")
55
+ benchmark_name = compliance_data.get("benchmark_name", "")
56
+ benchmark_version = compliance_data.get("benchmark_version", "")
57
+ status = compliance_data.get("status", "UNKNOWN")
58
+
59
+ # Extract check details
60
+ check_info = compliance_data.get("check_info", "")
61
+ solution = compliance_data.get("solution", "")
62
+ reference = compliance_data.get("reference", "")
63
+ see_also = compliance_data.get("see_also", "")
64
+
65
+ # Extract actual vs expected values
66
+ actual_value = compliance_data.get("actual_value", "")
67
+ expected_value = compliance_data.get("expected_value", "")
68
+
69
+ # Parse CIS level (1 or 2) from audit file name
70
+ # Example: "CIS_AlmaLinux_OS_8_Server_v3.0.0_L1.audit" -> Level 1
71
+ cis_level = _extract_cis_level(audit_file)
72
+
73
+ # Parse CIS benchmark ID from check_name or see_also URL
74
+ # Example: "1.1.1.1 Ensure mounting of cramfs filesystems is disabled"
75
+ cis_benchmark_id = _extract_cis_benchmark_id(check_name, see_also)
76
+
77
+ # Create descriptive title
78
+ title = f"CIS {cis_benchmark_id}: {check_name}" if cis_benchmark_id else check_name
79
+ issue_title = title
80
+
81
+ # Map status to checklist status
82
+ checklist_status = _map_cis_status_to_checklist(status)
83
+
84
+ # Map status to issue status (for tracking open/closed)
85
+ issue_status = (
86
+ regscale_models.IssueStatus.Open
87
+ if status in ["FAILED", "WARNING", "ERROR"]
88
+ else regscale_models.IssueStatus.Closed
89
+ )
90
+
91
+ # Map status to severity for failed checks
92
+ severity = _map_cis_status_to_severity(status, cis_level, check_name)
93
+
94
+ # Set priority based on severity
95
+ priority = severity.value.title() if severity else "Medium"
96
+
97
+ # Create comprehensive description
98
+ description = _create_cis_description(
99
+ check_info=check_info,
100
+ benchmark_name=benchmark_name,
101
+ benchmark_version=benchmark_version,
102
+ cis_level=cis_level,
103
+ actual_value=actual_value,
104
+ expected_value=expected_value,
105
+ solution=solution,
106
+ )
107
+
108
+ # Create detailed results text
109
+ results = _create_cis_results_text(compliance_data, cis_level, cis_benchmark_id)
110
+
111
+ # Extract control references (e.g., NIST 800-53 controls)
112
+ control_references = _extract_control_references(reference)
113
+
114
+ # Set timestamps
115
+ current_datetime = get_current_datetime()
116
+ created_date = compliance_data.get("first_seen", current_datetime)
117
+ last_seen = compliance_data.get("last_seen", current_datetime)
118
+
119
+ # Calculate due date based on severity (skip for NotAssigned/passed findings)
120
+ if severity != regscale_models.IssueSeverity.NotAssigned:
121
+ due_date = issue_due_date(severity, created_date)
122
+ else:
123
+ # For passed findings, set a far future date since no remediation is needed
124
+ due_date = _FAR_FUTURE_DATE
125
+
126
+ # Update finding object
127
+ finding.title = title
128
+ finding.category = f"CIS Benchmark - Level {cis_level}"
129
+ finding.plugin_id = check_id
130
+ finding.plugin_name = check_name
131
+ finding.severity = severity
132
+ finding.description = description
133
+ finding.status = issue_status
134
+ finding.checklist_status = checklist_status
135
+ finding.priority = priority
136
+ finding.first_seen = created_date
137
+ finding.last_seen = last_seen
138
+ finding.issue_title = issue_title
139
+ finding.issue_type = "Risk"
140
+ finding.date_created = created_date
141
+ finding.date_last_updated = last_seen
142
+ finding.due_date = due_date
143
+ finding.external_id = f"CIS:{check_id}:{finding.asset_identifier}"
144
+ finding.recommendation_for_mitigation = solution
145
+ finding.results = results
146
+ finding.baseline = f"{benchmark_name} {benchmark_version}"
147
+ finding.vulnerability_number = cis_benchmark_id
148
+ finding.rule_id = cis_benchmark_id
149
+ finding.control_labels = control_references
150
+ finding.observations = f"Actual: {actual_value}, Expected: {expected_value}"
151
+ finding.gaps = check_info
152
+ finding.evidence = f"Status: {status}, Check ID: {check_id}"
153
+ finding.impact = f"CIS Level {cis_level} compliance impact"
154
+
155
+ return finding
156
+
157
+
158
+ def _extract_cis_level(audit_file: str) -> str:
159
+ """
160
+ Extract CIS level (1 or 2) from audit file name.
161
+
162
+ :param str audit_file: The audit file name
163
+ :return: CIS level as string ("1" or "2"), defaults to "1" if not found
164
+ :rtype: str
165
+
166
+ Examples:
167
+ "CIS_AlmaLinux_OS_8_Server_v3.0.0_L1.audit" -> "1"
168
+ "CIS_Windows_Server_2019_v1.2.1_L2.audit" -> "2"
169
+ """
170
+ match = re.search(r"_L([12])\.audit", audit_file, re.IGNORECASE)
171
+ return match.group(1) if match else "1"
172
+
173
+
174
+ def _extract_cis_benchmark_id(check_name: str, see_also: str) -> str:
175
+ """
176
+ Extract CIS benchmark ID from check name or see_also URL.
177
+
178
+ :param str check_name: The check name
179
+ :param str see_also: The see_also URL
180
+ :return: CIS benchmark ID (e.g., "1.1.1.1") or empty string
181
+ :rtype: str
182
+
183
+ Examples:
184
+ "1.1.1.1 Ensure mounting of cramfs filesystems is disabled" -> "1.1.1.1"
185
+ "2.3.4 Ensure telnet client is not installed" -> "2.3.4"
186
+ """
187
+ # Try to extract from check name (most common format)
188
+ if match := re.match(r"^([\d.]+)\s+", check_name):
189
+ return match.group(1)
190
+
191
+ # Try to extract from see_also URL
192
+ # Example: "https://workbench.cisecurity.org/benchmarks/123"
193
+ if see_also and "workbench.cisecurity.org" in see_also:
194
+ # Extract numeric ID from URL
195
+ if match := re.search(r"/benchmarks/(\d+)", see_also):
196
+ return match.group(1)
197
+
198
+ return ""
199
+
200
+
201
+ def _map_cis_status_to_checklist(status: str) -> regscale_models.ChecklistStatus:
202
+ """
203
+ Map CIS compliance status to RegScale ChecklistStatus enum.
204
+
205
+ :param str status: The CIS compliance status
206
+ :return: RegScale ChecklistStatus enum value
207
+ :rtype: regscale_models.ChecklistStatus
208
+
209
+ Status Mapping:
210
+ PASSED -> PASS
211
+ FAILED -> FAIL
212
+ WARNING -> NOT_REVIEWED (manual check required)
213
+ ERROR -> FAIL
214
+ NOT_APPLICABLE -> NOT_APPLICABLE
215
+ """
216
+ status_map = {
217
+ "PASSED": regscale_models.ChecklistStatus.PASS,
218
+ "FAILED": regscale_models.ChecklistStatus.FAIL,
219
+ "ERROR": regscale_models.ChecklistStatus.FAIL,
220
+ "WARNING": regscale_models.ChecklistStatus.NOT_REVIEWED, # Manual check required
221
+ "NOT_APPLICABLE": regscale_models.ChecklistStatus.NOT_APPLICABLE,
222
+ "NOT APPLICABLE": regscale_models.ChecklistStatus.NOT_APPLICABLE,
223
+ }
224
+
225
+ result_key = status.upper().replace("_", " ").strip()
226
+ if result_key not in status_map:
227
+ logger.warning(f"CIS status '{status}' not found in status map, defaulting to NOT_REVIEWED")
228
+ return regscale_models.ChecklistStatus.NOT_REVIEWED
229
+
230
+ return status_map[result_key]
231
+
232
+
233
+ def _map_cis_status_to_severity(status: str, cis_level: str, check_name: str) -> regscale_models.IssueSeverity:
234
+ """
235
+ Map CIS compliance status and level to IssueSeverity enum.
236
+
237
+ CIS severity mapping follows Tenable conventions:
238
+ - PASSED: NotAssigned (Info level)
239
+ - FAILED: High for Level 1, Moderate for Level 2
240
+ - WARNING: Moderate (manual check)
241
+ - ERROR: High
242
+
243
+ :param str status: The CIS compliance status
244
+ :param str cis_level: The CIS level ("1" or "2")
245
+ :param str check_name: The check name (for additional context)
246
+ :return: IssueSeverity enum value
247
+ :rtype: regscale_models.IssueSeverity
248
+ """
249
+ # Check for critical keywords in check name
250
+ critical_keywords = ["critical", "essential", "must", "required"]
251
+ is_critical = any(keyword in check_name.lower() for keyword in critical_keywords)
252
+
253
+ status_upper = status.upper()
254
+
255
+ if status_upper == "PASSED":
256
+ return regscale_models.IssueSeverity.NotAssigned
257
+ elif status_upper == "FAILED":
258
+ # Level 1 failures are generally more critical
259
+ if cis_level == "1" or is_critical:
260
+ return regscale_models.IssueSeverity.High
261
+ else:
262
+ return regscale_models.IssueSeverity.Moderate
263
+ elif status_upper == "WARNING":
264
+ # Manual checks are moderate severity
265
+ return regscale_models.IssueSeverity.Moderate
266
+ elif status_upper == "ERROR":
267
+ return regscale_models.IssueSeverity.High
268
+ else:
269
+ return regscale_models.IssueSeverity.Low
270
+
271
+
272
+ def _create_cis_description(
273
+ check_info: str,
274
+ benchmark_name: str,
275
+ benchmark_version: str,
276
+ cis_level: str,
277
+ actual_value: str,
278
+ expected_value: str,
279
+ solution: str,
280
+ ) -> str:
281
+ """
282
+ Create a comprehensive description for the CIS finding.
283
+
284
+ :param str check_info: The check information
285
+ :param str benchmark_name: The benchmark name
286
+ :param str benchmark_version: The benchmark version
287
+ :param str cis_level: The CIS level
288
+ :param str actual_value: The actual value found
289
+ :param str expected_value: The expected value
290
+ :param str solution: The solution/remediation
291
+ :return: Formatted description
292
+ :rtype: str
293
+ """
294
+ description_parts = [
295
+ f"**CIS Benchmark**: {benchmark_name} {benchmark_version}",
296
+ f"**CIS Level**: {cis_level}",
297
+ "",
298
+ "**Check Information**:",
299
+ check_info or "No detailed information available.",
300
+ "",
301
+ "**Compliance Status**:",
302
+ f"- Expected Value: {expected_value or 'N/A'}",
303
+ f"- Actual Value: {actual_value or 'N/A'}",
304
+ ]
305
+
306
+ if solution:
307
+ description_parts.extend(
308
+ [
309
+ "",
310
+ "**Remediation**:",
311
+ solution,
312
+ ]
313
+ )
314
+
315
+ return "\n".join(description_parts)
316
+
317
+
318
+ def _create_cis_results_text(compliance_data: dict, cis_level: str, cis_benchmark_id: str) -> str:
319
+ """
320
+ Create detailed results text for the CIS finding.
321
+
322
+ :param dict compliance_data: The CIS compliance data dictionary
323
+ :param str cis_level: The CIS level
324
+ :param str cis_benchmark_id: The CIS benchmark ID
325
+ :return: Formatted results text
326
+ :rtype: str
327
+ """
328
+ check_id = compliance_data.get("check_id", "")
329
+ check_name = compliance_data.get("check_name", "")
330
+ benchmark_name = compliance_data.get("benchmark_name", "")
331
+ benchmark_version = compliance_data.get("benchmark_version", "")
332
+ status = compliance_data.get("status", "UNKNOWN")
333
+ actual_value = compliance_data.get("actual_value", "")
334
+ expected_value = compliance_data.get("expected_value", "")
335
+ check_info = compliance_data.get("check_info", "")
336
+ solution = compliance_data.get("solution", "")
337
+ reference = compliance_data.get("reference", "")
338
+
339
+ results = (
340
+ f"CIS Benchmark ID: {cis_benchmark_id}, Status: {status}, Level: {cis_level}<br><br>"
341
+ f"Benchmark: {benchmark_name} {benchmark_version}<br><br>"
342
+ f"Check Name: {check_name}<br><br>"
343
+ f"Check Content: {check_info}<br><br>"
344
+ f"Expected Value: {expected_value}<br>"
345
+ f"Actual Value: {actual_value}<br><br>"
346
+ f"Fix Text: {solution}<br><br>"
347
+ f"References: {reference}<br>"
348
+ f"Check ID: {check_id}"
349
+ )
350
+
351
+ return results
352
+
353
+
354
+ def _extract_control_references(reference: str) -> list:
355
+ """
356
+ Extract control framework references from the reference string.
357
+
358
+ :param str reference: The reference string (e.g., "800-53|AC-17,CSCv7|9.2")
359
+ :return: List of control reference strings
360
+ :rtype: list
361
+
362
+ Example:
363
+ "800-53|AC-17,CSCv7|9.2,PCI-DSSv3.2.1|2.2.4"
364
+ -> ["800-53:AC-17", "CSCv7:9.2", "PCI-DSSv3.2.1:2.2.4"]
365
+ """
366
+ if not reference:
367
+ return []
368
+
369
+ control_refs = []
370
+
371
+ # Split by comma to get individual framework references
372
+ ref_parts = reference.split(",")
373
+
374
+ for part in ref_parts:
375
+ # Split by pipe to get framework and control ID
376
+ if "|" in part:
377
+ framework, control_id = part.split("|", 1)
378
+ control_refs.append(f"{framework.strip()}:{control_id.strip()}")
379
+
380
+ return control_refs
381
+
382
+
383
+ def parse_tenable_sc_cis_result(plugin_output: str, finding: IntegrationFinding) -> IntegrationFinding:
384
+ """
385
+ Parse CIS benchmark results from Tenable Security Center plugin output.
386
+
387
+ This function handles the text-based plugin output format from Tenable SC
388
+ and extracts CIS benchmark compliance information.
389
+
390
+ :param str plugin_output: The plugin output text from Tenable SC
391
+ :param IntegrationFinding finding: The finding object to update
392
+ :return: Updated IntegrationFinding object
393
+ :rtype: IntegrationFinding
394
+
395
+ Example plugin_output format:
396
+ Check Name: 1.1.1.1: Ensure mounting of cramfs filesystems is disabled
397
+ Information: The cramfs filesystem...
398
+ Result: FAILED
399
+ Solution: Edit /etc/modprobe.d/...
400
+ Reference Information: Benchmark|CIS AlmaLinux OS 8 Benchmark v3.0.0 Level 1,Level|1
401
+ """
402
+ # Extract fields using regex patterns (optimized to avoid catastrophic backtracking)
403
+ check_name = _extract_field(r"Check Name:\s*([^\n]+)", plugin_output, re.MULTILINE)
404
+ information = _extract_field(r"Information:\s*([^\n]+)", plugin_output, re.MULTILINE)
405
+ result = _extract_field(r"Result:\s*([^\n]+)", plugin_output, re.IGNORECASE | re.MULTILINE)
406
+ solution = _extract_field(r"Solution:\s*(.*?)(?=\n\nReference Information:)", plugin_output, re.DOTALL)
407
+ ref_info = _extract_field(r"Reference Information:\s*(.*)", plugin_output, re.DOTALL | re.MULTILINE)
408
+
409
+ # Parse reference information with error handling
410
+ ref_dict = {}
411
+ for item in ref_info.split(","):
412
+ if "|" in item:
413
+ parts = item.split("|", 1)
414
+ if len(parts) == 2:
415
+ ref_dict[parts[0].strip()] = parts[1].strip()
416
+ benchmark_info = ref_dict.get("Benchmark", "")
417
+ level_info = ref_dict.get("Level", "1")
418
+
419
+ # Create compliance data structure
420
+ compliance_data = {
421
+ "check_id": finding.plugin_id or "",
422
+ "check_name": check_name,
423
+ "audit_file": f"CIS_L{level_info}.audit",
424
+ "benchmark_name": benchmark_info,
425
+ "benchmark_version": "", # Not always available in SC output
426
+ "status": result.upper(),
427
+ "actual_value": "", # Not always in SC output
428
+ "expected_value": "", # Not always in SC output
429
+ "check_info": information,
430
+ "solution": solution,
431
+ "reference": ref_info,
432
+ "see_also": "",
433
+ "first_seen": finding.first_seen or get_current_datetime(),
434
+ "last_seen": finding.last_seen or get_current_datetime(),
435
+ }
436
+
437
+ # Parse using main CIS parser
438
+ return parse_cis_compliance_result(compliance_data, finding)
439
+
440
+
441
+ def _extract_field(pattern: str, text: str, flags: Union[int, re.RegexFlag] = 0, group: int = 1) -> str:
442
+ """
443
+ Extract a field from a string using a regular expression.
444
+
445
+ :param str pattern: The regular expression pattern to search for
446
+ :param str text: The string to search in
447
+ :param Union[int, re.RegexFlag] flags: Optional regular expression flags
448
+ :param int group: The group number to return from the match
449
+ :return: The extracted field as a string, empty string if no match
450
+ :rtype: str
451
+ """
452
+ match = re.search(pattern, text, flags)
453
+ return match.group(group).strip() if match else ""