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,133 @@
1
+ """Check if Security Lake SQS queues are encrypted with CMK."""
2
+
3
+ from typing import List, Dict, Any
4
+ from sraverify.services.securitylake.base import SecurityLakeCheck
5
+ from sraverify.core.logging import logger
6
+
7
+
8
+ class SRA_SECURITYLAKE_02(SecurityLakeCheck):
9
+ """Check if Security Lake SQS queues are encrypted with CMK."""
10
+
11
+ def __init__(self):
12
+ """Initialize check."""
13
+ super().__init__()
14
+ self.check_id = "SRA-SECURITYLAKE-02"
15
+ self.check_name = "Security Lake SQS queues encrypted with CMK"
16
+ self.severity = "HIGH"
17
+ self.description = (
18
+ "This check verifies whether Security Lake manager SQS Queues within "
19
+ "delegated admin account is encrypted with a customer managed key from "
20
+ "AWS KMS. These SQS queues are used by AWS Lambda function for ETL job "
21
+ "and also by subscribers looking for new logs deposited into the data lake. "
22
+ "You must use a customer managed KMS key for the encryption as you have "
23
+ "greater control on the key usage and permission."
24
+ )
25
+ self.check_logic = (
26
+ "Gets all subscribers for Security Lake in the region. "
27
+ "For each subscriber with an SQS endpoint, checks if the queue is encrypted with a customer managed KMS key. "
28
+ "The check passes if all SQS queues are encrypted with customer managed keys (not AWS managed keys). "
29
+ "The check fails if any SQS queue is not encrypted or uses an AWS managed key (alias/aws/*)."
30
+ )
31
+
32
+ def execute(self) -> List[Dict[str, Any]]:
33
+ """
34
+ Execute the check.
35
+
36
+ Returns:
37
+ List of findings
38
+ """
39
+
40
+ for region in self.regions:
41
+ logger.debug(f"Checking if Security Lake SQS queues are encrypted with CMK in {region}")
42
+
43
+ # Get subscribers for the region using the base class method
44
+ subscribers = self.get_subscribers(region)
45
+
46
+ # Find SQS queues
47
+ sqs_queues = []
48
+ for subscriber in subscribers:
49
+ endpoint = subscriber.get("subscriberEndpoint", "")
50
+ if endpoint and "sqs" in endpoint.lower():
51
+ # Convert ARN to queue URL if needed
52
+ if endpoint.startswith("arn:aws:sqs:"):
53
+ # Extract components from ARN: arn:aws:sqs:region:account:queue-name
54
+ arn_parts = endpoint.split(":")
55
+ if len(arn_parts) >= 6:
56
+ queue_region = arn_parts[3]
57
+ account_id = arn_parts[4]
58
+ queue_name = arn_parts[5]
59
+ queue_url = f"https://sqs.{queue_region}.amazonaws.com/{account_id}/{queue_name}"
60
+ else:
61
+ continue
62
+ else:
63
+ queue_url = endpoint
64
+ queue_name = queue_url.split("/")[-1]
65
+
66
+ sqs_queues.append((queue_name, queue_url))
67
+
68
+ if not subscribers or not sqs_queues:
69
+ resource_id = f"arn:aws:securitylake:{region}:{self.account_id}:subscriber/none"
70
+ self.findings.append(
71
+ self.create_finding(
72
+ status="FAIL",
73
+ region=region,
74
+ resource_id=resource_id,
75
+ checked_value="SQS queues present and encrypted with CMK",
76
+ actual_value=f"No SQS queues found in {region}",
77
+ remediation=(
78
+ "Configure subscribers with SQS queues. In the Security Lake console, "
79
+ "navigate to Subscribers and add subscribers with SQS queue endpoints."
80
+ )
81
+ )
82
+ )
83
+ continue
84
+
85
+ # Check encryption for each queue
86
+ unencrypted_queues = []
87
+ for queue_name, queue_url in sqs_queues:
88
+ resource_id = f"arn:aws:sqs:{region}:{self.account_id}:{queue_name}"
89
+
90
+ # Check encryption using base class method
91
+ kms_key = self.get_sqs_queue_encryption(region, queue_url)
92
+
93
+ if not kms_key or kms_key.startswith("alias/aws/"):
94
+ unencrypted_queues.append((queue_name, queue_url))
95
+
96
+ if unencrypted_queues:
97
+ # Use the first unencrypted queue for the resource ID
98
+ queue_name = unencrypted_queues[0][0]
99
+ resource_id = f"arn:aws:sqs:{region}:{self.account_id}:{queue_name}"
100
+
101
+ logger.debug(f"Found {len(unencrypted_queues)} unencrypted SQS queues in {region}")
102
+ self.findings.append(
103
+ self.create_finding(
104
+ status="FAIL",
105
+ region=region,
106
+ resource_id=resource_id,
107
+ checked_value="All SQS queues encrypted with CMK",
108
+ actual_value=f"The following SQS queues are not encrypted with CMK: {', '.join([name for name, _ in unencrypted_queues])}",
109
+ remediation=(
110
+ "Configure SQS queue encryption with a customer managed KMS key. In the SQS console, "
111
+ "select each queue and under Server-side encryption, choose 'Enable server-side encryption' "
112
+ "and select a customer managed KMS key."
113
+ )
114
+ )
115
+ )
116
+ else:
117
+ # Use the first queue for the resource ID in the PASS case
118
+ queue_name = sqs_queues[0][0]
119
+ resource_id = f"arn:aws:sqs:{region}:{self.account_id}:{queue_name}"
120
+
121
+ logger.debug(f"All Security Lake SQS queues are encrypted with CMK in {region}")
122
+ self.findings.append(
123
+ self.create_finding(
124
+ status="PASS",
125
+ region=region,
126
+ resource_id=resource_id,
127
+ checked_value="All SQS queues encrypted with CMK",
128
+ actual_value=f"All Security Lake SQS queues are encrypted with CMK in {region}",
129
+ remediation="No remediation needed"
130
+ )
131
+ )
132
+
133
+ return self.findings
@@ -0,0 +1,116 @@
1
+ """Check if Security Lake SQS DLQ is encrypted with CMK."""
2
+
3
+ from typing import List, Dict, Any
4
+ from sraverify.services.securitylake.base import SecurityLakeCheck
5
+ from sraverify.core.logging import logger
6
+
7
+
8
+ class SRA_SECURITYLAKE_03(SecurityLakeCheck):
9
+ """Check if Security Lake SQS DLQ is encrypted with CMK."""
10
+
11
+ def __init__(self):
12
+ """Initialize check."""
13
+ super().__init__()
14
+ self.check_id = "SRA-SECURITYLAKE-03"
15
+ self.check_name = "Security Lake DLQ encrypted with CMK"
16
+ self.severity = "HIGH"
17
+ self.description = (
18
+ "This check verifies whether Security Lake SQS DLQ is encrypted in this "
19
+ "region with a customer managed key from AWS KMS. You must use a customer "
20
+ "managed KMS key for the encryption as you have greater control on the key "
21
+ "usage and permission."
22
+ )
23
+ self.check_logic = (
24
+ "Gets all subscribers for Security Lake in the region. "
25
+ "For each subscriber with a DLQ endpoint, checks if the queue is encrypted with a customer managed KMS key. "
26
+ "The check passes if all DLQ queues are encrypted with customer managed keys (not AWS managed keys). "
27
+ "The check fails if any DLQ queue is not encrypted or uses an AWS managed key (alias/aws/*)."
28
+ )
29
+
30
+ def execute(self) -> List[Dict[str, Any]]:
31
+ """
32
+ Execute the check.
33
+
34
+ Returns:
35
+ List of findings
36
+ """
37
+
38
+ for region in self.regions:
39
+ logger.debug(f"Checking if Security Lake SQS DLQ is encrypted with CMK in {region}")
40
+
41
+ # Get subscribers for the region using the base class method
42
+ subscribers = self.get_subscribers(region)
43
+
44
+ # Find DLQ queues
45
+ dlq_queues = []
46
+ for subscriber in subscribers:
47
+ endpoint = subscriber.get("subscriberEndpoint", "")
48
+ if endpoint and "sqs" in endpoint.lower() and "dlq" in endpoint.lower():
49
+ queue_url = endpoint
50
+ queue_name = queue_url.split("/")[-1]
51
+ dlq_queues.append((queue_name, queue_url))
52
+
53
+ if not subscribers or not dlq_queues:
54
+ resource_id = f"arn:aws:securitylake:{region}:{self.account_id}:dlq/none"
55
+ self.findings.append(
56
+ self.create_finding(
57
+ status="FAIL",
58
+ region=region,
59
+ resource_id=resource_id,
60
+ checked_value="DLQ queues present and encrypted with CMK",
61
+ actual_value=f"No DLQ queues found - Security Lake may not be enabled in {region}",
62
+ remediation=(
63
+ "Enable Security Lake and configure subscribers with DLQ queues. In the Security Lake console, "
64
+ "navigate to Subscribers and add subscribers with DLQ queue endpoints."
65
+ )
66
+ )
67
+ )
68
+ continue
69
+
70
+ # Check encryption for each queue
71
+ unencrypted_dlqs = []
72
+ for queue_name, queue_url in dlq_queues:
73
+ # Check encryption using base class method
74
+ kms_key = self.get_sqs_queue_encryption(region, queue_url)
75
+
76
+ if not kms_key or kms_key.startswith("alias/aws/"):
77
+ unencrypted_dlqs.append((queue_name, queue_url))
78
+
79
+ if unencrypted_dlqs:
80
+ # Use the first unencrypted queue for the resource ID
81
+ queue_name = unencrypted_dlqs[0][0]
82
+ resource_id = f"arn:aws:sqs:{region}:{self.account_id}:{queue_name}"
83
+
84
+ logger.debug(f"Found {len(unencrypted_dlqs)} unencrypted DLQ queues in {region}")
85
+ self.findings.append(
86
+ self.create_finding(
87
+ status="FAIL",
88
+ region=region,
89
+ resource_id=resource_id,
90
+ checked_value="All DLQ queues encrypted with CMK",
91
+ actual_value=f"The following DLQ queues are not encrypted with CMK: {', '.join([name for name, _ in unencrypted_dlqs])}",
92
+ remediation=(
93
+ "Configure DLQ queue encryption with a customer managed KMS key. In the SQS console, "
94
+ "select each DLQ queue and under Server-side encryption, choose 'Enable server-side encryption' "
95
+ "and select a customer managed KMS key."
96
+ )
97
+ )
98
+ )
99
+ else:
100
+ # Use the first queue for the resource ID in the PASS case
101
+ queue_name = dlq_queues[0][0]
102
+ resource_id = f"arn:aws:sqs:{region}:{self.account_id}:{queue_name}"
103
+
104
+ logger.debug(f"All Security Lake DLQ queues are encrypted with CMK in {region}")
105
+ self.findings.append(
106
+ self.create_finding(
107
+ status="PASS",
108
+ region=region,
109
+ resource_id=resource_id,
110
+ checked_value="All DLQ queues encrypted with CMK",
111
+ actual_value=f"All Security Lake DLQ queues are encrypted with CMK in {region}",
112
+ remediation="No remediation needed"
113
+ )
114
+ )
115
+
116
+ return self.findings
@@ -0,0 +1,72 @@
1
+ """Check if Security Lake organization configuration is enabled."""
2
+
3
+ from typing import List, Dict, Any
4
+ from sraverify.services.securitylake.base import SecurityLakeCheck
5
+ from sraverify.core.logging import logger
6
+
7
+
8
+ class SRA_SECURITYLAKE_04(SecurityLakeCheck):
9
+ """Check if Security Lake organization configuration is enabled."""
10
+
11
+ def __init__(self):
12
+ """Initialize check."""
13
+ super().__init__()
14
+ self.check_id = "SRA-SECURITYLAKE-04"
15
+ self.check_name = "Security Lake organization configuration enabled"
16
+ self.severity = "HIGH"
17
+ self.description = (
18
+ "This check verifies whether Amazon Security Lake has configuration that "
19
+ "will automatically enable new organization accounts as member accounts "
20
+ "from an Amazon Security Lake administrator account."
21
+ )
22
+ self.check_logic = (
23
+ "Gets the organization configuration for Security Lake in the region. "
24
+ "The check passes if organization configuration exists, indicating that "
25
+ "Security Lake is configured to automatically enable new organization accounts. "
26
+ "The check fails if no organization configuration is found."
27
+ )
28
+
29
+ def execute(self) -> List[Dict[str, Any]]:
30
+ """
31
+ Execute the check.
32
+
33
+ Returns:
34
+ List of findings
35
+ """
36
+
37
+ for region in self.regions:
38
+ logger.debug(f"Checking if Security Lake organization configuration is enabled in {region}")
39
+ resource_id = f"arn:aws:securitylake:{region}:{self.account_id}:organization-configuration/default"
40
+
41
+ # Get organization configuration using the base class method
42
+ config = self.get_organization_configuration(region)
43
+
44
+ if not config:
45
+ self.findings.append(
46
+ self.create_finding(
47
+ status="FAIL",
48
+ region=region,
49
+ resource_id=resource_id,
50
+ checked_value="Organization configuration enabled",
51
+ actual_value=f"Security Lake organization configuration is not enabled in {region}",
52
+ remediation=(
53
+ "Enable Security Lake organization configuration. In the Security Lake console, "
54
+ "navigate to Settings > Organization Configuration and enable organization configuration. "
55
+ "Alternatively, use the AWS CLI command: "
56
+ f"aws securitylake enable-organization-configuration --region {region}"
57
+ )
58
+ )
59
+ )
60
+ else:
61
+ self.findings.append(
62
+ self.create_finding(
63
+ status="PASS",
64
+ region=region,
65
+ resource_id=resource_id,
66
+ checked_value="Organization configuration enabled",
67
+ actual_value=f"Security Lake organization configuration is enabled in {region}",
68
+ remediation="No remediation needed"
69
+ )
70
+ )
71
+
72
+ return self.findings
@@ -0,0 +1,116 @@
1
+ """Check if Security Lake organization auto-enable configuration matches AWS defaults."""
2
+
3
+ from typing import List, Dict, Any
4
+ from sraverify.services.securitylake.base import SecurityLakeCheck
5
+ from sraverify.core.logging import logger
6
+
7
+
8
+ class SRA_SECURITYLAKE_05(SecurityLakeCheck):
9
+ """Check if Security Lake organization auto-enable configuration matches AWS defaults."""
10
+
11
+ # AWS default/recommended log sources for new accounts
12
+ AWS_DEFAULT_LOG_SOURCES = {
13
+ "CLOUD_TRAIL_MGMT",
14
+ "LAMBDA_EXECUTION",
15
+ "EKS_AUDIT",
16
+ "ROUTE53",
17
+ "SH_FINDINGS",
18
+ "VPC_FLOW"
19
+ }
20
+
21
+ def __init__(self):
22
+ """Initialize check."""
23
+ super().__init__()
24
+ self.account_type = "log-archive" # Organization config managed by delegated admin
25
+ self.check_id = "SRA-SECURITYLAKE-05"
26
+ self.check_name = "Security Lake organization auto-enable matches AWS defaults"
27
+ self.severity = "MEDIUM"
28
+ self.description = (
29
+ "This check verifies whether Amazon Security Lake organization auto-enable "
30
+ "configuration matches AWS default/recommended log sources for new accounts "
31
+ "(CLOUD_TRAIL_MGMT, LAMBDA_EXECUTION, EKS_AUDIT, ROUTE53, SH_FINDINGS, VPC_FLOW). "
32
+ "S3_DATA and WAF are excluded as they are optional due to high volume."
33
+ )
34
+ self.check_logic = (
35
+ "Gets the organization configuration for Security Lake auto-enable settings. "
36
+ "The check passes if all AWS default log sources are configured for auto-enable. "
37
+ "The check fails if any default log sources are missing from auto-enable configuration."
38
+ )
39
+
40
+ def execute(self) -> List[Dict[str, Any]]:
41
+ """
42
+ Execute the check.
43
+
44
+ Returns:
45
+ List of findings
46
+ """
47
+
48
+ for region in self.regions:
49
+ logger.debug(f"Checking Security Lake organization auto-enable configuration in {region}")
50
+ resource_id = f"arn:aws:securitylake:{region}:{self.account_id}:organization-configuration/auto-enable"
51
+
52
+ # Get organization configuration using the base class method
53
+ config = self.get_organization_configuration(region)
54
+
55
+ if not config:
56
+ self.findings.append(
57
+ self.create_finding(
58
+ status="FAIL",
59
+ region=region,
60
+ resource_id=resource_id,
61
+ checked_value=f"Auto-enable configured with AWS defaults: {', '.join(sorted(self.AWS_DEFAULT_LOG_SOURCES))}",
62
+ actual_value=f"No organization configuration found in {region}",
63
+ remediation=(
64
+ "Configure Security Lake organization auto-enable settings. In the Security Lake console, "
65
+ "navigate to Settings > Organization Configuration and enable auto-enable for new accounts "
66
+ "with the AWS default log sources."
67
+ )
68
+ )
69
+ )
70
+ continue
71
+
72
+ # Extract auto-enable sources from configuration
73
+ auto_enable_sources = set()
74
+ auto_enable_config = config.get("autoEnableNewAccount", [])
75
+
76
+ # Find the configuration for this region
77
+ for region_config in auto_enable_config:
78
+ if region_config.get("region") == region:
79
+ sources = region_config.get("sources", [])
80
+ for source in sources:
81
+ source_name = source.get("sourceName")
82
+ if source_name:
83
+ auto_enable_sources.add(source_name)
84
+ break
85
+
86
+ missing_sources = self.AWS_DEFAULT_LOG_SOURCES - auto_enable_sources
87
+
88
+ if missing_sources:
89
+ actual_configured = ', '.join(sorted(auto_enable_sources)) if auto_enable_sources else "None"
90
+ self.findings.append(
91
+ self.create_finding(
92
+ status="FAIL",
93
+ region=region,
94
+ resource_id=resource_id,
95
+ checked_value=f"Auto-enable configured with AWS defaults: {', '.join(sorted(self.AWS_DEFAULT_LOG_SOURCES))}",
96
+ actual_value=f"Currently configured: {actual_configured}. Missing: {', '.join(sorted(missing_sources))}",
97
+ remediation=(
98
+ "Update Security Lake organization auto-enable configuration to include missing sources. "
99
+ "In the Security Lake console, navigate to Settings > Organization Configuration and "
100
+ f"add the missing sources: {', '.join(sorted(missing_sources))}."
101
+ )
102
+ )
103
+ )
104
+ else:
105
+ self.findings.append(
106
+ self.create_finding(
107
+ status="PASS",
108
+ region=region,
109
+ resource_id=resource_id,
110
+ checked_value=f"Auto-enable configured with AWS defaults: {', '.join(sorted(self.AWS_DEFAULT_LOG_SOURCES))}",
111
+ actual_value=f"Currently configured: {', '.join(sorted(auto_enable_sources))}",
112
+ remediation="No remediation needed"
113
+ )
114
+ )
115
+
116
+ return self.findings
@@ -0,0 +1,104 @@
1
+ """Check if Route 53 log source is enabled for Security Lake."""
2
+
3
+ from typing import List, Dict, Any
4
+ from sraverify.services.securitylake.base import SecurityLakeCheck
5
+ from sraverify.core.logging import logger
6
+
7
+
8
+ class SRA_SECURITYLAKE_06(SecurityLakeCheck):
9
+ """Check if Route 53 log source is enabled for Security Lake."""
10
+
11
+ def __init__(self):
12
+ """Initialize check."""
13
+ super().__init__()
14
+ self.account_type = "log-archive" # Check from log archive account
15
+ self.check_id = "SRA-SECURITYLAKE-06"
16
+ self.check_name = "Security Lake Route 53 log source enabled with version 2.0 for all organization accounts"
17
+ self.severity = "HIGH"
18
+ self.description = (
19
+ "This check verifies whether Amazon Security Lake is configured with "
20
+ "Route 53 log and event source version 2.0 for all active accounts in the organization. "
21
+ "Route 53 resolver query logs track DNS queries made by resources within Amazon VPC. "
22
+ "Security Lake collects resolver query logs directly from Route 53 through an independent "
23
+ "and duplicated stream of events. This check runs from the delegated administrator account "
24
+ "and validates configuration across all organization member accounts."
25
+ )
26
+ self.check_logic = (
27
+ "Checks if the Route 53 log source is enabled in Security Lake with version 2.0. "
28
+ "The check passes if the ROUTE53 log source is configured. "
29
+ "The check fails if the ROUTE53 log source is not configured."
30
+ )
31
+
32
+ def execute(self) -> List[Dict[str, Any]]:
33
+ """
34
+ Execute the check.
35
+
36
+ Returns:
37
+ List of findings
38
+ """
39
+ for region in self.regions:
40
+ logger.debug(f"Checking if Route 53 log source is enabled in {region}")
41
+
42
+ # Get all organization accounts to check
43
+ org_accounts = self.get_organization_accounts(region)
44
+ if not org_accounts:
45
+ logger.warning("No organization accounts found")
46
+ org_accounts = [self.account_id] # Fall back to current account
47
+
48
+ # Create sets of active account IDs
49
+ active_org_account_ids = set()
50
+ for account in org_accounts:
51
+ if account.get('Status') == 'ACTIVE':
52
+ active_org_account_ids.add(account.get('Id'))
53
+
54
+ # Check each account in the organization
55
+ for account_id in active_org_account_ids:
56
+ resource_id = f"arn:aws:securitylake:{region}:{account_id}:log-source/ROUTE53"
57
+
58
+ # Check Route 53 log source configuration (call API once, check both versions)
59
+ route53_v2_enabled = self.check_log_source_configured(region, "ROUTE53", account_id, "2.0")
60
+
61
+ if not route53_v2_enabled:
62
+ # Only check v1.0 if v2.0 is not enabled (uses cached data)
63
+ route53_v1_enabled = self.check_log_source_configured(region, "ROUTE53", account_id, "1.0")
64
+
65
+ if route53_v1_enabled:
66
+ actual_value = f"Route 53 log source is configured with version 1.0 instead of 2.0 for account {account_id}"
67
+ remediation = (
68
+ f"Update Route 53 log source to version 2.0 for account {account_id}. "
69
+ "In the Security Lake console, navigate to Sources and update the Route 53 source version. "
70
+ "Alternatively, use the AWS CLI command: "
71
+ f"aws securitylake update-data-lake --sources '[{{\"regions\":[\"{region}\"],\"sourceName\":\"ROUTE53\",\"sourceVersion\":\"2.0\"}}]' --region {region}"
72
+ )
73
+ else:
74
+ actual_value = f"Route 53 log source is not configured for account {account_id}"
75
+ remediation = (
76
+ "Enable Route 53 log source in Security Lake. In the Security Lake console, "
77
+ "navigate to Settings > Log Sources and enable Route 53 logs. "
78
+ "Alternatively, use the AWS CLI command: "
79
+ f"aws securitylake create-aws-log-source --sources '[{{\"regions\":[\"{region}\"],\"sourceName\":\"ROUTE53\",\"sourceVersion\":\"2.0\"}}]' --region {region}"
80
+ )
81
+
82
+ self.findings.append(
83
+ self.create_finding(
84
+ status="FAIL",
85
+ region=region,
86
+ resource_id=resource_id,
87
+ checked_value="Route 53 log source enabled with version 2.0",
88
+ actual_value=actual_value,
89
+ remediation=remediation
90
+ )
91
+ )
92
+ else:
93
+ self.findings.append(
94
+ self.create_finding(
95
+ status="PASS",
96
+ region=region,
97
+ resource_id=resource_id,
98
+ checked_value="Route 53 log source enabled with version 2.0",
99
+ actual_value=f"Route 53 log source is configured in {region} for account {account_id}",
100
+ remediation="No remediation needed"
101
+ )
102
+ )
103
+
104
+ return self.findings
@@ -0,0 +1,108 @@
1
+ """Check if CloudTrail S3 data events are enabled for Security Lake."""
2
+
3
+ from typing import List, Dict, Any
4
+ from sraverify.services.securitylake.base import SecurityLakeCheck
5
+ from sraverify.core.logging import logger
6
+
7
+
8
+ class SRA_SECURITYLAKE_07(SecurityLakeCheck):
9
+ """Check if CloudTrail S3 data events are enabled for Security Lake."""
10
+
11
+ def __init__(self):
12
+ """Initialize check."""
13
+ super().__init__()
14
+ self.account_type = "log-archive" # Check all org accounts from delegated admin
15
+ self.check_id = "SRA-SECURITYLAKE-07"
16
+ self.check_name = "Security Lake CloudTrail S3 data events enabled with version 2.0 for all organization accounts"
17
+ self.severity = "HIGH"
18
+ self.description = (
19
+ "This check verifies whether Amazon Security Lake is configured with "
20
+ "CloudTrail data event for S3 log and event source version 2.0 for all active accounts in the organization. "
21
+ "CloudTrail data events, also known as data plane operations, show "
22
+ "the resource operations performed on or within resources in your AWS "
23
+ "account. These operations are often high-volume activities and should "
24
+ "be enabled as per your requirement. Security Lake pulls data directly "
25
+ "from S3 through an independent and duplicated stream of events. "
26
+ "This check runs from the delegated administrator account "
27
+ "and validates configuration across all organization member accounts."
28
+ )
29
+ self.check_logic = (
30
+ "Checks if the CloudTrail S3 data events log source version 2.0 is enabled in Security Lake "
31
+ "for all active organization accounts. The check passes if the S3_DATA log source version 2.0 is enabled. "
32
+ "The check fails if the S3_DATA log source is not enabled or configured with version 1.0."
33
+ )
34
+
35
+ def execute(self) -> List[Dict[str, Any]]:
36
+ """
37
+ Execute the check.
38
+
39
+ Returns:
40
+ List of findings
41
+ """
42
+
43
+ for region in self.regions:
44
+ logger.debug(f"Checking if CloudTrail S3 data events are enabled in {region}")
45
+
46
+ # Get all organization accounts
47
+ org_accounts = self.get_organization_accounts(region)
48
+ if not org_accounts:
49
+ logger.debug("No organization accounts found, checking current account only")
50
+ org_accounts = [{'Id': self.account_id, 'Status': 'ACTIVE'}]
51
+
52
+ # Create sets of active account IDs
53
+ active_org_account_ids = set()
54
+ for account in org_accounts:
55
+ if account.get('Status') == 'ACTIVE':
56
+ active_org_account_ids.add(account.get('Id'))
57
+
58
+ # Check each account in the organization
59
+ for account_id in active_org_account_ids:
60
+ resource_id = f"arn:aws:securitylake:{region}:{account_id}:log-source/S3_DATA"
61
+
62
+ # Check CloudTrail S3 data events configuration
63
+ s3_data_v2_enabled = self.check_log_source_configured(region, "S3_DATA", account_id, "2.0")
64
+
65
+ if not s3_data_v2_enabled:
66
+ # Only check v1.0 if v2.0 is not enabled (uses cached data)
67
+ s3_data_v1_enabled = self.check_log_source_configured(region, "S3_DATA", account_id, "1.0")
68
+
69
+ if s3_data_v1_enabled:
70
+ actual_value = f"CloudTrail S3 data events are configured with version 1.0 instead of 2.0 for account {account_id}"
71
+ remediation = (
72
+ f"Update CloudTrail S3 data events to version 2.0 for account {account_id}. "
73
+ "In the Security Lake console, navigate to Sources and update the S3 data events source version. "
74
+ "Alternatively, use the AWS CLI command: "
75
+ f"aws securitylake update-data-lake --sources '[{{\"regions\":[\"{region}\"],\"sourceName\":\"S3_DATA\",\"sourceVersion\":\"2.0\"}}]' --region {region}"
76
+ )
77
+ else:
78
+ actual_value = f"CloudTrail S3 data events are not configured for account {account_id}"
79
+ remediation = (
80
+ "Enable CloudTrail S3 data events in Security Lake. In the Security Lake console, "
81
+ "navigate to Settings > Log Sources and enable CloudTrail S3 data events. "
82
+ "Alternatively, use the AWS CLI command: "
83
+ f"aws securitylake create-aws-log-source --sources '[{{\"regions\":[\"{region}\"],\"sourceName\":\"S3_DATA\",\"sourceVersion\":\"2.0\"}}]' --region {region}"
84
+ )
85
+
86
+ self.findings.append(
87
+ self.create_finding(
88
+ status="FAIL",
89
+ region=region,
90
+ resource_id=resource_id,
91
+ checked_value="CloudTrail S3 data events enabled with version 2.0",
92
+ actual_value=actual_value,
93
+ remediation=remediation
94
+ )
95
+ )
96
+ else:
97
+ self.findings.append(
98
+ self.create_finding(
99
+ status="PASS",
100
+ region=region,
101
+ resource_id=resource_id,
102
+ checked_value="CloudTrail S3 data events enabled with version 2.0",
103
+ actual_value=f"CloudTrail S3 data events are enabled with version 2.0 in {region} for account {account_id}",
104
+ remediation="No remediation needed"
105
+ )
106
+ )
107
+
108
+ return self.findings