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,341 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Unit tests for Wiz Compliance Report Integration (no authentication required).
5
+
6
+ These tests focus on the core compliance workflow components without requiring
7
+ live authentication to RegScale or Wiz APIs. They test:
8
+ - Report parsing logic
9
+ - Data transformation
10
+ - Control consolidation
11
+ - Issue creation logic
12
+ """
13
+
14
+ import csv
15
+ import os
16
+ import tempfile
17
+ import unittest
18
+ from datetime import datetime
19
+
20
+ import pytest
21
+
22
+
23
+ class TestWizComplianceUnit(unittest.TestCase):
24
+ """Unit tests for Wiz Compliance Report functionality without authentication."""
25
+
26
+ def setUp(self):
27
+ """Set up test fixtures."""
28
+ # Sample compliance data representing the expected results format
29
+ self.compliance_data = [
30
+ # Passing controls
31
+ {
32
+ "Resource Name": "vm-production-001",
33
+ "Cloud Provider": "Azure",
34
+ "Cloud Provider ID": "/subscriptions/12345/resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/vm-production-001",
35
+ "Resource ID": "/subscriptions/12345/resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/vm-production-001",
36
+ "Resource Region": "East US 2",
37
+ "Subscription": "prod-subscription-123",
38
+ "Subscription Name": "Production Subscription",
39
+ "Policy Name": "Ensure VM has monitoring agent installed",
40
+ "Policy ID": "azure-vm-monitoring-001",
41
+ "Result": "Pass",
42
+ "Control IDs": "AC-2,AC-3",
43
+ "Framework": "NIST 800-53",
44
+ "Severity": "High",
45
+ "Control Family": "Access Control",
46
+ "Details": "Monitoring agent is properly installed and configured",
47
+ "Status": "Compliant",
48
+ },
49
+ # Failing control that should create an issue
50
+ {
51
+ "Resource Name": "vm-test-002",
52
+ "Cloud Provider": "Azure",
53
+ "Cloud Provider ID": "/subscriptions/12345/resourceGroups/test-rg/providers/Microsoft.Compute/virtualMachines/vm-test-002",
54
+ "Resource ID": "/subscriptions/12345/resourceGroups/test-rg/providers/Microsoft.Compute/virtualMachines/vm-test-002",
55
+ "Resource Region": "West US 2",
56
+ "Subscription": "test-subscription-456",
57
+ "Subscription Name": "Test Subscription",
58
+ "Policy Name": "Ensure disk encryption is enabled",
59
+ "Policy ID": "azure-disk-encryption-001",
60
+ "Result": "Fail",
61
+ "Control IDs": "SC-28,SC-13",
62
+ "Framework": "NIST 800-53",
63
+ "Severity": "Critical",
64
+ "Control Family": "System and Communications Protection",
65
+ "Details": "Disk encryption is not enabled on this virtual machine",
66
+ "Status": "Non-Compliant",
67
+ },
68
+ # Multiple control IDs test case
69
+ {
70
+ "Resource Name": "storage-account-001",
71
+ "Cloud Provider": "Azure",
72
+ "Cloud Provider ID": "/subscriptions/12345/resourceGroups/prod-rg/providers/Microsoft.Storage/storageAccounts/prodstore001",
73
+ "Resource ID": "/subscriptions/12345/resourceGroups/prod-rg/providers/Microsoft.Storage/storageAccounts/prodstore001",
74
+ "Resource Region": "East US",
75
+ "Subscription": "prod-subscription-123",
76
+ "Subscription Name": "Production Subscription",
77
+ "Policy Name": "Storage account should use secure transfer",
78
+ "Policy ID": "azure-storage-secure-001",
79
+ "Result": "Fail",
80
+ "Control IDs": "SC-8,SC-23,IA-7",
81
+ "Framework": "NIST 800-53",
82
+ "Severity": "Medium",
83
+ "Control Family": "System and Communications Protection",
84
+ "Details": "Secure transfer is not required for this storage account",
85
+ "Status": "Non-Compliant",
86
+ },
87
+ ]
88
+
89
+ def test_wiz_compliance_item_creation(self):
90
+ """Test creation of WizComplianceReportItem from CSV data."""
91
+ from regscale.integrations.commercial.wizv2.compliance_report import WizComplianceReportItem
92
+
93
+ csv_row = self.compliance_data[0] # Use the first test data item
94
+
95
+ compliance_item = WizComplianceReportItem(csv_row)
96
+
97
+ self.assertEqual(compliance_item.resource_name, "vm-production-001 (East US 2)")
98
+ self.assertEqual(compliance_item.cloud_provider, "Azure")
99
+ self.assertEqual(compliance_item.result, "Pass")
100
+ self.assertEqual(compliance_item.policy_name, "Ensure VM has monitoring agent installed")
101
+
102
+ def test_csv_data_parsing(self):
103
+ """Test that CSV data is properly parsed."""
104
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as temp_file:
105
+ writer = csv.DictWriter(temp_file, fieldnames=self.compliance_data[0].keys())
106
+ writer.writeheader()
107
+ writer.writerows(self.compliance_data)
108
+ temp_file.flush()
109
+
110
+ try:
111
+ with open(temp_file.name, "r") as f:
112
+ reader = csv.DictReader(f)
113
+ parsed_data = list(reader)
114
+
115
+ self.assertEqual(len(parsed_data), 3)
116
+ self.assertEqual(parsed_data[0]["Resource Name"], "vm-production-001")
117
+ self.assertEqual(parsed_data[1]["Result"], "Fail")
118
+ self.assertEqual(parsed_data[2]["Control IDs"], "SC-8,SC-23,IA-7")
119
+
120
+ finally:
121
+ os.unlink(temp_file.name)
122
+
123
+ def test_control_id_extraction(self):
124
+ """Test extraction of multiple control IDs from a single compliance item."""
125
+ test_data = {"Control IDs": "AC-2,AC-3,AC-4", "Framework": "NIST 800-53"}
126
+
127
+ # Simulate the control ID parsing logic
128
+ control_ids = [cid.strip() for cid in test_data["Control IDs"].split(",")]
129
+
130
+ self.assertEqual(len(control_ids), 3)
131
+ self.assertIn("AC-2", control_ids)
132
+ self.assertIn("AC-3", control_ids)
133
+ self.assertIn("AC-4", control_ids)
134
+
135
+ def test_status_matching_logic(self):
136
+ """Test that status values are properly mapped."""
137
+ # Test various status mapping scenarios
138
+ status_mappings = {
139
+ "Pass": "Compliant",
140
+ "Fail": "Non-Compliant",
141
+ "Warning": "Partially Compliant",
142
+ "Info": "Informational",
143
+ }
144
+
145
+ for result, expected_status in status_mappings.items():
146
+ # Simulate status mapping logic
147
+ if result.lower() == "pass":
148
+ mapped_status = "Compliant"
149
+ elif result.lower() == "fail":
150
+ mapped_status = "Non-Compliant"
151
+ elif result.lower() == "warning":
152
+ mapped_status = "Partially Compliant"
153
+ else:
154
+ mapped_status = "Informational"
155
+
156
+ self.assertEqual(mapped_status, expected_status)
157
+
158
+ def test_asset_creation_data_structure(self):
159
+ """Test that asset data is properly structured for RegScale."""
160
+ compliance_item = self.compliance_data[0]
161
+
162
+ # Simulate asset creation logic
163
+ asset_data = {
164
+ "name": compliance_item["Resource Name"],
165
+ "cloudProviderId": compliance_item["Cloud Provider ID"],
166
+ "region": compliance_item["Resource Region"],
167
+ "assetType": "Cloud Resource",
168
+ "description": f"{compliance_item['Cloud Provider']} resource",
169
+ }
170
+
171
+ self.assertEqual(asset_data["name"], "vm-production-001")
172
+ self.assertTrue(asset_data["cloudProviderId"].startswith("/subscriptions/"))
173
+ self.assertEqual(asset_data["region"], "East US 2")
174
+ self.assertEqual(asset_data["assetType"], "Cloud Resource")
175
+
176
+ def test_issue_creation_for_failed_controls(self):
177
+ """Test that issues are properly created for failed compliance items."""
178
+ failed_item = self.compliance_data[1] # The failing disk encryption item
179
+
180
+ # Simulate issue creation logic
181
+ if failed_item["Result"].lower() == "fail":
182
+ issue_data = {
183
+ "title": f"Wiz Compliance: {failed_item['Policy Name']}",
184
+ "description": failed_item["Details"],
185
+ "severity": failed_item["Severity"],
186
+ "status": "Open",
187
+ "source": "Wiz Compliance Scan",
188
+ }
189
+
190
+ self.assertEqual(issue_data["title"], "Wiz Compliance: Ensure disk encryption is enabled")
191
+ self.assertEqual(issue_data["severity"], "Critical")
192
+ self.assertEqual(issue_data["status"], "Open")
193
+ self.assertIn("encryption", issue_data["description"].lower())
194
+
195
+ def test_control_aggregation_threshold_logic(self):
196
+ """Test control aggregation and threshold logic."""
197
+
198
+ # Test multiple items for the same control
199
+ control_items = [
200
+ {"Control IDs": "AC-2", "Result": "Pass", "Resource Name": "resource1"},
201
+ {"Control IDs": "AC-2", "Result": "Fail", "Resource Name": "resource2"},
202
+ {"Control IDs": "AC-2", "Result": "Pass", "Resource Name": "resource3"},
203
+ ]
204
+
205
+ # Simulate aggregation logic
206
+ control_results = {}
207
+ for item in control_items:
208
+ control_id = item["Control IDs"]
209
+ if control_id not in control_results:
210
+ control_results[control_id] = {"pass": 0, "fail": 0, "total": 0}
211
+
212
+ control_results[control_id]["total"] += 1
213
+ if item["Result"].lower() == "pass":
214
+ control_results[control_id]["pass"] += 1
215
+ else:
216
+ control_results[control_id]["fail"] += 1
217
+
218
+ # Test the aggregated results
219
+ ac2_results = control_results["AC-2"]
220
+ self.assertEqual(ac2_results["total"], 3)
221
+ self.assertEqual(ac2_results["pass"], 2)
222
+ self.assertEqual(ac2_results["fail"], 1)
223
+
224
+ # Test threshold logic (e.g., >70% pass rate = compliant)
225
+ pass_rate = ac2_results["pass"] / ac2_results["total"]
226
+ control_status = "Compliant" if pass_rate > 0.7 else "Non-Compliant"
227
+ self.assertEqual(control_status, "Non-Compliant") # 66.7% pass rate
228
+
229
+ def test_compliance_item_creation_and_properties(self):
230
+ """Test that compliance items are created with correct properties."""
231
+ test_item = self.compliance_data[2] # Storage account item
232
+
233
+ # Simulate compliance item creation
234
+ compliance_item = {
235
+ "control_id": "SC-8", # First control ID
236
+ "status": "Non-Compliant" if test_item["Result"] == "Fail" else "Compliant",
237
+ "implementation_guidance": test_item["Details"],
238
+ "assessment_date": datetime.now().isoformat(),
239
+ "source": "Wiz Policy Compliance",
240
+ "evidence": f"Policy: {test_item['Policy Name']}, Resource: {test_item['Resource Name']}",
241
+ }
242
+
243
+ self.assertEqual(compliance_item["control_id"], "SC-8")
244
+ self.assertEqual(compliance_item["status"], "Non-Compliant")
245
+ self.assertIn("secure transfer", compliance_item["implementation_guidance"].lower())
246
+ self.assertIn("Wiz Policy", compliance_item["source"])
247
+
248
+ def test_report_reuse_functionality(self):
249
+ """Test that report files can be reused and cached."""
250
+ # Simulate report file caching logic
251
+ report_cache = {}
252
+ report_path = "/tmp/wiz_compliance_report.csv"
253
+ cache_key = f"wiz_report_{hash(report_path)}"
254
+
255
+ # First access - not in cache
256
+ self.assertNotIn(cache_key, report_cache)
257
+
258
+ # Simulate adding to cache
259
+ report_cache[cache_key] = {"path": report_path, "last_modified": datetime.now(), "data": self.compliance_data}
260
+
261
+ # Second access - should be in cache
262
+ self.assertIn(cache_key, report_cache)
263
+ cached_data = report_cache[cache_key]["data"]
264
+ self.assertEqual(len(cached_data), 3)
265
+ self.assertEqual(cached_data[0]["Resource Name"], "vm-production-001")
266
+
267
+ def test_multiple_control_ids_extraction(self):
268
+ """Test handling of compliance items with multiple control IDs."""
269
+ multi_control_item = self.compliance_data[2] # Has SC-8,SC-23,IA-7
270
+
271
+ control_ids = [cid.strip() for cid in multi_control_item["Control IDs"].split(",")]
272
+
273
+ # Verify all control IDs are extracted
274
+ expected_controls = ["SC-8", "SC-23", "IA-7"]
275
+ self.assertEqual(len(control_ids), 3)
276
+
277
+ for expected_control in expected_controls:
278
+ self.assertIn(expected_control, control_ids)
279
+
280
+ # Simulate creating separate compliance items for each control
281
+ compliance_items = []
282
+ for control_id in control_ids:
283
+ item = {
284
+ "control_id": control_id,
285
+ "resource_name": multi_control_item["Resource Name"],
286
+ "status": "Non-Compliant",
287
+ "policy_name": multi_control_item["Policy Name"],
288
+ }
289
+ compliance_items.append(item)
290
+
291
+ self.assertEqual(len(compliance_items), 3)
292
+ self.assertEqual(compliance_items[0]["control_id"], "SC-8")
293
+ self.assertEqual(compliance_items[1]["control_id"], "SC-23")
294
+ self.assertEqual(compliance_items[2]["control_id"], "IA-7")
295
+
296
+ def test_csv_file_parsing_edge_cases(self):
297
+ """Test CSV file parsing with various edge cases."""
298
+ # Test data with edge cases
299
+ edge_case_data = [
300
+ {
301
+ "Resource Name": "vm-with,comma",
302
+ "Control IDs": "AC-1,AC-2, AC-3 ", # Extra spaces
303
+ "Details": 'Description with "quotes" and newlines\nSecond line',
304
+ "Result": "PASS", # Different case
305
+ "Policy Name": "", # Empty field
306
+ }
307
+ ]
308
+
309
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as temp_file:
310
+ writer = csv.DictWriter(temp_file, fieldnames=edge_case_data[0].keys())
311
+ writer.writeheader()
312
+ writer.writerows(edge_case_data)
313
+ temp_file.flush()
314
+
315
+ try:
316
+ with open(temp_file.name, "r") as f:
317
+ reader = csv.DictReader(f)
318
+ parsed_data = list(reader)
319
+
320
+ self.assertEqual(len(parsed_data), 1)
321
+ item = parsed_data[0]
322
+
323
+ # Test comma in resource name is preserved
324
+ self.assertEqual(item["Resource Name"], "vm-with,comma")
325
+
326
+ # Test control ID parsing with spaces
327
+ control_ids = [cid.strip() for cid in item["Control IDs"].split(",")]
328
+ self.assertEqual(control_ids, ["AC-1", "AC-2", "AC-3"])
329
+
330
+ # Test case insensitive result parsing
331
+ self.assertEqual(item["Result"].lower(), "pass")
332
+
333
+ # Test empty policy name
334
+ self.assertEqual(item["Policy Name"], "")
335
+
336
+ finally:
337
+ os.unlink(temp_file.name)
338
+
339
+
340
+ if __name__ == "__main__":
341
+ unittest.main()
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env python3
2
+ """Test Wiz control ID normalization after fix."""
3
+
4
+ import re
5
+ import logging
6
+
7
+ logging.basicConfig(level=logging.INFO)
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class WizComplianceReportItemTest:
12
+ """Test version of WizComplianceReportItem with normalization methods."""
13
+
14
+ def _normalize_base_control(self, base_control: str) -> str:
15
+ """Normalize leading zeros in base control number (e.g., AC-01 -> AC-1)."""
16
+ if "-" in base_control:
17
+ prefix, number = base_control.split("-", 1)
18
+ try:
19
+ normalized_number = str(int(number))
20
+ return f"{prefix.upper()}-{normalized_number}"
21
+ except ValueError:
22
+ return base_control.upper()
23
+ else:
24
+ return base_control.upper()
25
+
26
+ def _format_control_id(self, base_control: str, enhancement: str) -> str:
27
+ """Format control ID with optional enhancement."""
28
+ if enhancement:
29
+ # Normalize enhancement number to remove leading zeros
30
+ try:
31
+ normalized_enhancement = str(int(enhancement))
32
+ except ValueError:
33
+ normalized_enhancement = enhancement
34
+ return f"{base_control}({normalized_enhancement})"
35
+ else:
36
+ return base_control
37
+
38
+ def get_all_control_ids(self, compliance_check_name: str) -> list:
39
+ """Extract all control IDs from compliance check name and normalize leading zeros."""
40
+ if not compliance_check_name:
41
+ return []
42
+
43
+ control_id_pattern = r"([A-Za-z]{2}-\d+)(?:\s*\(\s*(\d+)\s*\))?"
44
+ control_ids = []
45
+
46
+ for part in compliance_check_name.split(", "):
47
+ matches = re.findall(control_id_pattern, part.strip())
48
+ for match in matches:
49
+ base_control, enhancement = match
50
+ normalized_control = self._normalize_base_control(base_control)
51
+ formatted_control = self._format_control_id(normalized_control, enhancement)
52
+ control_ids.append(formatted_control)
53
+
54
+ return control_ids
55
+
56
+
57
+ def test_normalization():
58
+ """Test control ID normalization."""
59
+
60
+ test_item = WizComplianceReportItemTest()
61
+
62
+ # Test cases from actual Wiz data
63
+ test_cases = [
64
+ # Single controls
65
+ ("AC-3 Access Enforcement", ["AC-3"]),
66
+ ("AC-2(4) Account Management | Automated Audit Actions", ["AC-2(4)"]),
67
+ ("SI-4(20) System Monitoring | Privileged Users", ["SI-4(20)"]),
68
+ # Multi-control strings
69
+ (
70
+ "AC-2(4) Account Management | Automated Audit Actions, AC-6(9) Least Privilege | Log Use of Privileged Functions, AU-12 Audit Record Generation",
71
+ ["AC-2(4)", "AC-6(9)", "AU-12"],
72
+ ),
73
+ # Edge cases with leading zeros (potential future data)
74
+ ("AC-01 Access Control", ["AC-1"]),
75
+ ("AC-01(04) Access Control Enhancement", ["AC-1(4)"]),
76
+ ("SC-08(01) Transmission Security", ["SC-8(1)"]),
77
+ # Complex multi-control with various formats
78
+ ("AC-01(04) Access Control, AU-3(1) Audit Content, SI-04(20) Monitoring", ["AC-1(4)", "AU-3(1)", "SI-4(20)"]),
79
+ ]
80
+
81
+ logger.info("Testing Wiz Control ID Normalization")
82
+ logger.info("=" * 60)
83
+
84
+ all_passed = True
85
+
86
+ for input_string, expected_output in test_cases:
87
+ result = test_item.get_all_control_ids(input_string)
88
+
89
+ logger.info(f"\nInput: {input_string}")
90
+ logger.info(f"Expected: {expected_output}")
91
+ logger.info(f"Got: {result}")
92
+
93
+ if result == expected_output:
94
+ logger.info("✓ PASS")
95
+ else:
96
+ logger.error("✗ FAIL")
97
+ all_passed = False
98
+
99
+ logger.info("\n" + "=" * 60)
100
+ if all_passed:
101
+ logger.info("All tests PASSED ✓")
102
+ else:
103
+ logger.error("Some tests FAILED ✗")
104
+
105
+ # Test specific normalization cases
106
+ logger.info("\n" + "=" * 60)
107
+ logger.info("Testing specific normalization methods:")
108
+
109
+ # Test base control normalization
110
+ base_tests = [
111
+ ("AC-01", "AC-1"),
112
+ ("AC-1", "AC-1"),
113
+ ("AU-003", "AU-3"),
114
+ ("sc-7", "SC-7"), # lowercase
115
+ ]
116
+
117
+ for input_val, expected in base_tests:
118
+ result = test_item._normalize_base_control(input_val)
119
+ status = "✓" if result == expected else "✗"
120
+ logger.info(f" _normalize_base_control('{input_val}') -> '{result}' (expected: '{expected}') {status}")
121
+
122
+ # Test format control ID
123
+ format_tests = [
124
+ (("AC-1", "04"), "AC-1(4)"),
125
+ (("AC-1", "4"), "AC-1(4)"),
126
+ (("AC-1", ""), "AC-1"),
127
+ (("SC-7", "001"), "SC-7(1)"),
128
+ ]
129
+
130
+ logger.info("\nTesting _format_control_id:")
131
+ for (base, enhancement), expected in format_tests:
132
+ result = test_item._format_control_id(base, enhancement)
133
+ status = "✓" if result == expected else "✗"
134
+ logger.info(f" _format_control_id('{base}', '{enhancement}') -> '{result}' (expected: '{expected}') {status}")
135
+
136
+
137
+ if __name__ == "__main__":
138
+ test_normalization()