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.
- sraverify/__init__.py +36 -0
- sraverify/checks/__init__.py +56 -0
- sraverify/checks/accessanalyzer/SRA_IAA_1.py +188 -0
- sraverify/checks/accessanalyzer/SRA_IAA_2.py +162 -0
- sraverify/checks/accessanalyzer/SRA_IAA_3.py +260 -0
- sraverify/checks/accessanalyzer/SRA_IAA_4.py +207 -0
- sraverify/checks/accessanalyzer/__init__.py +3 -0
- sraverify/checks/cloudtrail/SRA-CT-1.py +220 -0
- sraverify/checks/cloudtrail/SRA-CT-10.py +229 -0
- sraverify/checks/cloudtrail/SRA-CT-11.py +242 -0
- sraverify/checks/cloudtrail/SRA-CT-12.py +163 -0
- sraverify/checks/cloudtrail/SRA-CT-13.py +279 -0
- sraverify/checks/cloudtrail/SRA-CT-2.py +218 -0
- sraverify/checks/cloudtrail/SRA-CT-3.py +196 -0
- sraverify/checks/cloudtrail/SRA-CT-4.py +161 -0
- sraverify/checks/cloudtrail/SRA-CT-5.py +200 -0
- sraverify/checks/cloudtrail/SRA-CT-6.py +161 -0
- sraverify/checks/cloudtrail/SRA-CT-7.py +194 -0
- sraverify/checks/cloudtrail/SRA-CT-8.py +226 -0
- sraverify/checks/cloudtrail/SRA-CT-9.py +226 -0
- sraverify/checks/cloudtrail/__init__.py +3 -0
- sraverify/checks/config/SRA-CONFIG-1.py +197 -0
- sraverify/checks/config/__init__.py +3 -0
- sraverify/core/__init__.py +3 -0
- sraverify/core/check.py +227 -0
- sraverify/core/logging.py +37 -0
- sraverify/core/session.py +47 -0
- sraverify/lib/__init__.py +4 -0
- sraverify/lib/audit_info.py +37 -0
- sraverify/lib/banner.py +42 -0
- sraverify/lib/check_loader.py +80 -0
- sraverify/lib/org_mgmt_checker.py +86 -0
- sraverify/lib/outputs.py +46 -0
- sraverify/lib/progress.py +75 -0
- sraverify/lib/regions.py +27 -0
- sraverify/lib/session.py +23 -0
- sraverify/main.py +350 -0
- sraverify/services/__init__.py +3 -0
- sraverify/services/accessanalyzer/__init__.py +15 -0
- sraverify/services/accessanalyzer/base.py +123 -0
- sraverify/services/accessanalyzer/checks/__init__.py +3 -0
- sraverify/services/accessanalyzer/checks/sra_accessanalyzer_01.py +82 -0
- sraverify/services/accessanalyzer/checks/sra_accessanalyzer_02.py +82 -0
- sraverify/services/accessanalyzer/checks/sra_accessanalyzer_03.py +103 -0
- sraverify/services/accessanalyzer/checks/sra_accessanalyzer_04.py +139 -0
- sraverify/services/accessanalyzer/client.py +123 -0
- sraverify/services/account/__init__.py +9 -0
- sraverify/services/account/base.py +56 -0
- sraverify/services/account/checks/__init__.py +1 -0
- sraverify/services/account/checks/sra_account_01.py +65 -0
- sraverify/services/account/checks/sra_account_02.py +63 -0
- sraverify/services/account/checks/sra_account_03.py +63 -0
- sraverify/services/account/client.py +51 -0
- sraverify/services/auditmanager/__init__.py +10 -0
- sraverify/services/auditmanager/base.py +72 -0
- sraverify/services/auditmanager/checks/__init__.py +1 -0
- sraverify/services/auditmanager/checks/sra_auditmanager_01.py +58 -0
- sraverify/services/auditmanager/checks/sra_auditmanager_02.py +80 -0
- sraverify/services/auditmanager/client.py +58 -0
- sraverify/services/cloudtrail/__init__.py +33 -0
- sraverify/services/cloudtrail/base.py +167 -0
- sraverify/services/cloudtrail/checks/__init__.py +1 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_01.py +83 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_02.py +99 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_03.py +94 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_04.py +92 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_05.py +106 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_06.py +93 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_07.py +96 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_08.py +145 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_09.py +167 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_10.py +162 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_11.py +178 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_12.py +77 -0
- sraverify/services/cloudtrail/checks/sra_cloudtrail_13.py +120 -0
- sraverify/services/cloudtrail/client.py +118 -0
- sraverify/services/config/__init__.py +25 -0
- sraverify/services/config/base.py +249 -0
- sraverify/services/config/checks/__init__.py +1 -0
- sraverify/services/config/checks/sra_config_01.py +123 -0
- sraverify/services/config/checks/sra_config_02.py +156 -0
- sraverify/services/config/checks/sra_config_03.py +149 -0
- sraverify/services/config/checks/sra_config_04.py +104 -0
- sraverify/services/config/checks/sra_config_05.py +104 -0
- sraverify/services/config/checks/sra_config_06.py +194 -0
- sraverify/services/config/checks/sra_config_07.py +162 -0
- sraverify/services/config/checks/sra_config_08.py +185 -0
- sraverify/services/config/checks/sra_config_09.py +177 -0
- sraverify/services/config/client.py +264 -0
- sraverify/services/ec2/__init__.py +8 -0
- sraverify/services/ec2/base.py +75 -0
- sraverify/services/ec2/checks/__init__.py +1 -0
- sraverify/services/ec2/checks/sra_ec2_01.py +83 -0
- sraverify/services/ec2/client.py +63 -0
- sraverify/services/firewallmanager/__init__.py +23 -0
- sraverify/services/firewallmanager/base.py +48 -0
- sraverify/services/firewallmanager/checks/__init__.py +1 -0
- sraverify/services/firewallmanager/checks/sra_firewallmanager_01.py +75 -0
- sraverify/services/firewallmanager/checks/sra_firewallmanager_02.py +57 -0
- sraverify/services/firewallmanager/checks/sra_firewallmanager_03.py +51 -0
- sraverify/services/firewallmanager/checks/sra_firewallmanager_04.py +51 -0
- sraverify/services/firewallmanager/checks/sra_firewallmanager_05.py +51 -0
- sraverify/services/firewallmanager/checks/sra_firewallmanager_06.py +51 -0
- sraverify/services/firewallmanager/checks/sra_firewallmanager_07.py +51 -0
- sraverify/services/firewallmanager/checks/sra_firewallmanager_08.py +61 -0
- sraverify/services/firewallmanager/checks/sra_firewallmanager_09.py +61 -0
- sraverify/services/firewallmanager/checks/sra_firewallmanager_10.py +71 -0
- sraverify/services/firewallmanager/client.py +40 -0
- sraverify/services/guardduty/__init__.py +58 -0
- sraverify/services/guardduty/base.py +207 -0
- sraverify/services/guardduty/checks/__init__.py +3 -0
- sraverify/services/guardduty/checks/sra_guardduty_01.py +51 -0
- sraverify/services/guardduty/checks/sra_guardduty_02.py +80 -0
- sraverify/services/guardduty/checks/sra_guardduty_03.py +77 -0
- sraverify/services/guardduty/checks/sra_guardduty_04.py +84 -0
- sraverify/services/guardduty/checks/sra_guardduty_05.py +84 -0
- sraverify/services/guardduty/checks/sra_guardduty_06.py +84 -0
- sraverify/services/guardduty/checks/sra_guardduty_07.py +85 -0
- sraverify/services/guardduty/checks/sra_guardduty_08.py +83 -0
- sraverify/services/guardduty/checks/sra_guardduty_09.py +84 -0
- sraverify/services/guardduty/checks/sra_guardduty_10.py +83 -0
- sraverify/services/guardduty/checks/sra_guardduty_11.py +93 -0
- sraverify/services/guardduty/checks/sra_guardduty_12.py +83 -0
- sraverify/services/guardduty/checks/sra_guardduty_13.py +90 -0
- sraverify/services/guardduty/checks/sra_guardduty_14.py +136 -0
- sraverify/services/guardduty/checks/sra_guardduty_15.py +94 -0
- sraverify/services/guardduty/checks/sra_guardduty_16.py +94 -0
- sraverify/services/guardduty/checks/sra_guardduty_17.py +91 -0
- sraverify/services/guardduty/checks/sra_guardduty_18.py +91 -0
- sraverify/services/guardduty/checks/sra_guardduty_19.py +91 -0
- sraverify/services/guardduty/checks/sra_guardduty_20.py +111 -0
- sraverify/services/guardduty/checks/sra_guardduty_21.py +112 -0
- sraverify/services/guardduty/checks/sra_guardduty_22.py +111 -0
- sraverify/services/guardduty/checks/sra_guardduty_23.py +154 -0
- sraverify/services/guardduty/checks/sra_guardduty_24.py +111 -0
- sraverify/services/guardduty/checks/sra_guardduty_25.py +111 -0
- sraverify/services/guardduty/client.py +107 -0
- sraverify/services/inspector/__init__.py +29 -0
- sraverify/services/inspector/base.py +233 -0
- sraverify/services/inspector/checks/__init__.py +3 -0
- sraverify/services/inspector/checks/sra_inspector_01.py +69 -0
- sraverify/services/inspector/checks/sra_inspector_02.py +68 -0
- sraverify/services/inspector/checks/sra_inspector_03.py +68 -0
- sraverify/services/inspector/checks/sra_inspector_04.py +70 -0
- sraverify/services/inspector/checks/sra_inspector_05.py +69 -0
- sraverify/services/inspector/checks/sra_inspector_06.py +115 -0
- sraverify/services/inspector/checks/sra_inspector_07.py +109 -0
- sraverify/services/inspector/checks/sra_inspector_08.py +69 -0
- sraverify/services/inspector/checks/sra_inspector_09.py +69 -0
- sraverify/services/inspector/checks/sra_inspector_10.py +69 -0
- sraverify/services/inspector/checks/sra_inspector_11.py +69 -0
- sraverify/services/inspector/client.py +99 -0
- sraverify/services/macie/__init__.py +27 -0
- sraverify/services/macie/base.py +271 -0
- sraverify/services/macie/checks/__init__.py +1 -0
- sraverify/services/macie/checks/sra_macie_01.py +100 -0
- sraverify/services/macie/checks/sra_macie_02.py +102 -0
- sraverify/services/macie/checks/sra_macie_03.py +152 -0
- sraverify/services/macie/checks/sra_macie_04.py +120 -0
- sraverify/services/macie/checks/sra_macie_05.py +85 -0
- sraverify/services/macie/checks/sra_macie_06.py +124 -0
- sraverify/services/macie/checks/sra_macie_07.py +138 -0
- sraverify/services/macie/checks/sra_macie_08.py +82 -0
- sraverify/services/macie/checks/sra_macie_09.py +103 -0
- sraverify/services/macie/checks/sra_macie_10.py +81 -0
- sraverify/services/macie/client.py +220 -0
- sraverify/services/s3/__init__.py +16 -0
- sraverify/services/s3/base.py +69 -0
- sraverify/services/s3/checks/__init__.py +1 -0
- sraverify/services/s3/checks/sra_s3_01.py +89 -0
- sraverify/services/s3/checks/sra_s3_02.py +89 -0
- sraverify/services/s3/checks/sra_s3_03.py +88 -0
- sraverify/services/s3/checks/sra_s3_04.py +88 -0
- sraverify/services/s3/client.py +52 -0
- sraverify/services/securityhub/__init__.py +27 -0
- sraverify/services/securityhub/base.py +349 -0
- sraverify/services/securityhub/checks/__init__.py +1 -0
- sraverify/services/securityhub/checks/sra_securityhub_01.py +115 -0
- sraverify/services/securityhub/checks/sra_securityhub_02.py +114 -0
- sraverify/services/securityhub/checks/sra_securityhub_03.py +136 -0
- sraverify/services/securityhub/checks/sra_securityhub_04.py +75 -0
- sraverify/services/securityhub/checks/sra_securityhub_05.py +102 -0
- sraverify/services/securityhub/checks/sra_securityhub_06.py +113 -0
- sraverify/services/securityhub/checks/sra_securityhub_07.py +121 -0
- sraverify/services/securityhub/checks/sra_securityhub_08.py +113 -0
- sraverify/services/securityhub/checks/sra_securityhub_09.py +100 -0
- sraverify/services/securityhub/checks/sra_securityhub_10.py +94 -0
- sraverify/services/securityhub/checks/sra_securityhub_11.py +73 -0
- sraverify/services/securityhub/client.py +249 -0
- sraverify/services/securityincidentresponse/__init__.py +13 -0
- sraverify/services/securityincidentresponse/base.py +95 -0
- sraverify/services/securityincidentresponse/checks/__init__.py +1 -0
- sraverify/services/securityincidentresponse/checks/sra_securityincidentresponse_01.py +77 -0
- sraverify/services/securityincidentresponse/checks/sra_securityincidentresponse_02.py +72 -0
- sraverify/services/securityincidentresponse/checks/sra_securityincidentresponse_03.py +86 -0
- sraverify/services/securityincidentresponse/checks/sra_securityincidentresponse_04.py +117 -0
- sraverify/services/securityincidentresponse/checks/sra_securityincidentresponse_05.py +55 -0
- sraverify/services/securityincidentresponse/client.py +71 -0
- sraverify/services/securitylake/__init__.py +39 -0
- sraverify/services/securitylake/base.py +461 -0
- sraverify/services/securitylake/checks/__init__.py +1 -0
- sraverify/services/securitylake/checks/sra_securitylake_01.py +98 -0
- sraverify/services/securitylake/checks/sra_securitylake_02.py +133 -0
- sraverify/services/securitylake/checks/sra_securitylake_03.py +116 -0
- sraverify/services/securitylake/checks/sra_securitylake_04.py +72 -0
- sraverify/services/securitylake/checks/sra_securitylake_05.py +116 -0
- sraverify/services/securitylake/checks/sra_securitylake_06.py +104 -0
- sraverify/services/securitylake/checks/sra_securitylake_07.py +108 -0
- sraverify/services/securitylake/checks/sra_securitylake_08.py +107 -0
- sraverify/services/securitylake/checks/sra_securitylake_09.py +107 -0
- sraverify/services/securitylake/checks/sra_securitylake_10.py +106 -0
- sraverify/services/securitylake/checks/sra_securitylake_11.py +109 -0
- sraverify/services/securitylake/checks/sra_securitylake_12.py +108 -0
- sraverify/services/securitylake/checks/sra_securitylake_13.py +108 -0
- sraverify/services/securitylake/checks/sra_securitylake_14.py +72 -0
- sraverify/services/securitylake/checks/sra_securitylake_15.py +120 -0
- sraverify/services/securitylake/checks/sra_securitylake_16.py +104 -0
- sraverify/services/securitylake/checks/sra_securitylake_17.py +103 -0
- sraverify/services/securitylake/client.py +247 -0
- sraverify/services/shield/__init__.py +33 -0
- sraverify/services/shield/base.py +199 -0
- sraverify/services/shield/checks/__init__.py +1 -0
- sraverify/services/shield/checks/sra_shield_01.py +68 -0
- sraverify/services/shield/checks/sra_shield_02.py +77 -0
- sraverify/services/shield/checks/sra_shield_03.py +84 -0
- sraverify/services/shield/checks/sra_shield_04.py +84 -0
- sraverify/services/shield/checks/sra_shield_05.py +84 -0
- sraverify/services/shield/checks/sra_shield_06.py +84 -0
- sraverify/services/shield/checks/sra_shield_07.py +84 -0
- sraverify/services/shield/checks/sra_shield_08.py +69 -0
- sraverify/services/shield/checks/sra_shield_09.py +86 -0
- sraverify/services/shield/checks/sra_shield_10.py +100 -0
- sraverify/services/shield/checks/sra_shield_11.py +71 -0
- sraverify/services/shield/checks/sra_shield_12.py +130 -0
- sraverify/services/shield/checks/sra_shield_13.py +112 -0
- sraverify/services/shield/checks/sra_shield_14.py +111 -0
- sraverify/services/shield/client.py +214 -0
- sraverify/services/waf/__init__.py +21 -0
- sraverify/services/waf/base.py +100 -0
- sraverify/services/waf/checks/__init__.py +1 -0
- sraverify/services/waf/checks/sra_waf_01.py +63 -0
- sraverify/services/waf/checks/sra_waf_02.py +82 -0
- sraverify/services/waf/checks/sra_waf_03.py +123 -0
- sraverify/services/waf/checks/sra_waf_04.py +94 -0
- sraverify/services/waf/checks/sra_waf_05.py +94 -0
- sraverify/services/waf/checks/sra_waf_06.py +91 -0
- sraverify/services/waf/checks/sra_waf_07.py +94 -0
- sraverify/services/waf/checks/sra_waf_08.py +66 -0
- sraverify/services/waf/checks/sra_waf_09.py +95 -0
- sraverify/services/waf/client.py +109 -0
- sraverify/utils/__init__.py +3 -0
- sraverify/utils/banner.py +65 -0
- sraverify/utils/outputs.py +57 -0
- sraverify/utils/progress.py +97 -0
- sraverify-0.1.0.dist-info/LICENSE +175 -0
- sraverify-0.1.0.dist-info/METADATA +516 -0
- sraverify-0.1.0.dist-info/NOTICE +1 -0
- sraverify-0.1.0.dist-info/RECORD +261 -0
- sraverify-0.1.0.dist-info/WHEEL +5 -0
- sraverify-0.1.0.dist-info/entry_points.txt +2 -0
- sraverify-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
from typing import Dict, Any
|
|
2
|
+
from sraverify.core.check import SecurityCheck
|
|
3
|
+
from sraverify.services.securityincidentresponse.client import SecurityIncidentResponseClient
|
|
4
|
+
from sraverify.core.logging import logger
|
|
5
|
+
|
|
6
|
+
class SecurityIncidentResponseCheck(SecurityCheck):
|
|
7
|
+
def __init__(self):
|
|
8
|
+
super().__init__(
|
|
9
|
+
account_type="management",
|
|
10
|
+
service="SecurityIncidentResponse",
|
|
11
|
+
resource_type="AWS::Organizations::DelegatedAdministrator"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
def _setup_clients(self):
|
|
15
|
+
self._clients.clear()
|
|
16
|
+
# Use first region specified, or us-east-1 as fallback
|
|
17
|
+
region = self.regions[0] if self.regions else "us-east-1"
|
|
18
|
+
self._clients[region] = SecurityIncidentResponseClient(region, session=self.session)
|
|
19
|
+
|
|
20
|
+
def get_delegated_administrators(self) -> Dict[str, Any]:
|
|
21
|
+
"""Get delegated administrators for Security Incident Response."""
|
|
22
|
+
region = self.regions[0] if self.regions else "us-east-1"
|
|
23
|
+
client = self.get_client(region)
|
|
24
|
+
if not client:
|
|
25
|
+
return {}
|
|
26
|
+
return client.list_delegated_administrators()
|
|
27
|
+
|
|
28
|
+
def list_memberships(self) -> Dict[str, Any]:
|
|
29
|
+
"""List Security Incident Response memberships."""
|
|
30
|
+
region = self.regions[0] if self.regions else "us-east-1"
|
|
31
|
+
client = self.get_client(region)
|
|
32
|
+
if not client:
|
|
33
|
+
return {}
|
|
34
|
+
return client.list_memberships()
|
|
35
|
+
|
|
36
|
+
def get_membership(self, membership_id: str) -> Dict[str, Any]:
|
|
37
|
+
"""Get Security Incident Response membership details."""
|
|
38
|
+
sir_region = self.discover_sir_region()
|
|
39
|
+
client = self.get_client(sir_region)
|
|
40
|
+
if not client:
|
|
41
|
+
self._clients[sir_region] = SecurityIncidentResponseClient(sir_region, session=self.session)
|
|
42
|
+
client = self.get_client(sir_region)
|
|
43
|
+
return client.get_membership(membership_id)
|
|
44
|
+
|
|
45
|
+
def batch_get_member_account_details(self, membership_id: str, account_ids: list) -> Dict[str, Any]:
|
|
46
|
+
"""Get member account details for multiple accounts."""
|
|
47
|
+
sir_region = self.discover_sir_region()
|
|
48
|
+
client = self.get_client(sir_region)
|
|
49
|
+
if not client:
|
|
50
|
+
self._clients[sir_region] = SecurityIncidentResponseClient(sir_region, session=self.session)
|
|
51
|
+
client = self.get_client(sir_region)
|
|
52
|
+
return client.batch_get_member_account_details(membership_id, account_ids)
|
|
53
|
+
|
|
54
|
+
def get_organization_accounts(self) -> list:
|
|
55
|
+
"""Get all accounts in the organization."""
|
|
56
|
+
region = self.regions[0] if self.regions else "us-east-1"
|
|
57
|
+
client = self.get_client(region)
|
|
58
|
+
if not client:
|
|
59
|
+
return []
|
|
60
|
+
|
|
61
|
+
response = client.list_accounts()
|
|
62
|
+
if "Error" in response:
|
|
63
|
+
return []
|
|
64
|
+
|
|
65
|
+
return response.get("Accounts", [])
|
|
66
|
+
|
|
67
|
+
def get_role(self, role_name: str) -> Dict[str, Any]:
|
|
68
|
+
"""Get IAM role details."""
|
|
69
|
+
region = self.regions[0] if self.regions else "us-east-1"
|
|
70
|
+
client = self.get_client(region)
|
|
71
|
+
if not client:
|
|
72
|
+
return {}
|
|
73
|
+
return client.get_role(role_name)
|
|
74
|
+
|
|
75
|
+
def discover_sir_region(self) -> str:
|
|
76
|
+
"""Discover the region where Security Incident Response is configured."""
|
|
77
|
+
# Try each region until we find one with memberships
|
|
78
|
+
regions_to_try = self.regions
|
|
79
|
+
|
|
80
|
+
for region in regions_to_try:
|
|
81
|
+
try:
|
|
82
|
+
# Create a temporary client for this region
|
|
83
|
+
temp_client = SecurityIncidentResponseClient(region, session=self.session)
|
|
84
|
+
response = temp_client.list_memberships()
|
|
85
|
+
|
|
86
|
+
if "Error" not in response:
|
|
87
|
+
memberships = response.get("items", [])
|
|
88
|
+
if memberships:
|
|
89
|
+
# Return the region from the first membership
|
|
90
|
+
return memberships[0].get("region", region)
|
|
91
|
+
except Exception:
|
|
92
|
+
continue
|
|
93
|
+
|
|
94
|
+
# Fallback to first region or us-east-1
|
|
95
|
+
return self.regions[0] if self.regions else "us-east-1"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Security Incident Response checks
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from typing import Dict, List, Any
|
|
2
|
+
from sraverify.services.securityincidentresponse.base import SecurityIncidentResponseCheck
|
|
3
|
+
|
|
4
|
+
class SRA_SECURITYINCIDENTRESPONSE_01(SecurityIncidentResponseCheck):
|
|
5
|
+
def __init__(self):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.check_id = "SRA-SECURITYINCIDENTRESPONSE-01"
|
|
8
|
+
self.check_name = "Security Incident Response delegated admin is audit account"
|
|
9
|
+
self.description = "Verifies that the Security Incident Response delegated administrator is configured and is the audit account"
|
|
10
|
+
self.severity = "HIGH"
|
|
11
|
+
self.check_logic = "Lists delegated administrators for security-ir.amazonaws.com and verifies the audit account is designated"
|
|
12
|
+
|
|
13
|
+
def execute(self) -> List[Dict[str, Any]]:
|
|
14
|
+
region = self.regions[0] if self.regions else "us-east-1"
|
|
15
|
+
|
|
16
|
+
# Check if audit accounts are provided
|
|
17
|
+
audit_accounts = getattr(self, '_audit_accounts', None)
|
|
18
|
+
if not audit_accounts:
|
|
19
|
+
self.findings.append(self.create_finding(
|
|
20
|
+
status="ERROR",
|
|
21
|
+
region=region,
|
|
22
|
+
resource_id=None,
|
|
23
|
+
actual_value="No audit accounts specified",
|
|
24
|
+
remediation="Run with --audit-account parameter to specify audit account IDs"
|
|
25
|
+
))
|
|
26
|
+
return self.findings
|
|
27
|
+
|
|
28
|
+
response = self.get_delegated_administrators()
|
|
29
|
+
|
|
30
|
+
if "Error" in response:
|
|
31
|
+
self.findings.append(self.create_finding(
|
|
32
|
+
status="ERROR",
|
|
33
|
+
region=region,
|
|
34
|
+
resource_id=None,
|
|
35
|
+
actual_value=response["Error"].get("Message", "Unknown error"),
|
|
36
|
+
remediation="Check IAM permissions for Organizations API access"
|
|
37
|
+
))
|
|
38
|
+
return self.findings
|
|
39
|
+
|
|
40
|
+
delegated_admins = response.get("DelegatedAdministrators", [])
|
|
41
|
+
|
|
42
|
+
if not delegated_admins:
|
|
43
|
+
self.findings.append(self.create_finding(
|
|
44
|
+
status="FAIL",
|
|
45
|
+
region=region,
|
|
46
|
+
resource_id=None,
|
|
47
|
+
actual_value="No delegated administrator configured for Security Incident Response",
|
|
48
|
+
remediation="Configure a delegated administrator for Security Incident Response using: aws organizations register-delegated-administrator --account-id <audit-account-id> --service-principal security-ir.amazonaws.com"
|
|
49
|
+
))
|
|
50
|
+
else:
|
|
51
|
+
# Check if any of the delegated admins is the audit account
|
|
52
|
+
audit_admin_found = False
|
|
53
|
+
|
|
54
|
+
for admin in delegated_admins:
|
|
55
|
+
admin_id = admin.get("Id")
|
|
56
|
+
if admin_id in audit_accounts:
|
|
57
|
+
audit_admin_found = True
|
|
58
|
+
self.findings.append(self.create_finding(
|
|
59
|
+
status="PASS",
|
|
60
|
+
region=region,
|
|
61
|
+
resource_id=admin_id,
|
|
62
|
+
actual_value=f"Audit account {admin_id} is configured as delegated administrator",
|
|
63
|
+
remediation="No remediation needed"
|
|
64
|
+
))
|
|
65
|
+
break
|
|
66
|
+
|
|
67
|
+
if not audit_admin_found:
|
|
68
|
+
admin_ids = [admin.get("Id") for admin in delegated_admins]
|
|
69
|
+
self.findings.append(self.create_finding(
|
|
70
|
+
status="FAIL",
|
|
71
|
+
region=region,
|
|
72
|
+
resource_id=None,
|
|
73
|
+
actual_value=f"Delegated administrators found: {admin_ids}, but none are audit accounts: {audit_accounts}",
|
|
74
|
+
remediation="Register the audit account as delegated administrator: aws organizations register-delegated-administrator --account-id <audit-account-id> --service-principal security-ir.amazonaws.com"
|
|
75
|
+
))
|
|
76
|
+
|
|
77
|
+
return self.findings
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from typing import Dict, List, Any
|
|
2
|
+
from sraverify.services.securityincidentresponse.base import SecurityIncidentResponseCheck
|
|
3
|
+
|
|
4
|
+
class SRA_SECURITYINCIDENTRESPONSE_02(SecurityIncidentResponseCheck):
|
|
5
|
+
def __init__(self):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.account_type = "audit"
|
|
8
|
+
self.check_id = "SRA-SECURITYINCIDENTRESPONSE-02"
|
|
9
|
+
self.check_name = "Security Incident Response membership active"
|
|
10
|
+
self.description = "Verifies that Security Incident Response membership is active"
|
|
11
|
+
self.severity = "HIGH"
|
|
12
|
+
self.check_logic = "Lists memberships and verifies status is Active"
|
|
13
|
+
|
|
14
|
+
def execute(self) -> List[Dict[str, Any]]:
|
|
15
|
+
region = self.regions[0] if self.regions else "us-east-1"
|
|
16
|
+
|
|
17
|
+
response = self.list_memberships()
|
|
18
|
+
|
|
19
|
+
if "Error" in response:
|
|
20
|
+
self.findings.append(self.create_finding(
|
|
21
|
+
status="ERROR",
|
|
22
|
+
region=region,
|
|
23
|
+
resource_id=None,
|
|
24
|
+
actual_value=response["Error"].get("Message", "Unknown error"),
|
|
25
|
+
remediation="Check IAM permissions for Security Incident Response API access"
|
|
26
|
+
))
|
|
27
|
+
return self.findings
|
|
28
|
+
|
|
29
|
+
memberships = response.get("items", [])
|
|
30
|
+
|
|
31
|
+
if not memberships:
|
|
32
|
+
self.findings.append(self.create_finding(
|
|
33
|
+
status="FAIL",
|
|
34
|
+
region=region,
|
|
35
|
+
resource_id=None,
|
|
36
|
+
actual_value="No Security Incident Response memberships found",
|
|
37
|
+
remediation="Create a Security Incident Response membership through the AWS console or API"
|
|
38
|
+
))
|
|
39
|
+
else:
|
|
40
|
+
active_found = False
|
|
41
|
+
for membership in memberships:
|
|
42
|
+
membership_id = membership.get("membershipId")
|
|
43
|
+
status = membership.get("membershipStatus")
|
|
44
|
+
|
|
45
|
+
if status == "Active":
|
|
46
|
+
active_found = True
|
|
47
|
+
self.findings.append(self.create_finding(
|
|
48
|
+
status="PASS",
|
|
49
|
+
region=region,
|
|
50
|
+
resource_id=membership_id,
|
|
51
|
+
actual_value=f"Membership {membership_id} is Active",
|
|
52
|
+
remediation="No remediation needed"
|
|
53
|
+
))
|
|
54
|
+
else:
|
|
55
|
+
self.findings.append(self.create_finding(
|
|
56
|
+
status="FAIL",
|
|
57
|
+
region=region,
|
|
58
|
+
resource_id=membership_id,
|
|
59
|
+
actual_value=f"Membership {membership_id} status is {status}",
|
|
60
|
+
remediation="Activate the Security Incident Response membership through the AWS console"
|
|
61
|
+
))
|
|
62
|
+
|
|
63
|
+
if not active_found:
|
|
64
|
+
self.findings.append(self.create_finding(
|
|
65
|
+
status="FAIL",
|
|
66
|
+
region=region,
|
|
67
|
+
resource_id=None,
|
|
68
|
+
actual_value="No active Security Incident Response memberships found",
|
|
69
|
+
remediation="Activate an existing membership or create a new active membership"
|
|
70
|
+
))
|
|
71
|
+
|
|
72
|
+
return self.findings
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from typing import Dict, List, Any
|
|
2
|
+
from sraverify.services.securityincidentresponse.base import SecurityIncidentResponseCheck
|
|
3
|
+
|
|
4
|
+
class SRA_SECURITYINCIDENTRESPONSE_03(SecurityIncidentResponseCheck):
|
|
5
|
+
def __init__(self):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.account_type = "audit"
|
|
8
|
+
self.check_id = "SRA-SECURITYINCIDENTRESPONSE-03"
|
|
9
|
+
self.check_name = "Security Incident Response proactive response enabled"
|
|
10
|
+
self.description = "Verifies that Security Incident Response proactive response (Triage) feature is enabled"
|
|
11
|
+
self.severity = "MEDIUM"
|
|
12
|
+
self.check_logic = "Lists memberships and checks if Triage opt-in feature is enabled"
|
|
13
|
+
|
|
14
|
+
def execute(self) -> List[Dict[str, Any]]:
|
|
15
|
+
# Discover the region where Security Incident Response is configured
|
|
16
|
+
region = self.discover_sir_region()
|
|
17
|
+
|
|
18
|
+
# First get list of memberships
|
|
19
|
+
memberships_response = self.list_memberships()
|
|
20
|
+
|
|
21
|
+
if "Error" in memberships_response:
|
|
22
|
+
self.findings.append(self.create_finding(
|
|
23
|
+
status="ERROR",
|
|
24
|
+
region=region,
|
|
25
|
+
resource_id=None,
|
|
26
|
+
actual_value=memberships_response["Error"].get("Message", "Unknown error"),
|
|
27
|
+
remediation="Check IAM permissions for Security Incident Response API access"
|
|
28
|
+
))
|
|
29
|
+
return self.findings
|
|
30
|
+
|
|
31
|
+
memberships = memberships_response.get("items", [])
|
|
32
|
+
|
|
33
|
+
if not memberships:
|
|
34
|
+
self.findings.append(self.create_finding(
|
|
35
|
+
status="FAIL",
|
|
36
|
+
region=region,
|
|
37
|
+
resource_id=None,
|
|
38
|
+
actual_value="No Security Incident Response memberships found",
|
|
39
|
+
remediation="Create a Security Incident Response membership first"
|
|
40
|
+
))
|
|
41
|
+
return self.findings
|
|
42
|
+
|
|
43
|
+
# Check each membership for proactive response
|
|
44
|
+
for membership in memberships:
|
|
45
|
+
membership_id = membership.get("membershipId")
|
|
46
|
+
|
|
47
|
+
# Get detailed membership info
|
|
48
|
+
membership_details = self.get_membership(membership_id)
|
|
49
|
+
|
|
50
|
+
if "Error" in membership_details:
|
|
51
|
+
self.findings.append(self.create_finding(
|
|
52
|
+
status="ERROR",
|
|
53
|
+
region=region,
|
|
54
|
+
resource_id=membership_id,
|
|
55
|
+
actual_value=membership_details["Error"].get("Message", "Unknown error"),
|
|
56
|
+
remediation="Check IAM permissions for Security Incident Response GetMembership API access"
|
|
57
|
+
))
|
|
58
|
+
continue
|
|
59
|
+
|
|
60
|
+
# Check opt-in features for Triage
|
|
61
|
+
opt_in_features = membership_details.get("optInFeatures", [])
|
|
62
|
+
triage_enabled = False
|
|
63
|
+
|
|
64
|
+
for feature in opt_in_features:
|
|
65
|
+
if feature.get("featureName") == "Triage" and feature.get("isEnabled"):
|
|
66
|
+
triage_enabled = True
|
|
67
|
+
break
|
|
68
|
+
|
|
69
|
+
if triage_enabled:
|
|
70
|
+
self.findings.append(self.create_finding(
|
|
71
|
+
status="PASS",
|
|
72
|
+
region=region,
|
|
73
|
+
resource_id=membership_id,
|
|
74
|
+
actual_value="Proactive response (Triage) is enabled",
|
|
75
|
+
remediation="No remediation needed"
|
|
76
|
+
))
|
|
77
|
+
else:
|
|
78
|
+
self.findings.append(self.create_finding(
|
|
79
|
+
status="FAIL",
|
|
80
|
+
region=region,
|
|
81
|
+
resource_id=membership_id,
|
|
82
|
+
actual_value="Proactive response (Triage) is not enabled",
|
|
83
|
+
remediation="Enable proactive response in the Security Incident Response console under membership settings"
|
|
84
|
+
))
|
|
85
|
+
|
|
86
|
+
return self.findings
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from typing import Dict, List, Any
|
|
2
|
+
from sraverify.services.securityincidentresponse.base import SecurityIncidentResponseCheck
|
|
3
|
+
|
|
4
|
+
class SRA_SECURITYINCIDENTRESPONSE_04(SecurityIncidentResponseCheck):
|
|
5
|
+
def __init__(self):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.account_type = "audit"
|
|
8
|
+
self.check_id = "SRA-SECURITYINCIDENTRESPONSE-04"
|
|
9
|
+
self.check_name = "Security Incident Response enabled for all organization accounts"
|
|
10
|
+
self.description = "Verifies that all active organization accounts are covered by Security Incident Response"
|
|
11
|
+
self.severity = "HIGH"
|
|
12
|
+
self.check_logic = "Gets all organization accounts and checks if each is associated with Security Incident Response membership"
|
|
13
|
+
|
|
14
|
+
def execute(self) -> List[Dict[str, Any]]:
|
|
15
|
+
# Discover the region where Security Incident Response is configured
|
|
16
|
+
region = self.discover_sir_region()
|
|
17
|
+
|
|
18
|
+
# Get all organization accounts
|
|
19
|
+
org_accounts = self.get_organization_accounts()
|
|
20
|
+
if not org_accounts:
|
|
21
|
+
self.findings.append(self.create_finding(
|
|
22
|
+
status="ERROR",
|
|
23
|
+
region=region,
|
|
24
|
+
resource_id=None,
|
|
25
|
+
actual_value="Unable to retrieve organization accounts",
|
|
26
|
+
remediation="Check IAM permissions for Organizations API access"
|
|
27
|
+
))
|
|
28
|
+
return self.findings
|
|
29
|
+
|
|
30
|
+
# Get active memberships
|
|
31
|
+
memberships_response = self.list_memberships()
|
|
32
|
+
if "Error" in memberships_response:
|
|
33
|
+
self.findings.append(self.create_finding(
|
|
34
|
+
status="ERROR",
|
|
35
|
+
region=region,
|
|
36
|
+
resource_id=None,
|
|
37
|
+
actual_value=memberships_response["Error"].get("Message", "Unknown error"),
|
|
38
|
+
remediation="Check IAM permissions for Security Incident Response API access"
|
|
39
|
+
))
|
|
40
|
+
return self.findings
|
|
41
|
+
|
|
42
|
+
memberships = memberships_response.get("items", [])
|
|
43
|
+
active_memberships = [m for m in memberships if m.get("membershipStatus") == "Active"]
|
|
44
|
+
|
|
45
|
+
if not active_memberships:
|
|
46
|
+
self.findings.append(self.create_finding(
|
|
47
|
+
status="ERROR",
|
|
48
|
+
region=region,
|
|
49
|
+
resource_id=None,
|
|
50
|
+
actual_value="No active Security Incident Response memberships found",
|
|
51
|
+
remediation="Create and activate a Security Incident Response membership first"
|
|
52
|
+
))
|
|
53
|
+
return self.findings
|
|
54
|
+
|
|
55
|
+
# Use first active membership
|
|
56
|
+
membership_id = active_memberships[0].get("membershipId")
|
|
57
|
+
|
|
58
|
+
# Get active organization accounts
|
|
59
|
+
active_accounts = [acc for acc in org_accounts if acc.get("Status") == "ACTIVE"]
|
|
60
|
+
account_ids = [acc.get("Id") for acc in active_accounts]
|
|
61
|
+
|
|
62
|
+
# Process accounts in batches of 100 (API limit)
|
|
63
|
+
batch_size = 100
|
|
64
|
+
for i in range(0, len(account_ids), batch_size):
|
|
65
|
+
batch_account_ids = account_ids[i:i + batch_size]
|
|
66
|
+
|
|
67
|
+
response = self.batch_get_member_account_details(membership_id, batch_account_ids)
|
|
68
|
+
|
|
69
|
+
if "Error" in response:
|
|
70
|
+
for account_id in batch_account_ids:
|
|
71
|
+
self.findings.append(self.create_finding(
|
|
72
|
+
status="ERROR",
|
|
73
|
+
region=region,
|
|
74
|
+
resource_id=account_id,
|
|
75
|
+
actual_value=response["Error"].get("Message", "Unknown error"),
|
|
76
|
+
remediation="Check IAM permissions for Security Incident Response BatchGetMemberAccountDetails API access or ensure you specified the region where Security Incident Response is enabled with the --regions flag"
|
|
77
|
+
))
|
|
78
|
+
continue
|
|
79
|
+
|
|
80
|
+
# Process results
|
|
81
|
+
items = response.get("items", [])
|
|
82
|
+
errors = response.get("errors", [])
|
|
83
|
+
|
|
84
|
+
# Handle errors
|
|
85
|
+
for error in errors:
|
|
86
|
+
account_id = error.get("accountId")
|
|
87
|
+
self.findings.append(self.create_finding(
|
|
88
|
+
status="ERROR",
|
|
89
|
+
region=region,
|
|
90
|
+
resource_id=account_id,
|
|
91
|
+
actual_value=error.get("message", "Unknown error"),
|
|
92
|
+
remediation="Check account status and Security Incident Response configuration"
|
|
93
|
+
))
|
|
94
|
+
|
|
95
|
+
# Check each account's association status
|
|
96
|
+
for item in items:
|
|
97
|
+
account_id = item.get("accountId")
|
|
98
|
+
relationship_status = item.get("relationshipStatus")
|
|
99
|
+
|
|
100
|
+
if relationship_status == "Associated":
|
|
101
|
+
self.findings.append(self.create_finding(
|
|
102
|
+
status="PASS",
|
|
103
|
+
region=region,
|
|
104
|
+
resource_id=account_id,
|
|
105
|
+
actual_value=f"Account {account_id} is associated with Security Incident Response",
|
|
106
|
+
remediation="No remediation needed"
|
|
107
|
+
))
|
|
108
|
+
else:
|
|
109
|
+
self.findings.append(self.create_finding(
|
|
110
|
+
status="FAIL",
|
|
111
|
+
region=region,
|
|
112
|
+
resource_id=account_id,
|
|
113
|
+
actual_value=f"Account {account_id} relationship status is {relationship_status}",
|
|
114
|
+
remediation="Associate the account with Security Incident Response membership through organizational units or direct association"
|
|
115
|
+
))
|
|
116
|
+
|
|
117
|
+
return self.findings
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from typing import Dict, List, Any
|
|
2
|
+
from sraverify.services.securityincidentresponse.base import SecurityIncidentResponseCheck
|
|
3
|
+
|
|
4
|
+
class SRA_SECURITYINCIDENTRESPONSE_05(SecurityIncidentResponseCheck):
|
|
5
|
+
def __init__(self):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.account_type = "application"
|
|
8
|
+
self.check_id = "SRA-SECURITYINCIDENTRESPONSE-05"
|
|
9
|
+
self.check_name = "Security Incident Response triage service linked role exists"
|
|
10
|
+
self.description = "Verifies that the AWSServiceRoleForSecurityIncidentResponse_Triage service linked role exists"
|
|
11
|
+
self.severity = "MEDIUM"
|
|
12
|
+
self.check_logic = "Checks if the AWSServiceRoleForSecurityIncidentResponse_Triage IAM role exists in the account"
|
|
13
|
+
|
|
14
|
+
def execute(self) -> List[Dict[str, Any]]:
|
|
15
|
+
region = "global" # IAM is global
|
|
16
|
+
role_name = "AWSServiceRoleForSecurityIncidentResponse_Triage"
|
|
17
|
+
management_account_id = self.get_management_accountId(self.session)
|
|
18
|
+
is_management_account = self.account_id == management_account_id
|
|
19
|
+
|
|
20
|
+
response = self.get_role(role_name)
|
|
21
|
+
|
|
22
|
+
if "Error" in response:
|
|
23
|
+
error_code = response["Error"].get("Code")
|
|
24
|
+
if error_code == "NoSuchEntity":
|
|
25
|
+
if is_management_account:
|
|
26
|
+
remediation = "Security Incident Response cannot automatically create the triage service linked role in the management account. Create it manually using: aws iam create-service-linked-role --aws-service-name triage.security-ir.amazonaws.com"
|
|
27
|
+
else:
|
|
28
|
+
remediation = "The triage service linked role is created when onboarding to Security Incident Response. If deleted, recreate by onboarding to the service again or manually using: aws iam create-service-linked-role --aws-service-name triage.security-ir.amazonaws.com"
|
|
29
|
+
|
|
30
|
+
self.findings.append(self.create_finding(
|
|
31
|
+
status="FAIL",
|
|
32
|
+
region=region,
|
|
33
|
+
resource_id=f"arn:aws:iam::{self.account_id}:role/{role_name}",
|
|
34
|
+
actual_value=f"Service linked role {role_name} does not exist",
|
|
35
|
+
remediation=remediation
|
|
36
|
+
))
|
|
37
|
+
else:
|
|
38
|
+
self.findings.append(self.create_finding(
|
|
39
|
+
status="ERROR",
|
|
40
|
+
region=region,
|
|
41
|
+
resource_id=f"arn:aws:iam::{self.account_id}:role/{role_name}",
|
|
42
|
+
actual_value=response["Error"].get("Message", "Unknown error"),
|
|
43
|
+
remediation="Check IAM permissions for GetRole API access"
|
|
44
|
+
))
|
|
45
|
+
else:
|
|
46
|
+
role_arn = response.get("Role", {}).get("Arn")
|
|
47
|
+
self.findings.append(self.create_finding(
|
|
48
|
+
status="PASS",
|
|
49
|
+
region=region,
|
|
50
|
+
resource_id=role_arn,
|
|
51
|
+
actual_value=f"Service linked role {role_name} exists",
|
|
52
|
+
remediation="No remediation needed"
|
|
53
|
+
))
|
|
54
|
+
|
|
55
|
+
return self.findings
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from typing import Dict, Optional, Any, List
|
|
2
|
+
import boto3
|
|
3
|
+
from botocore.exceptions import ClientError
|
|
4
|
+
from sraverify.core.logging import logger
|
|
5
|
+
|
|
6
|
+
class SecurityIncidentResponseClient:
|
|
7
|
+
def __init__(self, region: str, session: Optional[boto3.Session] = None):
|
|
8
|
+
self.region = region
|
|
9
|
+
self.session = session or boto3.Session()
|
|
10
|
+
self.org_client = self.session.client('organizations', region_name=region)
|
|
11
|
+
self.sir_client = self.session.client('security-ir', region_name=region)
|
|
12
|
+
self.iam_client = self.session.client('iam', region_name=region)
|
|
13
|
+
|
|
14
|
+
def list_delegated_administrators(self, service_principal: str = "security-ir.amazonaws.com") -> Dict[str, Any]:
|
|
15
|
+
"""List delegated administrators for Security Incident Response service."""
|
|
16
|
+
try:
|
|
17
|
+
response = self.org_client.list_delegated_administrators(
|
|
18
|
+
ServicePrincipal=service_principal
|
|
19
|
+
)
|
|
20
|
+
return response
|
|
21
|
+
except ClientError as e:
|
|
22
|
+
logger.error(f"Error listing delegated administrators in {self.region}: {e}")
|
|
23
|
+
return {"Error": {"Code": e.response['Error']['Code'], "Message": e.response['Error']['Message']}}
|
|
24
|
+
|
|
25
|
+
def list_memberships(self) -> Dict[str, Any]:
|
|
26
|
+
"""List Security Incident Response memberships."""
|
|
27
|
+
try:
|
|
28
|
+
response = self.sir_client.list_memberships()
|
|
29
|
+
return response
|
|
30
|
+
except ClientError as e:
|
|
31
|
+
logger.error(f"Error listing memberships in {self.region}: {e}")
|
|
32
|
+
return {"Error": {"Code": e.response['Error']['Code'], "Message": e.response['Error']['Message']}}
|
|
33
|
+
|
|
34
|
+
def get_membership(self, membership_id: str) -> Dict[str, Any]:
|
|
35
|
+
"""Get Security Incident Response membership details."""
|
|
36
|
+
try:
|
|
37
|
+
response = self.sir_client.get_membership(membershipId=membership_id)
|
|
38
|
+
return response
|
|
39
|
+
except ClientError as e:
|
|
40
|
+
logger.error(f"Error getting membership {membership_id} in {self.region}: {e}")
|
|
41
|
+
return {"Error": {"Code": e.response['Error']['Code'], "Message": e.response['Error']['Message']}}
|
|
42
|
+
|
|
43
|
+
def batch_get_member_account_details(self, membership_id: str, account_ids: List[str]) -> Dict[str, Any]:
|
|
44
|
+
"""Get member account details for multiple accounts."""
|
|
45
|
+
try:
|
|
46
|
+
response = self.sir_client.batch_get_member_account_details(
|
|
47
|
+
membershipId=membership_id,
|
|
48
|
+
accountIds=account_ids
|
|
49
|
+
)
|
|
50
|
+
return response
|
|
51
|
+
except ClientError as e:
|
|
52
|
+
logger.error(f"Error getting member account details for membership {membership_id} in {self.region}: {e}")
|
|
53
|
+
return {"Error": {"Code": e.response['Error']['Code'], "Message": e.response['Error']['Message']}}
|
|
54
|
+
|
|
55
|
+
def list_accounts(self) -> Dict[str, Any]:
|
|
56
|
+
"""List all accounts in the organization."""
|
|
57
|
+
try:
|
|
58
|
+
response = self.org_client.list_accounts()
|
|
59
|
+
return response
|
|
60
|
+
except ClientError as e:
|
|
61
|
+
logger.error(f"Error listing organization accounts in {self.region}: {e}")
|
|
62
|
+
return {"Error": {"Code": e.response['Error']['Code'], "Message": e.response['Error']['Message']}}
|
|
63
|
+
|
|
64
|
+
def get_role(self, role_name: str) -> Dict[str, Any]:
|
|
65
|
+
"""Get IAM role details."""
|
|
66
|
+
try:
|
|
67
|
+
response = self.iam_client.get_role(RoleName=role_name)
|
|
68
|
+
return response
|
|
69
|
+
except ClientError as e:
|
|
70
|
+
logger.error(f"Error getting role {role_name}: {e}")
|
|
71
|
+
return {"Error": {"Code": e.response['Error']['Code'], "Message": e.response['Error']['Message']}}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Security Lake checks."""
|
|
2
|
+
|
|
3
|
+
from sraverify.services.securitylake.checks.sra_securitylake_01 import SRA_SECURITYLAKE_01
|
|
4
|
+
from sraverify.services.securitylake.checks.sra_securitylake_02 import SRA_SECURITYLAKE_02
|
|
5
|
+
from sraverify.services.securitylake.checks.sra_securitylake_03 import SRA_SECURITYLAKE_03
|
|
6
|
+
from sraverify.services.securitylake.checks.sra_securitylake_04 import SRA_SECURITYLAKE_04
|
|
7
|
+
from sraverify.services.securitylake.checks.sra_securitylake_05 import SRA_SECURITYLAKE_05
|
|
8
|
+
from sraverify.services.securitylake.checks.sra_securitylake_06 import SRA_SECURITYLAKE_06
|
|
9
|
+
from sraverify.services.securitylake.checks.sra_securitylake_07 import SRA_SECURITYLAKE_07
|
|
10
|
+
from sraverify.services.securitylake.checks.sra_securitylake_08 import SRA_SECURITYLAKE_08
|
|
11
|
+
from sraverify.services.securitylake.checks.sra_securitylake_09 import SRA_SECURITYLAKE_09
|
|
12
|
+
from sraverify.services.securitylake.checks.sra_securitylake_10 import SRA_SECURITYLAKE_10
|
|
13
|
+
from sraverify.services.securitylake.checks.sra_securitylake_11 import SRA_SECURITYLAKE_11
|
|
14
|
+
from sraverify.services.securitylake.checks.sra_securitylake_12 import SRA_SECURITYLAKE_12
|
|
15
|
+
from sraverify.services.securitylake.checks.sra_securitylake_13 import SRA_SECURITYLAKE_13
|
|
16
|
+
from sraverify.services.securitylake.checks.sra_securitylake_14 import SRA_SECURITYLAKE_14
|
|
17
|
+
from sraverify.services.securitylake.checks.sra_securitylake_15 import SRA_SECURITYLAKE_15
|
|
18
|
+
from sraverify.services.securitylake.checks.sra_securitylake_16 import SRA_SECURITYLAKE_16
|
|
19
|
+
from sraverify.services.securitylake.checks.sra_securitylake_17 import SRA_SECURITYLAKE_17
|
|
20
|
+
|
|
21
|
+
CHECKS = {
|
|
22
|
+
"SRA-SECURITYLAKE-01": SRA_SECURITYLAKE_01,
|
|
23
|
+
"SRA-SECURITYLAKE-02": SRA_SECURITYLAKE_02,
|
|
24
|
+
"SRA-SECURITYLAKE-03": SRA_SECURITYLAKE_03,
|
|
25
|
+
"SRA-SECURITYLAKE-04": SRA_SECURITYLAKE_04,
|
|
26
|
+
"SRA-SECURITYLAKE-05": SRA_SECURITYLAKE_05,
|
|
27
|
+
"SRA-SECURITYLAKE-06": SRA_SECURITYLAKE_06,
|
|
28
|
+
"SRA-SECURITYLAKE-07": SRA_SECURITYLAKE_07,
|
|
29
|
+
"SRA-SECURITYLAKE-08": SRA_SECURITYLAKE_08,
|
|
30
|
+
"SRA-SECURITYLAKE-09": SRA_SECURITYLAKE_09,
|
|
31
|
+
"SRA-SECURITYLAKE-10": SRA_SECURITYLAKE_10,
|
|
32
|
+
"SRA-SECURITYLAKE-11": SRA_SECURITYLAKE_11,
|
|
33
|
+
"SRA-SECURITYLAKE-12": SRA_SECURITYLAKE_12,
|
|
34
|
+
"SRA-SECURITYLAKE-13": SRA_SECURITYLAKE_13,
|
|
35
|
+
"SRA-SECURITYLAKE-14": SRA_SECURITYLAKE_14,
|
|
36
|
+
"SRA-SECURITYLAKE-15": SRA_SECURITYLAKE_15,
|
|
37
|
+
"SRA-SECURITYLAKE-16": SRA_SECURITYLAKE_16,
|
|
38
|
+
"SRA-SECURITYLAKE-17": SRA_SECURITYLAKE_17
|
|
39
|
+
}
|