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,199 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base class for Shield security checks.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Dict, Any
|
|
5
|
+
from sraverify.core.check import SecurityCheck
|
|
6
|
+
from sraverify.services.shield.client import ShieldClient
|
|
7
|
+
from sraverify.core.logging import logger
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ShieldCheck(SecurityCheck):
|
|
11
|
+
"""Base class for all Shield security checks."""
|
|
12
|
+
|
|
13
|
+
# Class-level cache shared across all instances
|
|
14
|
+
_subscription_cache = {}
|
|
15
|
+
|
|
16
|
+
def __init__(self):
|
|
17
|
+
"""Initialize Shield base check."""
|
|
18
|
+
super().__init__(
|
|
19
|
+
account_type="application",
|
|
20
|
+
service="Shield",
|
|
21
|
+
resource_type="AWS::Shield::Subscription"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def _setup_clients(self):
|
|
25
|
+
"""Set up Shield clients for each region."""
|
|
26
|
+
self._clients.clear()
|
|
27
|
+
if hasattr(self, 'regions') and self.regions:
|
|
28
|
+
for region in self.regions:
|
|
29
|
+
self._clients[region] = ShieldClient(region, session=self.session)
|
|
30
|
+
|
|
31
|
+
def get_subscription_state(self, region: str) -> Dict[str, Any]:
|
|
32
|
+
"""
|
|
33
|
+
Get Shield Advanced subscription state with caching.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
region: AWS region name
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Dictionary containing subscription details or empty dict if not available
|
|
40
|
+
"""
|
|
41
|
+
cache_key = f"{self.session.region_name}:{region}"
|
|
42
|
+
if cache_key in ShieldCheck._subscription_cache:
|
|
43
|
+
logger.debug(f"Shield: Using cached subscription state for {region}")
|
|
44
|
+
return ShieldCheck._subscription_cache[cache_key]
|
|
45
|
+
|
|
46
|
+
client = self.get_client(region)
|
|
47
|
+
if not client:
|
|
48
|
+
logger.warning(f"Shield: No Shield client available for region {region}")
|
|
49
|
+
return {}
|
|
50
|
+
|
|
51
|
+
logger.debug(f"Shield: Fetching subscription state for {region}")
|
|
52
|
+
subscription = client.get_subscription_state()
|
|
53
|
+
|
|
54
|
+
ShieldCheck._subscription_cache[cache_key] = subscription
|
|
55
|
+
logger.debug(f"Shield: Cached subscription state for {region}")
|
|
56
|
+
|
|
57
|
+
return subscription
|
|
58
|
+
|
|
59
|
+
def get_subscription_status(self, region: str) -> Dict[str, Any]:
|
|
60
|
+
"""
|
|
61
|
+
Get Shield Advanced subscription status (ACTIVE/INACTIVE) with caching.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
region: AWS region name
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Dictionary containing subscription status or empty dict if not available
|
|
68
|
+
"""
|
|
69
|
+
cache_key = f"status:{self.session.region_name}:{region}"
|
|
70
|
+
if cache_key in ShieldCheck._subscription_cache:
|
|
71
|
+
logger.debug(f"Shield: Using cached subscription status for {region}")
|
|
72
|
+
return ShieldCheck._subscription_cache[cache_key]
|
|
73
|
+
|
|
74
|
+
client = self.get_client(region)
|
|
75
|
+
if not client:
|
|
76
|
+
logger.warning(f"Shield: No Shield client available for region {region}")
|
|
77
|
+
return {}
|
|
78
|
+
|
|
79
|
+
logger.debug(f"Shield: Fetching subscription status for {region}")
|
|
80
|
+
status = client.get_subscription_status()
|
|
81
|
+
|
|
82
|
+
ShieldCheck._subscription_cache[cache_key] = status
|
|
83
|
+
logger.debug(f"Shield: Cached subscription status for {region}")
|
|
84
|
+
|
|
85
|
+
return status
|
|
86
|
+
|
|
87
|
+
def list_protections(self, region: str, resource_type: str = None) -> Dict[str, Any]:
|
|
88
|
+
"""
|
|
89
|
+
List Shield Advanced protections with caching.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
region: AWS region name
|
|
93
|
+
resource_type: Optional resource type filter
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Dictionary containing protections list or empty dict if not available
|
|
97
|
+
"""
|
|
98
|
+
cache_key = f"protections:{self.session.region_name}:{region}:{resource_type or 'all'}"
|
|
99
|
+
if cache_key in ShieldCheck._subscription_cache:
|
|
100
|
+
logger.debug(f"Shield: Using cached protections for {region}")
|
|
101
|
+
return ShieldCheck._subscription_cache[cache_key]
|
|
102
|
+
|
|
103
|
+
client = self.get_client(region)
|
|
104
|
+
if not client:
|
|
105
|
+
logger.warning(f"Shield: No Shield client available for region {region}")
|
|
106
|
+
return {}
|
|
107
|
+
|
|
108
|
+
logger.debug(f"Shield: Listing protections for {region}")
|
|
109
|
+
protections = client.list_protections(resource_type)
|
|
110
|
+
|
|
111
|
+
ShieldCheck._subscription_cache[cache_key] = protections
|
|
112
|
+
logger.debug(f"Shield: Cached protections for {region}")
|
|
113
|
+
|
|
114
|
+
return protections
|
|
115
|
+
|
|
116
|
+
def describe_drt_access(self, region: str) -> Dict[str, Any]:
|
|
117
|
+
"""
|
|
118
|
+
Describe Shield Response Team (SRT) access configuration with caching.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
region: AWS region name
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Dictionary containing DRT access details or empty dict if not available
|
|
125
|
+
"""
|
|
126
|
+
cache_key = f"drt_access:{self.session.region_name}:{region}"
|
|
127
|
+
if cache_key in ShieldCheck._subscription_cache:
|
|
128
|
+
logger.debug(f"Shield: Using cached DRT access for {region}")
|
|
129
|
+
return ShieldCheck._subscription_cache[cache_key]
|
|
130
|
+
|
|
131
|
+
client = self.get_client(region)
|
|
132
|
+
if not client:
|
|
133
|
+
logger.warning(f"Shield: No Shield client available for region {region}")
|
|
134
|
+
return {}
|
|
135
|
+
|
|
136
|
+
logger.debug(f"Shield: Describing DRT access for {region}")
|
|
137
|
+
drt_access = client.describe_drt_access()
|
|
138
|
+
|
|
139
|
+
ShieldCheck._subscription_cache[cache_key] = drt_access
|
|
140
|
+
logger.debug(f"Shield: Cached DRT access for {region}")
|
|
141
|
+
|
|
142
|
+
return drt_access
|
|
143
|
+
|
|
144
|
+
def get_lambda_function(self, region: str, function_name: str) -> Dict[str, Any]:
|
|
145
|
+
"""
|
|
146
|
+
Get Lambda function details.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
region: AWS region name
|
|
150
|
+
function_name: Name of the Lambda function
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Dictionary containing function details or empty dict if not available
|
|
154
|
+
"""
|
|
155
|
+
client = self.get_client(region)
|
|
156
|
+
if not client:
|
|
157
|
+
logger.warning(f"Shield: No Shield client available for region {region}")
|
|
158
|
+
return {}
|
|
159
|
+
|
|
160
|
+
logger.debug(f"Shield: Getting Lambda function {function_name} for {region}")
|
|
161
|
+
return client.get_lambda_function(function_name)
|
|
162
|
+
|
|
163
|
+
def get_web_acl_for_resource(self, region: str, resource_arn: str) -> Dict[str, Any]:
|
|
164
|
+
"""
|
|
165
|
+
Get WAF web ACL associated with a resource.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
region: AWS region name
|
|
169
|
+
resource_arn: ARN of the resource
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
Dictionary containing web ACL details or empty dict if not available
|
|
173
|
+
"""
|
|
174
|
+
client = self.get_client(region)
|
|
175
|
+
if not client:
|
|
176
|
+
logger.warning(f"Shield: No Shield client available for region {region}")
|
|
177
|
+
return {}
|
|
178
|
+
|
|
179
|
+
logger.debug(f"Shield: Getting web ACL for resource {resource_arn} in {region}")
|
|
180
|
+
return client.get_web_acl_for_resource(resource_arn)
|
|
181
|
+
|
|
182
|
+
def get_cloudwatch_alarms_for_resource(self, region: str, resource_arn: str) -> Dict[str, Any]:
|
|
183
|
+
"""
|
|
184
|
+
Get CloudWatch alarms for Shield Advanced DDoS metrics for a resource.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
region: AWS region name
|
|
188
|
+
resource_arn: ARN of the resource
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
Dictionary containing alarm details or empty dict if not available
|
|
192
|
+
"""
|
|
193
|
+
client = self.get_client(region)
|
|
194
|
+
if not client:
|
|
195
|
+
logger.warning(f"Shield: No Shield client available for region {region}")
|
|
196
|
+
return {}
|
|
197
|
+
|
|
198
|
+
logger.debug(f"Shield: Getting CloudWatch alarms for resource {resource_arn} in {region}")
|
|
199
|
+
return client.get_cloudwatch_alarms_for_resource(resource_arn)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Shield checks module."""
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Check if Shield Advanced is enabled.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Dict, List, Any
|
|
5
|
+
from sraverify.services.shield.base import ShieldCheck
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SRA_SHIELD_01(ShieldCheck):
|
|
9
|
+
"""Check if Shield Advanced is enabled."""
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
"""Initialize Shield Advanced enabled check."""
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.check_id = "SRA-SHIELD-01"
|
|
15
|
+
self.check_name = "Shield Advanced is enabled"
|
|
16
|
+
self.description = ("This check verifies that AWS Shield Advanced is enabled. "
|
|
17
|
+
"Shield Advanced provides enhanced DDoS protection for your AWS resources "
|
|
18
|
+
"and includes 24/7 access to the AWS DDoS Response Team (DRT).")
|
|
19
|
+
self.severity = "HIGH"
|
|
20
|
+
self.check_logic = "Get Shield subscription state. Check fails if subscription is not active."
|
|
21
|
+
|
|
22
|
+
def execute(self) -> List[Dict[str, Any]]:
|
|
23
|
+
"""
|
|
24
|
+
Execute the check.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
List of findings
|
|
28
|
+
"""
|
|
29
|
+
# Shield is a global service, check only in us-east-1
|
|
30
|
+
region = "us-east-1"
|
|
31
|
+
status = self.get_subscription_status(region)
|
|
32
|
+
|
|
33
|
+
if "Error" in status:
|
|
34
|
+
error_code = status["Error"].get("Code", "")
|
|
35
|
+
if error_code == "ResourceNotFoundException":
|
|
36
|
+
self.findings.append(self.create_finding(
|
|
37
|
+
status="FAIL",
|
|
38
|
+
region=region,
|
|
39
|
+
resource_id=None,
|
|
40
|
+
actual_value="Shield Advanced not subscribed",
|
|
41
|
+
remediation="Enable Shield Advanced subscription in the AWS Shield console"
|
|
42
|
+
))
|
|
43
|
+
else:
|
|
44
|
+
self.findings.append(self.create_finding(
|
|
45
|
+
status="ERROR",
|
|
46
|
+
region=region,
|
|
47
|
+
resource_id=None,
|
|
48
|
+
actual_value=status["Error"].get("Message", "Unknown error"),
|
|
49
|
+
remediation="Check IAM permissions for Shield API access"
|
|
50
|
+
))
|
|
51
|
+
elif status.get("SubscriptionState") == "ACTIVE":
|
|
52
|
+
self.findings.append(self.create_finding(
|
|
53
|
+
status="PASS",
|
|
54
|
+
region=region,
|
|
55
|
+
resource_id="shield:subscription",
|
|
56
|
+
actual_value="Shield Advanced is active",
|
|
57
|
+
remediation=""
|
|
58
|
+
))
|
|
59
|
+
else:
|
|
60
|
+
self.findings.append(self.create_finding(
|
|
61
|
+
status="FAIL",
|
|
62
|
+
region=region,
|
|
63
|
+
resource_id=None,
|
|
64
|
+
actual_value=f"Subscription state: {status.get('SubscriptionState', 'Unknown')}",
|
|
65
|
+
remediation="Enable Shield Advanced subscription in the AWS Shield console"
|
|
66
|
+
))
|
|
67
|
+
|
|
68
|
+
return self.findings
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Check if Shield Advanced auto-renew is enabled.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Dict, List, Any
|
|
5
|
+
from sraverify.services.shield.base import ShieldCheck
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SRA_SHIELD_02(ShieldCheck):
|
|
9
|
+
"""Check if Shield Advanced auto-renew is enabled."""
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
"""Initialize Shield Advanced auto-renew check."""
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.check_id = "SRA-SHIELD-02"
|
|
15
|
+
self.check_name = "Shield Advanced auto-renew is enabled"
|
|
16
|
+
self.description = ("This check verifies that AWS Shield Advanced subscription "
|
|
17
|
+
"has auto-renew enabled to ensure continuous protection.")
|
|
18
|
+
self.severity = "MEDIUM"
|
|
19
|
+
self.check_logic = "Get Shield subscription details. Check fails if auto-renew is disabled."
|
|
20
|
+
|
|
21
|
+
def execute(self) -> List[Dict[str, Any]]:
|
|
22
|
+
"""
|
|
23
|
+
Execute the check.
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
List of findings
|
|
27
|
+
"""
|
|
28
|
+
# Shield is a global service, check only in us-east-1
|
|
29
|
+
region = "us-east-1"
|
|
30
|
+
subscription = self.get_subscription_state(region)
|
|
31
|
+
|
|
32
|
+
if "Error" in subscription:
|
|
33
|
+
error_code = subscription["Error"].get("Code", "")
|
|
34
|
+
if error_code == "ResourceNotFoundException":
|
|
35
|
+
self.findings.append(self.create_finding(
|
|
36
|
+
status="FAIL",
|
|
37
|
+
region=region,
|
|
38
|
+
resource_id=None,
|
|
39
|
+
actual_value="Shield Advanced not subscribed",
|
|
40
|
+
remediation="Enable Shield Advanced subscription in the AWS Shield console"
|
|
41
|
+
))
|
|
42
|
+
else:
|
|
43
|
+
self.findings.append(self.create_finding(
|
|
44
|
+
status="ERROR",
|
|
45
|
+
region=region,
|
|
46
|
+
resource_id=None,
|
|
47
|
+
actual_value=subscription["Error"].get("Message", "Unknown error"),
|
|
48
|
+
remediation="Check IAM permissions for Shield API access"
|
|
49
|
+
))
|
|
50
|
+
elif "Subscription" in subscription:
|
|
51
|
+
auto_renew = subscription["Subscription"].get("AutoRenew", "")
|
|
52
|
+
if auto_renew == "ENABLED":
|
|
53
|
+
self.findings.append(self.create_finding(
|
|
54
|
+
status="PASS",
|
|
55
|
+
region=region,
|
|
56
|
+
resource_id="shield:subscription",
|
|
57
|
+
actual_value="Auto-renew is enabled",
|
|
58
|
+
remediation=""
|
|
59
|
+
))
|
|
60
|
+
else:
|
|
61
|
+
self.findings.append(self.create_finding(
|
|
62
|
+
status="FAIL",
|
|
63
|
+
region=region,
|
|
64
|
+
resource_id="shield:subscription",
|
|
65
|
+
actual_value=f"Auto-renew is {auto_renew}",
|
|
66
|
+
remediation="Enable auto-renew for Shield Advanced subscription using UpdateSubscription API"
|
|
67
|
+
))
|
|
68
|
+
else:
|
|
69
|
+
self.findings.append(self.create_finding(
|
|
70
|
+
status="FAIL",
|
|
71
|
+
region=region,
|
|
72
|
+
resource_id=None,
|
|
73
|
+
actual_value="Shield Advanced subscription not found",
|
|
74
|
+
remediation="Enable Shield Advanced subscription in the AWS Shield console"
|
|
75
|
+
))
|
|
76
|
+
|
|
77
|
+
return self.findings
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Check if Shield Advanced is configured for CloudFront distributions.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Dict, List, Any
|
|
5
|
+
from sraverify.services.shield.base import ShieldCheck
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SRA_SHIELD_03(ShieldCheck):
|
|
9
|
+
"""Check if Shield Advanced is configured for CloudFront distributions."""
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
"""Initialize Shield Advanced CloudFront protection check."""
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.check_id = "SRA-SHIELD-03"
|
|
15
|
+
self.check_name = "Shield Advanced is configured for CloudFront distributions"
|
|
16
|
+
self.description = ("This check verifies that AWS Shield Advanced is protecting "
|
|
17
|
+
"at least one CloudFront distribution.")
|
|
18
|
+
self.severity = "HIGH"
|
|
19
|
+
self.check_logic = ("List Shield protections filtered by CloudFront resource type. "
|
|
20
|
+
"Check fails if no CloudFront distributions are protected.")
|
|
21
|
+
|
|
22
|
+
def execute(self) -> List[Dict[str, Any]]:
|
|
23
|
+
"""
|
|
24
|
+
Execute the check.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
List of findings
|
|
28
|
+
"""
|
|
29
|
+
# Shield is a global service, check only in us-east-1
|
|
30
|
+
region = "us-east-1"
|
|
31
|
+
protections = self.list_protections(region)
|
|
32
|
+
|
|
33
|
+
if "Error" in protections:
|
|
34
|
+
error_code = protections["Error"].get("Code", "")
|
|
35
|
+
if error_code == "ResourceNotFoundException":
|
|
36
|
+
self.findings.append(self.create_finding(
|
|
37
|
+
status="FAIL",
|
|
38
|
+
region=region,
|
|
39
|
+
resource_id=None,
|
|
40
|
+
actual_value="Shield Advanced subscription not found",
|
|
41
|
+
remediation="Enable Shield Advanced subscription to protect resources"
|
|
42
|
+
))
|
|
43
|
+
else:
|
|
44
|
+
self.findings.append(self.create_finding(
|
|
45
|
+
status="ERROR",
|
|
46
|
+
region=region,
|
|
47
|
+
resource_id=None,
|
|
48
|
+
actual_value=protections["Error"].get("Message", "Unknown error"),
|
|
49
|
+
remediation="Check IAM permissions for Shield API access"
|
|
50
|
+
))
|
|
51
|
+
elif protections.get("Protections"):
|
|
52
|
+
# Filter for CloudFront distributions by checking ResourceArn
|
|
53
|
+
cloudfront_protections = [
|
|
54
|
+
p for p in protections["Protections"]
|
|
55
|
+
if "cloudfront" in p.get("ResourceArn", "").lower()
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
if cloudfront_protections:
|
|
59
|
+
protected_count = len(cloudfront_protections)
|
|
60
|
+
self.findings.append(self.create_finding(
|
|
61
|
+
status="PASS",
|
|
62
|
+
region=region,
|
|
63
|
+
resource_id="shield:cloudfront-protections",
|
|
64
|
+
actual_value=f"{protected_count} CloudFront distribution(s) protected",
|
|
65
|
+
remediation=""
|
|
66
|
+
))
|
|
67
|
+
else:
|
|
68
|
+
self.findings.append(self.create_finding(
|
|
69
|
+
status="FAIL",
|
|
70
|
+
region=region,
|
|
71
|
+
resource_id=None,
|
|
72
|
+
actual_value="No CloudFront distributions protected",
|
|
73
|
+
remediation="Enable Shield Advanced protection for CloudFront distributions in the AWS Shield console"
|
|
74
|
+
))
|
|
75
|
+
else:
|
|
76
|
+
self.findings.append(self.create_finding(
|
|
77
|
+
status="FAIL",
|
|
78
|
+
region=region,
|
|
79
|
+
resource_id=None,
|
|
80
|
+
actual_value="No CloudFront distributions protected",
|
|
81
|
+
remediation="Enable Shield Advanced protection for CloudFront distributions in the AWS Shield console"
|
|
82
|
+
))
|
|
83
|
+
|
|
84
|
+
return self.findings
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Check if Shield Advanced is configured for load balancers.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Dict, List, Any
|
|
5
|
+
from sraverify.services.shield.base import ShieldCheck
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SRA_SHIELD_04(ShieldCheck):
|
|
9
|
+
"""Check if Shield Advanced is configured for load balancers."""
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
"""Initialize Shield Advanced load balancer protection check."""
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.check_id = "SRA-SHIELD-04"
|
|
15
|
+
self.check_name = "Shield Advanced is configured for load balancers"
|
|
16
|
+
self.description = ("This check verifies that AWS Shield Advanced is protecting "
|
|
17
|
+
"at least one load balancer (Application or Classic Load Balancer).")
|
|
18
|
+
self.severity = "HIGH"
|
|
19
|
+
self.check_logic = ("List Shield protections and filter by load balancer ARNs. "
|
|
20
|
+
"Check fails if no load balancers are protected.")
|
|
21
|
+
|
|
22
|
+
def execute(self) -> List[Dict[str, Any]]:
|
|
23
|
+
"""
|
|
24
|
+
Execute the check.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
List of findings
|
|
28
|
+
"""
|
|
29
|
+
# Shield is a global service, check only in us-east-1
|
|
30
|
+
region = "us-east-1"
|
|
31
|
+
protections = self.list_protections(region)
|
|
32
|
+
|
|
33
|
+
if "Error" in protections:
|
|
34
|
+
error_code = protections["Error"].get("Code", "")
|
|
35
|
+
if error_code == "ResourceNotFoundException":
|
|
36
|
+
self.findings.append(self.create_finding(
|
|
37
|
+
status="FAIL",
|
|
38
|
+
region=region,
|
|
39
|
+
resource_id=None,
|
|
40
|
+
actual_value="Shield Advanced subscription not found",
|
|
41
|
+
remediation="Enable Shield Advanced subscription to protect resources"
|
|
42
|
+
))
|
|
43
|
+
else:
|
|
44
|
+
self.findings.append(self.create_finding(
|
|
45
|
+
status="ERROR",
|
|
46
|
+
region=region,
|
|
47
|
+
resource_id=None,
|
|
48
|
+
actual_value=protections["Error"].get("Message", "Unknown error"),
|
|
49
|
+
remediation="Check IAM permissions for Shield API access"
|
|
50
|
+
))
|
|
51
|
+
elif protections.get("Protections"):
|
|
52
|
+
# Filter for load balancers by checking ResourceArn
|
|
53
|
+
lb_protections = [
|
|
54
|
+
p for p in protections["Protections"]
|
|
55
|
+
if "elasticloadbalancing" in p.get("ResourceArn", "").lower()
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
if lb_protections:
|
|
59
|
+
protected_count = len(lb_protections)
|
|
60
|
+
self.findings.append(self.create_finding(
|
|
61
|
+
status="PASS",
|
|
62
|
+
region=region,
|
|
63
|
+
resource_id="shield:loadbalancer-protections",
|
|
64
|
+
actual_value=f"{protected_count} load balancer(s) protected",
|
|
65
|
+
remediation=""
|
|
66
|
+
))
|
|
67
|
+
else:
|
|
68
|
+
self.findings.append(self.create_finding(
|
|
69
|
+
status="FAIL",
|
|
70
|
+
region=region,
|
|
71
|
+
resource_id=None,
|
|
72
|
+
actual_value="No load balancers protected",
|
|
73
|
+
remediation="Enable Shield Advanced protection for Application or Classic Load Balancers in the AWS Shield console"
|
|
74
|
+
))
|
|
75
|
+
else:
|
|
76
|
+
self.findings.append(self.create_finding(
|
|
77
|
+
status="FAIL",
|
|
78
|
+
region=region,
|
|
79
|
+
resource_id=None,
|
|
80
|
+
actual_value="No load balancers protected",
|
|
81
|
+
remediation="Enable Shield Advanced protection for Application or Classic Load Balancers in the AWS Shield console"
|
|
82
|
+
))
|
|
83
|
+
|
|
84
|
+
return self.findings
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Check if Shield Advanced is configured for Elastic IP addresses.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Dict, List, Any
|
|
5
|
+
from sraverify.services.shield.base import ShieldCheck
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SRA_SHIELD_05(ShieldCheck):
|
|
9
|
+
"""Check if Shield Advanced is configured for Elastic IP addresses."""
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
"""Initialize Shield Advanced Elastic IP protection check."""
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.check_id = "SRA-SHIELD-05"
|
|
15
|
+
self.check_name = "Shield Advanced is configured for Elastic IP addresses"
|
|
16
|
+
self.description = ("This check verifies that AWS Shield Advanced is protecting "
|
|
17
|
+
"at least one Elastic IP address.")
|
|
18
|
+
self.severity = "HIGH"
|
|
19
|
+
self.check_logic = ("List Shield protections and filter by Elastic IP ARNs. "
|
|
20
|
+
"Check fails if no Elastic IP addresses are protected.")
|
|
21
|
+
|
|
22
|
+
def execute(self) -> List[Dict[str, Any]]:
|
|
23
|
+
"""
|
|
24
|
+
Execute the check.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
List of findings
|
|
28
|
+
"""
|
|
29
|
+
# Shield is a global service, check only in us-east-1
|
|
30
|
+
region = "us-east-1"
|
|
31
|
+
protections = self.list_protections(region)
|
|
32
|
+
|
|
33
|
+
if "Error" in protections:
|
|
34
|
+
error_code = protections["Error"].get("Code", "")
|
|
35
|
+
if error_code == "ResourceNotFoundException":
|
|
36
|
+
self.findings.append(self.create_finding(
|
|
37
|
+
status="FAIL",
|
|
38
|
+
region=region,
|
|
39
|
+
resource_id=None,
|
|
40
|
+
actual_value="Shield Advanced subscription not found",
|
|
41
|
+
remediation="Enable Shield Advanced subscription to protect resources"
|
|
42
|
+
))
|
|
43
|
+
else:
|
|
44
|
+
self.findings.append(self.create_finding(
|
|
45
|
+
status="ERROR",
|
|
46
|
+
region=region,
|
|
47
|
+
resource_id=None,
|
|
48
|
+
actual_value=protections["Error"].get("Message", "Unknown error"),
|
|
49
|
+
remediation="Check IAM permissions for Shield API access"
|
|
50
|
+
))
|
|
51
|
+
elif protections.get("Protections"):
|
|
52
|
+
# Filter for Elastic IPs by checking ResourceArn
|
|
53
|
+
eip_protections = [
|
|
54
|
+
p for p in protections["Protections"]
|
|
55
|
+
if "eip-allocation" in p.get("ResourceArn", "").lower()
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
if eip_protections:
|
|
59
|
+
protected_count = len(eip_protections)
|
|
60
|
+
self.findings.append(self.create_finding(
|
|
61
|
+
status="PASS",
|
|
62
|
+
region=region,
|
|
63
|
+
resource_id="shield:eip-protections",
|
|
64
|
+
actual_value=f"{protected_count} Elastic IP address(es) protected",
|
|
65
|
+
remediation=""
|
|
66
|
+
))
|
|
67
|
+
else:
|
|
68
|
+
self.findings.append(self.create_finding(
|
|
69
|
+
status="FAIL",
|
|
70
|
+
region=region,
|
|
71
|
+
resource_id=None,
|
|
72
|
+
actual_value="No Elastic IP addresses protected",
|
|
73
|
+
remediation="Enable Shield Advanced protection for Elastic IP addresses in the AWS Shield console"
|
|
74
|
+
))
|
|
75
|
+
else:
|
|
76
|
+
self.findings.append(self.create_finding(
|
|
77
|
+
status="FAIL",
|
|
78
|
+
region=region,
|
|
79
|
+
resource_id=None,
|
|
80
|
+
actual_value="No Elastic IP addresses protected",
|
|
81
|
+
remediation="Enable Shield Advanced protection for Elastic IP addresses in the AWS Shield console"
|
|
82
|
+
))
|
|
83
|
+
|
|
84
|
+
return self.findings
|