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,564 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Unit tests for AWS GuardDuty Control Mappings."""
4
+
5
+ import pytest
6
+
7
+ from regscale.integrations.commercial.aws.guardduty_control_mappings import (
8
+ CVE_RELATED_FINDING_TYPES,
9
+ GUARDDUTY_CONTROL_MAPPINGS,
10
+ SEVERITY_MAPPING,
11
+ GuardDutyControlMapper,
12
+ )
13
+
14
+
15
+ class TestGuardDutyControlMapper:
16
+ """Test GuardDutyControlMapper class."""
17
+
18
+ def test_init_default_framework(self):
19
+ """Test initialization with default framework."""
20
+ mapper = GuardDutyControlMapper()
21
+ assert mapper.framework == "NIST800-53R5"
22
+ assert mapper.mappings == GUARDDUTY_CONTROL_MAPPINGS
23
+
24
+ def test_init_custom_framework(self):
25
+ """Test initialization with custom framework."""
26
+ mapper = GuardDutyControlMapper(framework="ISO27001")
27
+ assert mapper.framework == "ISO27001"
28
+ assert mapper.mappings == GUARDDUTY_CONTROL_MAPPINGS
29
+
30
+ def test_get_mapped_controls(self):
31
+ """Test getting list of mapped controls."""
32
+ mapper = GuardDutyControlMapper()
33
+ controls = mapper.get_mapped_controls()
34
+ assert isinstance(controls, list)
35
+ assert len(controls) > 0
36
+ assert "SI-4" in controls
37
+ assert "IR-4" in controls
38
+ assert "IR-5" in controls
39
+ assert "SI-3" in controls
40
+ assert "RA-5" in controls
41
+
42
+ def test_get_control_description_valid(self):
43
+ """Test getting control description for valid control."""
44
+ mapper = GuardDutyControlMapper()
45
+ description = mapper.get_control_description("SI-4")
46
+ assert description is not None
47
+ assert "System Monitoring" in description
48
+ assert "Monitor the system to detect attacks" in description
49
+
50
+ def test_get_control_description_invalid(self):
51
+ """Test getting control description for invalid control."""
52
+ mapper = GuardDutyControlMapper()
53
+ description = mapper.get_control_description("INVALID-CONTROL")
54
+ assert description is None
55
+
56
+ def test_get_check_details_valid(self):
57
+ """Test getting check details for valid control."""
58
+ mapper = GuardDutyControlMapper()
59
+ checks = mapper.get_check_details("SI-4")
60
+ assert checks is not None
61
+ assert isinstance(checks, dict)
62
+ assert "detector_enabled" in checks
63
+ assert "findings_processed" in checks
64
+ assert checks["detector_enabled"]["weight"] == 100
65
+
66
+ def test_get_check_details_invalid(self):
67
+ """Test getting check details for invalid control."""
68
+ mapper = GuardDutyControlMapper()
69
+ checks = mapper.get_check_details("INVALID-CONTROL")
70
+ assert checks is None
71
+
72
+
73
+ class TestAssessGuardDutyCompliance:
74
+ """Test assess_guardduty_compliance method."""
75
+
76
+ def test_assess_compliance_all_pass(self):
77
+ """Test assessment when all controls pass."""
78
+ mapper = GuardDutyControlMapper()
79
+ guardduty_data = {
80
+ "Detectors": [
81
+ {
82
+ "DetectorId": "test-detector",
83
+ "Status": "ENABLED",
84
+ "DataSources": {"S3Logs": {"Status": "ENABLED"}},
85
+ }
86
+ ],
87
+ "Findings": [],
88
+ }
89
+ results = mapper.assess_guardduty_compliance(guardduty_data)
90
+ assert results["SI-4"] == "PASS"
91
+ assert results["IR-4"] == "PASS"
92
+ assert results["IR-5"] == "PASS"
93
+ assert results["SI-3"] == "PASS"
94
+ assert results["RA-5"] == "PASS"
95
+
96
+ def test_assess_compliance_non_nist_framework(self):
97
+ """Test assessment with non-NIST framework returns empty results."""
98
+ mapper = GuardDutyControlMapper(framework="ISO27001")
99
+ guardduty_data = {"Detectors": []}
100
+ results = mapper.assess_guardduty_compliance(guardduty_data)
101
+ assert results == {}
102
+
103
+
104
+ class TestAssessSI4:
105
+ """Test _assess_si4 (System Monitoring) compliance."""
106
+
107
+ def test_si4_pass_detectors_enabled(self):
108
+ """Test SI-4 passes when detectors are enabled."""
109
+ mapper = GuardDutyControlMapper()
110
+ guardduty_data = {"Detectors": [{"DetectorId": "test-detector", "Status": "ENABLED"}]}
111
+ result = mapper._assess_si4(guardduty_data)
112
+ assert result == "PASS"
113
+
114
+ def test_si4_pass_multiple_detectors_enabled(self):
115
+ """Test SI-4 passes when multiple detectors are enabled."""
116
+ mapper = GuardDutyControlMapper()
117
+ guardduty_data = {
118
+ "Detectors": [
119
+ {"DetectorId": "detector1", "Status": "ENABLED"},
120
+ {"DetectorId": "detector2", "Status": "ENABLED"},
121
+ ]
122
+ }
123
+ result = mapper._assess_si4(guardduty_data)
124
+ assert result == "PASS"
125
+
126
+ def test_si4_fail_no_detectors(self):
127
+ """Test SI-4 fails when no detectors configured."""
128
+ mapper = GuardDutyControlMapper()
129
+ guardduty_data = {"Detectors": []}
130
+ result = mapper._assess_si4(guardduty_data)
131
+ assert result == "FAIL"
132
+
133
+ def test_si4_fail_detector_disabled(self):
134
+ """Test SI-4 fails when detector is disabled."""
135
+ mapper = GuardDutyControlMapper()
136
+ guardduty_data = {"Detectors": [{"DetectorId": "test-detector", "Status": "DISABLED"}]}
137
+ result = mapper._assess_si4(guardduty_data)
138
+ assert result == "FAIL"
139
+
140
+ def test_si4_fail_mixed_detector_status(self):
141
+ """Test SI-4 fails when some detectors are disabled."""
142
+ mapper = GuardDutyControlMapper()
143
+ guardduty_data = {
144
+ "Detectors": [
145
+ {"DetectorId": "detector1", "Status": "ENABLED"},
146
+ {"DetectorId": "detector2", "Status": "DISABLED"},
147
+ ]
148
+ }
149
+ result = mapper._assess_si4(guardduty_data)
150
+ assert result == "FAIL"
151
+
152
+
153
+ class TestAssessIR4:
154
+ """Test _assess_ir4 (Incident Handling) compliance."""
155
+
156
+ def test_ir4_pass_no_high_severity_findings(self):
157
+ """Test IR-4 passes when no high severity findings."""
158
+ mapper = GuardDutyControlMapper()
159
+ guardduty_data = {
160
+ "Findings": [
161
+ {"Id": "finding1", "Severity": 3.5},
162
+ {"Id": "finding2", "Severity": 5.0},
163
+ ]
164
+ }
165
+ result = mapper._assess_ir4(guardduty_data)
166
+ assert result == "PASS"
167
+
168
+ def test_ir4_pass_empty_findings(self):
169
+ """Test IR-4 passes when no findings."""
170
+ mapper = GuardDutyControlMapper()
171
+ guardduty_data = {"Findings": []}
172
+ result = mapper._assess_ir4(guardduty_data)
173
+ assert result == "PASS"
174
+
175
+ def test_ir4_fail_high_severity_findings(self):
176
+ """Test IR-4 fails when high severity findings present."""
177
+ mapper = GuardDutyControlMapper()
178
+ guardduty_data = {"Findings": [{"Id": "finding1", "Severity": 7.5}]}
179
+ result = mapper._assess_ir4(guardduty_data)
180
+ assert result == "FAIL"
181
+
182
+ def test_ir4_fail_critical_severity_findings(self):
183
+ """Test IR-4 fails when critical severity findings present."""
184
+ mapper = GuardDutyControlMapper()
185
+ guardduty_data = {"Findings": [{"Id": "finding1", "Severity": 9.5}]}
186
+ result = mapper._assess_ir4(guardduty_data)
187
+ assert result == "FAIL"
188
+
189
+ def test_ir4_fail_multiple_high_critical_findings(self):
190
+ """Test IR-4 fails with multiple high/critical findings."""
191
+ mapper = GuardDutyControlMapper()
192
+ guardduty_data = {
193
+ "Findings": [
194
+ {"Id": "finding1", "Severity": 7.5},
195
+ {"Id": "finding2", "Severity": 9.0},
196
+ {"Id": "finding3", "Severity": 3.0},
197
+ ]
198
+ }
199
+ result = mapper._assess_ir4(guardduty_data)
200
+ assert result == "FAIL"
201
+
202
+
203
+ class TestAssessIR5:
204
+ """Test _assess_ir5 (Incident Monitoring) compliance."""
205
+
206
+ def test_ir5_pass_findings_tracked(self):
207
+ """Test IR-5 passes when findings are tracked."""
208
+ mapper = GuardDutyControlMapper()
209
+ guardduty_data = {"Findings": [{"Id": "finding1"}, {"Id": "finding2"}]}
210
+ result = mapper._assess_ir5(guardduty_data)
211
+ assert result == "PASS"
212
+
213
+ def test_ir5_pass_no_findings(self):
214
+ """Test IR-5 passes when no findings (acceptable state)."""
215
+ mapper = GuardDutyControlMapper()
216
+ guardduty_data = {"Findings": []}
217
+ result = mapper._assess_ir5(guardduty_data)
218
+ assert result == "PASS"
219
+
220
+
221
+ class TestAssessSI3:
222
+ """Test _assess_si3 (Malicious Code Protection) compliance."""
223
+
224
+ def test_si3_pass_detectors_enabled_no_malware(self):
225
+ """Test SI-3 passes when detectors enabled and no malware findings."""
226
+ mapper = GuardDutyControlMapper()
227
+ guardduty_data = {
228
+ "Detectors": [{"DetectorId": "test-detector", "Status": "ENABLED"}],
229
+ "Findings": [{"Type": "UnauthorizedAccess:EC2/SSHBruteForce"}],
230
+ }
231
+ result = mapper._assess_si3(guardduty_data)
232
+ assert result == "PASS"
233
+
234
+ def test_si3_pass_detectors_enabled_with_malware_findings(self):
235
+ """Test SI-3 passes when detectors enabled (even with malware findings - detection working)."""
236
+ mapper = GuardDutyControlMapper()
237
+ guardduty_data = {
238
+ "Detectors": [{"DetectorId": "test-detector", "Status": "ENABLED"}],
239
+ "Findings": [
240
+ {"Type": "Trojan:EC2/PhishingDomainRequest.Reputation"},
241
+ {"Type": "CryptoCurrency:EC2/BitcoinTool.B"},
242
+ ],
243
+ }
244
+ result = mapper._assess_si3(guardduty_data)
245
+ assert result == "PASS"
246
+
247
+ def test_si3_fail_no_detectors(self):
248
+ """Test SI-3 fails when no detectors configured."""
249
+ mapper = GuardDutyControlMapper()
250
+ guardduty_data = {"Detectors": [], "Findings": []}
251
+ result = mapper._assess_si3(guardduty_data)
252
+ assert result == "FAIL"
253
+
254
+ def test_si3_fail_all_detectors_disabled(self):
255
+ """Test SI-3 fails when all detectors are disabled."""
256
+ mapper = GuardDutyControlMapper()
257
+ guardduty_data = {
258
+ "Detectors": [
259
+ {"DetectorId": "detector1", "Status": "DISABLED"},
260
+ {"DetectorId": "detector2", "Status": "DISABLED"},
261
+ ],
262
+ "Findings": [],
263
+ }
264
+ result = mapper._assess_si3(guardduty_data)
265
+ assert result == "FAIL"
266
+
267
+
268
+ class TestAssessRA5:
269
+ """Test _assess_ra5 (Vulnerability Monitoring) compliance."""
270
+
271
+ def test_ra5_pass_threat_intel_enabled(self):
272
+ """Test RA-5 passes when threat intelligence enabled."""
273
+ mapper = GuardDutyControlMapper()
274
+ guardduty_data = {
275
+ "Detectors": [
276
+ {
277
+ "DetectorId": "test-detector",
278
+ "DataSources": {"S3Logs": {"Status": "ENABLED"}},
279
+ }
280
+ ]
281
+ }
282
+ result = mapper._assess_ra5(guardduty_data)
283
+ assert result == "PASS"
284
+
285
+ def test_ra5_fail_threat_intel_disabled(self):
286
+ """Test RA-5 fails when threat intelligence not enabled."""
287
+ mapper = GuardDutyControlMapper()
288
+ guardduty_data = {
289
+ "Detectors": [
290
+ {
291
+ "DetectorId": "test-detector",
292
+ "DataSources": {"S3Logs": {"Status": "DISABLED"}},
293
+ }
294
+ ]
295
+ }
296
+ result = mapper._assess_ra5(guardduty_data)
297
+ assert result == "FAIL"
298
+
299
+ def test_ra5_fail_no_data_sources(self):
300
+ """Test RA-5 fails when no data sources configured."""
301
+ mapper = GuardDutyControlMapper()
302
+ guardduty_data = {"Detectors": [{"DetectorId": "test-detector"}]}
303
+ result = mapper._assess_ra5(guardduty_data)
304
+ assert result == "FAIL"
305
+
306
+
307
+ class TestGetSeverityLevel:
308
+ """Test _get_severity_level method."""
309
+
310
+ def test_low_severity(self):
311
+ """Test mapping low severity scores."""
312
+ mapper = GuardDutyControlMapper()
313
+ assert mapper._get_severity_level(0.1) == "LOW"
314
+ assert mapper._get_severity_level(2.0) == "LOW"
315
+ assert mapper._get_severity_level(3.9) == "LOW"
316
+
317
+ def test_medium_severity(self):
318
+ """Test mapping medium severity scores."""
319
+ mapper = GuardDutyControlMapper()
320
+ assert mapper._get_severity_level(4.0) == "MEDIUM"
321
+ assert mapper._get_severity_level(5.5) == "MEDIUM"
322
+ assert mapper._get_severity_level(6.9) == "MEDIUM"
323
+
324
+ def test_high_severity(self):
325
+ """Test mapping high severity scores."""
326
+ mapper = GuardDutyControlMapper()
327
+ assert mapper._get_severity_level(7.0) == "HIGH"
328
+ assert mapper._get_severity_level(8.0) == "HIGH"
329
+ assert mapper._get_severity_level(8.9) == "HIGH"
330
+
331
+ def test_critical_severity(self):
332
+ """Test mapping critical severity scores."""
333
+ mapper = GuardDutyControlMapper()
334
+ assert mapper._get_severity_level(9.0) == "CRITICAL"
335
+ assert mapper._get_severity_level(9.5) == "CRITICAL"
336
+ assert mapper._get_severity_level(10.0) == "CRITICAL"
337
+
338
+ def test_out_of_range_severity(self):
339
+ """Test severity score outside expected range."""
340
+ mapper = GuardDutyControlMapper()
341
+ assert mapper._get_severity_level(0.0) == "LOW"
342
+ assert mapper._get_severity_level(11.0) == "LOW"
343
+ assert mapper._get_severity_level(-1.0) == "LOW"
344
+
345
+
346
+ class TestIsMalwareFinding:
347
+ """Test _is_malware_finding method."""
348
+
349
+ def test_trojan_finding(self):
350
+ """Test detection of Trojan findings."""
351
+ mapper = GuardDutyControlMapper()
352
+ finding = {"Type": "Trojan:EC2/PhishingDomainRequest.Reputation"}
353
+ assert mapper._is_malware_finding(finding) is True
354
+
355
+ def test_backdoor_finding(self):
356
+ """Test detection of Backdoor findings."""
357
+ mapper = GuardDutyControlMapper()
358
+ finding = {"Type": "Backdoor:EC2/C&CActivity.B"}
359
+ assert mapper._is_malware_finding(finding) is True
360
+
361
+ def test_cryptocurrency_finding(self):
362
+ """Test detection of CryptoCurrency findings."""
363
+ mapper = GuardDutyControlMapper()
364
+ finding = {"Type": "CryptoCurrency:EC2/BitcoinTool.B"}
365
+ assert mapper._is_malware_finding(finding) is True
366
+
367
+ def test_malware_finding(self):
368
+ """Test detection of Malware findings."""
369
+ mapper = GuardDutyControlMapper()
370
+ finding = {"Type": "Malware:EC2/MaliciousFile"}
371
+ assert mapper._is_malware_finding(finding) is True
372
+
373
+ def test_bitcoin_finding(self):
374
+ """Test detection of Bitcoin findings."""
375
+ mapper = GuardDutyControlMapper()
376
+ finding = {"Type": "CryptoCurrency:EC2/BitcoinTool.B!DNS"}
377
+ assert mapper._is_malware_finding(finding) is True
378
+
379
+ def test_non_malware_finding(self):
380
+ """Test non-malware finding returns False."""
381
+ mapper = GuardDutyControlMapper()
382
+ finding = {"Type": "UnauthorizedAccess:EC2/SSHBruteForce"}
383
+ assert mapper._is_malware_finding(finding) is False
384
+
385
+ def test_empty_type(self):
386
+ """Test finding with empty type."""
387
+ mapper = GuardDutyControlMapper()
388
+ finding = {"Type": ""}
389
+ assert mapper._is_malware_finding(finding) is False
390
+
391
+
392
+ class TestHasCVEReference:
393
+ """Test has_cve_reference method."""
394
+
395
+ def test_cve_in_description(self):
396
+ """Test CVE detection in description."""
397
+ mapper = GuardDutyControlMapper()
398
+ finding = {"Description": "This vulnerability is related to CVE-2023-12345"}
399
+ assert mapper.has_cve_reference(finding) is True
400
+
401
+ def test_cve_in_title(self):
402
+ """Test CVE detection in title."""
403
+ mapper = GuardDutyControlMapper()
404
+ finding = {"Title": "Exploit for CVE-2024-56789 detected"}
405
+ assert mapper.has_cve_reference(finding) is True
406
+
407
+ def test_cve_in_additional_info(self):
408
+ """Test CVE detection in additional info."""
409
+ mapper = GuardDutyControlMapper()
410
+ finding = {"Service": {"AdditionalInfo": {"vulnerability": "CVE-2023-99999"}}}
411
+ assert mapper.has_cve_reference(finding) is True
412
+
413
+ def test_no_cve_reference(self):
414
+ """Test finding without CVE reference."""
415
+ mapper = GuardDutyControlMapper()
416
+ finding = {
417
+ "Description": "Unauthorized access detected",
418
+ "Title": "Security Alert",
419
+ }
420
+ assert mapper.has_cve_reference(finding) is False
421
+
422
+ def test_empty_finding(self):
423
+ """Test empty finding dictionary."""
424
+ mapper = GuardDutyControlMapper()
425
+ finding = {}
426
+ assert mapper.has_cve_reference(finding) is False
427
+
428
+
429
+ class TestExtractCVEsFromFinding:
430
+ """Test extract_cves_from_finding method."""
431
+
432
+ def test_extract_single_cve(self):
433
+ """Test extracting single CVE."""
434
+ mapper = GuardDutyControlMapper()
435
+ finding = {"Description": "This vulnerability is CVE-2023-12345"}
436
+ cves = mapper.extract_cves_from_finding(finding)
437
+ assert len(cves) == 1
438
+ assert "CVE-2023-12345" in cves
439
+
440
+ def test_extract_multiple_cves(self):
441
+ """Test extracting multiple CVEs."""
442
+ mapper = GuardDutyControlMapper()
443
+ finding = {
444
+ "Description": "Related to CVE-2023-12345 and CVE-2024-56789",
445
+ "Title": "Also see CVE-2023-99999",
446
+ }
447
+ cves = mapper.extract_cves_from_finding(finding)
448
+ assert len(cves) == 3
449
+ assert "CVE-2023-12345" in cves
450
+ assert "CVE-2024-56789" in cves
451
+ assert "CVE-2023-99999" in cves
452
+
453
+ def test_extract_cves_case_insensitive(self):
454
+ """Test CVE extraction is case-insensitive and normalized."""
455
+ mapper = GuardDutyControlMapper()
456
+ finding = {"Description": "cve-2023-12345 and CVE-2024-56789"}
457
+ cves = mapper.extract_cves_from_finding(finding)
458
+ assert len(cves) == 2
459
+ assert all(cve.startswith("CVE-") for cve in cves)
460
+
461
+ def test_extract_cves_deduplicated(self):
462
+ """Test duplicate CVEs are removed."""
463
+ mapper = GuardDutyControlMapper()
464
+ finding = {
465
+ "Description": "CVE-2023-12345 detected",
466
+ "Title": "Alert for CVE-2023-12345",
467
+ }
468
+ cves = mapper.extract_cves_from_finding(finding)
469
+ assert len(cves) == 1
470
+ assert "CVE-2023-12345" in cves
471
+
472
+ def test_extract_cves_various_formats(self):
473
+ """Test extracting CVEs with different number lengths."""
474
+ mapper = GuardDutyControlMapper()
475
+ finding = {"Description": "CVE-2023-1234 (4 digits), CVE-2023-12345 (5 digits), CVE-2023-1234567 (7 digits)"}
476
+ cves = mapper.extract_cves_from_finding(finding)
477
+ assert len(cves) == 3
478
+ assert "CVE-2023-1234" in cves
479
+ assert "CVE-2023-12345" in cves
480
+ assert "CVE-2023-1234567" in cves
481
+
482
+ def test_no_cves_found(self):
483
+ """Test finding with no CVEs."""
484
+ mapper = GuardDutyControlMapper()
485
+ finding = {"Description": "General security alert"}
486
+ cves = mapper.extract_cves_from_finding(finding)
487
+ assert len(cves) == 0
488
+
489
+
490
+ class TestGuardDutyControlMappings:
491
+ """Test GUARDDUTY_CONTROL_MAPPINGS structure."""
492
+
493
+ def test_mappings_exist(self):
494
+ """Test that mappings dictionary exists and has content."""
495
+ assert len(GUARDDUTY_CONTROL_MAPPINGS) > 0
496
+
497
+ def test_si4_mapping_structure(self):
498
+ """Test SI-4 mapping structure."""
499
+ assert "SI-4" in GUARDDUTY_CONTROL_MAPPINGS
500
+ si4 = GUARDDUTY_CONTROL_MAPPINGS["SI-4"]
501
+ assert "name" in si4
502
+ assert "description" in si4
503
+ assert "checks" in si4
504
+ assert "detector_enabled" in si4["checks"]
505
+ assert "findings_processed" in si4["checks"]
506
+
507
+ def test_ir4_mapping_structure(self):
508
+ """Test IR-4 mapping structure."""
509
+ assert "IR-4" in GUARDDUTY_CONTROL_MAPPINGS
510
+ ir4 = GUARDDUTY_CONTROL_MAPPINGS["IR-4"]
511
+ assert len(ir4["checks"]) >= 2
512
+ assert "high_severity_findings" in ir4["checks"]
513
+ assert "incident_response" in ir4["checks"]
514
+
515
+ def test_all_controls_have_required_fields(self):
516
+ """Test all control mappings have required fields."""
517
+ for control_id, control_data in GUARDDUTY_CONTROL_MAPPINGS.items():
518
+ assert "name" in control_data
519
+ assert "description" in control_data
520
+ assert "checks" in control_data
521
+ assert isinstance(control_data["checks"], dict)
522
+ for check_name, check_data in control_data["checks"].items():
523
+ assert "weight" in check_data
524
+ assert "pass_criteria" in check_data
525
+ assert "fail_criteria" in check_data
526
+
527
+
528
+ class TestSeverityMapping:
529
+ """Test SEVERITY_MAPPING constant."""
530
+
531
+ def test_severity_mapping_exists(self):
532
+ """Test severity mapping dictionary exists."""
533
+ assert len(SEVERITY_MAPPING) == 4
534
+
535
+ def test_severity_mapping_structure(self):
536
+ """Test severity mapping has correct structure."""
537
+ assert "LOW" in SEVERITY_MAPPING
538
+ assert "MEDIUM" in SEVERITY_MAPPING
539
+ assert "HIGH" in SEVERITY_MAPPING
540
+ assert "CRITICAL" in SEVERITY_MAPPING
541
+
542
+ def test_severity_ranges_valid(self):
543
+ """Test severity ranges are valid tuples."""
544
+ for level, (min_val, max_val) in SEVERITY_MAPPING.items():
545
+ assert isinstance(min_val, float)
546
+ assert isinstance(max_val, float)
547
+ assert min_val < max_val
548
+
549
+
550
+ class TestCVERelatedFindingTypes:
551
+ """Test CVE_RELATED_FINDING_TYPES constant."""
552
+
553
+ def test_cve_finding_types_exist(self):
554
+ """Test CVE-related finding types list exists."""
555
+ assert len(CVE_RELATED_FINDING_TYPES) > 0
556
+
557
+ def test_cve_finding_types_structure(self):
558
+ """Test CVE-related finding types are strings."""
559
+ for finding_type in CVE_RELATED_FINDING_TYPES:
560
+ assert isinstance(finding_type, str)
561
+
562
+
563
+ if __name__ == "__main__":
564
+ pytest.main([__file__, "-v"])