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,123 @@
1
+ """
2
+ SRA-CONFIG-01: AWS Config Recorder Configured.
3
+ """
4
+ from typing import List, Dict, Any
5
+ from sraverify.services.config.base import ConfigCheck
6
+ from sraverify.core.logging import logger
7
+
8
+
9
+ class SRA_CONFIG_01(ConfigCheck):
10
+ """Check if AWS Config recorder is configured in each region."""
11
+
12
+ def __init__(self):
13
+ """Initialize the check."""
14
+ super().__init__()
15
+ self.check_id = "SRA-CONFIG-01"
16
+ self.check_name = "AWS Config recorder is configured in this region"
17
+ self.account_type = "application"
18
+ self.severity = "HIGH"
19
+ self.description = (
20
+ "This check verifies that a configuration recorder exists in the AWS Region. "
21
+ "AWS Config uses the configuration recorder to detect changes in your resource configurations "
22
+ "and capture these changes as configuration items. You must create a configuration recorder "
23
+ "in every AWS Region for AWS Config can track your resource configurations in the region."
24
+ )
25
+ self.check_logic = (
26
+ "Checks if AWS Config recorder exists in each region using describe-configuration-recorder-status API."
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
+ if not self.regions:
39
+ findings.append(
40
+ self.create_finding(
41
+ status="ERROR",
42
+ region="global",
43
+ resource_id="config:global",
44
+ actual_value="No regions specified for check",
45
+ remediation="Specify at least one region when running the check"
46
+ )
47
+ )
48
+ return findings
49
+
50
+ # Check each region for configuration recorder
51
+ for region in self.regions:
52
+ # Get configuration recorders for the region
53
+ recorders = self.get_configuration_recorders(region)
54
+
55
+ # Get configuration recorder status for the region
56
+ recorder_statuses = self.get_configuration_recorder_status(region)
57
+
58
+ if not recorders:
59
+ # No configuration recorder found in this region
60
+ findings.append(
61
+ self.create_finding(
62
+ status="FAIL",
63
+ region=region,
64
+ resource_id=f"arn:aws:config:{region}:{self.account_id}:configurationRecorder/default",
65
+ actual_value="No configuration recorder found in this region",
66
+ remediation=(
67
+ f"1. Check if the AWS Config service-linked role exists: aws iam get-role --role-name AWSServiceRoleForConfig. "
68
+ f"2. If the role doesn't exist, create it: aws iam create-service-linked-role --aws-service-name config.amazonaws.com. "
69
+ f"3. Create a configuration recorder in {region}: aws configservice put-configuration-recorder --configuration-recorder name=default,roleARN=arn:aws:iam::{self.account_id}:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig --recording-group allSupported=true,includeGlobalResourceTypes=true --region {region}"
70
+ )
71
+ )
72
+ )
73
+ else:
74
+ # Configuration recorder exists, check if it's enabled
75
+ recorder_name = recorders[0].get('name', 'default')
76
+ recorder_role_arn = recorders[0].get('roleARN', '')
77
+
78
+ # Construct the Config Recorder ARN
79
+ recorder_arn = f"arn:aws:config:{region}:{self.account_id}:configurationRecorder/{recorder_name}"
80
+
81
+ # Find the status for this recorder
82
+ recorder_status = next((status for status in recorder_statuses if status.get('name') == recorder_name), None)
83
+
84
+ if recorder_status and recorder_status.get('recording', False):
85
+ # Configuration recorder exists and is recording
86
+ findings.append(
87
+ self.create_finding(
88
+ status="PASS",
89
+ region=region,
90
+ resource_id=recorder_arn,
91
+ actual_value=f"Configuration recorder '{recorder_name}' exists and is recording",
92
+ remediation="No remediation needed"
93
+ )
94
+ )
95
+ elif recorder_status:
96
+ # Configuration recorder exists but is not recording
97
+ findings.append(
98
+ self.create_finding(
99
+ status="FAIL",
100
+ region=region,
101
+ resource_id=recorder_arn,
102
+ actual_value=f"Configuration recorder '{recorder_name}' exists but is not recording",
103
+ remediation=(
104
+ f"Start the configuration recorder in {region} using the AWS CLI command: "
105
+ f"aws configservice start-configuration-recorder --configuration-recorder-name {recorder_name} --region {region}"
106
+ )
107
+ )
108
+ )
109
+ else:
110
+ # Configuration recorder exists but no status found
111
+ findings.append(
112
+ self.create_finding(
113
+ status="FAIL",
114
+ region=region,
115
+ resource_id=recorder_arn,
116
+ actual_value=f"Configuration recorder '{recorder_name}' exists but status could not be determined",
117
+ remediation=(
118
+ f"Check the configuration recorder status in {region} and ensure it's properly configured"
119
+ )
120
+ )
121
+ )
122
+
123
+ return findings
@@ -0,0 +1,156 @@
1
+ """
2
+ SRA-CONFIG-02: AWS Config Delivery Channel Configured.
3
+ """
4
+ from typing import List, Dict, Any
5
+ from sraverify.services.config.base import ConfigCheck
6
+ from sraverify.core.logging import logger
7
+
8
+
9
+ class SRA_CONFIG_02(ConfigCheck):
10
+ """Check if AWS Config recorder is running."""
11
+
12
+ def __init__(self):
13
+ """Initialize the check."""
14
+ super().__init__()
15
+ self.check_id = "SRA-CONFIG-02"
16
+ self.check_name = "AWS Config recorder is running"
17
+ self.account_type = "application"
18
+ self.severity = "HIGH"
19
+ self.description = (
20
+ "This check verifies that configuration recorder is running. AWS Config configuration "
21
+ "recorder must be started and running to record resource configurations. If you set up "
22
+ "AWS Config by using the console or the AWS CLI, AWS Config automatically creates and "
23
+ "then starts the configuration recorder for you. Users with right permission have the "
24
+ "ability to stop configuration recorder."
25
+ )
26
+ self.check_logic = (
27
+ "Checks if AWS Config recorder is running by verifying the lastStatus is SUCCESS."
28
+ )
29
+
30
+ def execute(self) -> List[Dict[str, Any]]:
31
+ """
32
+ Execute the check.
33
+
34
+ Returns:
35
+ List of findings
36
+ """
37
+ findings = []
38
+
39
+ if not self.regions:
40
+ findings.append(
41
+ self.create_finding(
42
+ status="ERROR",
43
+ region="global",
44
+ resource_id="config:global",
45
+ actual_value="No regions specified for check",
46
+ remediation="Specify at least one region when running the check"
47
+ )
48
+ )
49
+ return findings
50
+
51
+ # Check each region for configuration recorder status
52
+ for region in self.regions:
53
+ # Get configuration recorders for the region
54
+ recorders = self.get_configuration_recorders(region)
55
+
56
+ # Get configuration recorder status for the region
57
+ recorder_statuses = self.get_configuration_recorder_status(region)
58
+
59
+ if not recorders:
60
+ # No configuration recorder found in this region
61
+ findings.append(
62
+ self.create_finding(
63
+ status="FAIL",
64
+ region=region,
65
+ resource_id=f"arn:aws:config:{region}:{self.account_id}:configurationRecorder/default",
66
+ actual_value="No configuration recorder found in this region",
67
+ remediation=(
68
+ f"First create a configuration recorder in {region} using: aws configservice put-configuration-recorder --configuration-recorder name=default,roleARN=arn:aws:iam::{self.account_id}:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig --recording-group allSupported=true,includeGlobalResourceTypes=true --region {region}. "
69
+ f"Then start the recorder with: aws configservice start-configuration-recorder --configuration-recorder-name default --region {region}"
70
+ )
71
+ )
72
+ )
73
+ continue
74
+
75
+ # Configuration recorder exists, check if it's running
76
+ recorder_name = recorders[0].get('name', 'default')
77
+
78
+ # Find the status for this recorder
79
+ recorder_status = next((status for status in recorder_statuses if status.get('name') == recorder_name), None)
80
+
81
+ # Get the full ARN from the status if available
82
+ recorder_arn = None
83
+ if recorder_status and 'arn' in recorder_status:
84
+ recorder_arn = recorder_status.get('arn')
85
+ else:
86
+ # Construct the Config Recorder ARN if not available in status
87
+ recorder_arn = f"arn:aws:config:{region}:{self.account_id}:configurationRecorder/{recorder_name}"
88
+
89
+ if not recorder_status:
90
+ # No status found for this recorder
91
+ findings.append(
92
+ self.create_finding(
93
+ status="FAIL",
94
+ region=region,
95
+ resource_id=recorder_arn,
96
+ actual_value=f"Configuration recorder '{recorder_name}' exists but status could not be determined",
97
+ remediation=(
98
+ f"Check the configuration recorder status in {region} and ensure it's properly configured"
99
+ )
100
+ )
101
+ )
102
+ continue
103
+
104
+ # Check if the recorder is recording
105
+ is_recording = recorder_status.get('recording', False)
106
+ last_status = recorder_status.get('lastStatus', 'UNKNOWN')
107
+ last_error_code = recorder_status.get('lastErrorCode', '')
108
+ last_error_message = recorder_status.get('lastErrorMessage', '')
109
+
110
+ if is_recording and last_status == "SUCCESS":
111
+ # Configuration recorder is running successfully
112
+ findings.append(
113
+ self.create_finding(
114
+ status="PASS",
115
+ region=region,
116
+ resource_id=recorder_arn,
117
+ actual_value=f"Configuration recorder '{recorder_name}' is running with lastStatus: SUCCESS",
118
+ remediation="No remediation needed"
119
+ )
120
+ )
121
+ elif is_recording:
122
+ # Configuration recorder is recording but not in SUCCESS state
123
+ error_info = f"lastStatus: {last_status}"
124
+ if last_error_code:
125
+ error_info += f", errorCode: {last_error_code}"
126
+ if last_error_message:
127
+ error_info += f", errorMessage: {last_error_message}"
128
+
129
+ findings.append(
130
+ self.create_finding(
131
+ status="FAIL",
132
+ region=region,
133
+ resource_id=recorder_arn,
134
+ actual_value=f"Configuration recorder '{recorder_name}' is recording but has issues: {error_info}",
135
+ remediation=(
136
+ f"Check the AWS Config logs and permissions in {region}. "
137
+ f"Ensure the Config service role has the necessary permissions to record resources."
138
+ )
139
+ )
140
+ )
141
+ else:
142
+ # Configuration recorder is not recording
143
+ findings.append(
144
+ self.create_finding(
145
+ status="FAIL",
146
+ region=region,
147
+ resource_id=recorder_arn,
148
+ actual_value=f"Configuration recorder '{recorder_name}' is not recording",
149
+ remediation=(
150
+ f"Start the configuration recorder in {region} using the AWS CLI command: "
151
+ f"aws configservice start-configuration-recorder --configuration-recorder-name {recorder_name} --region {region}"
152
+ )
153
+ )
154
+ )
155
+
156
+ return findings
@@ -0,0 +1,149 @@
1
+ """
2
+ SRA-CONFIG-03: AWS Config Recording All Resource Types.
3
+ """
4
+ from typing import List, Dict, Any
5
+ from sraverify.services.config.base import ConfigCheck
6
+ from sraverify.core.logging import logger
7
+
8
+
9
+ class SRA_CONFIG_03(ConfigCheck):
10
+ """Check if AWS Config latest recording event is processed successfully."""
11
+
12
+ def __init__(self):
13
+ """Initialize the check."""
14
+ super().__init__()
15
+ self.check_id = "SRA-CONFIG-03"
16
+ self.check_name = "AWS Config latest recording event is processed successfully"
17
+ self.account_type = "application" # This check applies to all account types
18
+ self.severity = "HIGH"
19
+ self.description = (
20
+ "This check verifies whether the last delivery attempt to the delivery channel was successful "
21
+ "to ensure you receive configuration change notifications. As AWS Config continually records "
22
+ "the changes that occur to your AWS resources, it sends notifications and updated configuration "
23
+ "states through the delivery channel."
24
+ )
25
+ self.check_logic = (
26
+ "Checks if the lastStatus of the delivery channel is SUCCESS."
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
+ if not self.regions:
39
+ findings.append(
40
+ self.create_finding(
41
+ status="ERROR",
42
+ region="global",
43
+ resource_id="config:global",
44
+ actual_value="No regions specified for check",
45
+ remediation="Specify at least one region when running the check"
46
+ )
47
+ )
48
+ return findings
49
+
50
+ # Check each region for delivery channel status
51
+ for region in self.regions:
52
+ # Get delivery channels for the region
53
+ channels = self.get_delivery_channels(region)
54
+
55
+ # Get delivery channel status for the region
56
+ channel_statuses = self.get_delivery_channel_status(region)
57
+
58
+ if not channels:
59
+ # No delivery channel found in this region
60
+ findings.append(
61
+ self.create_finding(
62
+ status="FAIL",
63
+ region=region,
64
+ resource_id=f"arn:aws:config:{region}:{self.account_id}:deliveryChannel/default",
65
+ actual_value="No delivery channel found in this region",
66
+ remediation=(
67
+ f"Create a delivery channel in {region} using: aws configservice put-delivery-channel --delivery-channel name=default,s3BucketName=config-bucket-{self.account_id},snsTopicARN=arn:aws:sns:{region}:{self.account_id}:config-notifications --region {region}. "
68
+ f"Note: You must first create an S3 bucket and SNS topic with appropriate permissions for AWS Config."
69
+ )
70
+ )
71
+ )
72
+ continue
73
+
74
+ if not channel_statuses:
75
+ # No delivery channel status found in this region
76
+ findings.append(
77
+ self.create_finding(
78
+ status="FAIL",
79
+ region=region,
80
+ resource_id=f"arn:aws:config:{region}:{self.account_id}:deliveryChannel/default",
81
+ actual_value="No delivery channel status found in this region",
82
+ remediation=(
83
+ f"Check the delivery channel configuration in {region} and ensure it's properly configured. "
84
+ f"Verify S3 bucket permissions and SNS topic permissions are correctly set up for AWS Config."
85
+ )
86
+ )
87
+ )
88
+ continue
89
+
90
+ # Check each delivery channel status
91
+ for status in channel_statuses:
92
+ channel_name = status.get('name', 'default')
93
+ resource_id = f"config:deliveryChannel:{channel_name}"
94
+
95
+ # Check configHistoryDeliveryInfo - this is the most important one
96
+ history_info = status.get('configHistoryDeliveryInfo', {})
97
+ history_status = history_info.get('lastStatus', 'UNKNOWN')
98
+ history_attempt_time = history_info.get('lastAttemptTime', 'UNKNOWN')
99
+ history_success_time = history_info.get('lastSuccessfulTime', 'UNKNOWN')
100
+
101
+ # Check configSnapshotDeliveryInfo - may be UNKNOWN if no snapshot has been taken yet
102
+ snapshot_info = status.get('configSnapshotDeliveryInfo', {})
103
+ snapshot_status = snapshot_info.get('lastStatus', 'UNKNOWN')
104
+
105
+ # Check configStreamDeliveryInfo - may be NOT_APPLICABLE if streaming is not configured
106
+ stream_info = status.get('configStreamDeliveryInfo', {})
107
+ stream_status = stream_info.get('lastStatus', 'UNKNOWN')
108
+
109
+ # Determine overall status - focus on history delivery as the primary indicator
110
+ # Stream may be NOT_APPLICABLE and snapshot may be UNKNOWN if not configured/used
111
+ if history_status == "SUCCESS":
112
+ # History delivery is successful, which is the most important
113
+ findings.append(
114
+ self.create_finding(
115
+ status="PASS",
116
+ region=region,
117
+ resource_id=resource_id,
118
+ actual_value=(
119
+ f"Delivery channel '{channel_name}' is processing events successfully: "
120
+ f"Config History: {history_status} (Last success: {history_success_time}), "
121
+ f"Config Snapshot: {snapshot_status}, "
122
+ f"Config Stream: {stream_status}"
123
+ ),
124
+ remediation="No remediation needed"
125
+ )
126
+ )
127
+ else:
128
+ # History delivery is not successful
129
+ findings.append(
130
+ self.create_finding(
131
+ status="FAIL",
132
+ region=region,
133
+ resource_id=resource_id,
134
+ actual_value=(
135
+ f"Delivery channel '{channel_name}' has issues processing events: "
136
+ f"Config History: {history_status} (Last attempt: {history_attempt_time}), "
137
+ f"Config Snapshot: {snapshot_status}, "
138
+ f"Config Stream: {stream_status}"
139
+ ),
140
+ remediation=(
141
+ "Check the following: 1. S3 bucket permissions - ensure Config has write access. "
142
+ "2. SNS topic permissions - ensure Config can publish to the topic. "
143
+ "3. IAM role permissions - ensure Config service role has necessary permissions. "
144
+ "4. Check CloudWatch Logs for Config service errors."
145
+ )
146
+ )
147
+ )
148
+
149
+ return findings
@@ -0,0 +1,104 @@
1
+ """
2
+ SRA-CONFIG-04: AWS Config Recording Global Resources.
3
+ """
4
+ from typing import List, Dict, Any
5
+ from sraverify.services.config.base import ConfigCheck
6
+ from sraverify.core.logging import logger
7
+
8
+
9
+ class SRA_CONFIG_04(ConfigCheck):
10
+ """Check if AWS Config has an organization aggregator."""
11
+
12
+ def __init__(self):
13
+ """Initialize the check."""
14
+ super().__init__()
15
+ self.check_id = "SRA-CONFIG-04"
16
+ self.check_name = "AWS Config has organization aggregator"
17
+ self.account_type = "audit" # This check applies to audit account
18
+ self.severity = "HIGH"
19
+ self.description = (
20
+ "This check verifies that a AWS Config aggregator exists in the AWS Region that collects "
21
+ "configuration and compliance data from all member accounts of the AWS Organization. "
22
+ "It periodically retrieves configuration snapshots from the source accounts and stores "
23
+ "them in the designated S3 bucket."
24
+ )
25
+ self.check_logic = (
26
+ "Checks if AWS Config aggregator exists using describe-configuration-aggregators API."
27
+ )
28
+ self.resource_type = "AWS::Config::ConfigurationAggregator"
29
+
30
+ def execute(self) -> List[Dict[str, Any]]:
31
+ """
32
+ Execute the check.
33
+
34
+ Returns:
35
+ List of findings
36
+ """
37
+ findings = []
38
+
39
+ if not self.regions:
40
+ findings.append(
41
+ self.create_finding(
42
+ status="ERROR",
43
+ region="global",
44
+ resource_id="config:global",
45
+ checked_value="Configuration aggregator exists",
46
+ actual_value="No regions specified for check",
47
+ remediation="Specify at least one region when running the check"
48
+ )
49
+ )
50
+ return findings
51
+
52
+ # Check if an organization aggregator exists in any region
53
+ found_org_aggregator = False
54
+ org_aggregator_region = None
55
+ org_aggregator_name = None
56
+ org_aggregator_arn = None
57
+
58
+ for region in self.regions:
59
+ # Get configuration aggregators for the region using the cache
60
+ aggregators = self.get_configuration_aggregators(region)
61
+
62
+ # Check if any of the aggregators is an organization aggregator
63
+ for aggregator in aggregators:
64
+ if 'OrganizationAggregationSource' in aggregator:
65
+ found_org_aggregator = True
66
+ org_aggregator_region = region
67
+ org_aggregator_name = aggregator.get('ConfigurationAggregatorName', 'Unknown')
68
+ org_aggregator_arn = aggregator.get('ConfigurationAggregatorArn',
69
+ f"arn:aws:config:{region}:{self.account_id}:config-aggregator/{org_aggregator_name}")
70
+ break
71
+
72
+ if found_org_aggregator:
73
+ break
74
+
75
+ # Return a single finding based on whether an organization aggregator was found
76
+ if found_org_aggregator:
77
+ findings.append(
78
+ self.create_finding(
79
+ status="PASS",
80
+ region="global",
81
+ resource_id=org_aggregator_arn,
82
+ checked_value="Configuration aggregator exists",
83
+ actual_value=f"Configuration aggregator '{org_aggregator_name}' exists in region {org_aggregator_region} with Source Type \"My Organization\"",
84
+ remediation="No remediation needed"
85
+ )
86
+ )
87
+ else:
88
+ findings.append(
89
+ self.create_finding(
90
+ status="FAIL",
91
+ region="global",
92
+ resource_id=f"arn:aws:config:global:{self.account_id}:config-aggregator/none",
93
+ checked_value="Configuration aggregator exists",
94
+ actual_value="No organization aggregator found in any region",
95
+ remediation=(
96
+ "Create an organization configuration aggregator in at least one region using: aws configservice put-configuration-aggregator "
97
+ "--configuration-aggregator-name organization-aggregator --organization-aggregation-source "
98
+ f"\"EnableAllRegions=true,RoleArn=arn:aws:iam::{self.account_id}:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfigServiceRole\" "
99
+ "--region <region>"
100
+ )
101
+ )
102
+ )
103
+
104
+ return findings
@@ -0,0 +1,104 @@
1
+ """
2
+ SRA-CONFIG-05: AWS Config Recorder Status.
3
+ """
4
+ from typing import List, Dict, Any
5
+ from sraverify.services.config.base import ConfigCheck
6
+ from sraverify.core.logging import logger
7
+
8
+
9
+ class SRA_CONFIG_05(ConfigCheck):
10
+ """Check if AWS Config organization aggregator includes all regions."""
11
+
12
+ def __init__(self):
13
+ """Initialize the check."""
14
+ super().__init__()
15
+ self.check_id = "SRA-CONFIG-05"
16
+ self.check_name = "AWS Config organization aggregator includes all regions"
17
+ self.account_type = "audit" # This check applies to audit account
18
+ self.severity = "MEDIUM"
19
+ self.description = (
20
+ "This check verifies that the AWS Config organization aggregator is configured to aggregate "
21
+ "config data from all existing and future AWS Regions. This provides you visibility into "
22
+ "activities across all regions even if your business does not operate in the region."
23
+ )
24
+ self.check_logic = (
25
+ "Checks if AWS Config organization aggregator has AllAwsRegions set to true."
26
+ )
27
+ self.resource_type = "AWS::Config::ConfigurationAggregator"
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
+ if not self.regions:
39
+ findings.append(
40
+ self.create_finding(
41
+ status="ERROR",
42
+ region="global",
43
+ resource_id="config:global",
44
+ checked_value="AllAwsRegions: true",
45
+ actual_value="No regions specified for check",
46
+ remediation="Specify at least one region when running the check"
47
+ )
48
+ )
49
+ return findings
50
+
51
+ # Check if an organization aggregator with AllAwsRegions=true exists in any region
52
+ found_all_regions_aggregator = False
53
+ all_regions_aggregator_region = None
54
+ all_regions_aggregator_name = None
55
+ all_regions_aggregator_arn = None
56
+
57
+ for region in self.regions:
58
+ # Get configuration aggregators for the region from cache
59
+ aggregators = self.get_configuration_aggregators(region)
60
+
61
+ # Check if any of the aggregators is an organization aggregator with all regions enabled
62
+ for aggregator in aggregators:
63
+ if ('OrganizationAggregationSource' in aggregator and
64
+ aggregator.get('OrganizationAggregationSource', {}).get('AllAwsRegions', False)):
65
+ found_all_regions_aggregator = True
66
+ all_regions_aggregator_region = region
67
+ all_regions_aggregator_name = aggregator.get('ConfigurationAggregatorName', 'Unknown')
68
+ all_regions_aggregator_arn = aggregator.get('ConfigurationAggregatorArn',
69
+ f"arn:aws:config:{region}:{self.account_id}:config-aggregator/{all_regions_aggregator_name}")
70
+ break
71
+
72
+ if found_all_regions_aggregator:
73
+ break
74
+
75
+ # Return a single finding based on whether an organization aggregator with AllAwsRegions=true was found
76
+ if found_all_regions_aggregator:
77
+ findings.append(
78
+ self.create_finding(
79
+ status="PASS",
80
+ region="global",
81
+ resource_id=all_regions_aggregator_arn,
82
+ checked_value="AllAwsRegions: true",
83
+ actual_value=f"Configuration aggregator '{all_regions_aggregator_name}' is configured to aggregate all regions, located in region {all_regions_aggregator_region} with Region selection \"All current and future AWS regions\"",
84
+ remediation="No remediation needed"
85
+ )
86
+ )
87
+ else:
88
+ findings.append(
89
+ self.create_finding(
90
+ status="FAIL",
91
+ region="global",
92
+ resource_id=f"arn:aws:config:global:{self.account_id}:config-aggregator/none",
93
+ checked_value="AllAwsRegions: true",
94
+ actual_value="No organization aggregator with AllAwsRegions=true found in any region",
95
+ remediation=(
96
+ "Create an organization configuration aggregator with AllAwsRegions=true in at least one region using: aws configservice put-configuration-aggregator "
97
+ "--configuration-aggregator-name organization-aggregator --organization-aggregation-source "
98
+ f"\"EnableAllRegions=true,RoleArn=arn:aws:iam::{self.account_id}:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfigServiceRole\" "
99
+ "--region <region>"
100
+ )
101
+ )
102
+ )
103
+
104
+ return findings