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
@@ -1,17 +1,25 @@
1
1
  """AWS resource inventory collection module."""
2
2
 
3
+ import logging
3
4
  import os
4
5
  from typing import Dict, Any, Optional
5
6
 
6
7
  from regscale.integrations.commercial.aws.inventory.base import BaseCollector
8
+ from regscale.integrations.commercial.aws.inventory.resources.analytics import AnalyticsCollector
9
+ from regscale.integrations.commercial.aws.inventory.resources.applications import ApplicationCollector
7
10
  from regscale.integrations.commercial.aws.inventory.resources.compute import ComputeCollector
11
+ from regscale.integrations.commercial.aws.inventory.resources.config import ConfigCollector
8
12
  from regscale.integrations.commercial.aws.inventory.resources.containers import ContainerCollector
9
13
  from regscale.integrations.commercial.aws.inventory.resources.database import DatabaseCollector
14
+ from regscale.integrations.commercial.aws.inventory.resources.developer_tools import DeveloperToolsCollector
10
15
  from regscale.integrations.commercial.aws.inventory.resources.integration import IntegrationCollector
16
+ from regscale.integrations.commercial.aws.inventory.resources.machine_learning import MachineLearningCollector
11
17
  from regscale.integrations.commercial.aws.inventory.resources.networking import NetworkingCollector
12
18
  from regscale.integrations.commercial.aws.inventory.resources.security import SecurityCollector
13
19
  from regscale.integrations.commercial.aws.inventory.resources.storage import StorageCollector
14
20
 
21
+ logger = logging.getLogger("regscale")
22
+
15
23
 
16
24
  class AWSInventoryCollector:
17
25
  """Collects inventory of AWS resources."""
@@ -19,40 +27,318 @@ class AWSInventoryCollector:
19
27
  def __init__(
20
28
  self,
21
29
  region: str = os.getenv("AWS_REGION", "us-east-1"),
30
+ profile: Optional[str] = None,
22
31
  aws_access_key_id: Optional[str] = None,
23
32
  aws_secret_access_key: Optional[str] = None,
24
33
  aws_session_token: Optional[str] = None,
34
+ account_id: Optional[str] = None,
35
+ tags: Optional[Dict[str, str]] = None,
36
+ enabled_services: Optional[Dict[str, bool]] = None,
37
+ collect_findings: bool = True,
25
38
  ):
26
39
  """
27
40
  Initialize the AWS inventory collector.
28
41
 
29
42
  :param str region: AWS region to collect inventory from
30
- :param str aws_access_key_id: Optional AWS access key ID
31
- :param str aws_secret_access_key: Optional AWS secret access key
32
- :param str aws_session_token: Optional AWS session ID
43
+ :param str profile: Optional AWS profile name from ~/.aws/credentials
44
+ :param str aws_access_key_id: Optional AWS access key ID (overrides profile)
45
+ :param str aws_secret_access_key: Optional AWS secret access key (overrides profile)
46
+ :param str aws_session_token: Optional AWS session token (overrides profile)
47
+ :param str account_id: Optional AWS account ID to filter resources
48
+ :param dict tags: Optional dictionary of tag key-value pairs to filter resources
49
+ :param dict enabled_services: Optional dictionary of service names to boolean flags for enabling/disabling collection
50
+ :param bool collect_findings: Whether to collect security findings (GuardDuty, Security Hub, Inspector). Default True.
33
51
  """
34
52
  import boto3
35
53
 
36
54
  self.region = region
37
- self.session = boto3.Session(
38
- aws_access_key_id=aws_access_key_id,
39
- aws_secret_access_key=aws_secret_access_key,
40
- region_name=region,
41
- aws_session_token=aws_session_token,
55
+ self.account_id = account_id
56
+ self.tags = tags
57
+ self.enabled_services = self._get_enabled_services(enabled_services)
58
+
59
+ # If explicit credentials are provided, use them; otherwise use profile
60
+ if aws_access_key_id or aws_secret_access_key:
61
+ self.session = boto3.Session(
62
+ aws_access_key_id=aws_access_key_id,
63
+ aws_secret_access_key=aws_secret_access_key,
64
+ region_name=region,
65
+ aws_session_token=aws_session_token,
66
+ )
67
+ else:
68
+ # Use profile or default credential chain
69
+ self.session = boto3.Session(
70
+ profile_name=profile,
71
+ region_name=region,
72
+ )
73
+
74
+ # Initialize collectors based on enabled services
75
+ compute_config = self.enabled_services.get("compute", {"enabled": True, "services": {}})
76
+ self.compute = (
77
+ ComputeCollector(self.session, self.region, account_id, tags, compute_config.get("services", {}))
78
+ if compute_config.get("enabled", True)
79
+ else None
80
+ )
81
+
82
+ storage_config = self.enabled_services.get("storage", {"enabled": True, "services": {}})
83
+ self.storage = (
84
+ StorageCollector(self.session, self.region, account_id, tags, storage_config.get("services", {}))
85
+ if storage_config.get("enabled", True)
86
+ else None
87
+ )
88
+
89
+ database_config = self.enabled_services.get("database", {"enabled": True, "services": {}})
90
+ self.database = (
91
+ DatabaseCollector(self.session, self.region, account_id, tags, database_config.get("services", {}))
92
+ if database_config.get("enabled", True)
93
+ else None
94
+ )
95
+
96
+ networking_config = self.enabled_services.get("networking", {"enabled": True, "services": {}})
97
+ self.networking = (
98
+ NetworkingCollector(self.session, self.region, account_id, tags, networking_config.get("services", {}))
99
+ if networking_config.get("enabled", True)
100
+ else None
101
+ )
102
+
103
+ security_config = self.enabled_services.get("security", {"enabled": True, "services": {}})
104
+ self.security = (
105
+ SecurityCollector(
106
+ self.session, self.region, account_id, tags, security_config.get("services", {}), collect_findings
107
+ )
108
+ if security_config.get("enabled", True)
109
+ else None
110
+ )
111
+
112
+ integration_config = self.enabled_services.get("integration", {"enabled": True, "services": {}})
113
+ self.integration = (
114
+ IntegrationCollector(self.session, self.region, account_id, tags, integration_config.get("services", {}))
115
+ if integration_config.get("enabled", True)
116
+ else None
117
+ )
118
+
119
+ containers_config = self.enabled_services.get("containers", {"enabled": True, "services": {}})
120
+ self.containers = (
121
+ ContainerCollector(self.session, self.region, account_id, tags, containers_config.get("services", {}))
122
+ if containers_config.get("enabled", True)
123
+ else None
42
124
  )
43
125
 
44
- # Initialize collectors
45
- self.compute = ComputeCollector(self.session, self.region)
46
- self.storage = StorageCollector(self.session, self.region)
47
- self.database = DatabaseCollector(self.session, self.region)
48
- self.networking = NetworkingCollector(self.session, self.region)
49
- self.security = SecurityCollector(self.session, self.region)
50
- self.integration = IntegrationCollector(self.session, self.region)
51
- self.containers = ContainerCollector(self.session, self.region)
126
+ config_config = self.enabled_services.get("config", {"enabled": True, "services": {}})
127
+ self.config = (
128
+ ConfigCollector(self.session, self.region, account_id, tags) if config_config.get("enabled", True) else None
129
+ )
130
+
131
+ # New collectors for analytics, ML, developer tools, and applications
132
+ analytics_config = self.enabled_services.get("analytics", {"enabled": True, "services": {}})
133
+ self.analytics = (
134
+ AnalyticsCollector(self.session, self.region, account_id, tags, analytics_config.get("services", {}))
135
+ if analytics_config.get("enabled", True)
136
+ else None
137
+ )
138
+
139
+ ml_config = self.enabled_services.get("machine_learning", {"enabled": True, "services": {}})
140
+ self.machine_learning = (
141
+ MachineLearningCollector(self.session, self.region, account_id, tags, ml_config.get("services", {}))
142
+ if ml_config.get("enabled", True)
143
+ else None
144
+ )
145
+
146
+ devtools_config = self.enabled_services.get("developer_tools", {"enabled": True, "services": {}})
147
+ self.developer_tools = (
148
+ DeveloperToolsCollector(self.session, self.region, account_id, tags, devtools_config.get("services", {}))
149
+ if devtools_config.get("enabled", True)
150
+ else None
151
+ )
152
+
153
+ applications_config = self.enabled_services.get("applications", {"enabled": True, "services": {}})
154
+ self.applications = (
155
+ ApplicationCollector(self.session, self.region, account_id, tags, applications_config.get("services", {}))
156
+ if applications_config.get("enabled", True)
157
+ else None
158
+ )
159
+
160
+ def _get_enabled_services(self, enabled_services: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
161
+ """
162
+ Get enabled services configuration with support for nested structure.
163
+ Supports both simple (category: bool) and nested (category: {enabled: bool, services: {...}}) formats.
164
+
165
+ :param dict enabled_services: Optional dictionary of service names to boolean flags or nested config
166
+ :return: Dictionary of service configurations
167
+ :rtype: Dict[str, Any]
168
+ """
169
+ # Default all services to enabled with all sub-services enabled
170
+ default_services = {
171
+ "compute": {
172
+ "enabled": True,
173
+ "services": {
174
+ "ec2": True,
175
+ "lambda": True,
176
+ "ecs": True,
177
+ "systems_manager": True,
178
+ "batch": True,
179
+ "app_runner": True,
180
+ "elastic_beanstalk": True,
181
+ "lightsail": True,
182
+ },
183
+ },
184
+ "storage": {
185
+ "enabled": True,
186
+ "services": {
187
+ "s3": True,
188
+ "ebs": True,
189
+ "efs": True,
190
+ "fsx": True,
191
+ "storage_gateway": True,
192
+ "backup": True,
193
+ },
194
+ },
195
+ "database": {
196
+ "enabled": True,
197
+ "services": {
198
+ "rds": True,
199
+ "dynamodb": True,
200
+ "elasticache": True,
201
+ "neptune": True,
202
+ "docdb": True,
203
+ "redshift": True,
204
+ "keyspaces": True,
205
+ "timestream": True,
206
+ "qldb": True,
207
+ },
208
+ },
209
+ "networking": {
210
+ "enabled": True,
211
+ "services": {
212
+ "vpc": True,
213
+ "elastic_ips": True,
214
+ "load_balancers": True,
215
+ "cloudfront": True,
216
+ "route53": True,
217
+ "direct_connect": True,
218
+ "transit_gateway": True,
219
+ "vpn": True,
220
+ "global_accelerator": True,
221
+ "network_firewall": True,
222
+ "route53_resolver": True,
223
+ },
224
+ },
225
+ "security": {
226
+ "enabled": True,
227
+ "services": {
228
+ "iam": True,
229
+ "kms": True,
230
+ "secrets_manager": True,
231
+ "waf": True,
232
+ "acm": True,
233
+ "cloudtrail": True,
234
+ "config": True,
235
+ "guardduty": True,
236
+ "securityhub": True,
237
+ "inspector": True,
238
+ "audit_manager": True,
239
+ },
240
+ },
241
+ "integration": {
242
+ "enabled": True,
243
+ "services": {"api_gateway": True, "sns": True, "sqs": True, "eventbridge": True},
244
+ },
245
+ "containers": {"enabled": True, "services": {"ecr": True}},
246
+ "config": {"enabled": True, "services": {}},
247
+ "analytics": {
248
+ "enabled": True,
249
+ "services": {
250
+ "emr": True,
251
+ "kinesis_streams": True,
252
+ "kinesis_firehose": True,
253
+ "glue": True,
254
+ "athena": True,
255
+ "msk": True,
256
+ },
257
+ },
258
+ "machine_learning": {
259
+ "enabled": True,
260
+ "services": {
261
+ "sagemaker_endpoints": True,
262
+ "sagemaker_models": True,
263
+ "sagemaker_notebooks": True,
264
+ "sagemaker_training_jobs": True,
265
+ "rekognition": True,
266
+ "comprehend": True,
267
+ },
268
+ },
269
+ "developer_tools": {
270
+ "enabled": True,
271
+ "services": {
272
+ "codepipeline": True,
273
+ "codebuild": True,
274
+ "codedeploy": True,
275
+ "codecommit": True,
276
+ },
277
+ },
278
+ "applications": {
279
+ "enabled": True,
280
+ "services": {
281
+ "step_functions": True,
282
+ "appsync": True,
283
+ "workspaces": True,
284
+ "iot": True,
285
+ },
286
+ },
287
+ }
288
+
289
+ # If no config provided, return defaults
290
+ if enabled_services is None:
291
+ return default_services
292
+
293
+ # Process configuration - support both simple and nested formats
294
+ merged_config = {}
295
+ for category, default_value in default_services.items():
296
+ if category not in enabled_services:
297
+ # Category not specified, use default
298
+ merged_config[category] = default_value
299
+ elif isinstance(enabled_services[category], bool):
300
+ # Simple format: security: true/false
301
+ # Convert to nested format with all services matching the category setting
302
+ merged_config[category] = {
303
+ "enabled": enabled_services[category],
304
+ "services": {
305
+ service: enabled_services[category] for service in default_value.get("services", {}).keys()
306
+ },
307
+ }
308
+ elif isinstance(enabled_services[category], dict):
309
+ # Nested format: security: {enabled: true, services: {...}}
310
+ category_config = enabled_services[category]
311
+ enabled_flag = category_config.get("enabled", True)
312
+ provided_services = category_config.get("services", {})
313
+
314
+ # Merge provided services with defaults
315
+ merged_services = default_value.get("services", {}).copy()
316
+ merged_services.update(provided_services)
317
+
318
+ merged_config[category] = {"enabled": enabled_flag, "services": merged_services}
319
+ else:
320
+ # Invalid format, use default
321
+ logger.warning(f"Invalid configuration format for category '{category}', using defaults")
322
+ merged_config[category] = default_value
323
+
324
+ # Log disabled categories and services
325
+ disabled_categories = [name for name, config in merged_config.items() if not config.get("enabled", True)]
326
+ if disabled_categories:
327
+ logger.info(f"AWS inventory collection disabled for categories: {', '.join(disabled_categories)}")
328
+
329
+ for category, config in merged_config.items():
330
+ if config.get("enabled", True):
331
+ disabled_services = [service for service, enabled in config.get("services", {}).items() if not enabled]
332
+ if disabled_services:
333
+ logger.info(
334
+ f"AWS inventory collection disabled for {category} services: {', '.join(disabled_services)}"
335
+ )
336
+
337
+ return merged_config
52
338
 
53
339
  def collect_all(self) -> Dict[str, Any]:
54
340
  """
55
- Collect all AWS resources.
341
+ Collect all AWS resources from enabled collectors.
56
342
 
57
343
  :return: Dictionary containing all AWS resource information
58
344
  :rtype: Dict[str, Any]
@@ -66,9 +352,19 @@ class AWSInventoryCollector:
66
352
  self.security,
67
353
  self.integration,
68
354
  self.containers,
355
+ self.config,
356
+ self.analytics,
357
+ self.machine_learning,
358
+ self.developer_tools,
359
+ self.applications,
69
360
  ]
70
361
 
71
- for collector in collectors:
362
+ # Filter out None collectors (disabled services)
363
+ active_collectors = [c for c in collectors if c is not None]
364
+
365
+ logger.info(f"Collecting AWS inventory from {len(active_collectors)} enabled service(s)")
366
+
367
+ for collector in active_collectors:
72
368
  try:
73
369
  resources = collector.collect()
74
370
  inventory.update(resources)
@@ -83,21 +379,41 @@ class AWSInventoryCollector:
83
379
 
84
380
  def collect_all_inventory(
85
381
  region: str = os.getenv("AWS_REGION", "us-east-1"),
382
+ profile: Optional[str] = None,
86
383
  aws_access_key_id: Optional[str] = None,
87
384
  aws_secret_access_key: Optional[str] = None,
88
385
  aws_session_token: Optional[str] = None,
386
+ account_id: Optional[str] = None,
387
+ tags: Optional[Dict[str, str]] = None,
388
+ enabled_services: Optional[Dict[str, bool]] = None,
389
+ collect_findings: bool = True,
89
390
  ) -> Dict[str, Any]:
90
391
  """
91
392
  Collect inventory of all AWS resources.
92
393
 
93
394
  :param str region: AWS region to collect inventory from
94
- :param str aws_access_key_id: Optional AWS access key ID
95
- :param str aws_secret_access_key: Optional AWS secret access key
96
- :param str aws_session_token: Optional AWS session ID
395
+ :param str profile: Optional AWS profile name from ~/.aws/credentials
396
+ :param str aws_access_key_id: Optional AWS access key ID (overrides profile)
397
+ :param str aws_secret_access_key: Optional AWS secret access key (overrides profile)
398
+ :param str aws_session_token: Optional AWS session token (overrides profile)
399
+ :param str account_id: Optional AWS account ID to filter resources
400
+ :param dict tags: Optional dictionary of tag key-value pairs to filter resources
401
+ :param dict enabled_services: Optional dictionary of service names to boolean flags for enabling/disabling collection
402
+ :param bool collect_findings: Whether to collect security findings (GuardDuty, Security Hub, Inspector). Default True.
97
403
  :return: Dictionary containing all AWS resource information
98
404
  :rtype: Dict[str, Any]
99
405
  """
100
- collector = AWSInventoryCollector(region, aws_access_key_id, aws_secret_access_key, aws_session_token)
406
+ collector = AWSInventoryCollector(
407
+ region,
408
+ profile,
409
+ aws_access_key_id,
410
+ aws_secret_access_key,
411
+ aws_session_token,
412
+ account_id,
413
+ tags,
414
+ enabled_services,
415
+ collect_findings,
416
+ )
101
417
  return collector.collect_all()
102
418
 
103
419
 
@@ -1,7 +1,7 @@
1
1
  """Base classes for AWS resource collection."""
2
2
 
3
3
  import logging
4
- from typing import Any, Dict, TYPE_CHECKING
4
+ from typing import Any, Dict, Optional, TYPE_CHECKING
5
5
 
6
6
  from botocore.exceptions import ClientError
7
7
 
@@ -12,17 +12,27 @@ logger = logging.getLogger("regscale")
12
12
 
13
13
 
14
14
  class BaseCollector:
15
- """Base class for AWS resource collectors."""
15
+ """Base class for AWS resource collectors with universal filtering support."""
16
16
 
17
- def __init__(self, session: "boto3.Session", region: str):
17
+ def __init__(
18
+ self,
19
+ session: "boto3.Session",
20
+ region: str,
21
+ account_id: Optional[str] = None,
22
+ tags: Optional[Dict[str, str]] = None,
23
+ ):
18
24
  """
19
- Initialize the base collector.
25
+ Initialize the base collector with filtering support.
20
26
 
21
27
  :param boto3.Session session: AWS session to use for API calls
22
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 dictionary of tag key-value pairs to filter resources (AND logic)
23
31
  """
24
32
  self.session = session
25
33
  self.region = region
34
+ self.account_id = account_id
35
+ self.tags = tags or {}
26
36
 
27
37
  def _get_client(self, service_name: str) -> Any:
28
38
  """
@@ -32,7 +42,99 @@ class BaseCollector:
32
42
  :return: Boto3 client for the service
33
43
  :rtype: Any
34
44
  """
35
- return self.session.client(service_name)
45
+ return self.session.client(service_name, region_name=self.region)
46
+
47
+ def _matches_account(self, resource_arn: str) -> bool:
48
+ """
49
+ Check if resource belongs to target account.
50
+
51
+ :param str resource_arn: AWS Resource ARN
52
+ :return: True if resource matches account filter or no filter specified
53
+ :rtype: bool
54
+
55
+ ARN format: arn:partition:service:region:account-id:resource
56
+ """
57
+ if not self.account_id:
58
+ return True # No filter, include all
59
+
60
+ try:
61
+ # ARN format: arn:aws:service:region:account-id:resource-id
62
+ arn_parts = resource_arn.split(":")
63
+ if len(arn_parts) >= 5:
64
+ arn_account = arn_parts[4]
65
+ match = arn_account == self.account_id
66
+ if not match:
67
+ logger.debug(f"Filtering out resource {resource_arn} - account {arn_account} != {self.account_id}")
68
+ return match
69
+ except (IndexError, AttributeError) as e:
70
+ logger.debug(f"Could not parse account from ARN {resource_arn}: {e}")
71
+ return True # Can't parse, include by default
72
+
73
+ return True
74
+
75
+ def _matches_tags(self, resource_tags: Any) -> bool:
76
+ """
77
+ Check if all filter tags match resource tags (AND logic).
78
+
79
+ Supports multiple AWS tag formats:
80
+ - Dict: {'Key': 'Value', ...}
81
+ - List of dicts: [{'Key': 'k', 'Value': 'v'}, ...]
82
+ - List of Tags: [{'key': 'k', 'value': 'v'}, ...] (lowercase)
83
+
84
+ :param resource_tags: Resource tags in any AWS format
85
+ :return: True if all filter tags match (or no filter), False otherwise
86
+ :rtype: bool
87
+ """
88
+ if not self.tags:
89
+ return True # No filter, include all
90
+
91
+ # Normalize tags to dict format
92
+ normalized_tags = self._normalize_tags(resource_tags)
93
+
94
+ # All filter tags must match (AND logic)
95
+ for key, value in self.tags.items():
96
+ if normalized_tags.get(key) != value:
97
+ logger.debug(
98
+ f"Resource does not match tag filter: expected {key}={value}, got {normalized_tags.get(key)}"
99
+ )
100
+ return False
101
+
102
+ return True
103
+
104
+ def _normalize_tags(self, tags: Any) -> Dict[str, str]:
105
+ """
106
+ Normalize various AWS tag formats to simple dict.
107
+
108
+ Handles:
109
+ - Dict format: {'Key': 'Value'}
110
+ - List format: [{'Key': 'k', 'Value': 'v'}] (uppercase)
111
+ - List format: [{'key': 'k', 'value': 'v'}] (lowercase)
112
+ - None or empty
113
+
114
+ :param tags: Tags in any AWS format
115
+ :return: Normalized dict of tags
116
+ :rtype: Dict[str, str]
117
+ """
118
+ if not tags:
119
+ return {}
120
+
121
+ if isinstance(tags, dict):
122
+ return tags
123
+
124
+ if isinstance(tags, list):
125
+ result = {}
126
+ for tag in tags:
127
+ if isinstance(tag, dict):
128
+ # Handle uppercase format (most common)
129
+ if "Key" in tag and "Value" in tag:
130
+ result[tag["Key"]] = tag["Value"]
131
+ # Handle lowercase format
132
+ elif "key" in tag and "value" in tag:
133
+ result[tag["key"]] = tag["value"]
134
+ return result
135
+
136
+ logger.warning(f"Unexpected tag format: {type(tags)}")
137
+ return {}
36
138
 
37
139
  def _handle_error(self, error: Exception, resource_type: str) -> None:
38
140
  """