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,253 @@
1
+ """AWS developer tools resource collectors."""
2
+
3
+ import logging
4
+ from typing import Dict, List, Any, Optional
5
+
6
+ from ..base import BaseCollector
7
+
8
+ logger = logging.getLogger("regscale")
9
+
10
+
11
+ class DeveloperToolsCollector(BaseCollector):
12
+ """Collector for AWS developer tools resources with filtering support."""
13
+
14
+ def __init__(
15
+ self,
16
+ session: Any,
17
+ region: str,
18
+ account_id: Optional[str] = None,
19
+ tags: Optional[Dict[str, str]] = None,
20
+ enabled_services: Optional[Dict[str, bool]] = None,
21
+ ):
22
+ """
23
+ Initialize developer tools collector with filtering support.
24
+
25
+ :param session: AWS session to use for API calls
26
+ :param str region: AWS region to collect from
27
+ :param str account_id: Optional AWS account ID to filter resources
28
+ :param dict tags: Optional tag filters (AND logic)
29
+ :param dict enabled_services: Optional dict of service names to boolean flags for enabling/disabling collection
30
+ """
31
+ super().__init__(session, region, account_id, tags)
32
+ self.enabled_services = enabled_services or {}
33
+
34
+ def get_codepipeline_pipelines(self) -> List[Dict[str, Any]]:
35
+ """
36
+ Get information about CodePipeline pipelines.
37
+
38
+ :return: List of CodePipeline pipeline information
39
+ :rtype: List[Dict[str, Any]]
40
+ """
41
+ pipelines = []
42
+ try:
43
+ codepipeline_client = self._get_client("codepipeline")
44
+ paginator = codepipeline_client.get_paginator("list_pipelines")
45
+
46
+ for page in paginator.paginate():
47
+ for pipeline_summary in page.get("pipelines", []):
48
+ pipeline_name = pipeline_summary.get("name")
49
+
50
+ try:
51
+ pipeline_detail = codepipeline_client.get_pipeline(name=pipeline_name)
52
+ pipeline = pipeline_detail.get("pipeline", {})
53
+ pipeline_arn = pipeline.get("pipelineArn", "")
54
+
55
+ if not self._matches_account(pipeline_arn):
56
+ continue
57
+
58
+ tags_response = codepipeline_client.list_tags_for_resource(resourceArn=pipeline_arn)
59
+ pipeline_tags = tags_response.get("tags", [])
60
+
61
+ if not self._matches_tags(pipeline_tags):
62
+ continue
63
+
64
+ pipelines.append(
65
+ {
66
+ "Region": self.region,
67
+ "PipelineName": pipeline_name,
68
+ "PipelineArn": pipeline_arn,
69
+ "RoleArn": pipeline.get("roleArn"),
70
+ "Version": pipeline.get("version"),
71
+ "Created": pipeline_summary.get("created"),
72
+ "Updated": pipeline_summary.get("updated"),
73
+ "Tags": pipeline_tags,
74
+ }
75
+ )
76
+ except Exception as pipeline_error:
77
+ logger.debug("Error getting CodePipeline details for %s: %s", pipeline_name, pipeline_error)
78
+ continue
79
+
80
+ except Exception as e:
81
+ self._handle_error(e, "CodePipeline pipelines")
82
+ return pipelines
83
+
84
+ def get_codebuild_projects(self) -> List[Dict[str, Any]]:
85
+ """
86
+ Get information about CodeBuild projects.
87
+
88
+ :return: List of CodeBuild project information
89
+ :rtype: List[Dict[str, Any]]
90
+ """
91
+ projects = []
92
+ try:
93
+ codebuild_client = self._get_client("codebuild")
94
+ paginator = codebuild_client.get_paginator("list_projects")
95
+
96
+ for page in paginator.paginate():
97
+ project_names = page.get("projects", [])
98
+
99
+ if not project_names:
100
+ continue
101
+
102
+ batch_response = codebuild_client.batch_get_projects(names=project_names)
103
+ for project in batch_response.get("projects", []):
104
+ project_arn = project.get("arn", "")
105
+
106
+ if not self._matches_account(project_arn):
107
+ continue
108
+
109
+ if not self._matches_tags(project.get("tags", [])):
110
+ continue
111
+
112
+ projects.append(
113
+ {
114
+ "Region": self.region,
115
+ "ProjectName": project.get("name"),
116
+ "ProjectArn": project_arn,
117
+ "Description": project.get("description"),
118
+ "ServiceRole": project.get("serviceRole"),
119
+ "Created": project.get("created"),
120
+ "LastModified": project.get("lastModified"),
121
+ "Environment": project.get("environment"),
122
+ "Tags": project.get("tags", []),
123
+ }
124
+ )
125
+
126
+ except Exception as e:
127
+ self._handle_error(e, "CodeBuild projects")
128
+ return projects
129
+
130
+ def get_codedeploy_applications(self) -> List[Dict[str, Any]]:
131
+ """
132
+ Get information about CodeDeploy applications.
133
+
134
+ :return: List of CodeDeploy application information
135
+ :rtype: List[Dict[str, Any]]
136
+ """
137
+ applications = []
138
+ try:
139
+ codedeploy_client = self._get_client("codedeploy")
140
+ paginator = codedeploy_client.get_paginator("list_applications")
141
+
142
+ for page in paginator.paginate():
143
+ for app_name in page.get("applications", []):
144
+ try:
145
+ app_detail = codedeploy_client.get_application(applicationName=app_name)
146
+ application = app_detail.get("application", {})
147
+ app_arn = f"arn:aws:codedeploy:{self.region}:{self.account_id or '*'}:application:{app_name}"
148
+
149
+ if not self._matches_account(app_arn):
150
+ continue
151
+
152
+ tags_response = codedeploy_client.list_tags_for_resource(ResourceArn=app_arn)
153
+ app_tags = tags_response.get("Tags", [])
154
+
155
+ if not self._matches_tags(app_tags):
156
+ continue
157
+
158
+ applications.append(
159
+ {
160
+ "Region": self.region,
161
+ "ApplicationName": app_name,
162
+ "ApplicationId": application.get("applicationId"),
163
+ "CreateTime": application.get("createTime"),
164
+ "ComputePlatform": application.get("computePlatform"),
165
+ "Tags": app_tags,
166
+ }
167
+ )
168
+ except Exception as app_error:
169
+ logger.debug("Error getting CodeDeploy application details for %s: %s", app_name, app_error)
170
+ continue
171
+
172
+ except Exception as e:
173
+ self._handle_error(e, "CodeDeploy applications")
174
+ return applications
175
+
176
+ def get_codecommit_repositories(self) -> List[Dict[str, Any]]:
177
+ """
178
+ Get information about CodeCommit repositories.
179
+
180
+ :return: List of CodeCommit repository information
181
+ :rtype: List[Dict[str, Any]]
182
+ """
183
+ repositories = []
184
+ try:
185
+ codecommit_client = self._get_client("codecommit")
186
+ paginator = codecommit_client.get_paginator("list_repositories")
187
+
188
+ for page in paginator.paginate():
189
+ for repo_metadata in page.get("repositories", []):
190
+ repo_name = repo_metadata.get("repositoryName")
191
+
192
+ try:
193
+ repo_detail = codecommit_client.get_repository(repositoryName=repo_name)
194
+ repository = repo_detail.get("repositoryMetadata", {})
195
+ repo_arn = repository.get("Arn", "")
196
+
197
+ if not self._matches_account(repo_arn):
198
+ continue
199
+
200
+ tags_response = codecommit_client.list_tags_for_resource(resourceArn=repo_arn)
201
+ repo_tags = tags_response.get("tags", {})
202
+
203
+ if not self._matches_tags(repo_tags):
204
+ continue
205
+
206
+ repositories.append(
207
+ {
208
+ "Region": self.region,
209
+ "RepositoryName": repo_name,
210
+ "RepositoryId": repository.get("repositoryId"),
211
+ "RepositoryArn": repo_arn,
212
+ "DefaultBranch": repository.get("defaultBranch"),
213
+ "CloneUrlHttp": repository.get("cloneUrlHttp"),
214
+ "CloneUrlSsh": repository.get("cloneUrlSsh"),
215
+ "CreationDate": repository.get("creationDate"),
216
+ "LastModifiedDate": repository.get("lastModifiedDate"),
217
+ "Tags": repo_tags,
218
+ }
219
+ )
220
+ except Exception as repo_error:
221
+ logger.debug("Error getting CodeCommit repository details for %s: %s", repo_name, repo_error)
222
+ continue
223
+
224
+ except Exception as e:
225
+ self._handle_error(e, "CodeCommit repositories")
226
+ return repositories
227
+
228
+ def collect(self) -> Dict[str, Any]:
229
+ """
230
+ Collect developer tools resources based on enabled_services configuration.
231
+
232
+ :return: Dictionary containing enabled developer tools resource information
233
+ :rtype: Dict[str, Any]
234
+ """
235
+ result = {}
236
+
237
+ # CodePipeline
238
+ if self.enabled_services.get("codepipeline", True):
239
+ result["CodePipelinePipelines"] = self.get_codepipeline_pipelines()
240
+
241
+ # CodeBuild
242
+ if self.enabled_services.get("codebuild", True):
243
+ result["CodeBuildProjects"] = self.get_codebuild_projects()
244
+
245
+ # CodeDeploy
246
+ if self.enabled_services.get("codedeploy", True):
247
+ result["CodeDeployApplications"] = self.get_codedeploy_applications()
248
+
249
+ # CodeCommit
250
+ if self.enabled_services.get("codecommit", True):
251
+ result["CodeCommitRepositories"] = self.get_codecommit_repositories()
252
+
253
+ return result
@@ -0,0 +1,286 @@
1
+ """AWS GuardDuty resource collection."""
2
+
3
+ import logging
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ from botocore.exceptions import ClientError
7
+
8
+ from regscale.integrations.commercial.aws.inventory.base import BaseCollector
9
+
10
+ logger = logging.getLogger("regscale")
11
+
12
+
13
+ class GuardDutyCollector(BaseCollector):
14
+ """Collector for AWS GuardDuty resources."""
15
+
16
+ def __init__(
17
+ self,
18
+ session: Any,
19
+ region: str,
20
+ account_id: Optional[str] = None,
21
+ tags: Optional[Dict[str, str]] = None,
22
+ collect_findings: bool = True,
23
+ ):
24
+ """
25
+ Initialize GuardDuty collector.
26
+
27
+ :param session: AWS session to use for API calls
28
+ :param str region: AWS region to collect from
29
+ :param str account_id: Optional AWS account ID to filter resources
30
+ :param dict tags: Optional tags to filter resources (key-value pairs)
31
+ :param bool collect_findings: Whether to collect GuardDuty findings. Default True.
32
+ """
33
+ super().__init__(session, region)
34
+ self.account_id = account_id
35
+ self.tags = tags or {}
36
+ self.collect_findings = collect_findings
37
+
38
+ def collect(self) -> Dict[str, Any]:
39
+ """
40
+ Collect GuardDuty resources.
41
+
42
+ :return: Dictionary containing GuardDuty detectors, findings, and members
43
+ :rtype: Dict[str, Any]
44
+ """
45
+ result = {"Detectors": [], "Findings": [], "Members": []}
46
+
47
+ try:
48
+ client = self._get_client("guardduty")
49
+ detector_ids = self._list_detectors(client)
50
+
51
+ for detector_id in detector_ids:
52
+ self._process_detector(client, detector_id, result)
53
+
54
+ if self.collect_findings:
55
+ logger.info(
56
+ f"Collected {len(result['Detectors'])} GuardDuty detector(s), "
57
+ f"{len(result['Findings'])} finding(s) from {self.region}"
58
+ )
59
+ else:
60
+ logger.info(f"Collected {len(result['Detectors'])} GuardDuty detector(s) from {self.region}")
61
+
62
+ except ClientError as e:
63
+ self._handle_error(e, "GuardDuty resources")
64
+ except Exception as e:
65
+ logger.error(f"Unexpected error collecting GuardDuty resources: {e}", exc_info=True)
66
+
67
+ return result
68
+
69
+ def _process_detector(self, client: Any, detector_id: str, result: Dict[str, Any]) -> None:
70
+ """
71
+ Process a single detector and add its details to result.
72
+
73
+ :param client: GuardDuty client
74
+ :param str detector_id: Detector ID to process
75
+ :param dict result: Result dictionary to populate
76
+ """
77
+ detector_info = self._get_detector(client, detector_id)
78
+ if not detector_info:
79
+ return
80
+
81
+ if not self._should_include_detector(detector_info, detector_id):
82
+ return
83
+
84
+ detector_info = self._enrich_detector_info(client, detector_id, detector_info)
85
+ result["Detectors"].append(detector_info)
86
+
87
+ if self.collect_findings:
88
+ findings = self._list_and_get_findings(client, detector_id)
89
+ result["Findings"].extend(findings)
90
+ else:
91
+ logger.debug(f"Skipping GuardDuty findings collection for detector {detector_id} (collect_findings=False)")
92
+
93
+ members = self._list_members(client, detector_id)
94
+ result["Members"].extend(members)
95
+
96
+ def _should_include_detector(self, detector_info: Dict[str, Any], detector_id: str) -> bool:
97
+ """
98
+ Check if detector should be included based on filters.
99
+
100
+ :param dict detector_info: Detector information
101
+ :param str detector_id: Detector ID
102
+ :return: True if detector should be included
103
+ :rtype: bool
104
+ """
105
+ if self.account_id and not self._matches_account_id(detector_info.get("AccountId", "")):
106
+ logger.debug(f"Skipping detector {detector_id} - does not match account ID {self.account_id}")
107
+ return False
108
+
109
+ if self.tags:
110
+ detector_tags = self._get_detector_tags(
111
+ self._get_client("guardduty"), detector_id, detector_info.get("AccountId", "")
112
+ )
113
+ if not self._matches_tags(detector_tags):
114
+ logger.debug(f"Skipping detector {detector_id} - does not match tag filters")
115
+ return False
116
+
117
+ return True
118
+
119
+ def _enrich_detector_info(self, client: Any, detector_id: str, detector_info: Dict[str, Any]) -> Dict[str, Any]:
120
+ """
121
+ Enrich detector info with additional metadata.
122
+
123
+ :param client: GuardDuty client
124
+ :param str detector_id: Detector ID
125
+ :param dict detector_info: Detector information to enrich
126
+ :return: Enriched detector information
127
+ :rtype: Dict[str, Any]
128
+ """
129
+ if self.tags:
130
+ detector_tags = self._get_detector_tags(client, detector_id, detector_info.get("AccountId", ""))
131
+ detector_info["Tags"] = detector_tags
132
+
133
+ detector_info["DetectorId"] = detector_id
134
+ detector_info["Region"] = self.region
135
+ return detector_info
136
+
137
+ def _list_detectors(self, client: Any) -> List[str]:
138
+ """
139
+ List GuardDuty detectors.
140
+
141
+ :param client: GuardDuty client
142
+ :return: List of detector IDs
143
+ :rtype: List[str]
144
+ """
145
+ try:
146
+ response = client.list_detectors()
147
+ return response.get("DetectorIds", [])
148
+ except ClientError as e:
149
+ if e.response["Error"]["Code"] == "AccessDeniedException":
150
+ logger.warning(f"Access denied to list GuardDuty detectors in {self.region}")
151
+ return []
152
+ raise
153
+
154
+ def _get_detector(self, client: Any, detector_id: str) -> Optional[Dict[str, Any]]:
155
+ """
156
+ Get details about a specific GuardDuty detector.
157
+
158
+ :param client: GuardDuty client
159
+ :param str detector_id: Detector ID
160
+ :return: Detector details or None
161
+ :rtype: Optional[Dict[str, Any]]
162
+ """
163
+ try:
164
+ response = client.get_detector(DetectorId=detector_id)
165
+ # Remove ResponseMetadata
166
+ response.pop("ResponseMetadata", None)
167
+ return response
168
+ except ClientError as e:
169
+ logger.error(f"Error getting detector {detector_id}: {e}")
170
+ return None
171
+
172
+ def _list_and_get_findings(self, client: Any, detector_id: str, max_findings: int = 50) -> List[Dict[str, Any]]:
173
+ """
174
+ List and get detailed information about GuardDuty findings.
175
+
176
+ :param client: GuardDuty client
177
+ :param str detector_id: Detector ID
178
+ :param int max_findings: Maximum number of findings to retrieve
179
+ :return: List of findings with details
180
+ :rtype: List[Dict[str, Any]]
181
+ """
182
+ findings = []
183
+
184
+ try:
185
+ # List finding IDs
186
+ list_response = client.list_findings(DetectorId=detector_id, MaxResults=max_findings)
187
+ finding_ids = list_response.get("FindingIds", [])
188
+
189
+ if not finding_ids:
190
+ return findings
191
+
192
+ # Get detailed information for findings
193
+ get_response = client.get_findings(DetectorId=detector_id, FindingIds=finding_ids)
194
+ findings = get_response.get("Findings", [])
195
+
196
+ # Add region information
197
+ for finding in findings:
198
+ finding["Region"] = self.region
199
+ finding["DetectorId"] = detector_id
200
+
201
+ except ClientError as e:
202
+ if e.response["Error"]["Code"] == "AccessDeniedException":
203
+ logger.warning(f"Access denied to list findings for detector {detector_id}")
204
+ else:
205
+ logger.error(f"Error listing findings for detector {detector_id}: {e}")
206
+
207
+ return findings
208
+
209
+ def _list_members(self, client: Any, detector_id: str) -> List[Dict[str, Any]]:
210
+ """
211
+ List member accounts for a GuardDuty detector.
212
+
213
+ :param client: GuardDuty client
214
+ :param str detector_id: Detector ID
215
+ :return: List of member accounts
216
+ :rtype: List[Dict[str, Any]]
217
+ """
218
+ members = []
219
+
220
+ try:
221
+ response = client.list_members(DetectorId=detector_id)
222
+ members = response.get("Members", [])
223
+
224
+ # Add region and detector information
225
+ for member in members:
226
+ member["Region"] = self.region
227
+ member["DetectorId"] = detector_id
228
+
229
+ except ClientError as e:
230
+ if e.response["Error"]["Code"] == "AccessDeniedException":
231
+ logger.debug(f"Access denied to list members for detector {detector_id}")
232
+ else:
233
+ logger.error(f"Error listing members for detector {detector_id}: {e}")
234
+
235
+ return members
236
+
237
+ def _matches_account_id(self, detector_account_id: str) -> bool:
238
+ """
239
+ Check if detector account ID matches the specified account ID.
240
+
241
+ :param str detector_account_id: Account ID from detector
242
+ :return: True if matches or no account_id filter specified
243
+ :rtype: bool
244
+ """
245
+ if not self.account_id:
246
+ return True
247
+
248
+ return detector_account_id == self.account_id
249
+
250
+ def _get_detector_tags(self, client: Any, detector_id: str, account_id: str) -> Dict[str, str]:
251
+ """
252
+ Get tags for a GuardDuty detector.
253
+
254
+ :param client: GuardDuty client
255
+ :param str detector_id: Detector ID
256
+ :param str account_id: AWS account ID
257
+ :return: Dictionary of tags (TagKey -> TagValue)
258
+ :rtype: Dict[str, str]
259
+ """
260
+ try:
261
+ # Construct the detector ARN
262
+ detector_arn = f"arn:aws:guardduty:{self.region}:{account_id}:detector/{detector_id}"
263
+ response = client.list_tags_for_resource(ResourceArn=detector_arn)
264
+ tags = response.get("Tags", {})
265
+ return tags
266
+ except ClientError as e:
267
+ logger.debug(f"Error getting tags for detector {detector_id}: {e}")
268
+ return {}
269
+
270
+ def _matches_tags(self, resource_tags: Dict[str, str]) -> bool:
271
+ """
272
+ Check if resource tags match the specified filter tags.
273
+
274
+ :param dict resource_tags: Tags on the resource
275
+ :return: True if all filter tags match
276
+ :rtype: bool
277
+ """
278
+ if not self.tags:
279
+ return True
280
+
281
+ # All filter tags must match
282
+ for key, value in self.tags.items():
283
+ if resource_tags.get(key) != value:
284
+ return False
285
+
286
+ return True