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,406 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Comprehensive unit tests for compliance status mapping in ComplianceIntegration.
5
+
6
+ These tests ensure that:
7
+ 1. ONLY compliance settings from the SSP are used
8
+ 2. No defaults are applied when compliance settings exist
9
+ 3. The correct status is selected based on framework
10
+ 4. The scoring/weight system works correctly
11
+ """
12
+
13
+ import unittest
14
+ from unittest.mock import MagicMock, patch, PropertyMock
15
+ from typing import List, Optional
16
+
17
+ from regscale.integrations.compliance_integration import ComplianceIntegration
18
+ from regscale.models.regscale_models import ComplianceSettings, SecurityPlan, ControlImplementation
19
+
20
+
21
+ class MockComplianceIntegration(ComplianceIntegration):
22
+ """Mock implementation of ComplianceIntegration for testing."""
23
+
24
+ def __init__(self, **kwargs):
25
+ """Override init to avoid API calls."""
26
+ # Store the values without calling super().__init__
27
+ self.plan_id = kwargs.get("plan_id", 100)
28
+ self.catalog_id = kwargs.get("catalog_id")
29
+ self.framework = kwargs.get("framework", "TEST_FRAMEWORK")
30
+ self.create_issues = kwargs.get("create_issues", False)
31
+ self.update_control_status = kwargs.get("update_control_status", True)
32
+ self.create_poams = kwargs.get("create_poams", False)
33
+
34
+ # Initialize required attributes
35
+ self._compliance_settings = None
36
+ self.scan_date = kwargs.get("scan_date", "2024-01-15")
37
+ self.parent_module = kwargs.get("parent_module", "securityplans")
38
+
39
+ # Initialize the constant properties
40
+ self.NOT_APPLICABLE_LABEL = "Not Applicable"
41
+ self.NOT_APPLICABLE_LOWER = "not applicable"
42
+ self.NOT_APPLICABLE_UNDERSCORE = "not_applicable"
43
+
44
+ @property
45
+ def module(self) -> str:
46
+ return "test_module"
47
+
48
+ @property
49
+ def title(self) -> str:
50
+ return "Test Integration"
51
+
52
+ def _get_compliance_items_from_data(self) -> List:
53
+ return []
54
+
55
+ def fetch_compliance_data(self) -> List:
56
+ """Mock implementation of abstract method."""
57
+ return []
58
+
59
+ def create_compliance_item(self, data: dict) -> object:
60
+ """Mock implementation of abstract method."""
61
+ return MagicMock()
62
+
63
+
64
+ class TestComplianceStatusMapping(unittest.TestCase):
65
+ """Test cases for compliance status mapping logic."""
66
+
67
+ def setUp(self):
68
+ """Set up test fixtures."""
69
+ # Create mock integration with necessary attributes
70
+ self.integration = MockComplianceIntegration(
71
+ plan_id=100,
72
+ catalog_id=None,
73
+ framework="TEST_FRAMEWORK",
74
+ create_issues=False,
75
+ update_control_status=True,
76
+ )
77
+
78
+ def create_mock_compliance_settings(self, title: str, status_labels: List[str]) -> ComplianceSettings:
79
+ """
80
+ Create mock compliance settings with specified status labels.
81
+
82
+ :param str title: Title of the compliance settings (e.g., "DoD RMF Settings")
83
+ :param List[str] status_labels: List of available status values
84
+ :return: Mock ComplianceSettings object
85
+ """
86
+ mock_settings = MagicMock(spec=ComplianceSettings)
87
+ mock_settings.title = title
88
+ mock_settings.get_field_labels = MagicMock(return_value=status_labels)
89
+ return mock_settings
90
+
91
+ def test_dod_fail_status_only_uses_compliance_settings(self):
92
+ """Test that DoD framework ONLY uses status values from compliance settings, not defaults."""
93
+ # Create DoD compliance settings with specific status values
94
+ dod_status_labels = [
95
+ "Implemented",
96
+ "Not Implemented", # This should be selected for FAIL
97
+ "Planned",
98
+ "In Remediation", # This should NOT be selected for DoD
99
+ "Partially Implemented",
100
+ ]
101
+
102
+ mock_settings = self.create_mock_compliance_settings("DoD RMF Controls", dod_status_labels)
103
+
104
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
105
+ # Get status for FAIL result
106
+ status = self.integration._get_implementation_status_from_result("Fail")
107
+
108
+ # For DoD, it should select "Not Implemented" NOT "In Remediation"
109
+ self.assertEqual(status, "Not Implemented")
110
+ # Ensure get_field_labels was called
111
+ mock_settings.get_field_labels.assert_called_with("implementationStatus")
112
+
113
+ def test_fedramp_fail_status_only_uses_compliance_settings(self):
114
+ """Test that FedRAMP framework ONLY uses status values from compliance settings."""
115
+ # Create FedRAMP compliance settings with specific status values
116
+ fedramp_status_labels = [
117
+ "Fully Implemented",
118
+ "In Remediation", # This should be selected for FAIL
119
+ "Partially Implemented",
120
+ "Not Implemented",
121
+ "Not Applicable",
122
+ ]
123
+
124
+ mock_settings = self.create_mock_compliance_settings("FedRAMP Moderate", fedramp_status_labels)
125
+
126
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
127
+ # Get status for FAIL result
128
+ status = self.integration._get_implementation_status_from_result("Fail")
129
+
130
+ # For FedRAMP, it should select "In Remediation"
131
+ self.assertEqual(status, "In Remediation")
132
+ mock_settings.get_field_labels.assert_called_with("implementationStatus")
133
+
134
+ def test_pass_status_uses_only_compliance_settings(self):
135
+ """Test that PASS status only uses values from compliance settings."""
136
+ # Test with DoD settings
137
+ dod_status_labels = [
138
+ "Implemented", # Should be selected for PASS
139
+ "Not Implemented",
140
+ "Planned",
141
+ "In Remediation",
142
+ ]
143
+
144
+ mock_settings = self.create_mock_compliance_settings("DoD RMF", dod_status_labels)
145
+
146
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
147
+ status = self.integration._get_implementation_status_from_result("Pass")
148
+ self.assertEqual(status, "Implemented")
149
+
150
+ def test_no_default_fallback_when_compliance_settings_exist(self):
151
+ """Test that the system does NOT fall back to defaults when compliance settings exist."""
152
+ # Create settings with LIMITED status options (no default values)
153
+ limited_status_labels = [
154
+ "Custom Status 1",
155
+ "Custom Status 2",
156
+ "Not Implemented", # Only failure status available
157
+ ]
158
+
159
+ mock_settings = self.create_mock_compliance_settings("Custom Framework", limited_status_labels)
160
+
161
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
162
+ # Test FAIL - should use "Not Implemented" from the limited options
163
+ fail_status = self.integration._get_implementation_status_from_result("Fail")
164
+ self.assertEqual(fail_status, "Not Implemented")
165
+
166
+ # Test PASS - should return None or empty since no matching status
167
+ pass_status = self.integration._get_implementation_status_from_result("Pass")
168
+ # Should fall back to default ONLY when no match found
169
+ self.assertIn(pass_status, ["Custom Status 1", "Custom Status 2", "Fully Implemented"])
170
+
171
+ def test_scoring_system_priority(self):
172
+ """Test that the scoring system correctly prioritizes status values."""
173
+ # Create settings with multiple fail options
174
+ status_labels = [
175
+ "Implemented",
176
+ "Not Implemented",
177
+ "Planned",
178
+ "In Remediation",
179
+ "Partially Implemented",
180
+ "Failed",
181
+ ]
182
+
183
+ # Test DoD scoring priorities
184
+ dod_settings = self.create_mock_compliance_settings("DoD RMF Framework", status_labels)
185
+
186
+ with patch.object(self.integration, "_get_compliance_settings", return_value=dod_settings):
187
+ status = self.integration._get_implementation_status_from_result("Fail")
188
+ # DoD should prioritize "Not Implemented" over "In Remediation"
189
+ self.assertEqual(status, "Not Implemented")
190
+
191
+ # Test FedRAMP scoring priorities
192
+ fedramp_settings = self.create_mock_compliance_settings("FedRAMP High", status_labels)
193
+
194
+ with patch.object(self.integration, "_get_compliance_settings", return_value=fedramp_settings):
195
+ status = self.integration._get_implementation_status_from_result("Fail")
196
+ # FedRAMP should prioritize "In Remediation"
197
+ self.assertEqual(status, "In Remediation")
198
+
199
+ def test_exact_match_vs_partial_match(self):
200
+ """Test that exact matches are prioritized over partial matches."""
201
+ status_labels = [
202
+ "Implemented",
203
+ "Not Implemented", # Exact match
204
+ "Partially Not Implemented", # Partial match
205
+ "In Remediation",
206
+ "Remediation Required", # Partial match
207
+ ]
208
+
209
+ mock_settings = self.create_mock_compliance_settings("Test Framework", status_labels)
210
+
211
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
212
+ # Should select exact "Not Implemented" over partial matches
213
+ with patch.object(self.integration, "_detect_compliance_framework", return_value="DoD"):
214
+ status = self.integration._get_implementation_status_from_result("Fail")
215
+ self.assertEqual(status, "Not Implemented")
216
+
217
+ def test_framework_detection(self):
218
+ """Test that framework detection correctly identifies different frameworks."""
219
+ test_cases = [
220
+ ("DoD RMF Controls", "DoD"),
221
+ ("RMF Implementation", "DoD"),
222
+ ("Department of Defense", "DoD"),
223
+ ("Military Security Controls", "DoD"),
224
+ ("FedRAMP Moderate", "FedRAMP"),
225
+ ("FedRAMP High Baseline", "FedRAMP"),
226
+ ("NIST 800-53 Controls", "NIST"),
227
+ ("NIST SP 800-53", "NIST"),
228
+ ("FISMA Controls", "NIST"),
229
+ ("Custom Framework", "Default"),
230
+ ("", "Default"),
231
+ ]
232
+
233
+ for title, expected_framework in test_cases:
234
+ mock_settings = self.create_mock_compliance_settings(title, [])
235
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
236
+ detected = self.integration._detect_compliance_framework()
237
+ self.assertEqual(
238
+ detected, expected_framework, f"Failed to detect {expected_framework} from title '{title}'"
239
+ )
240
+
241
+ def test_no_compliance_settings_falls_back_to_default(self):
242
+ """Test that when NO compliance settings exist, system uses defaults."""
243
+ with patch.object(self.integration, "_get_compliance_settings", return_value=None):
244
+ # Should fall back to default mapping
245
+ fail_status = self.integration._get_implementation_status_from_result("Fail")
246
+ self.assertEqual(fail_status, "In Remediation")
247
+
248
+ pass_status = self.integration._get_implementation_status_from_result("Pass")
249
+ self.assertEqual(pass_status, "Fully Implemented")
250
+
251
+ def test_case_insensitive_matching(self):
252
+ """Test that status matching is case-insensitive."""
253
+ status_labels = [
254
+ "IMPLEMENTED", # All caps
255
+ "Not Implemented", # Mixed case
256
+ "planned", # Lower case
257
+ "IN REMEDIATION", # All caps with space
258
+ ]
259
+
260
+ mock_settings = self.create_mock_compliance_settings("Test", status_labels)
261
+
262
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
263
+ with patch.object(self.integration, "_detect_compliance_framework", return_value="DoD"):
264
+ # Should match "Not Implemented" despite case differences
265
+ status = self.integration._get_implementation_status_from_result("fail") # lowercase fail
266
+ self.assertEqual(status, "Not Implemented")
267
+
268
+ def test_not_applicable_status_mapping(self):
269
+ """Test that Not Applicable status is correctly mapped."""
270
+ status_labels = [
271
+ "Implemented",
272
+ "Not Implemented",
273
+ "Not Applicable",
274
+ "N/A",
275
+ ]
276
+
277
+ mock_settings = self.create_mock_compliance_settings("Test", status_labels)
278
+
279
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
280
+ # Test various forms of not applicable
281
+ for result in ["Not Applicable", "not_applicable", "N/A", "na"]:
282
+ status = self.integration._get_implementation_status_from_result(result)
283
+ self.assertIn(status, ["Not Applicable", "N/A"])
284
+
285
+ def test_empty_status_labels(self):
286
+ """Test behavior when compliance settings have no status labels."""
287
+ mock_settings = self.create_mock_compliance_settings("Empty Settings", [])
288
+
289
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
290
+ # Should fall back to defaults when no labels available
291
+ fail_status = self.integration._get_implementation_status_from_result("Fail")
292
+ self.assertEqual(fail_status, "In Remediation")
293
+
294
+ def test_update_implementation_status_integration(self):
295
+ """Test the full integration of status update with compliance settings."""
296
+ # Create a mock control implementation with required attributes
297
+ mock_impl = MagicMock(spec=ControlImplementation)
298
+ mock_impl.id = 123
299
+ mock_impl.status = "Old Status" # Use 'status' not 'implementationStatus'
300
+ mock_impl.responsibility = "Test Responsibility"
301
+ mock_impl.implementation = "Test implementation details"
302
+ mock_impl.save = MagicMock()
303
+
304
+ # Create DoD compliance settings
305
+ dod_status_labels = [
306
+ "Implemented",
307
+ "Not Implemented",
308
+ "Planned",
309
+ "In Remediation",
310
+ ]
311
+ mock_settings = self.create_mock_compliance_settings("DoD RMF", dod_status_labels)
312
+
313
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
314
+ # Update status for a FAIL result
315
+ self.integration._update_implementation_status(mock_impl, "Fail")
316
+
317
+ # Verify the status was set to "Not Implemented" for DoD
318
+ self.assertEqual(mock_impl.status, "Not Implemented")
319
+ mock_impl.save.assert_called_once()
320
+
321
+ def test_scoring_with_similar_labels(self):
322
+ """Test scoring when multiple similar labels exist."""
323
+ status_labels = [
324
+ "Implemented",
325
+ "Fully Implemented",
326
+ "Partially Implemented",
327
+ "Not Implemented",
328
+ "Not Yet Implemented",
329
+ "Implementation Planned",
330
+ ]
331
+
332
+ mock_settings = self.create_mock_compliance_settings("Test", status_labels)
333
+
334
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
335
+ # For PASS, should prefer "Implemented" over "Fully Implemented"
336
+ pass_status = self.integration._get_implementation_status_from_result("Pass")
337
+ self.assertEqual(pass_status, "Implemented")
338
+
339
+ # For FAIL with DoD, should prefer "Not Implemented"
340
+ with patch.object(self.integration, "_detect_compliance_framework", return_value="DoD"):
341
+ fail_status = self.integration._get_implementation_status_from_result("Fail")
342
+ self.assertEqual(fail_status, "Not Implemented")
343
+
344
+
345
+ class TestComplianceStatusMappingEdgeCases(unittest.TestCase):
346
+ """Test edge cases and error conditions in status mapping."""
347
+
348
+ def setUp(self):
349
+ """Set up test fixtures."""
350
+ self.integration = MockComplianceIntegration(
351
+ plan_id=100,
352
+ catalog_id=None,
353
+ framework="TEST_FRAMEWORK",
354
+ create_issues=False,
355
+ update_control_status=True,
356
+ )
357
+
358
+ def test_get_field_labels_exception(self):
359
+ """Test behavior when get_field_labels throws an exception."""
360
+ mock_settings = MagicMock(spec=ComplianceSettings)
361
+ mock_settings.title = "Test Settings"
362
+ mock_settings.get_field_labels.side_effect = Exception("Database error")
363
+
364
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
365
+ # Should fall back to default when exception occurs
366
+ status = self.integration._get_implementation_status_from_result("Fail")
367
+ self.assertEqual(status, "In Remediation") # Default fail status
368
+
369
+ def test_none_result_input(self):
370
+ """Test behavior with None or empty result input."""
371
+ mock_settings = MagicMock(spec=ComplianceSettings)
372
+ mock_settings.title = "Test"
373
+ mock_settings.get_field_labels.return_value = ["Implemented", "Not Implemented"]
374
+
375
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
376
+ # Test with None
377
+ status = self.integration._get_implementation_status_from_result(None)
378
+ self.assertIsNotNone(status) # Should handle gracefully
379
+
380
+ # Test with empty string
381
+ status = self.integration._get_implementation_status_from_result("")
382
+ self.assertIsNotNone(status) # Should handle gracefully
383
+
384
+ def test_special_characters_in_labels(self):
385
+ """Test handling of special characters in status labels."""
386
+ status_labels = [
387
+ "Implemented (Full)",
388
+ "Not-Implemented",
389
+ "In_Remediation",
390
+ "Planned/Scheduled",
391
+ ]
392
+
393
+ mock_settings = MagicMock(spec=ComplianceSettings)
394
+ mock_settings.title = "Test"
395
+ mock_settings.get_field_labels.return_value = status_labels
396
+
397
+ with patch.object(self.integration, "_get_compliance_settings", return_value=mock_settings):
398
+ # Should handle special characters in matching
399
+ with patch.object(self.integration, "_detect_compliance_framework", return_value="DoD"):
400
+ status = self.integration._get_implementation_status_from_result("Fail")
401
+ # Should still match "Not-Implemented" despite hyphen
402
+ self.assertIn(status, status_labels)
403
+
404
+
405
+ if __name__ == "__main__":
406
+ unittest.main()