complio 0.1.1__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.
- CHANGELOG.md +208 -0
- README.md +343 -0
- complio/__init__.py +48 -0
- complio/cli/__init__.py +0 -0
- complio/cli/banner.py +87 -0
- complio/cli/commands/__init__.py +0 -0
- complio/cli/commands/history.py +439 -0
- complio/cli/commands/scan.py +700 -0
- complio/cli/main.py +115 -0
- complio/cli/output.py +338 -0
- complio/config/__init__.py +17 -0
- complio/config/settings.py +333 -0
- complio/connectors/__init__.py +9 -0
- complio/connectors/aws/__init__.py +0 -0
- complio/connectors/aws/client.py +342 -0
- complio/connectors/base.py +135 -0
- complio/core/__init__.py +10 -0
- complio/core/registry.py +228 -0
- complio/core/runner.py +351 -0
- complio/py.typed +0 -0
- complio/reporters/__init__.py +7 -0
- complio/reporters/generator.py +417 -0
- complio/tests_library/__init__.py +0 -0
- complio/tests_library/base.py +492 -0
- complio/tests_library/identity/__init__.py +0 -0
- complio/tests_library/identity/access_key_rotation.py +302 -0
- complio/tests_library/identity/mfa_enforcement.py +327 -0
- complio/tests_library/identity/root_account_protection.py +470 -0
- complio/tests_library/infrastructure/__init__.py +0 -0
- complio/tests_library/infrastructure/cloudtrail_encryption.py +286 -0
- complio/tests_library/infrastructure/cloudtrail_log_validation.py +274 -0
- complio/tests_library/infrastructure/cloudtrail_logging.py +400 -0
- complio/tests_library/infrastructure/ebs_encryption.py +244 -0
- complio/tests_library/infrastructure/ec2_security_groups.py +321 -0
- complio/tests_library/infrastructure/iam_password_policy.py +460 -0
- complio/tests_library/infrastructure/nacl_security.py +356 -0
- complio/tests_library/infrastructure/rds_encryption.py +252 -0
- complio/tests_library/infrastructure/s3_encryption.py +301 -0
- complio/tests_library/infrastructure/s3_public_access.py +369 -0
- complio/tests_library/infrastructure/secrets_manager_encryption.py +248 -0
- complio/tests_library/infrastructure/vpc_flow_logs.py +287 -0
- complio/tests_library/logging/__init__.py +0 -0
- complio/tests_library/logging/cloudwatch_alarms.py +354 -0
- complio/tests_library/logging/cloudwatch_logs_encryption.py +281 -0
- complio/tests_library/logging/cloudwatch_retention.py +252 -0
- complio/tests_library/logging/config_enabled.py +393 -0
- complio/tests_library/logging/eventbridge_rules.py +460 -0
- complio/tests_library/logging/guardduty_enabled.py +436 -0
- complio/tests_library/logging/security_hub_enabled.py +416 -0
- complio/tests_library/logging/sns_encryption.py +273 -0
- complio/tests_library/network/__init__.py +0 -0
- complio/tests_library/network/alb_nlb_security.py +421 -0
- complio/tests_library/network/api_gateway_security.py +452 -0
- complio/tests_library/network/cloudfront_https.py +332 -0
- complio/tests_library/network/direct_connect_security.py +343 -0
- complio/tests_library/network/nacl_configuration.py +367 -0
- complio/tests_library/network/network_firewall.py +355 -0
- complio/tests_library/network/transit_gateway_security.py +318 -0
- complio/tests_library/network/vpc_endpoints_security.py +339 -0
- complio/tests_library/network/vpn_security.py +333 -0
- complio/tests_library/network/waf_configuration.py +428 -0
- complio/tests_library/security/__init__.py +0 -0
- complio/tests_library/security/kms_key_rotation.py +314 -0
- complio/tests_library/storage/__init__.py +0 -0
- complio/tests_library/storage/backup_encryption.py +288 -0
- complio/tests_library/storage/dynamodb_encryption.py +280 -0
- complio/tests_library/storage/efs_encryption.py +257 -0
- complio/tests_library/storage/elasticache_encryption.py +370 -0
- complio/tests_library/storage/redshift_encryption.py +252 -0
- complio/tests_library/storage/s3_versioning.py +264 -0
- complio/utils/__init__.py +26 -0
- complio/utils/errors.py +179 -0
- complio/utils/exceptions.py +151 -0
- complio/utils/history.py +243 -0
- complio/utils/logger.py +391 -0
- complio-0.1.1.dist-info/METADATA +385 -0
- complio-0.1.1.dist-info/RECORD +79 -0
- complio-0.1.1.dist-info/WHEEL +4 -0
- complio-0.1.1.dist-info/entry_points.txt +3 -0
|
File without changes
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Application Load Balancer and Network Load Balancer security compliance test.
|
|
3
|
+
|
|
4
|
+
Checks that ALBs and NLBs use secure configurations including HTTPS listeners.
|
|
5
|
+
|
|
6
|
+
ISO 27001 Control: A.8.22 - Network segregation
|
|
7
|
+
Requirement: Load balancers must use secure protocols and configurations
|
|
8
|
+
|
|
9
|
+
Example:
|
|
10
|
+
>>> from complio.connectors.aws.client import AWSConnector
|
|
11
|
+
>>> from complio.tests_library.network.alb_nlb_security import ALBNLBSecurityTest
|
|
12
|
+
>>>
|
|
13
|
+
>>> connector = AWSConnector("production", "us-east-1")
|
|
14
|
+
>>> connector.connect()
|
|
15
|
+
>>>
|
|
16
|
+
>>> test = ALBNLBSecurityTest(connector)
|
|
17
|
+
>>> result = test.run()
|
|
18
|
+
>>> print(f"Passed: {result.passed}, Score: {result.score}")
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from typing import Any, Dict, List
|
|
22
|
+
|
|
23
|
+
from botocore.exceptions import ClientError
|
|
24
|
+
|
|
25
|
+
from complio.connectors.aws.client import AWSConnector
|
|
26
|
+
from complio.tests_library.base import (
|
|
27
|
+
ComplianceTest,
|
|
28
|
+
Severity,
|
|
29
|
+
TestResult,
|
|
30
|
+
TestStatus,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ALBNLBSecurityTest(ComplianceTest):
|
|
35
|
+
"""Test for ALB/NLB security compliance.
|
|
36
|
+
|
|
37
|
+
Verifies that Application and Network Load Balancers use secure configurations:
|
|
38
|
+
- ALBs should use HTTPS listeners
|
|
39
|
+
- HTTPS listeners should use modern TLS versions (TLS 1.2+)
|
|
40
|
+
- Should have access logging enabled
|
|
41
|
+
- Should have deletion protection enabled (recommended)
|
|
42
|
+
|
|
43
|
+
Compliance Requirements:
|
|
44
|
+
- ALBs should have at least one HTTPS listener
|
|
45
|
+
- HTTPS listeners must use TLS 1.2 or higher
|
|
46
|
+
- Access logging should be enabled for audit trail
|
|
47
|
+
- Deletion protection recommended for production
|
|
48
|
+
|
|
49
|
+
Scoring:
|
|
50
|
+
- 100% if all load balancers meet security requirements
|
|
51
|
+
- Proportional score based on compliant/total ratio
|
|
52
|
+
- 100% if no load balancers exist
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
>>> test = ALBNLBSecurityTest(connector)
|
|
56
|
+
>>> result = test.execute()
|
|
57
|
+
>>> for finding in result.findings:
|
|
58
|
+
... print(f"{finding.resource_id}: {finding.title}")
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(self, connector: AWSConnector) -> None:
|
|
62
|
+
"""Initialize ALB/NLB security test.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
connector: AWS connector instance
|
|
66
|
+
"""
|
|
67
|
+
super().__init__(
|
|
68
|
+
test_id="alb_nlb_security",
|
|
69
|
+
test_name="ALB/NLB Security Check",
|
|
70
|
+
description="Verify Application and Network Load Balancers use secure configurations",
|
|
71
|
+
control_id="A.8.22",
|
|
72
|
+
connector=connector,
|
|
73
|
+
scope="regional",
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
def _check_alb_security(self, lb_arn: str, lb_name: str, listeners: List[Dict], attributes: Dict) -> tuple:
|
|
77
|
+
"""Check ALB security configuration.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
lb_arn: Load balancer ARN
|
|
81
|
+
lb_name: Load balancer name
|
|
82
|
+
listeners: List of listener configurations
|
|
83
|
+
attributes: Load balancer attributes
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Tuple of (has_issues, issues_list, severity)
|
|
87
|
+
"""
|
|
88
|
+
issues = []
|
|
89
|
+
severity = Severity.MEDIUM
|
|
90
|
+
|
|
91
|
+
# Check if there's at least one HTTPS listener
|
|
92
|
+
https_listeners = [l for l in listeners if l.get("Protocol") == "HTTPS"]
|
|
93
|
+
http_listeners = [l for l in listeners if l.get("Protocol") == "HTTP"]
|
|
94
|
+
|
|
95
|
+
if len(https_listeners) == 0 and len(http_listeners) > 0:
|
|
96
|
+
issues.append("No HTTPS listeners configured (only HTTP)")
|
|
97
|
+
severity = Severity.HIGH
|
|
98
|
+
|
|
99
|
+
# Check HTTPS listener SSL policies
|
|
100
|
+
for listener in https_listeners:
|
|
101
|
+
ssl_policy = listener.get("SslPolicy", "")
|
|
102
|
+
# Check for outdated SSL policies
|
|
103
|
+
if ssl_policy and any(weak in ssl_policy for weak in ["ELBSecurityPolicy-2016", "ELBSecurityPolicy-TLS"]):
|
|
104
|
+
if "TLS-1-2" not in ssl_policy:
|
|
105
|
+
issues.append(f"HTTPS listener uses outdated SSL policy: {ssl_policy}")
|
|
106
|
+
severity = Severity.HIGH
|
|
107
|
+
|
|
108
|
+
# Check if access logging is enabled
|
|
109
|
+
access_logs_enabled = False
|
|
110
|
+
for attr in attributes:
|
|
111
|
+
if attr.get("Key") == "access_logs.s3.enabled":
|
|
112
|
+
access_logs_enabled = attr.get("Value") == "true"
|
|
113
|
+
break
|
|
114
|
+
|
|
115
|
+
if not access_logs_enabled:
|
|
116
|
+
issues.append("Access logging not enabled")
|
|
117
|
+
if severity == Severity.MEDIUM:
|
|
118
|
+
severity = Severity.MEDIUM
|
|
119
|
+
|
|
120
|
+
# Check deletion protection (best practice, not critical)
|
|
121
|
+
deletion_protection = False
|
|
122
|
+
for attr in attributes:
|
|
123
|
+
if attr.get("Key") == "deletion_protection.enabled":
|
|
124
|
+
deletion_protection = attr.get("Value") == "true"
|
|
125
|
+
break
|
|
126
|
+
|
|
127
|
+
if not deletion_protection:
|
|
128
|
+
issues.append("Deletion protection not enabled (recommended for production)")
|
|
129
|
+
|
|
130
|
+
return len(issues) > 0, issues, severity
|
|
131
|
+
|
|
132
|
+
def _check_nlb_security(self, lb_arn: str, lb_name: str, listeners: List[Dict], attributes: Dict) -> tuple:
|
|
133
|
+
"""Check NLB security configuration.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
lb_arn: Load balancer ARN
|
|
137
|
+
lb_name: Load balancer name
|
|
138
|
+
listeners: List of listener configurations
|
|
139
|
+
attributes: Load balancer attributes
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
Tuple of (has_issues, issues_list, severity)
|
|
143
|
+
"""
|
|
144
|
+
issues = []
|
|
145
|
+
severity = Severity.MEDIUM
|
|
146
|
+
|
|
147
|
+
# NLBs can use TLS listeners for secure traffic
|
|
148
|
+
tls_listeners = [l for l in listeners if l.get("Protocol") == "TLS"]
|
|
149
|
+
tcp_listeners = [l for l in listeners if l.get("Protocol") == "TCP"]
|
|
150
|
+
|
|
151
|
+
# Check if TLS is used where appropriate
|
|
152
|
+
if len(tls_listeners) == 0 and len(tcp_listeners) > 0:
|
|
153
|
+
# Check if any TCP listener is on standard HTTPS port (443)
|
|
154
|
+
https_tcp_listeners = [l for l in tcp_listeners if l.get("Port") == 443]
|
|
155
|
+
if https_tcp_listeners:
|
|
156
|
+
issues.append("TCP listener on port 443 without TLS (should use TLS protocol)")
|
|
157
|
+
severity = Severity.HIGH
|
|
158
|
+
|
|
159
|
+
# Check TLS listener SSL policies
|
|
160
|
+
for listener in tls_listeners:
|
|
161
|
+
ssl_policy = listener.get("SslPolicy", "")
|
|
162
|
+
if ssl_policy and "TLS-1-2" not in ssl_policy:
|
|
163
|
+
issues.append(f"TLS listener uses outdated SSL policy: {ssl_policy}")
|
|
164
|
+
severity = Severity.HIGH
|
|
165
|
+
|
|
166
|
+
# Check if access logging is enabled (NLB supports this via S3)
|
|
167
|
+
access_logs_enabled = False
|
|
168
|
+
for attr in attributes:
|
|
169
|
+
if attr.get("Key") == "access_logs.s3.enabled":
|
|
170
|
+
access_logs_enabled = attr.get("Value") == "true"
|
|
171
|
+
break
|
|
172
|
+
|
|
173
|
+
if not access_logs_enabled:
|
|
174
|
+
issues.append("Access logging not enabled")
|
|
175
|
+
|
|
176
|
+
# Check deletion protection
|
|
177
|
+
deletion_protection = False
|
|
178
|
+
for attr in attributes:
|
|
179
|
+
if attr.get("Key") == "deletion_protection.enabled":
|
|
180
|
+
deletion_protection = attr.get("Value") == "true"
|
|
181
|
+
break
|
|
182
|
+
|
|
183
|
+
if not deletion_protection:
|
|
184
|
+
issues.append("Deletion protection not enabled (recommended for production)")
|
|
185
|
+
|
|
186
|
+
return len(issues) > 0, issues, severity
|
|
187
|
+
|
|
188
|
+
def execute(self) -> TestResult:
|
|
189
|
+
"""Execute ALB/NLB security compliance test.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
TestResult with findings for insecure load balancers
|
|
193
|
+
|
|
194
|
+
Example:
|
|
195
|
+
>>> test = ALBNLBSecurityTest(connector)
|
|
196
|
+
>>> result = test.execute()
|
|
197
|
+
>>> print(result.score)
|
|
198
|
+
90.0
|
|
199
|
+
"""
|
|
200
|
+
result = TestResult(
|
|
201
|
+
test_id=self.test_id,
|
|
202
|
+
test_name=self.test_name,
|
|
203
|
+
status=TestStatus.PASSED,
|
|
204
|
+
passed=True,
|
|
205
|
+
score=100.0,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
try:
|
|
209
|
+
# Get ELBv2 client
|
|
210
|
+
elbv2_client = self.connector.get_client("elbv2")
|
|
211
|
+
|
|
212
|
+
# List all load balancers (ALB and NLB)
|
|
213
|
+
self.logger.info("listing_load_balancers")
|
|
214
|
+
lbs_response = elbv2_client.describe_load_balancers()
|
|
215
|
+
load_balancers = lbs_response.get("LoadBalancers", [])
|
|
216
|
+
|
|
217
|
+
if not load_balancers:
|
|
218
|
+
self.logger.info("no_load_balancers_found")
|
|
219
|
+
result.metadata["message"] = "No load balancers found in region"
|
|
220
|
+
return result
|
|
221
|
+
|
|
222
|
+
self.logger.info("load_balancers_found", count=len(load_balancers))
|
|
223
|
+
|
|
224
|
+
# Check security for each load balancer
|
|
225
|
+
secure_lb_count = 0
|
|
226
|
+
|
|
227
|
+
for lb in load_balancers:
|
|
228
|
+
lb_arn = lb["LoadBalancerArn"]
|
|
229
|
+
lb_name = lb["LoadBalancerName"]
|
|
230
|
+
lb_type = lb.get("Type", "application") # application or network
|
|
231
|
+
lb_scheme = lb.get("Scheme", "internet-facing")
|
|
232
|
+
|
|
233
|
+
result.resources_scanned += 1
|
|
234
|
+
|
|
235
|
+
# Get listeners for this load balancer
|
|
236
|
+
listeners_response = elbv2_client.describe_listeners(LoadBalancerArn=lb_arn)
|
|
237
|
+
listeners = listeners_response.get("Listeners", [])
|
|
238
|
+
|
|
239
|
+
# Get load balancer attributes
|
|
240
|
+
attributes_response = elbv2_client.describe_load_balancer_attributes(LoadBalancerArn=lb_arn)
|
|
241
|
+
attributes = attributes_response.get("Attributes", [])
|
|
242
|
+
|
|
243
|
+
# Check security based on type
|
|
244
|
+
if lb_type == "application":
|
|
245
|
+
has_issues, issues_list, severity = self._check_alb_security(
|
|
246
|
+
lb_arn, lb_name, listeners, attributes
|
|
247
|
+
)
|
|
248
|
+
elif lb_type == "network":
|
|
249
|
+
has_issues, issues_list, severity = self._check_nlb_security(
|
|
250
|
+
lb_arn, lb_name, listeners, attributes
|
|
251
|
+
)
|
|
252
|
+
else:
|
|
253
|
+
# Gateway load balancers - skip for now
|
|
254
|
+
continue
|
|
255
|
+
|
|
256
|
+
# Create evidence
|
|
257
|
+
evidence = self.create_evidence(
|
|
258
|
+
resource_id=lb_arn,
|
|
259
|
+
resource_type="load_balancer",
|
|
260
|
+
data={
|
|
261
|
+
"load_balancer_arn": lb_arn,
|
|
262
|
+
"load_balancer_name": lb_name,
|
|
263
|
+
"type": lb_type,
|
|
264
|
+
"scheme": lb_scheme,
|
|
265
|
+
"listener_count": len(listeners),
|
|
266
|
+
"has_issues": has_issues,
|
|
267
|
+
"issues": issues_list,
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
result.add_evidence(evidence)
|
|
271
|
+
|
|
272
|
+
if not has_issues:
|
|
273
|
+
secure_lb_count += 1
|
|
274
|
+
self.logger.debug(
|
|
275
|
+
"load_balancer_secure",
|
|
276
|
+
lb_name=lb_name,
|
|
277
|
+
lb_type=lb_type
|
|
278
|
+
)
|
|
279
|
+
else:
|
|
280
|
+
# Create finding for insecure load balancer
|
|
281
|
+
finding = self.create_finding(
|
|
282
|
+
resource_id=lb_arn,
|
|
283
|
+
resource_type="load_balancer",
|
|
284
|
+
severity=severity,
|
|
285
|
+
title=f"{lb_type.upper()} has security configuration issues",
|
|
286
|
+
description=f"{lb_type.upper()} '{lb_name}' has security configuration issues: "
|
|
287
|
+
f"{'; '.join(issues_list)}. Load balancers should use secure protocols "
|
|
288
|
+
"(HTTPS/TLS), modern SSL/TLS policies (TLS 1.2+), enable access logging "
|
|
289
|
+
"for audit trails, and enable deletion protection for production workloads. "
|
|
290
|
+
"ISO 27001 A.8.22 requires secure network segregation and encryption.",
|
|
291
|
+
remediation=(
|
|
292
|
+
f"Improve {lb_type.upper()} '{lb_name}' security:\n\n"
|
|
293
|
+
"1. Add HTTPS/TLS listener:\n"
|
|
294
|
+
f"aws elbv2 create-listener \\\n"
|
|
295
|
+
f" --load-balancer-arn {lb_arn} \\\n"
|
|
296
|
+
" --protocol {'HTTPS' if lb_type == 'application' else 'TLS'} \\\n"
|
|
297
|
+
" --port 443 \\\n"
|
|
298
|
+
" --certificates CertificateArn=<ACM-CERT-ARN> \\\n"
|
|
299
|
+
" --default-actions Type=forward,TargetGroupArn=<TG-ARN> \\\n"
|
|
300
|
+
" --ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06\n\n"
|
|
301
|
+
"2. Enable access logging:\n"
|
|
302
|
+
f"aws elbv2 modify-load-balancer-attributes \\\n"
|
|
303
|
+
f" --load-balancer-arn {lb_arn} \\\n"
|
|
304
|
+
" --attributes \\\n"
|
|
305
|
+
" Key=access_logs.s3.enabled,Value=true \\\n"
|
|
306
|
+
" Key=access_logs.s3.bucket,Value=<S3-BUCKET-NAME> \\\n"
|
|
307
|
+
" Key=access_logs.s3.prefix,Value=<PREFIX>\n\n"
|
|
308
|
+
"3. Enable deletion protection:\n"
|
|
309
|
+
f"aws elbv2 modify-load-balancer-attributes \\\n"
|
|
310
|
+
f" --load-balancer-arn {lb_arn} \\\n"
|
|
311
|
+
" --attributes Key=deletion_protection.enabled,Value=true\n\n"
|
|
312
|
+
"4. Update SSL policy to modern version:\n"
|
|
313
|
+
f"aws elbv2 modify-listener \\\n"
|
|
314
|
+
" --listener-arn <LISTENER-ARN> \\\n"
|
|
315
|
+
" --ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06\n\n"
|
|
316
|
+
"Or use AWS Console:\n"
|
|
317
|
+
"1. Go to EC2 console → Load Balancers\n"
|
|
318
|
+
f"2. Select '{lb_name}'\n"
|
|
319
|
+
"3. Add HTTPS/TLS listener:\n"
|
|
320
|
+
" - Click 'Add listener'\n"
|
|
321
|
+
" - Select protocol: {'HTTPS' if lb_type == 'application' else 'TLS'}\n"
|
|
322
|
+
" - Port: 443\n"
|
|
323
|
+
" - Default SSL certificate: Select from ACM\n"
|
|
324
|
+
" - Security policy: ELBSecurityPolicy-TLS13-1-2-2021-06\n"
|
|
325
|
+
"4. Enable access logs:\n"
|
|
326
|
+
" - Go to 'Attributes' tab\n"
|
|
327
|
+
" - Edit 'Access logs'\n"
|
|
328
|
+
" - Enable and specify S3 bucket\n"
|
|
329
|
+
"5. Enable deletion protection:\n"
|
|
330
|
+
" - Edit 'Deletion protection'\n"
|
|
331
|
+
" - Enable\n\n"
|
|
332
|
+
"Recommended SSL/TLS policies (in order of preference):\n"
|
|
333
|
+
"- ELBSecurityPolicy-TLS13-1-2-2021-06 (TLS 1.3 + 1.2)\n"
|
|
334
|
+
"- ELBSecurityPolicy-TLS13-1-2-Res-2021-06 (Restricted)\n"
|
|
335
|
+
"- ELBSecurityPolicy-TLS-1-2-2017-01 (TLS 1.2 minimum)\n\n"
|
|
336
|
+
"Security best practices:\n"
|
|
337
|
+
"- Use AWS Certificate Manager (ACM) for SSL/TLS certificates\n"
|
|
338
|
+
"- Enable automatic certificate renewal\n"
|
|
339
|
+
"- Configure HTTP to HTTPS redirect for ALBs\n"
|
|
340
|
+
"- Use security groups to restrict access\n"
|
|
341
|
+
"- Enable WAF for ALBs handling web traffic\n"
|
|
342
|
+
"- Monitor access logs for suspicious activity\n"
|
|
343
|
+
"- Use CloudWatch alarms for unhealthy targets"
|
|
344
|
+
),
|
|
345
|
+
evidence=evidence
|
|
346
|
+
)
|
|
347
|
+
result.add_finding(finding)
|
|
348
|
+
|
|
349
|
+
self.logger.warning(
|
|
350
|
+
"load_balancer_security_issues",
|
|
351
|
+
lb_name=lb_name,
|
|
352
|
+
lb_type=lb_type,
|
|
353
|
+
issues=issues_list
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
# Calculate compliance score
|
|
357
|
+
result.score = (secure_lb_count / len(load_balancers)) * 100
|
|
358
|
+
|
|
359
|
+
# Determine pass/fail
|
|
360
|
+
result.passed = secure_lb_count == len(load_balancers)
|
|
361
|
+
result.status = TestStatus.PASSED if result.passed else TestStatus.FAILED
|
|
362
|
+
|
|
363
|
+
# Add metadata
|
|
364
|
+
result.metadata = {
|
|
365
|
+
"total_load_balancers": len(load_balancers),
|
|
366
|
+
"secure_load_balancers": secure_lb_count,
|
|
367
|
+
"insecure_load_balancers": len(load_balancers) - secure_lb_count,
|
|
368
|
+
"compliance_percentage": result.score,
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
self.logger.info(
|
|
372
|
+
"alb_nlb_security_test_completed",
|
|
373
|
+
total_load_balancers=len(load_balancers),
|
|
374
|
+
secure=secure_lb_count,
|
|
375
|
+
score=result.score,
|
|
376
|
+
passed=result.passed
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
except ClientError as e:
|
|
380
|
+
error_code = e.response.get("Error", {}).get("Code")
|
|
381
|
+
self.logger.error("alb_nlb_security_test_error", error_code=error_code, error=str(e))
|
|
382
|
+
result.status = TestStatus.ERROR
|
|
383
|
+
result.passed = False
|
|
384
|
+
result.score = 0.0
|
|
385
|
+
result.error_message = f"AWS API Error: {error_code} - {str(e)}"
|
|
386
|
+
|
|
387
|
+
except Exception as e:
|
|
388
|
+
self.logger.error("alb_nlb_security_test_error", error=str(e))
|
|
389
|
+
result.status = TestStatus.ERROR
|
|
390
|
+
result.passed = False
|
|
391
|
+
result.score = 0.0
|
|
392
|
+
result.error_message = str(e)
|
|
393
|
+
|
|
394
|
+
return result
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
# ============================================================================
|
|
398
|
+
# CONVENIENCE FUNCTION
|
|
399
|
+
# ============================================================================
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def run_alb_nlb_security_test(connector: AWSConnector) -> TestResult:
|
|
403
|
+
"""Run ALB/NLB security compliance test.
|
|
404
|
+
|
|
405
|
+
Convenience function for running the test.
|
|
406
|
+
|
|
407
|
+
Args:
|
|
408
|
+
connector: AWS connector
|
|
409
|
+
|
|
410
|
+
Returns:
|
|
411
|
+
TestResult
|
|
412
|
+
|
|
413
|
+
Example:
|
|
414
|
+
>>> from complio.connectors.aws.client import AWSConnector
|
|
415
|
+
>>> connector = AWSConnector("production", "us-east-1")
|
|
416
|
+
>>> connector.connect()
|
|
417
|
+
>>> result = run_alb_nlb_security_test(connector)
|
|
418
|
+
>>> print(f"Score: {result.score}%")
|
|
419
|
+
"""
|
|
420
|
+
test = ALBNLBSecurityTest(connector)
|
|
421
|
+
return test.execute()
|