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,77 @@
1
+ """
2
+ SRA-CLOUDTRAIL-12: CloudTrail Delegated Administrator Configuration.
3
+ """
4
+ from typing import List, Dict, Any
5
+ from sraverify.services.cloudtrail.base import CloudTrailCheck
6
+ from sraverify.core.logging import logger
7
+
8
+
9
+ class SRA_CLOUDTRAIL_12(CloudTrailCheck):
10
+ """Check if CloudTrail service administration is delegated out of AWS Organization management account."""
11
+
12
+ def __init__(self):
13
+ """Initialize the check."""
14
+ super().__init__()
15
+ self.check_id = "SRA-CLOUDTRAIL-12"
16
+ self.check_name = "Delegated Administrator set for CloudTrail"
17
+ self.account_type = "management"
18
+ self.severity = "MEDIUM"
19
+ self.description = (
20
+ "This check verifies whether CloudTrail service administration is delegated out of AWS Organization "
21
+ "management account. The delegated administrator has permissions to create and manage analyzers "
22
+ "with the AWS organization as the zone of trust."
23
+ )
24
+ self.check_logic = (
25
+ "Check if there is at least one delegated administrator for CloudTrail service."
26
+ )
27
+
28
+ def execute(self) -> List[Dict[str, Any]]:
29
+ """
30
+ Execute the check.
31
+
32
+ Returns:
33
+ List of findings
34
+ """
35
+ findings = []
36
+
37
+ # Get delegated administrators for CloudTrail
38
+ # This will use the cache if available or make API calls if needed
39
+ delegated_admins = self.get_delegated_administrators()
40
+
41
+ if not delegated_admins:
42
+ findings.append(
43
+ self.create_finding(
44
+ status="FAIL",
45
+ region="global",
46
+ resource_id=f"organization/{self.account_id}",
47
+ checked_value="At least one delegated administrator for CloudTrail",
48
+ actual_value="No delegated administrator configured for CloudTrail",
49
+ remediation=(
50
+ "Register a delegated administrator for CloudTrail using the AWS CLI command: "
51
+ "aws organizations register-delegated-administrator "
52
+ "--account-id ACCOUNT_ID --service-principal cloudtrail.amazonaws.com"
53
+ )
54
+ )
55
+ )
56
+ return findings
57
+
58
+ # If we have delegated administrators, create a PASS finding for each one
59
+ for admin in delegated_admins:
60
+ admin_id = admin.get('Id', 'Unknown')
61
+ admin_name = admin.get('Name', 'Unknown')
62
+
63
+ # Create a resource ID that includes the delegated admin info
64
+ resource_id = f"cloudtrail arn has delegated administrator set to {admin_id}"
65
+
66
+ findings.append(
67
+ self.create_finding(
68
+ status="PASS",
69
+ region="global",
70
+ resource_id=resource_id,
71
+ checked_value="At least one delegated administrator for CloudTrail",
72
+ actual_value=f"CloudTrail has delegated administrator: {admin_id} ({admin_name})",
73
+ remediation="No remediation needed"
74
+ )
75
+ )
76
+
77
+ return findings
@@ -0,0 +1,120 @@
1
+ """
2
+ SRA-CLOUDTRAIL-13: CloudTrail Delegated Administrator is the Audit Account.
3
+ """
4
+ from typing import List, Dict, Any
5
+ from sraverify.services.cloudtrail.base import CloudTrailCheck
6
+ from sraverify.core.logging import logger
7
+
8
+
9
+ class SRA_CLOUDTRAIL_13(CloudTrailCheck):
10
+ """Check if CloudTrail delegated administrator is the Audit account."""
11
+
12
+ def __init__(self):
13
+ """Initialize the check."""
14
+ super().__init__()
15
+ self.check_id = "SRA-CLOUDTRAIL-13"
16
+ self.check_name = "The audit account is the Delegated Administrator set for CloudTrail"
17
+ self.account_type = "management"
18
+ self.severity = "HIGH"
19
+ self.description = (
20
+ "This check verifies whether CloudTrail delegated admin account is the audit account of your AWS organization. "
21
+ "Audit account is dedicated to operating security services, monitoring AWS accounts, and "
22
+ "automating security alerting and response. CloudTrail helps monitor API activities across "
23
+ "all your AWS accounts and regions."
24
+ )
25
+ self.check_logic = (
26
+ "Check if the delegated administrator account matches any of the specified Audit account IDs."
27
+ )
28
+
29
+ def execute(self) -> List[Dict[str, Any]]:
30
+ """
31
+ Execute the check.
32
+
33
+ Returns:
34
+ List of findings
35
+ """
36
+ findings = []
37
+
38
+ # Get delegated administrators for CloudTrail
39
+ # This will use the cache if available or make API calls if needed
40
+ delegated_admins = self.get_delegated_administrators()
41
+
42
+ if not delegated_admins:
43
+ findings.append(
44
+ self.create_finding(
45
+ status="FAIL",
46
+ region="global",
47
+ resource_id=f"organization/{self.account_id}",
48
+ checked_value="CloudTrail delegated administrator is an Audit account",
49
+ actual_value="No delegated administrator configured for CloudTrail",
50
+ remediation=(
51
+ "Register an Audit account as delegated administrator for CloudTrail using the AWS CLI command: "
52
+ "aws organizations register-delegated-administrator "
53
+ "--account-id AUDIT_ACCOUNT_ID --service-principal cloudtrail.amazonaws.com"
54
+ )
55
+ )
56
+ )
57
+ return findings
58
+
59
+ # Check if audit_accounts is provided via _audit_accounts attribute
60
+ audit_accounts = []
61
+ if hasattr(self, '_audit_accounts') and self._audit_accounts:
62
+ audit_accounts = self._audit_accounts
63
+
64
+ if not audit_accounts:
65
+ findings.append(
66
+ self.create_finding(
67
+ status="ERROR",
68
+ region="global",
69
+ resource_id=f"organization/{self.account_id}",
70
+ checked_value="CloudTrail delegated administrator is an Audit account",
71
+ actual_value="Audit Account ID not provided",
72
+ remediation="Provide the Audit account IDs using --audit-account flag"
73
+ )
74
+ )
75
+ return findings
76
+
77
+ # Check if any of the delegated administrators is an Audit account
78
+ for admin in delegated_admins:
79
+ admin_id = admin.get('Id', 'Unknown')
80
+ admin_name = admin.get('Name', 'Unknown')
81
+
82
+ # Create a resource ID that includes the delegated admin and audit account info
83
+ resource_id = f"cloudtrail arn has delegated administrator set to {admin_id}, audit account is {audit_accounts[0]}, {admin_id in audit_accounts}"
84
+
85
+ if admin_id in audit_accounts:
86
+ # This delegated admin is in the audit accounts list
87
+ findings.append(
88
+ self.create_finding(
89
+ status="PASS",
90
+ region="global",
91
+ resource_id=resource_id,
92
+ checked_value=f"CloudTrail delegated administrator is an Audit account ({', '.join(audit_accounts)})",
93
+ actual_value=f"CloudTrail delegated administrator {admin_id} ({admin_name}) is an Audit account",
94
+ remediation="No remediation needed"
95
+ )
96
+ )
97
+ else:
98
+ # This delegated admin is not in the audit accounts list
99
+ findings.append(
100
+ self.create_finding(
101
+ status="FAIL",
102
+ region="global",
103
+ resource_id=resource_id,
104
+ checked_value=f"CloudTrail delegated administrator is an Audit account ({', '.join(audit_accounts)})",
105
+ actual_value=(
106
+ f"CloudTrail delegated administrator {admin_id} ({admin_name}) "
107
+ f"is not in the specified Audit accounts ({', '.join(audit_accounts)})"
108
+ ),
109
+ remediation=(
110
+ "Deregister the current delegated administrator and register an Audit account "
111
+ "as delegated administrator for CloudTrail using the AWS CLI commands: "
112
+ f"aws organizations deregister-delegated-administrator "
113
+ f"--account-id {admin_id} --service-principal cloudtrail.amazonaws.com && "
114
+ "aws organizations register-delegated-administrator "
115
+ f"--account-id {audit_accounts[0]} --service-principal cloudtrail.amazonaws.com"
116
+ )
117
+ )
118
+ )
119
+
120
+ return findings
@@ -0,0 +1,118 @@
1
+ """
2
+ CloudTrail client for interacting with AWS CloudTrail service.
3
+ """
4
+ from typing import Dict, List, Optional, Any
5
+ import boto3
6
+ from botocore.exceptions import ClientError
7
+ from sraverify.core.logging import logger
8
+
9
+
10
+ class CloudTrailClient:
11
+ """Client for interacting with AWS CloudTrail service."""
12
+
13
+ def __init__(self, region: str, session: Optional[boto3.Session] = None):
14
+ """
15
+ Initialize CloudTrail client for a specific region.
16
+
17
+ Args:
18
+ region: AWS region name
19
+ session: AWS session to use (if None, a new session will be created)
20
+ """
21
+ self.region = region
22
+ self.session = session or boto3.Session()
23
+ self.client = self.session.client('cloudtrail', region_name=region)
24
+ self.org_client = self.session.client('organizations', region_name=region)
25
+
26
+ def describe_trails(self, trail_name_list: Optional[List[str]] = None, include_shadow_trails: bool = True) -> List[Dict[str, Any]]:
27
+ """
28
+ Describe one or more trails.
29
+
30
+ Args:
31
+ trail_name_list: List of trail names to describe (if None, all trails are described)
32
+ include_shadow_trails: Include shadow trails in the response
33
+
34
+ Returns:
35
+ List of trail descriptions
36
+ """
37
+ try:
38
+ params = {}
39
+ if trail_name_list:
40
+ params['trailNameList'] = trail_name_list
41
+ params['includeShadowTrails'] = include_shadow_trails
42
+
43
+ logger.debug(f"Describing trails in {self.region} with params: {params}")
44
+ response = self.client.describe_trails(**params)
45
+ return response.get('trailList', [])
46
+ except ClientError as e:
47
+ logger.error(f"Error describing trails in {self.region}: {e}")
48
+ return []
49
+ except Exception as e:
50
+ logger.error(f"Unexpected error describing trails in {self.region}: {e}")
51
+ return []
52
+
53
+ def get_trail_status(self, trail_arn: str) -> Dict[str, Any]:
54
+ """
55
+ Get the status of a trail.
56
+
57
+ Args:
58
+ trail_arn: ARN of the trail
59
+
60
+ Returns:
61
+ Trail status
62
+ """
63
+ try:
64
+ logger.debug(f"Getting status for trail {trail_arn} in {self.region}")
65
+ response = self.client.get_trail_status(Name=trail_arn)
66
+ return response
67
+ except ClientError as e:
68
+ logger.error(f"Error getting trail status for {trail_arn} in {self.region}: {e}")
69
+ return {}
70
+ except Exception as e:
71
+ logger.error(f"Unexpected error getting trail status for {trail_arn} in {self.region}: {e}")
72
+ return {}
73
+
74
+ def list_delegated_administrators(self, service_principal: str = "cloudtrail.amazonaws.com") -> List[Dict[str, Any]]:
75
+ """
76
+ List delegated administrators for CloudTrail.
77
+
78
+ Args:
79
+ service_principal: Service principal to check for delegated administrators
80
+
81
+ Returns:
82
+ List of delegated administrators
83
+ """
84
+ try:
85
+ logger.debug(f"Listing delegated administrators for {service_principal} in {self.region}")
86
+ response = self.org_client.list_delegated_administrators(ServicePrincipal=service_principal)
87
+ delegated_admins = response.get('DelegatedAdministrators', [])
88
+ logger.debug(f"Found {len(delegated_admins)} delegated administrators for {service_principal}")
89
+ for admin in delegated_admins:
90
+ logger.debug(f"Delegated admin: {admin.get('Id')} - {admin.get('Name')}")
91
+ return delegated_admins
92
+ except ClientError as e:
93
+ logger.error(f"Error listing delegated administrators for {service_principal}: {e}")
94
+ return []
95
+ except Exception as e:
96
+ logger.error(f"Unexpected error listing delegated administrators: {e}")
97
+ return []
98
+
99
+ def get_account_id(self) -> Optional[str]:
100
+ """
101
+ Get the current account ID.
102
+
103
+ Returns:
104
+ Current account ID or None if not available
105
+ """
106
+ try:
107
+ logger.debug(f"Getting current account ID in {self.region}")
108
+ sts_client = self.session.client("sts")
109
+ response = sts_client.get_caller_identity()
110
+ account_id = response["Account"]
111
+ logger.debug(f"Current account ID: {account_id}")
112
+ return account_id
113
+ except ClientError as e:
114
+ logger.error(f"Error getting current account ID: {e}")
115
+ return None
116
+ except Exception as e:
117
+ logger.error(f"Unexpected error getting current account ID: {e}")
118
+ return None
@@ -0,0 +1,25 @@
1
+ """
2
+ AWS Config security checks.
3
+ """
4
+ from sraverify.services.config.checks.sra_config_01 import SRA_CONFIG_01
5
+ from sraverify.services.config.checks.sra_config_02 import SRA_CONFIG_02
6
+ from sraverify.services.config.checks.sra_config_03 import SRA_CONFIG_03
7
+ from sraverify.services.config.checks.sra_config_04 import SRA_CONFIG_04
8
+ from sraverify.services.config.checks.sra_config_05 import SRA_CONFIG_05
9
+ from sraverify.services.config.checks.sra_config_06 import SRA_CONFIG_06
10
+ from sraverify.services.config.checks.sra_config_07 import SRA_CONFIG_07
11
+ from sraverify.services.config.checks.sra_config_08 import SRA_CONFIG_08
12
+ from sraverify.services.config.checks.sra_config_09 import SRA_CONFIG_09
13
+
14
+ # Register checks
15
+ CHECKS = {
16
+ "SRA-CONFIG-01": SRA_CONFIG_01,
17
+ "SRA-CONFIG-02": SRA_CONFIG_02,
18
+ "SRA-CONFIG-03": SRA_CONFIG_03,
19
+ "SRA-CONFIG-04": SRA_CONFIG_04,
20
+ "SRA-CONFIG-05": SRA_CONFIG_05,
21
+ "SRA-CONFIG-06": SRA_CONFIG_06,
22
+ "SRA-CONFIG-07": SRA_CONFIG_07,
23
+ "SRA-CONFIG-08": SRA_CONFIG_08,
24
+ "SRA-CONFIG-09": SRA_CONFIG_09,
25
+ }
@@ -0,0 +1,249 @@
1
+ """
2
+ Base class for AWS Config security checks.
3
+ """
4
+ from typing import List, Optional, Dict, Any
5
+ from sraverify.core.check import SecurityCheck
6
+ from sraverify.services.config.client import ConfigClient
7
+ from sraverify.core.logging import logger
8
+
9
+
10
+ class ConfigCheck(SecurityCheck):
11
+ """Base class for all AWS Config security checks."""
12
+
13
+ # Class-level caches shared across all instances
14
+ _config_recorder_status_cache = {}
15
+ _config_delivery_channel_status_cache = {}
16
+ _config_organization_aggregator = {}
17
+ _config_delivery_channel_cache = {}
18
+ _config_delegated_admin_cache = {}
19
+
20
+ # Config service principals
21
+ CONFIG_SERVICE_PRINCIPALS = [
22
+ "config.amazonaws.com",
23
+ "config-multiaccountsetup.amazonaws.com"
24
+ ]
25
+
26
+ def __init__(self):
27
+ """Initialize Config base check."""
28
+ super().__init__(
29
+ account_type="account", # Default to account, can be overridden in child classes
30
+ service="Config",
31
+ resource_type="AWS::Config::ConfigurationRecorder"
32
+ )
33
+
34
+ def _setup_clients(self):
35
+ """Set up Config clients for each region."""
36
+ # Clear existing clients
37
+ self._clients.clear()
38
+ # Set up new clients only if regions are initialized
39
+ if hasattr(self, 'regions') and self.regions:
40
+ for region in self.regions:
41
+ self._clients[region] = ConfigClient(region, session=self.session)
42
+
43
+ def get_client(self, region: str) -> Optional[ConfigClient]:
44
+ """
45
+ Get Config client for a specific region.
46
+
47
+ Args:
48
+ region: AWS region name
49
+
50
+ Returns:
51
+ ConfigClient for the region or None if not available
52
+ """
53
+ return self._clients.get(region)
54
+
55
+ def get_configuration_recorders(self, region: str) -> List[Dict[str, Any]]:
56
+ """
57
+ Get configuration recorders for a specific region.
58
+
59
+ Args:
60
+ region: AWS region name
61
+
62
+ Returns:
63
+ List of configuration recorders
64
+ """
65
+ # Get client for the region
66
+ client = self.get_client(region)
67
+ if not client:
68
+ logger.warning(f"No Config client available for region {region}")
69
+ return []
70
+
71
+ # Get configuration recorders from client
72
+ recorders = client.describe_configuration_recorders()
73
+ logger.debug(f"Found {len(recorders)} configuration recorders for {region}")
74
+
75
+ return recorders
76
+
77
+ def get_configuration_recorder_status(self, region: str) -> List[Dict[str, Any]]:
78
+ """
79
+ Get configuration recorder status for a specific region with caching.
80
+
81
+ Args:
82
+ region: AWS region name
83
+
84
+ Returns:
85
+ List of configuration recorder statuses
86
+ """
87
+ # Check cache first
88
+ cache_key = f"{region}:{self.session.region_name}"
89
+ if cache_key in self.__class__._config_recorder_status_cache:
90
+ logger.debug(f"Using cached configuration recorder status for {region}")
91
+ return self.__class__._config_recorder_status_cache[cache_key]
92
+
93
+ # Get client for the region
94
+ client = self.get_client(region)
95
+ if not client:
96
+ logger.warning(f"No Config client available for region {region}")
97
+ return []
98
+
99
+ # Get configuration recorder status from client
100
+ statuses = client.describe_configuration_recorder_status()
101
+
102
+ # Cache the results - store the complete response
103
+ self.__class__._config_recorder_status_cache[cache_key] = statuses
104
+ logger.debug(f"Cached {len(statuses)} configuration recorder statuses for {region}")
105
+
106
+ return statuses
107
+
108
+ def get_delivery_channels(self, region: str) -> List[Dict[str, Any]]:
109
+ """
110
+ Get delivery channels for a specific region.
111
+
112
+ Args:
113
+ region: AWS region name
114
+
115
+ Returns:
116
+ List of delivery channels
117
+ """
118
+ # Check cache first
119
+ cache_key = f"{region}:{self.session.region_name}"
120
+ if cache_key in self.__class__._config_delivery_channel_cache:
121
+ logger.debug(f"Using cached delivery channels for {region}")
122
+ return self.__class__._config_delivery_channel_cache[cache_key]
123
+
124
+ # Get client for the region
125
+ client = self.get_client(region)
126
+ if not client:
127
+ logger.warning(f"No Config client available for region {region}")
128
+ return []
129
+
130
+ # Get delivery channels from client
131
+ channels = client.describe_delivery_channels()
132
+
133
+ # Cache the results
134
+ self.__class__._config_delivery_channel_cache[cache_key] = channels
135
+ logger.debug(f"Cached {len(channels)} delivery channels for {region}")
136
+
137
+ return channels
138
+
139
+ def get_delivery_channel_status(self, region: str) -> List[Dict[str, Any]]:
140
+ """
141
+ Get delivery channel status for a specific region with caching.
142
+
143
+ Args:
144
+ region: AWS region name
145
+
146
+ Returns:
147
+ List of delivery channel statuses
148
+ """
149
+ # Check cache first
150
+ cache_key = f"{region}:{self.session.region_name}"
151
+ if cache_key in self.__class__._config_delivery_channel_status_cache:
152
+ logger.debug(f"Using cached delivery channel status for {region}")
153
+ return self.__class__._config_delivery_channel_status_cache[cache_key]
154
+
155
+ # Get client for the region
156
+ client = self.get_client(region)
157
+ if not client:
158
+ logger.warning(f"No Config client available for region {region}")
159
+ return []
160
+
161
+ # Get delivery channel status from client
162
+ statuses = client.describe_delivery_channel_status()
163
+
164
+ # Cache the results - store the complete response
165
+ self.__class__._config_delivery_channel_status_cache[cache_key] = statuses
166
+ logger.debug(f"Cached {len(statuses)} delivery channel statuses for {region}")
167
+
168
+ return statuses
169
+
170
+ def get_configuration_aggregators(self, region: str) -> List[Dict[str, Any]]:
171
+ """
172
+ Get configuration aggregators for a specific region with caching.
173
+
174
+ Args:
175
+ region: AWS region name
176
+
177
+ Returns:
178
+ List of configuration aggregators
179
+ """
180
+ # Check cache first
181
+ cache_key = f"{region}:{self.session.region_name}"
182
+ if cache_key in self.__class__._config_organization_aggregator:
183
+ logger.debug(f"Using cached configuration aggregators for {region}")
184
+ return self.__class__._config_organization_aggregator[cache_key]
185
+
186
+ # Get client for the region
187
+ client = self.get_client(region)
188
+ if not client:
189
+ logger.warning(f"No Config client available for region {region}")
190
+ return []
191
+
192
+ # Get configuration aggregators from client
193
+ aggregators = client.describe_configuration_aggregators()
194
+
195
+ # Cache the results
196
+ self.__class__._config_organization_aggregator[cache_key] = aggregators
197
+ logger.debug(f"Cached {len(aggregators)} configuration aggregators for {region}")
198
+
199
+ return aggregators
200
+
201
+ def get_delegated_administrators(self, service_principal=None) -> List[Dict[str, Any]]:
202
+ """
203
+ Get Config delegated administrators with caching.
204
+
205
+ Args:
206
+ service_principal: Optional specific service principal to check
207
+
208
+ Returns:
209
+ List of delegated administrators
210
+ """
211
+ if not self.regions:
212
+ logger.warning("No regions specified")
213
+ return []
214
+
215
+ account_id = self.account_id
216
+ if not account_id:
217
+ logger.warning("Could not determine account ID")
218
+ return []
219
+
220
+ # If a specific service principal is provided, only check that one
221
+ service_principals = [service_principal] if service_principal else self.CONFIG_SERVICE_PRINCIPALS
222
+
223
+ all_delegated_admins = []
224
+
225
+ for sp in service_principals:
226
+ # Check cache first
227
+ cache_key = f"{account_id}:{self.session.region_name}:{sp}"
228
+ if cache_key in self.__class__._config_delegated_admin_cache:
229
+ logger.debug(f"Using cached delegated administrators for {cache_key}")
230
+ admins = self.__class__._config_delegated_admin_cache[cache_key]
231
+ all_delegated_admins.extend(admins)
232
+ continue
233
+
234
+ # Use any region to get delegated administrators
235
+ client = self.get_client(self.regions[0])
236
+ if not client:
237
+ logger.warning("No Config client available")
238
+ continue
239
+
240
+ # Get delegated administrators from client
241
+ delegated_admins = client.list_delegated_administrators(sp)
242
+
243
+ # Cache the results
244
+ self.__class__._config_delegated_admin_cache[cache_key] = delegated_admins
245
+ logger.debug(f"Cached {len(delegated_admins)} delegated administrators for {cache_key}")
246
+
247
+ all_delegated_admins.extend(delegated_admins)
248
+
249
+ return all_delegated_admins
@@ -0,0 +1 @@
1
+ """Config checks package."""