sraverify 0.1.0__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 (261) hide show
  1. sraverify/__init__.py +36 -0
  2. sraverify/checks/__init__.py +56 -0
  3. sraverify/checks/accessanalyzer/SRA_IAA_1.py +188 -0
  4. sraverify/checks/accessanalyzer/SRA_IAA_2.py +162 -0
  5. sraverify/checks/accessanalyzer/SRA_IAA_3.py +260 -0
  6. sraverify/checks/accessanalyzer/SRA_IAA_4.py +207 -0
  7. sraverify/checks/accessanalyzer/__init__.py +3 -0
  8. sraverify/checks/cloudtrail/SRA-CT-1.py +220 -0
  9. sraverify/checks/cloudtrail/SRA-CT-10.py +229 -0
  10. sraverify/checks/cloudtrail/SRA-CT-11.py +242 -0
  11. sraverify/checks/cloudtrail/SRA-CT-12.py +163 -0
  12. sraverify/checks/cloudtrail/SRA-CT-13.py +279 -0
  13. sraverify/checks/cloudtrail/SRA-CT-2.py +218 -0
  14. sraverify/checks/cloudtrail/SRA-CT-3.py +196 -0
  15. sraverify/checks/cloudtrail/SRA-CT-4.py +161 -0
  16. sraverify/checks/cloudtrail/SRA-CT-5.py +200 -0
  17. sraverify/checks/cloudtrail/SRA-CT-6.py +161 -0
  18. sraverify/checks/cloudtrail/SRA-CT-7.py +194 -0
  19. sraverify/checks/cloudtrail/SRA-CT-8.py +226 -0
  20. sraverify/checks/cloudtrail/SRA-CT-9.py +226 -0
  21. sraverify/checks/cloudtrail/__init__.py +3 -0
  22. sraverify/checks/config/SRA-CONFIG-1.py +197 -0
  23. sraverify/checks/config/__init__.py +3 -0
  24. sraverify/core/__init__.py +3 -0
  25. sraverify/core/check.py +227 -0
  26. sraverify/core/logging.py +37 -0
  27. sraverify/core/session.py +47 -0
  28. sraverify/lib/__init__.py +4 -0
  29. sraverify/lib/audit_info.py +37 -0
  30. sraverify/lib/banner.py +42 -0
  31. sraverify/lib/check_loader.py +80 -0
  32. sraverify/lib/org_mgmt_checker.py +86 -0
  33. sraverify/lib/outputs.py +46 -0
  34. sraverify/lib/progress.py +75 -0
  35. sraverify/lib/regions.py +27 -0
  36. sraverify/lib/session.py +23 -0
  37. sraverify/main.py +350 -0
  38. sraverify/services/__init__.py +3 -0
  39. sraverify/services/accessanalyzer/__init__.py +15 -0
  40. sraverify/services/accessanalyzer/base.py +123 -0
  41. sraverify/services/accessanalyzer/checks/__init__.py +3 -0
  42. sraverify/services/accessanalyzer/checks/sra_accessanalyzer_01.py +82 -0
  43. sraverify/services/accessanalyzer/checks/sra_accessanalyzer_02.py +82 -0
  44. sraverify/services/accessanalyzer/checks/sra_accessanalyzer_03.py +103 -0
  45. sraverify/services/accessanalyzer/checks/sra_accessanalyzer_04.py +139 -0
  46. sraverify/services/accessanalyzer/client.py +123 -0
  47. sraverify/services/account/__init__.py +9 -0
  48. sraverify/services/account/base.py +56 -0
  49. sraverify/services/account/checks/__init__.py +1 -0
  50. sraverify/services/account/checks/sra_account_01.py +65 -0
  51. sraverify/services/account/checks/sra_account_02.py +63 -0
  52. sraverify/services/account/checks/sra_account_03.py +63 -0
  53. sraverify/services/account/client.py +51 -0
  54. sraverify/services/auditmanager/__init__.py +10 -0
  55. sraverify/services/auditmanager/base.py +72 -0
  56. sraverify/services/auditmanager/checks/__init__.py +1 -0
  57. sraverify/services/auditmanager/checks/sra_auditmanager_01.py +58 -0
  58. sraverify/services/auditmanager/checks/sra_auditmanager_02.py +80 -0
  59. sraverify/services/auditmanager/client.py +58 -0
  60. sraverify/services/cloudtrail/__init__.py +33 -0
  61. sraverify/services/cloudtrail/base.py +167 -0
  62. sraverify/services/cloudtrail/checks/__init__.py +1 -0
  63. sraverify/services/cloudtrail/checks/sra_cloudtrail_01.py +83 -0
  64. sraverify/services/cloudtrail/checks/sra_cloudtrail_02.py +99 -0
  65. sraverify/services/cloudtrail/checks/sra_cloudtrail_03.py +94 -0
  66. sraverify/services/cloudtrail/checks/sra_cloudtrail_04.py +92 -0
  67. sraverify/services/cloudtrail/checks/sra_cloudtrail_05.py +106 -0
  68. sraverify/services/cloudtrail/checks/sra_cloudtrail_06.py +93 -0
  69. sraverify/services/cloudtrail/checks/sra_cloudtrail_07.py +96 -0
  70. sraverify/services/cloudtrail/checks/sra_cloudtrail_08.py +145 -0
  71. sraverify/services/cloudtrail/checks/sra_cloudtrail_09.py +167 -0
  72. sraverify/services/cloudtrail/checks/sra_cloudtrail_10.py +162 -0
  73. sraverify/services/cloudtrail/checks/sra_cloudtrail_11.py +178 -0
  74. sraverify/services/cloudtrail/checks/sra_cloudtrail_12.py +77 -0
  75. sraverify/services/cloudtrail/checks/sra_cloudtrail_13.py +120 -0
  76. sraverify/services/cloudtrail/client.py +118 -0
  77. sraverify/services/config/__init__.py +25 -0
  78. sraverify/services/config/base.py +249 -0
  79. sraverify/services/config/checks/__init__.py +1 -0
  80. sraverify/services/config/checks/sra_config_01.py +123 -0
  81. sraverify/services/config/checks/sra_config_02.py +156 -0
  82. sraverify/services/config/checks/sra_config_03.py +149 -0
  83. sraverify/services/config/checks/sra_config_04.py +104 -0
  84. sraverify/services/config/checks/sra_config_05.py +104 -0
  85. sraverify/services/config/checks/sra_config_06.py +194 -0
  86. sraverify/services/config/checks/sra_config_07.py +162 -0
  87. sraverify/services/config/checks/sra_config_08.py +185 -0
  88. sraverify/services/config/checks/sra_config_09.py +177 -0
  89. sraverify/services/config/client.py +264 -0
  90. sraverify/services/ec2/__init__.py +8 -0
  91. sraverify/services/ec2/base.py +75 -0
  92. sraverify/services/ec2/checks/__init__.py +1 -0
  93. sraverify/services/ec2/checks/sra_ec2_01.py +83 -0
  94. sraverify/services/ec2/client.py +63 -0
  95. sraverify/services/firewallmanager/__init__.py +23 -0
  96. sraverify/services/firewallmanager/base.py +48 -0
  97. sraverify/services/firewallmanager/checks/__init__.py +1 -0
  98. sraverify/services/firewallmanager/checks/sra_firewallmanager_01.py +75 -0
  99. sraverify/services/firewallmanager/checks/sra_firewallmanager_02.py +57 -0
  100. sraverify/services/firewallmanager/checks/sra_firewallmanager_03.py +51 -0
  101. sraverify/services/firewallmanager/checks/sra_firewallmanager_04.py +51 -0
  102. sraverify/services/firewallmanager/checks/sra_firewallmanager_05.py +51 -0
  103. sraverify/services/firewallmanager/checks/sra_firewallmanager_06.py +51 -0
  104. sraverify/services/firewallmanager/checks/sra_firewallmanager_07.py +51 -0
  105. sraverify/services/firewallmanager/checks/sra_firewallmanager_08.py +61 -0
  106. sraverify/services/firewallmanager/checks/sra_firewallmanager_09.py +61 -0
  107. sraverify/services/firewallmanager/checks/sra_firewallmanager_10.py +71 -0
  108. sraverify/services/firewallmanager/client.py +40 -0
  109. sraverify/services/guardduty/__init__.py +58 -0
  110. sraverify/services/guardduty/base.py +207 -0
  111. sraverify/services/guardduty/checks/__init__.py +3 -0
  112. sraverify/services/guardduty/checks/sra_guardduty_01.py +51 -0
  113. sraverify/services/guardduty/checks/sra_guardduty_02.py +80 -0
  114. sraverify/services/guardduty/checks/sra_guardduty_03.py +77 -0
  115. sraverify/services/guardduty/checks/sra_guardduty_04.py +84 -0
  116. sraverify/services/guardduty/checks/sra_guardduty_05.py +84 -0
  117. sraverify/services/guardduty/checks/sra_guardduty_06.py +84 -0
  118. sraverify/services/guardduty/checks/sra_guardduty_07.py +85 -0
  119. sraverify/services/guardduty/checks/sra_guardduty_08.py +83 -0
  120. sraverify/services/guardduty/checks/sra_guardduty_09.py +84 -0
  121. sraverify/services/guardduty/checks/sra_guardduty_10.py +83 -0
  122. sraverify/services/guardduty/checks/sra_guardduty_11.py +93 -0
  123. sraverify/services/guardduty/checks/sra_guardduty_12.py +83 -0
  124. sraverify/services/guardduty/checks/sra_guardduty_13.py +90 -0
  125. sraverify/services/guardduty/checks/sra_guardduty_14.py +136 -0
  126. sraverify/services/guardduty/checks/sra_guardduty_15.py +94 -0
  127. sraverify/services/guardduty/checks/sra_guardduty_16.py +94 -0
  128. sraverify/services/guardduty/checks/sra_guardduty_17.py +91 -0
  129. sraverify/services/guardduty/checks/sra_guardduty_18.py +91 -0
  130. sraverify/services/guardduty/checks/sra_guardduty_19.py +91 -0
  131. sraverify/services/guardduty/checks/sra_guardduty_20.py +111 -0
  132. sraverify/services/guardduty/checks/sra_guardduty_21.py +112 -0
  133. sraverify/services/guardduty/checks/sra_guardduty_22.py +111 -0
  134. sraverify/services/guardduty/checks/sra_guardduty_23.py +154 -0
  135. sraverify/services/guardduty/checks/sra_guardduty_24.py +111 -0
  136. sraverify/services/guardduty/checks/sra_guardduty_25.py +111 -0
  137. sraverify/services/guardduty/client.py +107 -0
  138. sraverify/services/inspector/__init__.py +29 -0
  139. sraverify/services/inspector/base.py +233 -0
  140. sraverify/services/inspector/checks/__init__.py +3 -0
  141. sraverify/services/inspector/checks/sra_inspector_01.py +69 -0
  142. sraverify/services/inspector/checks/sra_inspector_02.py +68 -0
  143. sraverify/services/inspector/checks/sra_inspector_03.py +68 -0
  144. sraverify/services/inspector/checks/sra_inspector_04.py +70 -0
  145. sraverify/services/inspector/checks/sra_inspector_05.py +69 -0
  146. sraverify/services/inspector/checks/sra_inspector_06.py +115 -0
  147. sraverify/services/inspector/checks/sra_inspector_07.py +109 -0
  148. sraverify/services/inspector/checks/sra_inspector_08.py +69 -0
  149. sraverify/services/inspector/checks/sra_inspector_09.py +69 -0
  150. sraverify/services/inspector/checks/sra_inspector_10.py +69 -0
  151. sraverify/services/inspector/checks/sra_inspector_11.py +69 -0
  152. sraverify/services/inspector/client.py +99 -0
  153. sraverify/services/macie/__init__.py +27 -0
  154. sraverify/services/macie/base.py +271 -0
  155. sraverify/services/macie/checks/__init__.py +1 -0
  156. sraverify/services/macie/checks/sra_macie_01.py +100 -0
  157. sraverify/services/macie/checks/sra_macie_02.py +102 -0
  158. sraverify/services/macie/checks/sra_macie_03.py +152 -0
  159. sraverify/services/macie/checks/sra_macie_04.py +120 -0
  160. sraverify/services/macie/checks/sra_macie_05.py +85 -0
  161. sraverify/services/macie/checks/sra_macie_06.py +124 -0
  162. sraverify/services/macie/checks/sra_macie_07.py +138 -0
  163. sraverify/services/macie/checks/sra_macie_08.py +82 -0
  164. sraverify/services/macie/checks/sra_macie_09.py +103 -0
  165. sraverify/services/macie/checks/sra_macie_10.py +81 -0
  166. sraverify/services/macie/client.py +220 -0
  167. sraverify/services/s3/__init__.py +16 -0
  168. sraverify/services/s3/base.py +69 -0
  169. sraverify/services/s3/checks/__init__.py +1 -0
  170. sraverify/services/s3/checks/sra_s3_01.py +89 -0
  171. sraverify/services/s3/checks/sra_s3_02.py +89 -0
  172. sraverify/services/s3/checks/sra_s3_03.py +88 -0
  173. sraverify/services/s3/checks/sra_s3_04.py +88 -0
  174. sraverify/services/s3/client.py +52 -0
  175. sraverify/services/securityhub/__init__.py +27 -0
  176. sraverify/services/securityhub/base.py +349 -0
  177. sraverify/services/securityhub/checks/__init__.py +1 -0
  178. sraverify/services/securityhub/checks/sra_securityhub_01.py +115 -0
  179. sraverify/services/securityhub/checks/sra_securityhub_02.py +114 -0
  180. sraverify/services/securityhub/checks/sra_securityhub_03.py +136 -0
  181. sraverify/services/securityhub/checks/sra_securityhub_04.py +75 -0
  182. sraverify/services/securityhub/checks/sra_securityhub_05.py +102 -0
  183. sraverify/services/securityhub/checks/sra_securityhub_06.py +113 -0
  184. sraverify/services/securityhub/checks/sra_securityhub_07.py +121 -0
  185. sraverify/services/securityhub/checks/sra_securityhub_08.py +113 -0
  186. sraverify/services/securityhub/checks/sra_securityhub_09.py +100 -0
  187. sraverify/services/securityhub/checks/sra_securityhub_10.py +94 -0
  188. sraverify/services/securityhub/checks/sra_securityhub_11.py +73 -0
  189. sraverify/services/securityhub/client.py +249 -0
  190. sraverify/services/securityincidentresponse/__init__.py +13 -0
  191. sraverify/services/securityincidentresponse/base.py +95 -0
  192. sraverify/services/securityincidentresponse/checks/__init__.py +1 -0
  193. sraverify/services/securityincidentresponse/checks/sra_securityincidentresponse_01.py +77 -0
  194. sraverify/services/securityincidentresponse/checks/sra_securityincidentresponse_02.py +72 -0
  195. sraverify/services/securityincidentresponse/checks/sra_securityincidentresponse_03.py +86 -0
  196. sraverify/services/securityincidentresponse/checks/sra_securityincidentresponse_04.py +117 -0
  197. sraverify/services/securityincidentresponse/checks/sra_securityincidentresponse_05.py +55 -0
  198. sraverify/services/securityincidentresponse/client.py +71 -0
  199. sraverify/services/securitylake/__init__.py +39 -0
  200. sraverify/services/securitylake/base.py +461 -0
  201. sraverify/services/securitylake/checks/__init__.py +1 -0
  202. sraverify/services/securitylake/checks/sra_securitylake_01.py +98 -0
  203. sraverify/services/securitylake/checks/sra_securitylake_02.py +133 -0
  204. sraverify/services/securitylake/checks/sra_securitylake_03.py +116 -0
  205. sraverify/services/securitylake/checks/sra_securitylake_04.py +72 -0
  206. sraverify/services/securitylake/checks/sra_securitylake_05.py +116 -0
  207. sraverify/services/securitylake/checks/sra_securitylake_06.py +104 -0
  208. sraverify/services/securitylake/checks/sra_securitylake_07.py +108 -0
  209. sraverify/services/securitylake/checks/sra_securitylake_08.py +107 -0
  210. sraverify/services/securitylake/checks/sra_securitylake_09.py +107 -0
  211. sraverify/services/securitylake/checks/sra_securitylake_10.py +106 -0
  212. sraverify/services/securitylake/checks/sra_securitylake_11.py +109 -0
  213. sraverify/services/securitylake/checks/sra_securitylake_12.py +108 -0
  214. sraverify/services/securitylake/checks/sra_securitylake_13.py +108 -0
  215. sraverify/services/securitylake/checks/sra_securitylake_14.py +72 -0
  216. sraverify/services/securitylake/checks/sra_securitylake_15.py +120 -0
  217. sraverify/services/securitylake/checks/sra_securitylake_16.py +104 -0
  218. sraverify/services/securitylake/checks/sra_securitylake_17.py +103 -0
  219. sraverify/services/securitylake/client.py +247 -0
  220. sraverify/services/shield/__init__.py +33 -0
  221. sraverify/services/shield/base.py +199 -0
  222. sraverify/services/shield/checks/__init__.py +1 -0
  223. sraverify/services/shield/checks/sra_shield_01.py +68 -0
  224. sraverify/services/shield/checks/sra_shield_02.py +77 -0
  225. sraverify/services/shield/checks/sra_shield_03.py +84 -0
  226. sraverify/services/shield/checks/sra_shield_04.py +84 -0
  227. sraverify/services/shield/checks/sra_shield_05.py +84 -0
  228. sraverify/services/shield/checks/sra_shield_06.py +84 -0
  229. sraverify/services/shield/checks/sra_shield_07.py +84 -0
  230. sraverify/services/shield/checks/sra_shield_08.py +69 -0
  231. sraverify/services/shield/checks/sra_shield_09.py +86 -0
  232. sraverify/services/shield/checks/sra_shield_10.py +100 -0
  233. sraverify/services/shield/checks/sra_shield_11.py +71 -0
  234. sraverify/services/shield/checks/sra_shield_12.py +130 -0
  235. sraverify/services/shield/checks/sra_shield_13.py +112 -0
  236. sraverify/services/shield/checks/sra_shield_14.py +111 -0
  237. sraverify/services/shield/client.py +214 -0
  238. sraverify/services/waf/__init__.py +21 -0
  239. sraverify/services/waf/base.py +100 -0
  240. sraverify/services/waf/checks/__init__.py +1 -0
  241. sraverify/services/waf/checks/sra_waf_01.py +63 -0
  242. sraverify/services/waf/checks/sra_waf_02.py +82 -0
  243. sraverify/services/waf/checks/sra_waf_03.py +123 -0
  244. sraverify/services/waf/checks/sra_waf_04.py +94 -0
  245. sraverify/services/waf/checks/sra_waf_05.py +94 -0
  246. sraverify/services/waf/checks/sra_waf_06.py +91 -0
  247. sraverify/services/waf/checks/sra_waf_07.py +94 -0
  248. sraverify/services/waf/checks/sra_waf_08.py +66 -0
  249. sraverify/services/waf/checks/sra_waf_09.py +95 -0
  250. sraverify/services/waf/client.py +109 -0
  251. sraverify/utils/__init__.py +3 -0
  252. sraverify/utils/banner.py +65 -0
  253. sraverify/utils/outputs.py +57 -0
  254. sraverify/utils/progress.py +97 -0
  255. sraverify-0.1.0.dist-info/LICENSE +175 -0
  256. sraverify-0.1.0.dist-info/METADATA +516 -0
  257. sraverify-0.1.0.dist-info/NOTICE +1 -0
  258. sraverify-0.1.0.dist-info/RECORD +261 -0
  259. sraverify-0.1.0.dist-info/WHEEL +5 -0
  260. sraverify-0.1.0.dist-info/entry_points.txt +2 -0
  261. sraverify-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,71 @@
1
+ from typing import Dict, List, Any
2
+ from sraverify.services.firewallmanager.base import FirewallManagerCheck
3
+
4
+ class SRA_FIREWALLMANAGER_10(FirewallManagerCheck):
5
+ def __init__(self):
6
+ super().__init__()
7
+ self.check_id = "SRA-FIREWALLMANAGER-10"
8
+ self.check_name = "Firewall Manager policy cleanup is enabled"
9
+ self.description = "Verifies that AWS Firewall Manager policies have cleanup enabled to remove protections from resources that leave policy scope"
10
+ self.severity = "MEDIUM"
11
+ self.check_logic = "Calls list_policies() per region and checks that policies have DeleteUnusedFMManagedResources set to true"
12
+
13
+ def execute(self) -> List[Dict[str, Any]]:
14
+ for region in self.regions:
15
+ policies_response = self.list_policies(region)
16
+
17
+ if "Error" in policies_response:
18
+ self.findings.append(self.create_finding(
19
+ status="ERROR",
20
+ region=region,
21
+ resource_id=None,
22
+ actual_value=policies_response["Error"].get("Message", "Unknown error"),
23
+ remediation="Check IAM permissions for Firewall Manager API access"
24
+ ))
25
+ continue
26
+
27
+ policies = policies_response.get("PolicyList", [])
28
+
29
+ if not policies:
30
+ self.findings.append(self.create_finding(
31
+ status="PASS",
32
+ region=region,
33
+ resource_id=None,
34
+ actual_value="No Firewall Manager policies configured in region",
35
+ remediation="No remediation needed"
36
+ ))
37
+ continue
38
+
39
+ for policy in policies:
40
+ policy_id = policy.get("PolicyId", "")
41
+ policy_name = policy.get("PolicyName", "Unknown")
42
+ security_service_type = policy.get("SecurityServiceType", "")
43
+ cleanup_enabled = policy.get("DeleteUnusedFMManagedResources", False)
44
+
45
+ # Shield Advanced and WAF Classic don't support cleanup
46
+ if security_service_type in ["SHIELD_ADVANCED", "WAF"]:
47
+ self.findings.append(self.create_finding(
48
+ status="PASS",
49
+ region=region,
50
+ resource_id=policy_id,
51
+ actual_value=f"Policy '{policy_name}' ({security_service_type}) does not support cleanup",
52
+ remediation="No remediation needed - cleanup not available for this policy type"
53
+ ))
54
+ elif not cleanup_enabled:
55
+ self.findings.append(self.create_finding(
56
+ status="FAIL",
57
+ region=region,
58
+ resource_id=policy_id,
59
+ actual_value=f"Policy '{policy_name}' has cleanup disabled",
60
+ remediation=f"Enable cleanup on policy '{policy_name}' to automatically remove protections from out-of-scope resources"
61
+ ))
62
+ else:
63
+ self.findings.append(self.create_finding(
64
+ status="PASS",
65
+ region=region,
66
+ resource_id=policy_id,
67
+ actual_value=f"Policy '{policy_name}' has cleanup enabled",
68
+ remediation="No remediation needed"
69
+ ))
70
+
71
+ return self.findings
@@ -0,0 +1,40 @@
1
+ from typing import Dict, Any, Optional
2
+ import boto3
3
+ from botocore.exceptions import ClientError
4
+ from sraverify.core.logging import logger
5
+
6
+ class FirewallManagerClient:
7
+ def __init__(self, region: str, session: Optional[boto3.Session] = None):
8
+ self.region = region
9
+ self.session = session or boto3.Session()
10
+ self.client = self.session.client('fms', region_name=region)
11
+
12
+ def get_admin_account(self) -> Dict[str, Any]:
13
+ try:
14
+ return self.client.get_admin_account()
15
+ except ClientError as e:
16
+ error_code = e.response.get('Error', {}).get('Code', '')
17
+ if error_code == 'ResourceNotFoundException':
18
+ return {"Error": {"Message": "No Firewall Manager administrator account configured"}}
19
+ logger.error(f"Error getting Firewall Manager admin account: {e}")
20
+ return {"Error": {"Message": str(e)}}
21
+
22
+ def list_policies(self) -> Dict[str, Any]:
23
+ try:
24
+ policies = []
25
+ next_token = None
26
+ while True:
27
+ if next_token:
28
+ response = self.client.list_policies(NextToken=next_token, MaxResults=100)
29
+ else:
30
+ response = self.client.list_policies(MaxResults=100)
31
+
32
+ policies.extend(response.get('PolicyList', []))
33
+ next_token = response.get('NextToken')
34
+ if not next_token:
35
+ break
36
+
37
+ return {"PolicyList": policies}
38
+ except ClientError as e:
39
+ logger.error(f"Error listing Firewall Manager policies in {self.region}: {e}")
40
+ return {"Error": {"Message": str(e)}}
@@ -0,0 +1,58 @@
1
+ """
2
+ GuardDuty security checks.
3
+ """
4
+ from sraverify.services.guardduty.checks.sra_guardduty_01 import SRA_GUARDDUTY_01
5
+ from sraverify.services.guardduty.checks.sra_guardduty_02 import SRA_GUARDDUTY_02
6
+ from sraverify.services.guardduty.checks.sra_guardduty_03 import SRA_GUARDDUTY_03
7
+ from sraverify.services.guardduty.checks.sra_guardduty_04 import SRA_GUARDDUTY_04
8
+ from sraverify.services.guardduty.checks.sra_guardduty_05 import SRA_GUARDDUTY_05
9
+ from sraverify.services.guardduty.checks.sra_guardduty_06 import SRA_GUARDDUTY_06
10
+ from sraverify.services.guardduty.checks.sra_guardduty_07 import SRA_GUARDDUTY_07
11
+ from sraverify.services.guardduty.checks.sra_guardduty_08 import SRA_GUARDDUTY_08
12
+ from sraverify.services.guardduty.checks.sra_guardduty_09 import SRA_GUARDDUTY_09
13
+ from sraverify.services.guardduty.checks.sra_guardduty_10 import SRA_GUARDDUTY_10
14
+ from sraverify.services.guardduty.checks.sra_guardduty_11 import SRA_GUARDDUTY_11
15
+ from sraverify.services.guardduty.checks.sra_guardduty_12 import SRA_GUARDDUTY_12
16
+ from sraverify.services.guardduty.checks.sra_guardduty_13 import SRA_GUARDDUTY_13
17
+ from sraverify.services.guardduty.checks.sra_guardduty_14 import SRA_GUARDDUTY_14
18
+ from sraverify.services.guardduty.checks.sra_guardduty_15 import SRA_GUARDDUTY_15
19
+ from sraverify.services.guardduty.checks.sra_guardduty_16 import SRA_GUARDDUTY_16
20
+ from sraverify.services.guardduty.checks.sra_guardduty_17 import SRA_GUARDDUTY_17
21
+ from sraverify.services.guardduty.checks.sra_guardduty_18 import SRA_GUARDDUTY_18
22
+ from sraverify.services.guardduty.checks.sra_guardduty_19 import SRA_GUARDDUTY_19
23
+ from sraverify.services.guardduty.checks.sra_guardduty_20 import SRA_GUARDDUTY_20
24
+ from sraverify.services.guardduty.checks.sra_guardduty_21 import SRA_GUARDDUTY_21
25
+ from sraverify.services.guardduty.checks.sra_guardduty_22 import SRA_GUARDDUTY_22
26
+ from sraverify.services.guardduty.checks.sra_guardduty_23 import SRA_GUARDDUTY_23
27
+ from sraverify.services.guardduty.checks.sra_guardduty_24 import SRA_GUARDDUTY_24
28
+ from sraverify.services.guardduty.checks.sra_guardduty_25 import SRA_GUARDDUTY_25
29
+
30
+ # Map check IDs to check classes for easy lookup
31
+ CHECKS = {
32
+ "SRA-GUARDDUTY-01": SRA_GUARDDUTY_01,
33
+ "SRA-GUARDDUTY-02": SRA_GUARDDUTY_02,
34
+ "SRA-GUARDDUTY-03": SRA_GUARDDUTY_03,
35
+ "SRA-GUARDDUTY-04": SRA_GUARDDUTY_04,
36
+ "SRA-GUARDDUTY-05": SRA_GUARDDUTY_05,
37
+ "SRA-GUARDDUTY-06": SRA_GUARDDUTY_06,
38
+ "SRA-GUARDDUTY-07": SRA_GUARDDUTY_07,
39
+ "SRA-GUARDDUTY-08": SRA_GUARDDUTY_08,
40
+ "SRA-GUARDDUTY-09": SRA_GUARDDUTY_09,
41
+ "SRA-GUARDDUTY-10": SRA_GUARDDUTY_10,
42
+ "SRA-GUARDDUTY-11": SRA_GUARDDUTY_11,
43
+ "SRA-GUARDDUTY-12": SRA_GUARDDUTY_12,
44
+ "SRA-GUARDDUTY-13": SRA_GUARDDUTY_13,
45
+ "SRA-GUARDDUTY-14": SRA_GUARDDUTY_14,
46
+ "SRA-GUARDDUTY-15": SRA_GUARDDUTY_15,
47
+ "SRA-GUARDDUTY-16": SRA_GUARDDUTY_16,
48
+ "SRA-GUARDDUTY-17": SRA_GUARDDUTY_17,
49
+ "SRA-GUARDDUTY-18": SRA_GUARDDUTY_18,
50
+ "SRA-GUARDDUTY-19": SRA_GUARDDUTY_19,
51
+ "SRA-GUARDDUTY-20": SRA_GUARDDUTY_20,
52
+ "SRA-GUARDDUTY-21": SRA_GUARDDUTY_21,
53
+ "SRA-GUARDDUTY-22": SRA_GUARDDUTY_22,
54
+ "SRA-GUARDDUTY-23": SRA_GUARDDUTY_23,
55
+ "SRA-GUARDDUTY-24": SRA_GUARDDUTY_24,
56
+ "SRA-GUARDDUTY-25": SRA_GUARDDUTY_25
57
+ # Add more checks here as they are implemented
58
+ }
@@ -0,0 +1,207 @@
1
+ """
2
+ Base class for GuardDuty security checks.
3
+ """
4
+ from typing import List, Optional, Dict, Any
5
+ from sraverify.core.check import SecurityCheck
6
+ from sraverify.services.guardduty.client import GuardDutyClient
7
+ from sraverify.core.logging import logger
8
+
9
+
10
+ class GuardDutyCheck(SecurityCheck):
11
+ """Base class for all GuardDuty security checks."""
12
+
13
+ # Class-level caches shared across all instances
14
+ _detector_details_cache = {}
15
+ _detector_ids_cache = {}
16
+ _org_config_cache = {}
17
+ _admin_accounts_cache = {}
18
+
19
+ def __init__(self):
20
+ """Initialize GuardDuty base check."""
21
+ super().__init__(
22
+ account_type="application",
23
+ service="GuardDuty",
24
+ resource_type="AWS::GuardDuty::Detector"
25
+ )
26
+
27
+ def _setup_clients(self):
28
+ """Set up GuardDuty clients for each region."""
29
+ # Clear existing clients
30
+ self._clients.clear()
31
+ # Set up new clients only if regions are initialized
32
+ if hasattr(self, 'regions') and self.regions:
33
+ for region in self.regions:
34
+ self._clients[region] = GuardDutyClient(region, session=self.session)
35
+
36
+ def get_detector_id(self, region: str) -> Optional[str]:
37
+ """
38
+ Get detector ID for a specific region with caching.
39
+
40
+ Args:
41
+ region: AWS region name
42
+
43
+ Returns:
44
+ Detector ID if available, None otherwise
45
+ """
46
+ # Check class-level cache
47
+ cache_key = f"{self.session.region_name}:{region}"
48
+ if cache_key in GuardDutyCheck._detector_ids_cache:
49
+ logger.debug(f"GuardDuty: Using cached detector ID for {region}")
50
+ return GuardDutyCheck._detector_ids_cache[cache_key]
51
+
52
+ # Get client
53
+ client = self.get_client(region)
54
+ if not client:
55
+ logger.warning(f"GuardDuty: No GuardDuty client available for region {region}")
56
+ return None
57
+
58
+ # Get detector ID
59
+ logger.debug(f"GuardDuty: Fetching detector ID for {region}")
60
+ detector_id = client.get_detector_id()
61
+
62
+ # Check if detector_id contains an error
63
+ if detector_id and isinstance(detector_id, str) and detector_id.startswith("ERROR:"):
64
+ _, error_code, error_message = detector_id.split(":", 2)
65
+ logger.warning(f"GuardDuty: Error accessing GuardDuty in {region}: {error_code}")
66
+ GuardDutyCheck._detector_ids_cache[cache_key] = None
67
+ return None
68
+
69
+ # Cache the detector ID
70
+ if detector_id:
71
+ logger.debug(f"GuardDuty: Found detector ID {detector_id} for {region}")
72
+ GuardDutyCheck._detector_ids_cache[cache_key] = detector_id
73
+ else:
74
+ logger.debug(f"GuardDuty: No detector ID found for {region}")
75
+
76
+ return detector_id
77
+
78
+ def get_detector_details(self, region: str) -> Dict[str, Any]:
79
+ """
80
+ Get detector details for a specific region.
81
+
82
+ Args:
83
+ region: AWS region name
84
+
85
+ Returns:
86
+ Dictionary containing detector details or empty dict if not available
87
+ """
88
+ # Check if we already have cached details in the class-level cache
89
+ cache_key = f"{self.session.region_name}:{region}" # Include session region to avoid conflicts
90
+ if cache_key in GuardDutyCheck._detector_details_cache:
91
+ logger.debug(f"GuardDuty: Using cached detector details for {region}")
92
+ return GuardDutyCheck._detector_details_cache[cache_key]
93
+
94
+ # Get detector ID
95
+ detector_id = self.get_detector_id(region)
96
+ if not detector_id:
97
+ logger.debug(f"GuardDuty: No detector ID found for region {region}")
98
+ return {}
99
+
100
+ # Get client
101
+ client = self.get_client(region)
102
+ if not client:
103
+ logger.warning(f"GuardDuty: No GuardDuty client available for region {region}")
104
+ return {}
105
+
106
+ # Get detector details
107
+ logger.debug(f"GuardDuty: Getting detector details for {detector_id} in {region}")
108
+ details = client.get_detector_details(detector_id)
109
+
110
+ # Cache the details in the class-level cache
111
+ GuardDutyCheck._detector_details_cache[cache_key] = details
112
+ logger.debug(f"GuardDuty: Cached detector details for {region}")
113
+
114
+ return details
115
+
116
+ def get_organization_configuration(self, region: str) -> Dict[str, Any]:
117
+ """
118
+ Get organization configuration for a specific region.
119
+
120
+ Args:
121
+ region: AWS region name
122
+
123
+ Returns:
124
+ Dictionary containing organization configuration details or empty dict if not available
125
+ """
126
+ # Check if we already have cached org config in the class-level cache
127
+ cache_key = f"{self.session.region_name}:{region}"
128
+ if cache_key in GuardDutyCheck._org_config_cache:
129
+ logger.debug(f"GuardDuty: Using cached organization configuration for {region}")
130
+ return GuardDutyCheck._org_config_cache[cache_key]
131
+
132
+ # Get detector ID
133
+ detector_id = self.get_detector_id(region)
134
+ if not detector_id:
135
+ logger.debug(f"GuardDuty: No detector ID found for region {region}")
136
+ return {}
137
+
138
+ # Get client
139
+ client = self.get_client(region)
140
+ if not client:
141
+ logger.warning(f"GuardDuty: No GuardDuty client available for region {region}")
142
+ return {}
143
+
144
+ # Get organization configuration
145
+ logger.debug(f"GuardDuty: Getting organization configuration for {detector_id} in {region}")
146
+ org_config = client.describe_organization_configuration(detector_id)
147
+
148
+ # Cache the org config in the class-level cache
149
+ GuardDutyCheck._org_config_cache[cache_key] = org_config
150
+ logger.debug(f"GuardDuty: Cached organization configuration for {region}")
151
+
152
+ return org_config
153
+
154
+ def list_organization_admin_accounts(self, region: str) -> Dict[str, Any]:
155
+ """
156
+ List organization admin accounts for GuardDuty.
157
+
158
+ Args:
159
+ region: AWS region name
160
+
161
+ Returns:
162
+ Dictionary containing organization admin accounts details or empty dict if not available
163
+ """
164
+ # Check if we already have cached admin accounts in the class-level cache
165
+ cache_key = f"{self.session.region_name}:{region}"
166
+ if cache_key in GuardDutyCheck._admin_accounts_cache:
167
+ logger.debug(f"GuardDuty: Using cached organization admin accounts for {region}")
168
+ return GuardDutyCheck._admin_accounts_cache[cache_key]
169
+
170
+ # Get client
171
+ client = self.get_client(region)
172
+ if not client:
173
+ logger.warning(f"GuardDuty: No GuardDuty client available for region {region}")
174
+ return {}
175
+
176
+ # List organization admin accounts
177
+ logger.debug(f"GuardDuty: Listing organization admin accounts in {region}")
178
+ admin_accounts = client.list_organization_admin_accounts()
179
+
180
+ # Cache the admin accounts in the class-level cache
181
+ GuardDutyCheck._admin_accounts_cache[cache_key] = admin_accounts
182
+ logger.debug(f"GuardDuty: Cached organization admin accounts for {region}")
183
+
184
+ return admin_accounts
185
+
186
+ def get_enabled_regions(self) -> List[str]:
187
+ """
188
+ Get list of regions where GuardDuty is enabled.
189
+
190
+ Returns:
191
+ List of region names where GuardDuty is enabled
192
+ """
193
+ # If no detector IDs have been discovered yet, try to discover them
194
+ if not any(k.endswith(f":{region}") for k in GuardDutyCheck._detector_ids_cache.keys()
195
+ for region in self.regions):
196
+ logger.debug("GuardDuty: No detector IDs cached, discovering them now")
197
+ for region in self.regions:
198
+ self.get_detector_id(region)
199
+
200
+ # Get regions from the class-level cache that match the current session
201
+ prefix = f"{self.session.region_name}:"
202
+ enabled_regions = [
203
+ key.split(":")[-1] for key in GuardDutyCheck._detector_ids_cache.keys()
204
+ if key.startswith(prefix) and GuardDutyCheck._detector_ids_cache[key] is not None
205
+ ]
206
+
207
+ return enabled_regions
@@ -0,0 +1,3 @@
1
+ """
2
+ GuardDuty security check implementations.
3
+ """
@@ -0,0 +1,51 @@
1
+ """
2
+ Check if GuardDuty detector exists.
3
+ """
4
+ from typing import Dict, List, Any
5
+ from sraverify.services.guardduty.base import GuardDutyCheck
6
+
7
+
8
+ class SRA_GUARDDUTY_01(GuardDutyCheck):
9
+ """Check if GuardDuty detector exists."""
10
+
11
+ def __init__(self):
12
+ """Initialize GuardDuty enabled check."""
13
+ super().__init__()
14
+ self.check_id = "SRA-GUARDDUTY-01"
15
+ self.check_name = "GuardDuty detector exists"
16
+ self.description = "This check verifies that an GuardDuty detector exists in the AWS Region.\
17
+ A detector is a resource that represents the GuardDuty service and should be present \
18
+ in all AWS member account and AWS Region so that GuardDuty can generate findings \
19
+ about unauthorized or unusual activity even in those Regions that you may not \
20
+ be using actively."
21
+ self.severity = "HIGH"
22
+ self.check_logic = "Get detector_id in each Region. Check fails if there is no detector_id"
23
+
24
+ def execute(self) -> List[Dict[str, Any]]:
25
+ """
26
+ Execute the check.
27
+
28
+ Returns:
29
+ List of findings
30
+ """
31
+ for region in self.regions:
32
+ detector_id = self.get_detector_id(region)
33
+
34
+ if not detector_id:
35
+ self.findings.append(self.create_finding(
36
+ status="FAIL",
37
+ region=region,
38
+ resource_id=None,
39
+ actual_value=None,
40
+ remediation=f"Enable GuardDuty in {region}"
41
+ ))
42
+ else:
43
+ self.findings.append(self.create_finding(
44
+ status="PASS",
45
+ region=region,
46
+ resource_id=f"guardduty:{region}:{detector_id}",
47
+ actual_value=None,
48
+ remediation=""
49
+ ))
50
+
51
+ return self.findings
@@ -0,0 +1,80 @@
1
+ """
2
+ Check if GuardDuty finding frequency is set.
3
+ """
4
+ from typing import Dict, List, Any
5
+ from sraverify.services.guardduty.base import GuardDutyCheck
6
+
7
+
8
+ class SRA_GUARDDUTY_02(GuardDutyCheck):
9
+ """Check if GuardDuty finding frequency is set."""
10
+
11
+ def __init__(self):
12
+ """Initialize GuardDuty enabled check."""
13
+ super().__init__()
14
+ self.check_id = "SRA-GUARDDUTY-02"
15
+ self.check_name = "GuardDuty finding frequency is set"
16
+ self.description = ("This check verifies that the GuardDuty finding frequency is set "
17
+ "as per your organization requirement. This determines how often updates to active "
18
+ "findings are exported to EventBridge, S3 (optional) and Detective (optional). "
19
+ "By default, updated findings are exported every 6 hours but you can set to "
20
+ "every 15 minutes or 1 hour.")
21
+ self.severity = "LOW"
22
+ self.check_logic = "Get detector details in each Region. Check value of FindingPublishingFrequency."
23
+
24
+ def execute(self) -> List[Dict[str, Any]]:
25
+ """
26
+ Execute the check.
27
+
28
+ Returns:
29
+ List of findings
30
+ """
31
+ findings = []
32
+ # Check all regions
33
+ for region in self.regions:
34
+ detector_id = self.get_detector_id(region)
35
+
36
+ # Handle regions where we can't access GuardDuty
37
+ if not detector_id:
38
+ findings.append(self.create_finding(
39
+ status="ERROR",
40
+ region=region,
41
+ resource_id=f"guardduty:{region}",
42
+ actual_value="Unable to access GuardDuty in this region",
43
+ remediation="Check permissions or if GuardDuty is supported in this region"
44
+ ))
45
+ continue
46
+
47
+ # Use helper method from the base class
48
+ detector_details = self.get_detector_details(region)
49
+
50
+ if detector_details:
51
+ finding_frequency = detector_details.get('FindingPublishingFrequency', 'Not set')
52
+
53
+ # Determine if the frequency is set to a valid value
54
+ valid_frequencies = ['FIFTEEN_MINUTES', 'ONE_HOUR', 'SIX_HOURS']
55
+ if finding_frequency in valid_frequencies:
56
+ findings.append(self.create_finding(
57
+ status="PASS",
58
+ region=region,
59
+ resource_id=f"guardduty:{region}:{detector_id}",
60
+ actual_value=f"Finding frequency is set to {finding_frequency}",
61
+ remediation="No remediation needed"
62
+ ))
63
+ else:
64
+ findings.append(self.create_finding(
65
+ status="FAIL",
66
+ region=region,
67
+ resource_id=f"guardduty:{region}:{detector_id}",
68
+ actual_value=f"Finding frequency is not properly set: {finding_frequency}",
69
+ remediation="Set GuardDuty finding frequency to FIFTEEN_MINUTES, ONE_HOUR, or SIX_HOURS"
70
+ ))
71
+ else:
72
+ findings.append(self.create_finding(
73
+ status="FAIL",
74
+ region=region,
75
+ resource_id=f"guardduty:{region}:{detector_id}",
76
+ actual_value="Unable to retrieve detector details",
77
+ remediation="Check GuardDuty permissions and configuration"
78
+ ))
79
+
80
+ return findings
@@ -0,0 +1,77 @@
1
+ """
2
+ Check if GuardDuty detector is enabled.
3
+ """
4
+ from typing import Dict, List, Any
5
+ from sraverify.services.guardduty.base import GuardDutyCheck
6
+
7
+
8
+ class SRA_GUARDDUTY_03(GuardDutyCheck):
9
+ """Check if GuardDuty detector is enabled."""
10
+
11
+ def __init__(self):
12
+ """Initialize GuardDuty enabled check."""
13
+ super().__init__()
14
+ self.check_id = "SRA-GUARDDUTY-03"
15
+ self.check_name = "GuardDuty detector is enabled"
16
+ self.description = ("This check verifies that the GuardDuty detector in the "
17
+ "AWS account and AWS region is enabled. Detector represents "
18
+ "GuardDuty service in the AWS account and specific region, "
19
+ "if disabled will not provided threat intelligence service.")
20
+ self.severity = "HIGH"
21
+ self.check_logic = "Get detector details in each Region. Check value of FindingPublishingFrequency."
22
+
23
+ def execute(self) -> List[Dict[str, Any]]:
24
+ """
25
+ Execute the check.
26
+
27
+ Returns:
28
+ List of findings
29
+ """
30
+ findings = []
31
+ # Check all regions
32
+ for region in self.regions:
33
+ detector_id = self.get_detector_id(region)
34
+
35
+ # Handle regions where we can't access GuardDuty
36
+ if not detector_id:
37
+ findings.append(self.create_finding(
38
+ status="ERROR",
39
+ region=region,
40
+ resource_id=f"guardduty:{region}",
41
+ actual_value="Unable to access GuardDuty in this region",
42
+ remediation="Check permissions or if GuardDuty is supported in this region"
43
+ ))
44
+ continue
45
+
46
+ # Use helper method from the base class
47
+ detector_details = self.get_detector_details(region)
48
+
49
+ if detector_details:
50
+ detector_status = detector_details.get('Status', 'Not set')
51
+
52
+ if detector_status == 'ENABLED':
53
+ findings.append(self.create_finding(
54
+ status="PASS",
55
+ region=region,
56
+ resource_id=f"guardduty:{region}:{detector_id}",
57
+ actual_value=f"Detector status is {detector_status}",
58
+ remediation="No remediation needed"
59
+ ))
60
+ else:
61
+ findings.append(self.create_finding(
62
+ status="FAIL",
63
+ region=region,
64
+ resource_id=f"guardduty:{region}:{detector_id}",
65
+ actual_value=f"Detector status is {detector_status}",
66
+ remediation="Enabled GuardDuty"
67
+ ))
68
+ else:
69
+ findings.append(self.create_finding(
70
+ status="FAIL",
71
+ region=region,
72
+ resource_id=f"guardduty:{region}:{detector_id}",
73
+ actual_value="Unable to retrieve detector details",
74
+ remediation="Check GuardDuty permissions and configuration"
75
+ ))
76
+
77
+ return findings
@@ -0,0 +1,84 @@
1
+ """
2
+ Check if GuardDuty has DNS logs enabled as a log source.
3
+ """
4
+ from typing import Dict, List, Any
5
+ from sraverify.services.guardduty.base import GuardDutyCheck
6
+
7
+
8
+ class SRA_GUARDDUTY_04(GuardDutyCheck):
9
+ """Check if GuardDuty has DNS logs enabled as a log source."""
10
+
11
+ def __init__(self):
12
+ """Initialize GuardDuty DNS logs check."""
13
+ super().__init__()
14
+ self.check_id = "SRA-GUARDDUTY-04"
15
+ self.check_name = "GuardDuty DNS logs enabled"
16
+ self.description = ("This check verifies that GuardDuty has DNS logs as one of the log sources, enabled. "
17
+ "If you use AWS DNS resolvers for your Amazon EC2 instances (the default setting), "
18
+ "then GuardDuty can access and process your request and response DNS logs through the "
19
+ "internal AWS DNS resolvers.")
20
+ self.severity = "MEDIUM"
21
+ self.check_logic = "Get detector details in each Region. Check if DNS logs are enabled in the Features array."
22
+
23
+ def execute(self) -> List[Dict[str, Any]]:
24
+ """
25
+ Execute the check.
26
+
27
+ Returns:
28
+ List of findings
29
+ """
30
+ findings = []
31
+ # Check all regions
32
+ for region in self.regions:
33
+ detector_id = self.get_detector_id(region)
34
+
35
+ # Handle regions where we can't access GuardDuty
36
+ if not detector_id:
37
+ findings.append(self.create_finding(
38
+ status="ERROR",
39
+ region=region,
40
+ resource_id=f"guardduty:{region}",
41
+ actual_value="Unable to access GuardDuty in this region",
42
+ remediation="Check permissions or if GuardDuty is supported in this region"
43
+ ))
44
+ continue
45
+
46
+ # Get detector details
47
+ detector_details = self.get_detector_details(region)
48
+
49
+ if detector_details:
50
+ # Check if DNS logs are enabled in the Features array
51
+ dns_logs_enabled = False
52
+ features = detector_details.get('Features', [])
53
+
54
+ for feature in features:
55
+ if feature.get('Name') == 'DNS_LOGS' and feature.get('Status') == 'ENABLED':
56
+ dns_logs_enabled = True
57
+ break
58
+
59
+ if dns_logs_enabled:
60
+ findings.append(self.create_finding(
61
+ status="PASS",
62
+ region=region,
63
+ resource_id=f"guardduty:{region}:{detector_id}",
64
+ actual_value="DNS logs are enabled as a data source",
65
+ remediation=""
66
+ ))
67
+ else:
68
+ findings.append(self.create_finding(
69
+ status="FAIL",
70
+ region=region,
71
+ resource_id=f"guardduty:{region}:{detector_id}",
72
+ actual_value="DNS logs are not enabled as a data source",
73
+ remediation=f"Enable DNS logs as a data source for GuardDuty in {region}"
74
+ ))
75
+ else:
76
+ findings.append(self.create_finding(
77
+ status="FAIL",
78
+ region=region,
79
+ resource_id=f"guardduty:{region}:{detector_id}",
80
+ actual_value="Unable to retrieve detector details",
81
+ remediation="Check GuardDuty permissions and configuration"
82
+ ))
83
+
84
+ return findings