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
sraverify/main.py ADDED
@@ -0,0 +1,350 @@
1
+ """
2
+ SRA Verify - Security Reference Architecture Verification Tool
3
+
4
+ This module provides both the library interface and CLI functionality.
5
+ The SRAVerify class implements the core functionality that can be used
6
+ as a library, while the CLI functions use this class to provide the
7
+ command-line interface.
8
+ """
9
+ import argparse
10
+ import datetime
11
+ from boto3 import Session
12
+ from typing import Dict, List, Any, Optional
13
+
14
+ from sraverify.core.session import get_session
15
+ from sraverify.core.logging import logger, configure_logging
16
+ from sraverify.utils.outputs import write_csv_output
17
+ from sraverify.utils.progress import ScanProgress
18
+ from sraverify.utils.banner import print_banner
19
+ from sraverify.services.guardduty import CHECKS as guardduty_checks
20
+ from sraverify.services.cloudtrail import CHECKS as cloudtrail_checks
21
+ from sraverify.services.accessanalyzer import CHECKS as accessanalyzer_checks
22
+ from sraverify.services.config import CHECKS as config_checks
23
+ from sraverify.services.securityhub import CHECKS as securityhub_checks
24
+ from sraverify.services.s3 import CHECKS as s3_checks
25
+ from sraverify.services.inspector import CHECKS as inspector_checks
26
+ from sraverify.services.ec2 import CHECKS as ec2_checks
27
+ from sraverify.services.macie import CHECKS as macie_checks
28
+ from sraverify.services.shield import CHECKS as shield_checks
29
+ from sraverify.services.waf import CHECKS as waf_checks
30
+ from sraverify.services.account import CHECKS as account_checks
31
+ from sraverify.services.auditmanager import CHECKS as auditmanager_checks
32
+ from sraverify.services.firewallmanager import CHECKS as firewallmanager_checks
33
+ from sraverify.services.securitylake import CHECKS as securitylake_checks
34
+ from sraverify.services.securityincidentresponse import CHECKS as securityincidentresponse_checks
35
+
36
+ # Collect all checks from different services
37
+ ALL_CHECKS = {
38
+ **guardduty_checks,
39
+ **cloudtrail_checks,
40
+ **accessanalyzer_checks,
41
+ **config_checks,
42
+ **securityhub_checks,
43
+ **s3_checks,
44
+ **inspector_checks,
45
+ **ec2_checks,
46
+ **macie_checks,
47
+ **shield_checks,
48
+ **waf_checks,
49
+ **account_checks,
50
+ **auditmanager_checks,
51
+ **firewallmanager_checks,
52
+ **securitylake_checks,
53
+ **securityincidentresponse_checks
54
+ # Add more service checks here as they're implemented
55
+ # **config_checks,
56
+ # etc.
57
+ }
58
+
59
+ class SRAVerify:
60
+ """Main class for SRA Verify functionality."""
61
+
62
+ def __init__(self, profile: Optional[str] = None, role_arn: Optional[str] = None,
63
+ regions: Optional[List[str]] = None, session: Optional[Session] = None,
64
+ debug: bool = False):
65
+ """
66
+ Initialize SRA Verify.
67
+
68
+ Args:
69
+ profile: AWS profile to use
70
+ role_arn: ARN of IAM role to assume
71
+ regions: List of AWS regions to check
72
+ session: Existing AWS session to use (if provided)
73
+ debug: Enable debug logging
74
+ """
75
+ configure_logging(debug)
76
+ self.regions = regions
77
+ self.session = session if session else get_session(profile=profile, role_arn=role_arn)
78
+ self.progress = None
79
+
80
+ def get_available_checks(self, account_type: str = 'all') -> Dict[str, Dict[str, str]]:
81
+ """
82
+ Get all available checks, optionally filtered by account type.
83
+
84
+ Args:
85
+ account_type: Type of accounts to list checks for ('application', 'audit', 'log-archive', 'management', or 'all')
86
+
87
+ Returns:
88
+ Dictionary mapping check IDs to check information
89
+ """
90
+ checks = {}
91
+ for check_id, check_class in sorted(ALL_CHECKS.items()):
92
+ check = check_class()
93
+ if account_type == 'all' or check.account_type == account_type:
94
+ checks[check_id] = {
95
+ 'name': check.check_name,
96
+ 'service': check.service,
97
+ 'account_type': check.account_type,
98
+ 'description': check.description,
99
+ 'severity': check.severity
100
+ }
101
+ return checks
102
+
103
+ def get_available_services(self) -> List[str]:
104
+ """
105
+ Get all available services.
106
+
107
+ Returns:
108
+ List of service names
109
+ """
110
+ services = set()
111
+ for check_class in ALL_CHECKS.values():
112
+ check = check_class()
113
+ services.add(check.service)
114
+ return sorted(list(services))
115
+
116
+ def run_checks(self, account_type: str = 'all', service: Optional[str] = None,
117
+ check_id: Optional[str] = None, audit_accounts: Optional[List[str]] = None,
118
+ log_archive_accounts: Optional[List[str]] = None,
119
+ show_progress: bool = False) -> List[Dict[str, Any]]:
120
+ """
121
+ Run security checks.
122
+
123
+ Args:
124
+ account_type: Type of accounts to check ('application', 'audit', 'log-archive', 'management', or 'all')
125
+ service: Run checks for a specific service
126
+ check_id: Run a specific check
127
+ audit_accounts: List of AWS accounts used for Audit/Security Tooling
128
+ log_archive_accounts: List of AWS accounts used for Logging
129
+ show_progress: Whether to show progress bar
130
+
131
+ Returns:
132
+ List of findings
133
+ """
134
+ # Start with all checks or filtered by account type
135
+ if account_type == 'all':
136
+ checks_to_run = ALL_CHECKS.copy()
137
+ else:
138
+ logger.debug(f"Filtering checks by account type: {account_type}")
139
+ checks_to_run = {
140
+ check_id: check_class for check_id, check_class in ALL_CHECKS.items()
141
+ if check_class().account_type == account_type
142
+ }
143
+
144
+ # Filter by specific check if provided
145
+ if check_id:
146
+ logger.debug(f"Filtering for specific check: {check_id}")
147
+ if check_id not in ALL_CHECKS:
148
+ logger.error(f"Check {check_id} not found")
149
+ return []
150
+
151
+ check = ALL_CHECKS[check_id]()
152
+ if account_type != 'all' and check.account_type != account_type:
153
+ logger.error(f"Check {check_id} is for {check.account_type} accounts, but account_type is set to {account_type}")
154
+ return []
155
+
156
+ checks_to_run = {check_id: ALL_CHECKS[check_id]}
157
+
158
+ # Filter by service if provided
159
+ if service:
160
+ logger.debug(f"Filtering checks by service: {service}")
161
+ service_checks = {}
162
+ for check_id, check_class in checks_to_run.items():
163
+ check = check_class()
164
+ if check.service.lower() == service.lower():
165
+ service_checks[check_id] = check_class
166
+
167
+ if not service_checks:
168
+ logger.error(f"No {account_type} checks found for service {service}")
169
+ return []
170
+
171
+ checks_to_run = service_checks
172
+
173
+ # Check if there are any checks after filtering
174
+ if not checks_to_run:
175
+ logger.error("No checks found with selected filters")
176
+ return []
177
+
178
+ all_findings = []
179
+
180
+ # Group checks by service for better organization
181
+ service_checks = {}
182
+ for check_id, check_class in checks_to_run.items():
183
+ check = check_class()
184
+ if check.service not in service_checks:
185
+ service_checks[check.service] = []
186
+ service_checks[check.service].append((check_id, check_class))
187
+
188
+ # Set up progress tracking if requested
189
+ if show_progress:
190
+ self.progress = ScanProgress(len(checks_to_run))
191
+
192
+ # Run checks by service
193
+ for service_name, checks in service_checks.items():
194
+ if self.progress:
195
+ self.progress.update(service_name)
196
+ logger.debug(f"Running {len(checks)} checks for service {service_name}")
197
+
198
+ for check_id, check_class in checks:
199
+ logger.debug(f"Initializing check {check_id}")
200
+ check = check_class()
201
+ check.initialize(self.session, regions=self.regions)
202
+
203
+ # Pass audit and log archive accounts to the check if it needs them
204
+ if audit_accounts:
205
+ check._audit_accounts = audit_accounts
206
+ if log_archive_accounts:
207
+ check._log_archive_accounts = log_archive_accounts
208
+
209
+ try:
210
+ logger.debug(f"Executing check {check_id}: {check.check_name}")
211
+ findings = check.execute()
212
+ all_findings.extend(findings)
213
+ logger.debug(f"Check {check_id} completed with {len(findings)} findings")
214
+ except Exception as e:
215
+ logger.error(f"Error running check {check_id}: {e}", exc_info=True)
216
+ # Add a failure finding
217
+ all_findings.append({
218
+ "CheckId": check_id,
219
+ "Status": "ERROR",
220
+ "Region": "global",
221
+ "Severity": "UNKNOWN",
222
+ "Title": f"Error running {check_id}",
223
+ "Description": f"An error occurred while running check {check_id}",
224
+ "ResourceId": None,
225
+ "ResourceType": None,
226
+ "AccountId": None,
227
+ "CheckedValue": None,
228
+ "ActualValue": str(e),
229
+ "Remediation": "Check the error message and try again",
230
+ "Service": service_name,
231
+ "CheckLogic": None,
232
+ "AccountType": check.account_type
233
+ })
234
+
235
+ if self.progress:
236
+ self.progress.increment()
237
+
238
+ if self.progress:
239
+ self.progress.finish()
240
+
241
+ return all_findings
242
+
243
+
244
+ def parse_args():
245
+ """Parse command line arguments."""
246
+ parser = argparse.ArgumentParser(description='SRA Verify - Security Rule Assessment Verification Tool')
247
+ parser.add_argument('--profile', type=str, help='AWS profile to use')
248
+ parser.add_argument('--role', type=str, help='ARN of IAM role to assume')
249
+ parser.add_argument('--regions', type=str, help='Comma-separated list of AWS regions to check')
250
+ parser.add_argument('--output', type=str, default='sraverify_findings.csv',
251
+ help='Output file name (default: sraverify_findings.csv)')
252
+ parser.add_argument('--check', type=str, help='Run a specific check (e.g., SRA-GD-1)')
253
+ parser.add_argument('--service', type=str, help='Run checks for a specific service (e.g., GuardDuty)')
254
+ parser.add_argument('--account-type', type=str,
255
+ choices=['application', 'audit', 'log-archive', 'management', 'all'],
256
+ default='all',
257
+ help='Type of accounts to run checks against: application, audit, log-archive, management, or all (default: all)')
258
+ parser.add_argument('--audit-account', type=str, metavar='ACCOUNTID1,ACCOUNTID2',
259
+ help='AWS accounts used for Audit/Security Tooling, use comma separated values')
260
+ parser.add_argument('--log-archive-account', type=str, metavar='ACCOUNTID1,ACCOUNTID2',
261
+ help='AWS accounts used for Logging, use comma separated values')
262
+ parser.add_argument('--list-checks', action='store_true', help='List available checks')
263
+ parser.add_argument('--list-services', action='store_true', help='List available services')
264
+ parser.add_argument('--debug', action='store_true', help='Enable debug logging')
265
+
266
+ return parser.parse_args()
267
+
268
+
269
+ def main():
270
+ """Main entry point."""
271
+ args = parse_args()
272
+
273
+ # Create SRAVerify instance
274
+ regions = [r.strip() for r in args.regions.split(',')] if args.regions else None
275
+ sra = SRAVerify(profile=args.profile, role_arn=args.role, regions=regions, debug=args.debug)
276
+
277
+ if args.list_checks:
278
+ checks = sra.get_available_checks(args.account_type)
279
+ print("Available checks:")
280
+ for check_id, info in checks.items():
281
+ print(f" {check_id}: {info['name']} ({info['service']}) [{info['account_type']}]")
282
+ return
283
+
284
+ if args.list_services:
285
+ services = sra.get_available_services()
286
+ print("Available services:")
287
+ for service in services:
288
+ print(f" {service}")
289
+ return
290
+
291
+ # Parse audit accounts if provided
292
+ audit_accounts = None
293
+ if args.audit_account:
294
+ audit_accounts = [a.strip() for a in args.audit_account.split(',')]
295
+ logger.debug(f"Using audit accounts: {', '.join(audit_accounts)}")
296
+
297
+ # Parse log archive accounts if provided
298
+ log_archive_accounts = None
299
+ if args.log_archive_account:
300
+ log_archive_accounts = [a.strip() for a in args.log_archive_account.split(',')]
301
+ logger.debug(f"Using log archive accounts: {', '.join(log_archive_accounts)}")
302
+
303
+ # Generate output filename with timestamp if not specified
304
+ output_file = args.output
305
+ if output_file == 'sraverify_findings.csv':
306
+ timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
307
+ output_file = f"sraverify_findings_{timestamp}.csv"
308
+
309
+ # Display banner with session information
310
+ print_banner(
311
+ profile=args.profile or 'default',
312
+ region=sra.session.region_name,
313
+ session=sra.session,
314
+ regions=regions,
315
+ account_type=args.account_type,
316
+ checks_count=len(sra.get_available_checks(args.account_type)),
317
+ output_file=output_file,
318
+ role=args.role
319
+ )
320
+
321
+ # Run checks
322
+ findings = sra.run_checks(
323
+ account_type=args.account_type,
324
+ service=args.service,
325
+ check_id=args.check,
326
+ audit_accounts=audit_accounts,
327
+ log_archive_accounts=log_archive_accounts,
328
+ show_progress=True
329
+ )
330
+
331
+ # Write output
332
+ logger.debug(f"Writing findings to {output_file}")
333
+ write_csv_output(findings, output_file)
334
+
335
+ # Print summary
336
+ pass_count = sum(1 for f in findings if f.get('Status') == 'PASS')
337
+ fail_count = sum(1 for f in findings if f.get('Status') == 'FAIL')
338
+ error_count = sum(1 for f in findings if f.get('Status') == 'ERROR')
339
+
340
+ logger.debug("Scan complete")
341
+ print("\n-> Scan complete!")
342
+ print(f" · Total findings: {len(findings)}")
343
+ print(f" · Pass: {pass_count}")
344
+ print(f" · Fail: {fail_count}")
345
+ print(f" · Error: {error_count}")
346
+ print(f" · Output: {output_file}")
347
+
348
+
349
+ if __name__ == "__main__":
350
+ main()
@@ -0,0 +1,3 @@
1
+ """
2
+ AWS service-specific modules.
3
+ """
@@ -0,0 +1,15 @@
1
+ """
2
+ Accessanalyzer security checks.
3
+ """
4
+ from sraverify.services.accessanalyzer.checks.sra_accessanalyzer_01 import SRA_ACCESSANALYZER_01
5
+ from sraverify.services.accessanalyzer.checks.sra_accessanalyzer_02 import SRA_ACCESSANALYZER_02
6
+ from sraverify.services.accessanalyzer.checks.sra_accessanalyzer_03 import SRA_ACCESSANALYZER_03
7
+ from sraverify.services.accessanalyzer.checks.sra_accessanalyzer_04 import SRA_ACCESSANALYZER_04
8
+
9
+ # Register checks
10
+ CHECKS = {
11
+ "SRA-ACCESSANALYZER-01": SRA_ACCESSANALYZER_01,
12
+ "SRA-ACCESSANALYZER-02": SRA_ACCESSANALYZER_02,
13
+ "SRA-ACCESSANALYZER-03": SRA_ACCESSANALYZER_03,
14
+ "SRA-ACCESSANALYZER-04": SRA_ACCESSANALYZER_04,
15
+ }
@@ -0,0 +1,123 @@
1
+ """
2
+ Base class for IAM Access Analyzer security checks.
3
+ """
4
+ from typing import List, Optional, Dict, Any
5
+ import boto3
6
+ from sraverify.core.check import SecurityCheck
7
+ from sraverify.services.accessanalyzer.client import AccessAnalyzerClient
8
+ from sraverify.core.logging import logger
9
+
10
+
11
+ class AccessAnalyzerCheck(SecurityCheck):
12
+ """Base class for all IAM Access Analyzer security checks."""
13
+
14
+ # Class-level caches shared across all instances
15
+ _delegated_admin_cache = {}
16
+ _analyzer_cache = {}
17
+
18
+ def __init__(self):
19
+ """Initialize IAM Access Analyzer base check."""
20
+ super().__init__(
21
+ account_type="application",
22
+ service="IAM Access Analyzer",
23
+ resource_type="AWS::AccessAnalyzer::Analyzer"
24
+ )
25
+
26
+ def _setup_clients(self):
27
+ """Set up AccessAnalyzer clients for enabled regions."""
28
+ # Clear existing clients
29
+ self._clients.clear()
30
+
31
+ if not hasattr(self, 'session') or not self.session:
32
+ logger.debug("No session available, skipping client setup")
33
+ return
34
+
35
+ # For organization checks, we need to check all specified regions
36
+ for region in self.regions:
37
+ try:
38
+ client = AccessAnalyzerClient(region, self.session)
39
+ if client.is_access_analyzer_available():
40
+ self._clients[region] = client
41
+ logger.debug(f"Access Analyzer client set up for region {region}")
42
+ else:
43
+ logger.debug(f"Access Analyzer not available in region {region}")
44
+ except Exception as e:
45
+ # Skip regions where client creation fails
46
+ logger.warning(f"Failed to create Access Analyzer client for region {region}: {e}")
47
+ continue
48
+
49
+ def get_client(self, region: str) -> Optional[AccessAnalyzerClient]:
50
+ """
51
+ Get Access Analyzer client for a region.
52
+
53
+ Args:
54
+ region: AWS region name
55
+
56
+ Returns:
57
+ AccessAnalyzerClient for the region or None if not available
58
+ """
59
+ return self._clients.get(region)
60
+
61
+ def get_analyzers(self, region: str) -> List[Dict[str, Any]]:
62
+ """
63
+ Get analyzers for a specific region with caching.
64
+
65
+ Args:
66
+ region: AWS region name
67
+
68
+ Returns:
69
+ List of analyzers in the region
70
+ """
71
+ # Check class-level cache
72
+ cache_key = f"{self.session.region_name}:{region}"
73
+ if cache_key in AccessAnalyzerCheck._analyzer_cache:
74
+ logger.debug(f"Using cached analyzers for {region}")
75
+ return AccessAnalyzerCheck._analyzer_cache[cache_key]
76
+
77
+ # Get client
78
+ client = self.get_client(region)
79
+ if not client:
80
+ logger.warning(f"No Access Analyzer client available for region {region}")
81
+ return []
82
+
83
+ # Get analyzers
84
+ logger.debug(f"Fetching analyzers for {region}")
85
+ analyzers = client.list_analyzers()
86
+
87
+ # Cache the analyzers
88
+ AccessAnalyzerCheck._analyzer_cache[cache_key] = analyzers
89
+ logger.debug(f"Cached {len(analyzers)} analyzers for {region}")
90
+
91
+ return analyzers
92
+
93
+ def get_delegated_admin(self) -> Dict[str, Any]:
94
+ """
95
+ Get the delegated administrator for IAM Access Analyzer with caching.
96
+
97
+ Returns:
98
+ Dictionary containing delegated administrator details or empty dict if none
99
+ """
100
+ account_id = self.account_id
101
+
102
+ # Check class-level cache
103
+ if account_id in AccessAnalyzerCheck._delegated_admin_cache:
104
+ logger.debug(f"Using cached delegated admin for account {account_id}")
105
+ return AccessAnalyzerCheck._delegated_admin_cache[account_id]
106
+
107
+ # If not in cache, get it from the client
108
+ # Use the first available region to make the API call
109
+ if not self._clients:
110
+ logger.warning("No Access Analyzer clients available")
111
+ return {}
112
+
113
+ # Use the first available region's client
114
+ region = next(iter(self._clients))
115
+ client = self._clients[region]
116
+
117
+ # Get delegated admin from client
118
+ delegated_admin = client.get_delegated_admin()
119
+
120
+ # Cache the result
121
+ AccessAnalyzerCheck._delegated_admin_cache[account_id] = delegated_admin
122
+
123
+ return delegated_admin
@@ -0,0 +1,3 @@
1
+ """
2
+ IAM Access Analyzer security checks.
3
+ """
@@ -0,0 +1,82 @@
1
+ """
2
+ Check if IAM Access Analyzer external access analyzer is configured with account zone of trust.
3
+ """
4
+ from typing import Dict, List, Any
5
+ from sraverify.services.accessanalyzer.base import AccessAnalyzerCheck
6
+ from sraverify.core.logging import logger
7
+
8
+
9
+ class SRA_ACCESSANALYZER_01(AccessAnalyzerCheck):
10
+ """Check if IAM Access Analyzer external access analyzer is configured with account zone of trust."""
11
+
12
+ def __init__(self):
13
+ """Initialize IAM Access Analyzer check."""
14
+ super().__init__()
15
+ self.check_id = "SRA-ACCESSANALYZER-01"
16
+ self.check_name = "IAM Access Analyzer Account Zone of trust"
17
+ self.description = ("This check verifies whether IAA external access analyzer is configured with a zone of "
18
+ "trust of AWS account. IAM Access Analyzer generates a finding for each instance of a "
19
+ "resource-based policy that grants access to a resource within your zone of trust to a "
20
+ "principal that is not within your zone of trust. When you configure an AWS account as "
21
+ "the zone of trust for an analyzer- IAA generates findings or each instance of a "
22
+ "resource-based policy that grants access to a resource within your AWS account whether "
23
+ "the analyzer exists to a principal that is not within your AWS account.")
24
+ self.severity = "HIGH"
25
+ self.check_logic = "List analyzers in each Region. Check if analyzer exists and is configured with account zone of trust."
26
+
27
+ def execute(self) -> List[Dict[str, Any]]:
28
+ """Execute the check for each region."""
29
+ findings = []
30
+ logger.debug(f"Executing {self.check_id} check for account {self.account_id}")
31
+
32
+ # If no regions have Access Analyzer available, return a single failure
33
+ if not self._clients:
34
+ logger.warning("No regions with Access Analyzer available")
35
+ findings.append(
36
+ self.create_finding(
37
+ status="FAIL",
38
+ region="global",
39
+ resource_id="accessanalyzer:global", # Generic format for global failure
40
+ actual_value="IAM Access Analyzer not available in any region",
41
+ remediation="Enable IAM Access Analyzer in at least one region and configure "
42
+ "with account zone of trust"
43
+ )
44
+ )
45
+ return findings
46
+
47
+ # Check each region where Access Analyzer is available
48
+ for region, client in self._clients.items():
49
+ logger.debug(f"Checking region {region} for account-level analyzers")
50
+ analyzers = self.get_analyzers(region)
51
+
52
+ # Check if any analyzer exists with account-level zone of trust
53
+ account_analyzer = None
54
+ for analyzer in analyzers:
55
+ if analyzer.get('type') == 'ACCOUNT':
56
+ account_analyzer = analyzer
57
+ logger.debug(f"Found account analyzer in {region}: {analyzer.get('name')}")
58
+ break
59
+
60
+ if account_analyzer:
61
+ findings.append(
62
+ self.create_finding(
63
+ status="PASS",
64
+ region=region,
65
+ resource_id=account_analyzer['arn'], # Use the actual analyzer ARN for PASS
66
+ actual_value="IAM Access Analyzer configured with account zone of trust",
67
+ remediation="No remediation needed"
68
+ )
69
+ )
70
+ else:
71
+ logger.debug(f"No account analyzer found in {region}")
72
+ findings.append(
73
+ self.create_finding(
74
+ status="FAIL",
75
+ region=region,
76
+ resource_id=f"accessanalyzer:{region}", # Keep generic format for FAIL
77
+ actual_value="No IAM Access Analyzer configured with account zone of trust",
78
+ remediation="Create an IAM Access Analyzer with account zone of trust in this region"
79
+ )
80
+ )
81
+
82
+ return findings
@@ -0,0 +1,82 @@
1
+ """
2
+ Check if IAM Access Analyzer has a delegated administrator for the organization.
3
+ """
4
+ from typing import Dict, List, Any
5
+ from sraverify.services.accessanalyzer.base import AccessAnalyzerCheck
6
+ from sraverify.core.logging import logger
7
+
8
+
9
+ class SRA_ACCESSANALYZER_02(AccessAnalyzerCheck):
10
+ """Check if IAM Access Analyzer has a delegated administrator for the organization."""
11
+
12
+ def __init__(self):
13
+ """Initialize IAM Access Analyzer check."""
14
+ super().__init__()
15
+ self.check_id = "SRA-ACCESSANALYZER-02"
16
+ self.check_name = "IAM Access Analyzer Organization Delegated Administrator"
17
+ self.description = ("This check verifies whether IAA service administration for your AWS "
18
+ "Organization is delegated out of your AWS Organization management account. "
19
+ "The delegated administrator has permissions to create and manage analyzers "
20
+ "with the AWS organization as the zone of trust.")
21
+ self.severity = "HIGH"
22
+ self.account_type = "management"
23
+ self.check_logic = ("Check if a delegated administrator is configured for IAM Access Analyzer in the organization")
24
+
25
+ def execute(self) -> List[Dict[str, Any]]:
26
+ """Execute the check."""
27
+ findings = []
28
+ logger.debug(f"Executing {self.check_id} check for account {self.account_id}")
29
+
30
+ # Check for delegated administrator
31
+ try:
32
+ logger.debug("Checking for IAM Access Analyzer delegated administrator")
33
+ org_client = self.session.client('organizations')
34
+ response = org_client.list_delegated_administrators(
35
+ ServicePrincipal='access-analyzer.amazonaws.com'
36
+ )
37
+
38
+ # Store in class-level cache
39
+ if response['DelegatedAdministrators']:
40
+ delegated_admin = response['DelegatedAdministrators'][0]
41
+ self.__class__._delegated_admin_cache[self.account_id] = delegated_admin
42
+ logger.debug(f"Found delegated administrator: {delegated_admin['Id']}")
43
+
44
+ findings.append(
45
+ self.create_finding(
46
+ status="PASS",
47
+ region="global",
48
+ resource_id=delegated_admin['Id'],
49
+ actual_value=f"IAM Access Analyzer delegated administrator configured: "
50
+ f"Account {delegated_admin['Id']}",
51
+ remediation="No remediation needed"
52
+ )
53
+ )
54
+ else:
55
+ logger.debug("No delegated administrator found for IAM Access Analyzer")
56
+ self.__class__._delegated_admin_cache[self.account_id] = {}
57
+ findings.append(
58
+ self.create_finding(
59
+ status="FAIL",
60
+ region="global",
61
+ resource_id=f"organization/{self.account_id}",
62
+ actual_value="No delegated administrator configured for IAM Access Analyzer",
63
+ remediation="Configure a delegated administrator for IAM Access Analyzer using "
64
+ "AWS Organizations"
65
+ )
66
+ )
67
+
68
+ except Exception as e:
69
+ logger.error(f"Error checking delegated administrator: {e}")
70
+ self.__class__._delegated_admin_cache[self.account_id] = {}
71
+ findings.append(
72
+ self.create_finding(
73
+ status="FAIL",
74
+ region="global",
75
+ resource_id=f"organization/{self.account_id}",
76
+ actual_value=f"Error checking delegated administrator: {str(e)}",
77
+ remediation="Ensure proper permissions to check delegated administrators "
78
+ "and that Organizations is enabled"
79
+ )
80
+ )
81
+
82
+ return findings