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,656 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Unit tests for AWS KMS Control Mappings."""
4
+
5
+ import json
6
+ import logging
7
+ import pytest
8
+
9
+ from regscale.integrations.commercial.aws.kms_control_mappings import (
10
+ APPROVED_KEY_SPECS,
11
+ ISO_27001_MAPPINGS,
12
+ KMS_CONTROL_MAPPINGS,
13
+ KMSControlMapper,
14
+ NON_COMPLIANT_KEY_STATES,
15
+ )
16
+
17
+
18
+ class TestKMSControlMappings:
19
+ """Test KMS control mappings constants."""
20
+
21
+ def test_kms_control_mappings_exist(self):
22
+ """Test that KMS control mappings dictionary exists and has content."""
23
+ assert len(KMS_CONTROL_MAPPINGS) > 0
24
+ assert "SC-12" in KMS_CONTROL_MAPPINGS
25
+ assert "SC-13" in KMS_CONTROL_MAPPINGS
26
+ assert "SC-28" in KMS_CONTROL_MAPPINGS
27
+
28
+ def test_sc12_mapping_structure(self):
29
+ """Test SC-12 mapping structure."""
30
+ sc12 = KMS_CONTROL_MAPPINGS["SC-12"]
31
+ assert "name" in sc12
32
+ assert "description" in sc12
33
+ assert "checks" in sc12
34
+ assert "rotation_enabled" in sc12["checks"]
35
+ assert "key_state" in sc12["checks"]
36
+ assert "key_manager" in sc12["checks"]
37
+
38
+ def test_sc13_mapping_structure(self):
39
+ """Test SC-13 mapping structure."""
40
+ sc13 = KMS_CONTROL_MAPPINGS["SC-13"]
41
+ assert "name" in sc13
42
+ assert "description" in sc13
43
+ assert "checks" in sc13
44
+ assert "key_spec" in sc13["checks"]
45
+ assert "key_usage" in sc13["checks"]
46
+ assert "key_origin" in sc13["checks"]
47
+
48
+ def test_sc28_mapping_structure(self):
49
+ """Test SC-28 mapping structure."""
50
+ sc28 = KMS_CONTROL_MAPPINGS["SC-28"]
51
+ assert "name" in sc28
52
+ assert "description" in sc28
53
+ assert "checks" in sc28
54
+ assert "key_exists" in sc28["checks"]
55
+ assert "multi_region" in sc28["checks"]
56
+ assert "grants" in sc28["checks"]
57
+
58
+ def test_iso_27001_mappings_exist(self):
59
+ """Test ISO 27001 mappings exist."""
60
+ assert len(ISO_27001_MAPPINGS) > 0
61
+ assert "A.10.1.1" in ISO_27001_MAPPINGS
62
+ assert "A.10.1.2" in ISO_27001_MAPPINGS
63
+
64
+ def test_approved_key_specs(self):
65
+ """Test approved key specifications list."""
66
+ assert "SYMMETRIC_DEFAULT" in APPROVED_KEY_SPECS
67
+ assert "RSA_2048" in APPROVED_KEY_SPECS
68
+ assert "ECC_NIST_P256" in APPROVED_KEY_SPECS
69
+ assert "HMAC_256" in APPROVED_KEY_SPECS
70
+
71
+ def test_non_compliant_key_states(self):
72
+ """Test non-compliant key states list."""
73
+ assert "PendingDeletion" in NON_COMPLIANT_KEY_STATES
74
+ assert "PendingImport" in NON_COMPLIANT_KEY_STATES
75
+ assert "Unavailable" in NON_COMPLIANT_KEY_STATES
76
+
77
+
78
+ class TestKMSControlMapperInitialization:
79
+ """Test KMSControlMapper initialization."""
80
+
81
+ def test_init_with_nist_framework(self):
82
+ """Test initialization with NIST framework."""
83
+ mapper = KMSControlMapper(framework="NIST800-53R5")
84
+ assert mapper.framework == "NIST800-53R5"
85
+ assert mapper.mappings == KMS_CONTROL_MAPPINGS
86
+
87
+ def test_init_with_iso_framework(self):
88
+ """Test initialization with ISO framework."""
89
+ mapper = KMSControlMapper(framework="ISO27001")
90
+ assert mapper.framework == "ISO27001"
91
+ assert mapper.mappings == ISO_27001_MAPPINGS
92
+
93
+ def test_init_default_framework(self):
94
+ """Test initialization with default framework."""
95
+ mapper = KMSControlMapper()
96
+ assert mapper.framework == "NIST800-53R5"
97
+ assert mapper.mappings == KMS_CONTROL_MAPPINGS
98
+
99
+
100
+ class TestAssessKeyCompliance:
101
+ """Test assess_key_compliance method."""
102
+
103
+ def test_assess_compliant_customer_key(self):
104
+ """Test assessing a compliant customer-managed key."""
105
+ mapper = KMSControlMapper()
106
+ key_data = {
107
+ "KeyId": "test-key-123",
108
+ "KeyManager": "CUSTOMER",
109
+ "RotationEnabled": True,
110
+ "KeyState": "Enabled",
111
+ "KeySpec": "SYMMETRIC_DEFAULT",
112
+ "Origin": "AWS_KMS",
113
+ "Enabled": True,
114
+ }
115
+
116
+ results = mapper.assess_key_compliance(key_data)
117
+
118
+ assert results["SC-12"] == "PASS"
119
+ assert results["SC-13"] == "PASS"
120
+ assert results["SC-28"] == "PASS"
121
+
122
+ def test_assess_aws_managed_key(self):
123
+ """Test assessing AWS-managed key."""
124
+ mapper = KMSControlMapper()
125
+ key_data = {
126
+ "KeyId": "aws-managed-key",
127
+ "KeyManager": "AWS",
128
+ "RotationEnabled": False,
129
+ "KeyState": "Enabled",
130
+ "KeySpec": "SYMMETRIC_DEFAULT",
131
+ "Origin": "AWS_KMS",
132
+ "Enabled": True,
133
+ }
134
+
135
+ results = mapper.assess_key_compliance(key_data)
136
+
137
+ # AWS-managed keys pass SC-12 even without explicit rotation
138
+ assert results["SC-12"] == "PASS"
139
+ assert results["SC-13"] == "PASS"
140
+ assert results["SC-28"] == "PASS"
141
+
142
+ def test_assess_key_without_rotation(self):
143
+ """Test assessing customer key without rotation."""
144
+ mapper = KMSControlMapper()
145
+ key_data = {
146
+ "KeyId": "test-key-456",
147
+ "KeyManager": "CUSTOMER",
148
+ "RotationEnabled": False,
149
+ "KeyState": "Enabled",
150
+ "KeySpec": "SYMMETRIC_DEFAULT",
151
+ "Origin": "AWS_KMS",
152
+ "Enabled": True,
153
+ }
154
+
155
+ results = mapper.assess_key_compliance(key_data)
156
+
157
+ assert results["SC-12"] == "FAIL"
158
+ assert results["SC-13"] == "PASS"
159
+ assert results["SC-28"] == "PASS"
160
+
161
+ def test_assess_key_pending_deletion(self):
162
+ """Test assessing key in PendingDeletion state."""
163
+ mapper = KMSControlMapper()
164
+ key_data = {
165
+ "KeyId": "test-key-789",
166
+ "KeyManager": "CUSTOMER",
167
+ "RotationEnabled": True,
168
+ "KeyState": "PendingDeletion",
169
+ "KeySpec": "SYMMETRIC_DEFAULT",
170
+ "Origin": "AWS_KMS",
171
+ "Enabled": False,
172
+ }
173
+
174
+ results = mapper.assess_key_compliance(key_data)
175
+
176
+ assert results["SC-12"] == "FAIL"
177
+ assert results["SC-13"] == "PASS"
178
+ assert results["SC-28"] == "FAIL"
179
+
180
+ def test_assess_key_with_unapproved_spec(self):
181
+ """Test assessing key with unapproved key spec."""
182
+ mapper = KMSControlMapper()
183
+ key_data = {
184
+ "KeyId": "test-key-invalid",
185
+ "KeyManager": "CUSTOMER",
186
+ "RotationEnabled": True,
187
+ "KeyState": "Enabled",
188
+ "KeySpec": "INVALID_SPEC",
189
+ "Origin": "AWS_KMS",
190
+ "Enabled": True,
191
+ }
192
+
193
+ results = mapper.assess_key_compliance(key_data)
194
+
195
+ assert results["SC-12"] == "PASS"
196
+ assert results["SC-13"] == "FAIL"
197
+ assert results["SC-28"] == "PASS"
198
+
199
+ def test_assess_key_with_external_origin(self):
200
+ """Test assessing key with external origin (warning case)."""
201
+ mapper = KMSControlMapper()
202
+ key_data = {
203
+ "KeyId": "test-key-external",
204
+ "KeyManager": "CUSTOMER",
205
+ "RotationEnabled": True,
206
+ "KeyState": "Enabled",
207
+ "KeySpec": "SYMMETRIC_DEFAULT",
208
+ "Origin": "EXTERNAL",
209
+ "Enabled": True,
210
+ }
211
+
212
+ results = mapper.assess_key_compliance(key_data)
213
+
214
+ # External origin should still pass but generate warning
215
+ assert results["SC-12"] == "PASS"
216
+ assert results["SC-13"] == "PASS"
217
+ assert results["SC-28"] == "PASS"
218
+
219
+ def test_assess_disabled_key(self):
220
+ """Test assessing disabled key."""
221
+ mapper = KMSControlMapper()
222
+ key_data = {
223
+ "KeyId": "test-key-disabled",
224
+ "KeyManager": "CUSTOMER",
225
+ "RotationEnabled": True,
226
+ "KeyState": "Disabled",
227
+ "KeySpec": "SYMMETRIC_DEFAULT",
228
+ "Origin": "AWS_KMS",
229
+ "Enabled": False,
230
+ }
231
+
232
+ results = mapper.assess_key_compliance(key_data)
233
+
234
+ # Note: "Disabled" is not in NON_COMPLIANT_KEY_STATES, so SC-12 passes
235
+ # but SC-28 checks the Enabled flag, so it fails
236
+ assert results["SC-12"] == "PASS"
237
+ assert results["SC-13"] == "PASS"
238
+ assert results["SC-28"] == "FAIL"
239
+
240
+
241
+ class TestAssessSC12:
242
+ """Test _assess_sc12 method."""
243
+
244
+ def test_aws_managed_key_passes(self):
245
+ """Test that AWS-managed keys automatically pass SC-12."""
246
+ mapper = KMSControlMapper()
247
+ key_data = {
248
+ "KeyId": "aws-key",
249
+ "KeyManager": "AWS",
250
+ "RotationEnabled": False,
251
+ "KeyState": "Enabled",
252
+ }
253
+
254
+ result = mapper._assess_sc12(key_data)
255
+ assert result == "PASS"
256
+
257
+ def test_customer_key_with_rotation_passes(self):
258
+ """Test customer-managed key with rotation passes."""
259
+ mapper = KMSControlMapper()
260
+ key_data = {
261
+ "KeyId": "customer-key",
262
+ "KeyManager": "CUSTOMER",
263
+ "RotationEnabled": True,
264
+ "KeyState": "Enabled",
265
+ }
266
+
267
+ result = mapper._assess_sc12(key_data)
268
+ assert result == "PASS"
269
+
270
+ def test_customer_key_without_rotation_fails(self):
271
+ """Test customer-managed key without rotation fails."""
272
+ mapper = KMSControlMapper()
273
+ key_data = {
274
+ "KeyId": "customer-key-no-rotation",
275
+ "KeyManager": "CUSTOMER",
276
+ "RotationEnabled": False,
277
+ "KeyState": "Enabled",
278
+ }
279
+
280
+ result = mapper._assess_sc12(key_data)
281
+ assert result == "FAIL"
282
+
283
+ def test_key_in_pending_deletion_fails(self):
284
+ """Test key in PendingDeletion state fails."""
285
+ mapper = KMSControlMapper()
286
+ key_data = {
287
+ "KeyId": "key-pending-deletion",
288
+ "KeyManager": "CUSTOMER",
289
+ "RotationEnabled": True,
290
+ "KeyState": "PendingDeletion",
291
+ }
292
+
293
+ result = mapper._assess_sc12(key_data)
294
+ assert result == "FAIL"
295
+
296
+ def test_key_in_pending_import_fails(self):
297
+ """Test key in PendingImport state fails."""
298
+ mapper = KMSControlMapper()
299
+ key_data = {
300
+ "KeyId": "key-pending-import",
301
+ "KeyManager": "CUSTOMER",
302
+ "RotationEnabled": True,
303
+ "KeyState": "PendingImport",
304
+ }
305
+
306
+ result = mapper._assess_sc12(key_data)
307
+ assert result == "FAIL"
308
+
309
+ def test_key_unavailable_fails(self):
310
+ """Test unavailable key fails."""
311
+ mapper = KMSControlMapper()
312
+ key_data = {
313
+ "KeyId": "key-unavailable",
314
+ "KeyManager": "CUSTOMER",
315
+ "RotationEnabled": True,
316
+ "KeyState": "Unavailable",
317
+ }
318
+
319
+ result = mapper._assess_sc12(key_data)
320
+ assert result == "FAIL"
321
+
322
+
323
+ class TestAssessSC13:
324
+ """Test _assess_sc13 method."""
325
+
326
+ def test_symmetric_default_passes(self):
327
+ """Test SYMMETRIC_DEFAULT key spec passes."""
328
+ mapper = KMSControlMapper()
329
+ key_data = {
330
+ "KeyId": "test-key",
331
+ "KeySpec": "SYMMETRIC_DEFAULT",
332
+ "Origin": "AWS_KMS",
333
+ }
334
+
335
+ result = mapper._assess_sc13(key_data)
336
+ assert result == "PASS"
337
+
338
+ def test_rsa_key_specs_pass(self):
339
+ """Test RSA key specs pass."""
340
+ mapper = KMSControlMapper()
341
+
342
+ for key_spec in ["RSA_2048", "RSA_3072", "RSA_4096"]:
343
+ key_data = {"KeyId": f"test-key-{key_spec}", "KeySpec": key_spec, "Origin": "AWS_KMS"}
344
+ result = mapper._assess_sc13(key_data)
345
+ assert result == "PASS"
346
+
347
+ def test_ecc_key_specs_pass(self):
348
+ """Test ECC key specs pass."""
349
+ mapper = KMSControlMapper()
350
+
351
+ for key_spec in ["ECC_NIST_P256", "ECC_NIST_P384", "ECC_NIST_P521", "ECC_SECG_P256K1"]:
352
+ key_data = {"KeyId": f"test-key-{key_spec}", "KeySpec": key_spec, "Origin": "AWS_KMS"}
353
+ result = mapper._assess_sc13(key_data)
354
+ assert result == "PASS"
355
+
356
+ def test_hmac_key_specs_pass(self):
357
+ """Test HMAC key specs pass."""
358
+ mapper = KMSControlMapper()
359
+
360
+ for key_spec in ["HMAC_224", "HMAC_256", "HMAC_384", "HMAC_512"]:
361
+ key_data = {"KeyId": f"test-key-{key_spec}", "KeySpec": key_spec, "Origin": "AWS_KMS"}
362
+ result = mapper._assess_sc13(key_data)
363
+ assert result == "PASS"
364
+
365
+ def test_unapproved_key_spec_fails(self):
366
+ """Test unapproved key spec fails."""
367
+ mapper = KMSControlMapper()
368
+ key_data = {
369
+ "KeyId": "test-key-invalid",
370
+ "KeySpec": "INVALID_ALGORITHM",
371
+ "Origin": "AWS_KMS",
372
+ }
373
+
374
+ result = mapper._assess_sc13(key_data)
375
+ assert result == "FAIL"
376
+
377
+ def test_external_origin_passes_with_warning(self, caplog):
378
+ """Test external origin passes but generates warning."""
379
+ mapper = KMSControlMapper()
380
+ key_data = {
381
+ "KeyId": "test-key-external",
382
+ "KeySpec": "SYMMETRIC_DEFAULT",
383
+ "Origin": "EXTERNAL",
384
+ }
385
+
386
+ with caplog.at_level(logging.WARNING):
387
+ result = mapper._assess_sc13(key_data)
388
+
389
+ assert result == "PASS"
390
+ assert any("EXTERNAL origin" in record.message for record in caplog.records)
391
+
392
+ def test_cloudhsm_origin_passes(self):
393
+ """Test AWS_CLOUDHSM origin passes."""
394
+ mapper = KMSControlMapper()
395
+ key_data = {
396
+ "KeyId": "test-key-cloudhsm",
397
+ "KeySpec": "SYMMETRIC_DEFAULT",
398
+ "Origin": "AWS_CLOUDHSM",
399
+ }
400
+
401
+ result = mapper._assess_sc13(key_data)
402
+ assert result == "PASS"
403
+
404
+
405
+ class TestAssessSC28:
406
+ """Test _assess_sc28 method."""
407
+
408
+ def test_enabled_key_passes(self):
409
+ """Test enabled key passes."""
410
+ mapper = KMSControlMapper()
411
+ key_data = {
412
+ "KeyId": "test-key-enabled",
413
+ "KeyState": "Enabled",
414
+ "Enabled": True,
415
+ }
416
+
417
+ result = mapper._assess_sc28(key_data)
418
+ assert result == "PASS"
419
+
420
+ def test_disabled_key_fails(self):
421
+ """Test disabled key fails."""
422
+ mapper = KMSControlMapper()
423
+ key_data = {
424
+ "KeyId": "test-key-disabled",
425
+ "KeyState": "Disabled",
426
+ "Enabled": False,
427
+ }
428
+
429
+ result = mapper._assess_sc28(key_data)
430
+ assert result == "FAIL"
431
+
432
+ def test_key_pending_deletion_fails(self):
433
+ """Test key in PendingDeletion fails."""
434
+ mapper = KMSControlMapper()
435
+ key_data = {
436
+ "KeyId": "test-key-pending-deletion",
437
+ "KeyState": "PendingDeletion",
438
+ "Enabled": False,
439
+ }
440
+
441
+ result = mapper._assess_sc28(key_data)
442
+ assert result == "FAIL"
443
+
444
+ def test_key_with_permissive_policy_passes_with_warning(self, caplog):
445
+ """Test key with overly permissive policy passes but generates warning."""
446
+ mapper = KMSControlMapper()
447
+ policy = json.dumps({"Statement": [{"Effect": "Allow", "Principal": "*", "Action": "kms:*"}]})
448
+
449
+ key_data = {"KeyId": "test-key-permissive", "KeyState": "Enabled", "Enabled": True, "Policy": policy}
450
+
451
+ with caplog.at_level(logging.WARNING):
452
+ result = mapper._assess_sc28(key_data)
453
+
454
+ assert result == "PASS"
455
+ assert any("overly permissive" in record.message for record in caplog.records)
456
+
457
+ def test_key_with_safe_policy_passes(self):
458
+ """Test key with safe policy passes."""
459
+ mapper = KMSControlMapper()
460
+ policy = json.dumps(
461
+ {
462
+ "Statement": [
463
+ {
464
+ "Effect": "Allow",
465
+ "Principal": {"AWS": "arn:aws:iam::123456789012:root"},
466
+ "Action": "kms:*",
467
+ }
468
+ ]
469
+ }
470
+ )
471
+
472
+ key_data = {"KeyId": "test-key-safe", "KeyState": "Enabled", "Enabled": True, "Policy": policy}
473
+
474
+ result = mapper._assess_sc28(key_data)
475
+ assert result == "PASS"
476
+
477
+
478
+ class TestHasOverlyPermissivePolicy:
479
+ """Test _has_overly_permissive_policy method."""
480
+
481
+ def test_wildcard_principal_detected(self):
482
+ """Test detection of wildcard principal."""
483
+ mapper = KMSControlMapper()
484
+ policy = json.dumps({"Statement": [{"Effect": "Allow", "Principal": "*", "Action": "kms:*"}]})
485
+
486
+ result = mapper._has_overly_permissive_policy(policy)
487
+ assert result is True
488
+
489
+ def test_wildcard_aws_principal_detected(self):
490
+ """Test detection of wildcard AWS principal."""
491
+ mapper = KMSControlMapper()
492
+ policy = json.dumps({"Statement": [{"Effect": "Allow", "Principal": {"AWS": "*"}, "Action": "kms:*"}]})
493
+
494
+ result = mapper._has_overly_permissive_policy(policy)
495
+ assert result is True
496
+
497
+ def test_specific_principal_allowed(self):
498
+ """Test specific principal is allowed."""
499
+ mapper = KMSControlMapper()
500
+ policy = json.dumps(
501
+ {
502
+ "Statement": [
503
+ {
504
+ "Effect": "Allow",
505
+ "Principal": {"AWS": "arn:aws:iam::123456789012:root"},
506
+ "Action": "kms:*",
507
+ }
508
+ ]
509
+ }
510
+ )
511
+
512
+ result = mapper._has_overly_permissive_policy(policy)
513
+ assert result is False
514
+
515
+ def test_deny_effect_with_wildcard_allowed(self):
516
+ """Test Deny effect with wildcard is allowed."""
517
+ mapper = KMSControlMapper()
518
+ policy = json.dumps({"Statement": [{"Effect": "Deny", "Principal": "*", "Action": "kms:*"}]})
519
+
520
+ result = mapper._has_overly_permissive_policy(policy)
521
+ assert result is False
522
+
523
+ def test_invalid_json_returns_false(self):
524
+ """Test invalid JSON returns False."""
525
+ mapper = KMSControlMapper()
526
+ policy = "invalid json"
527
+
528
+ result = mapper._has_overly_permissive_policy(policy)
529
+ assert result is False
530
+
531
+ def test_missing_statement_returns_false(self):
532
+ """Test policy without Statement returns False."""
533
+ mapper = KMSControlMapper()
534
+ policy = json.dumps({"Version": "2012-10-17"})
535
+
536
+ result = mapper._has_overly_permissive_policy(policy)
537
+ assert result is False
538
+
539
+
540
+ class TestGetControlDescription:
541
+ """Test get_control_description method."""
542
+
543
+ def test_get_sc12_description(self):
544
+ """Test getting SC-12 description."""
545
+ mapper = KMSControlMapper()
546
+ description = mapper.get_control_description("SC-12")
547
+
548
+ assert description is not None
549
+ assert "Cryptographic Key Establishment and Management" in description
550
+
551
+ def test_get_sc13_description(self):
552
+ """Test getting SC-13 description."""
553
+ mapper = KMSControlMapper()
554
+ description = mapper.get_control_description("SC-13")
555
+
556
+ assert description is not None
557
+ assert "Cryptographic Protection" in description
558
+
559
+ def test_get_sc28_description(self):
560
+ """Test getting SC-28 description."""
561
+ mapper = KMSControlMapper()
562
+ description = mapper.get_control_description("SC-28")
563
+
564
+ assert description is not None
565
+ assert "Protection of Information at Rest" in description
566
+
567
+ def test_get_unknown_control_description(self):
568
+ """Test getting description for unknown control."""
569
+ mapper = KMSControlMapper()
570
+ description = mapper.get_control_description("UNKNOWN-1")
571
+
572
+ assert description is None
573
+
574
+ def test_get_iso_control_description(self):
575
+ """Test getting ISO control description."""
576
+ mapper = KMSControlMapper(framework="ISO27001")
577
+ description = mapper.get_control_description("A.10.1.1")
578
+
579
+ assert description is not None
580
+ assert "cryptographic controls" in description.lower()
581
+
582
+
583
+ class TestGetMappedControls:
584
+ """Test get_mapped_controls method."""
585
+
586
+ def test_get_nist_controls(self):
587
+ """Test getting NIST controls."""
588
+ mapper = KMSControlMapper()
589
+ controls = mapper.get_mapped_controls()
590
+
591
+ assert len(controls) > 0
592
+ assert "SC-12" in controls
593
+ assert "SC-13" in controls
594
+ assert "SC-28" in controls
595
+
596
+ def test_get_iso_controls(self):
597
+ """Test getting ISO controls."""
598
+ mapper = KMSControlMapper(framework="ISO27001")
599
+ controls = mapper.get_mapped_controls()
600
+
601
+ assert len(controls) > 0
602
+ assert "A.10.1.1" in controls
603
+ assert "A.10.1.2" in controls
604
+
605
+ def test_controls_are_unique(self):
606
+ """Test that returned controls are unique."""
607
+ mapper = KMSControlMapper()
608
+ controls = mapper.get_mapped_controls()
609
+
610
+ assert len(controls) == len(set(controls))
611
+
612
+
613
+ class TestGetCheckDetails:
614
+ """Test get_check_details method."""
615
+
616
+ def test_get_sc12_check_details(self):
617
+ """Test getting SC-12 check details."""
618
+ mapper = KMSControlMapper()
619
+ details = mapper.get_check_details("SC-12")
620
+
621
+ assert details is not None
622
+ assert "rotation_enabled" in details
623
+ assert "key_state" in details
624
+ assert "key_manager" in details
625
+ assert details["rotation_enabled"]["weight"] == 100
626
+
627
+ def test_get_sc13_check_details(self):
628
+ """Test getting SC-13 check details."""
629
+ mapper = KMSControlMapper()
630
+ details = mapper.get_check_details("SC-13")
631
+
632
+ assert details is not None
633
+ assert "key_spec" in details
634
+ assert "key_usage" in details
635
+ assert "key_origin" in details
636
+
637
+ def test_get_unknown_control_check_details(self):
638
+ """Test getting check details for unknown control."""
639
+ mapper = KMSControlMapper()
640
+ details = mapper.get_check_details("UNKNOWN-1")
641
+
642
+ assert details is None
643
+
644
+ def test_check_details_structure(self):
645
+ """Test check details have required structure."""
646
+ mapper = KMSControlMapper()
647
+ details = mapper.get_check_details("SC-12")
648
+
649
+ for check_name, check_data in details.items():
650
+ assert "weight" in check_data
651
+ assert "pass_criteria" in check_data
652
+ assert "fail_criteria" in check_data
653
+
654
+
655
+ if __name__ == "__main__":
656
+ pytest.main([__file__, "-v"])