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.
Files changed (79) hide show
  1. CHANGELOG.md +208 -0
  2. README.md +343 -0
  3. complio/__init__.py +48 -0
  4. complio/cli/__init__.py +0 -0
  5. complio/cli/banner.py +87 -0
  6. complio/cli/commands/__init__.py +0 -0
  7. complio/cli/commands/history.py +439 -0
  8. complio/cli/commands/scan.py +700 -0
  9. complio/cli/main.py +115 -0
  10. complio/cli/output.py +338 -0
  11. complio/config/__init__.py +17 -0
  12. complio/config/settings.py +333 -0
  13. complio/connectors/__init__.py +9 -0
  14. complio/connectors/aws/__init__.py +0 -0
  15. complio/connectors/aws/client.py +342 -0
  16. complio/connectors/base.py +135 -0
  17. complio/core/__init__.py +10 -0
  18. complio/core/registry.py +228 -0
  19. complio/core/runner.py +351 -0
  20. complio/py.typed +0 -0
  21. complio/reporters/__init__.py +7 -0
  22. complio/reporters/generator.py +417 -0
  23. complio/tests_library/__init__.py +0 -0
  24. complio/tests_library/base.py +492 -0
  25. complio/tests_library/identity/__init__.py +0 -0
  26. complio/tests_library/identity/access_key_rotation.py +302 -0
  27. complio/tests_library/identity/mfa_enforcement.py +327 -0
  28. complio/tests_library/identity/root_account_protection.py +470 -0
  29. complio/tests_library/infrastructure/__init__.py +0 -0
  30. complio/tests_library/infrastructure/cloudtrail_encryption.py +286 -0
  31. complio/tests_library/infrastructure/cloudtrail_log_validation.py +274 -0
  32. complio/tests_library/infrastructure/cloudtrail_logging.py +400 -0
  33. complio/tests_library/infrastructure/ebs_encryption.py +244 -0
  34. complio/tests_library/infrastructure/ec2_security_groups.py +321 -0
  35. complio/tests_library/infrastructure/iam_password_policy.py +460 -0
  36. complio/tests_library/infrastructure/nacl_security.py +356 -0
  37. complio/tests_library/infrastructure/rds_encryption.py +252 -0
  38. complio/tests_library/infrastructure/s3_encryption.py +301 -0
  39. complio/tests_library/infrastructure/s3_public_access.py +369 -0
  40. complio/tests_library/infrastructure/secrets_manager_encryption.py +248 -0
  41. complio/tests_library/infrastructure/vpc_flow_logs.py +287 -0
  42. complio/tests_library/logging/__init__.py +0 -0
  43. complio/tests_library/logging/cloudwatch_alarms.py +354 -0
  44. complio/tests_library/logging/cloudwatch_logs_encryption.py +281 -0
  45. complio/tests_library/logging/cloudwatch_retention.py +252 -0
  46. complio/tests_library/logging/config_enabled.py +393 -0
  47. complio/tests_library/logging/eventbridge_rules.py +460 -0
  48. complio/tests_library/logging/guardduty_enabled.py +436 -0
  49. complio/tests_library/logging/security_hub_enabled.py +416 -0
  50. complio/tests_library/logging/sns_encryption.py +273 -0
  51. complio/tests_library/network/__init__.py +0 -0
  52. complio/tests_library/network/alb_nlb_security.py +421 -0
  53. complio/tests_library/network/api_gateway_security.py +452 -0
  54. complio/tests_library/network/cloudfront_https.py +332 -0
  55. complio/tests_library/network/direct_connect_security.py +343 -0
  56. complio/tests_library/network/nacl_configuration.py +367 -0
  57. complio/tests_library/network/network_firewall.py +355 -0
  58. complio/tests_library/network/transit_gateway_security.py +318 -0
  59. complio/tests_library/network/vpc_endpoints_security.py +339 -0
  60. complio/tests_library/network/vpn_security.py +333 -0
  61. complio/tests_library/network/waf_configuration.py +428 -0
  62. complio/tests_library/security/__init__.py +0 -0
  63. complio/tests_library/security/kms_key_rotation.py +314 -0
  64. complio/tests_library/storage/__init__.py +0 -0
  65. complio/tests_library/storage/backup_encryption.py +288 -0
  66. complio/tests_library/storage/dynamodb_encryption.py +280 -0
  67. complio/tests_library/storage/efs_encryption.py +257 -0
  68. complio/tests_library/storage/elasticache_encryption.py +370 -0
  69. complio/tests_library/storage/redshift_encryption.py +252 -0
  70. complio/tests_library/storage/s3_versioning.py +264 -0
  71. complio/utils/__init__.py +26 -0
  72. complio/utils/errors.py +179 -0
  73. complio/utils/exceptions.py +151 -0
  74. complio/utils/history.py +243 -0
  75. complio/utils/logger.py +391 -0
  76. complio-0.1.1.dist-info/METADATA +385 -0
  77. complio-0.1.1.dist-info/RECORD +79 -0
  78. complio-0.1.1.dist-info/WHEEL +4 -0
  79. complio-0.1.1.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,436 @@
1
+ """
2
+ AWS GuardDuty enabled compliance test.
3
+
4
+ Checks that AWS GuardDuty is enabled for threat detection and monitoring.
5
+
6
+ ISO 27001 Control: A.8.16 - Monitoring activities
7
+ Requirement: GuardDuty should be enabled for continuous security monitoring
8
+
9
+ Example:
10
+ >>> from complio.connectors.aws.client import AWSConnector
11
+ >>> from complio.tests_library.logging.guardduty_enabled import GuardDutyEnabledTest
12
+ >>>
13
+ >>> connector = AWSConnector("production", "us-east-1")
14
+ >>> connector.connect()
15
+ >>>
16
+ >>> test = GuardDutyEnabledTest(connector)
17
+ >>> result = test.run()
18
+ >>> print(f"Passed: {result.passed}, Score: {result.score}")
19
+ """
20
+
21
+ from typing import Any, Dict
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 GuardDutyEnabledTest(ComplianceTest):
35
+ """Test for AWS GuardDuty enabled compliance.
36
+
37
+ Verifies that AWS GuardDuty is properly enabled:
38
+ - GuardDuty detector should be enabled
39
+ - Should be publishing findings (not suspended)
40
+ - S3 Protection should be enabled
41
+ - EKS Protection should be enabled (if using EKS)
42
+ - Malware Protection should be enabled
43
+
44
+ Compliance Requirements:
45
+ - GuardDuty enabled in region
46
+ - Detector actively monitoring (not suspended)
47
+ - Additional protections enabled (S3, EKS, Malware)
48
+ - Findings published to EventBridge/SNS
49
+
50
+ Scoring:
51
+ - 100% if GuardDuty fully enabled with protections
52
+ - Partial score for basic enablement
53
+ - 0% if GuardDuty not enabled
54
+
55
+ Example:
56
+ >>> test = GuardDutyEnabledTest(connector)
57
+ >>> result = test.execute()
58
+ >>> for finding in result.findings:
59
+ ... print(f"{finding.resource_id}: {finding.title}")
60
+ """
61
+
62
+ def __init__(self, connector: AWSConnector) -> None:
63
+ """Initialize GuardDuty enabled test.
64
+
65
+ Args:
66
+ connector: AWS connector instance
67
+ """
68
+ super().__init__(
69
+ test_id="guardduty_enabled",
70
+ test_name="AWS GuardDuty Enabled Check",
71
+ description="Verify AWS GuardDuty is enabled for threat detection and monitoring",
72
+ control_id="A.8.16",
73
+ connector=connector,
74
+ scope="regional",
75
+ )
76
+
77
+ def execute(self) -> TestResult:
78
+ """Execute GuardDuty enabled compliance test.
79
+
80
+ Returns:
81
+ TestResult with findings if GuardDuty is not properly enabled
82
+
83
+ Example:
84
+ >>> test = GuardDutyEnabledTest(connector)
85
+ >>> result = test.execute()
86
+ >>> print(result.score)
87
+ 100.0
88
+ """
89
+ result = TestResult(
90
+ test_id=self.test_id,
91
+ test_name=self.test_name,
92
+ status=TestStatus.PASSED,
93
+ passed=True,
94
+ score=100.0,
95
+ )
96
+
97
+ try:
98
+ # Get GuardDuty client
99
+ guardduty_client = self.connector.get_client("guardduty")
100
+
101
+ # List detectors
102
+ self.logger.info("listing_guardduty_detectors")
103
+ detectors_response = guardduty_client.list_detectors()
104
+ detector_ids = detectors_response.get("DetectorIds", [])
105
+
106
+ if not detector_ids:
107
+ self.logger.warning("no_guardduty_detectors_found")
108
+
109
+ # Create finding for GuardDuty not enabled
110
+ finding = self.create_finding(
111
+ resource_id="guardduty",
112
+ resource_type="guardduty_detector",
113
+ severity=Severity.HIGH,
114
+ title="AWS GuardDuty not enabled",
115
+ description="AWS GuardDuty is not enabled in this region. GuardDuty provides intelligent "
116
+ "threat detection by continuously monitoring AWS account and workload activity. "
117
+ "It analyzes VPC Flow Logs, CloudTrail events, and DNS logs to identify "
118
+ "malicious activity, unauthorized behavior, and potential security threats. "
119
+ "ISO 27001 A.8.16 requires monitoring of system activities for security events.",
120
+ remediation=(
121
+ "Enable AWS GuardDuty in this region:\n\n"
122
+ "1. Enable GuardDuty:\n"
123
+ "aws guardduty create-detector --enable\n\n"
124
+ "2. Enable additional protections:\n"
125
+ "# Get detector ID\n"
126
+ "DETECTOR_ID=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)\n\n"
127
+ "# Enable S3 Protection\n"
128
+ "aws guardduty update-detector \\\n"
129
+ " --detector-id $DETECTOR_ID \\\n"
130
+ " --data-sources S3Logs={Enable=true}\n\n"
131
+ "# Enable EKS Protection (if using EKS)\n"
132
+ "aws guardduty update-detector \\\n"
133
+ " --detector-id $DETECTOR_ID \\\n"
134
+ " --data-sources Kubernetes={AuditLogs={Enable=true}}\n\n"
135
+ "# Enable Malware Protection (for EBS volumes)\n"
136
+ "aws guardduty update-malware-protection-plan \\\n"
137
+ " --detector-id $DETECTOR_ID \\\n"
138
+ " --enable\n\n"
139
+ "3. Configure findings export (optional but recommended):\n"
140
+ "# Export to S3\n"
141
+ "aws guardduty create-publishing-destination \\\n"
142
+ " --detector-id $DETECTOR_ID \\\n"
143
+ " --destination-type S3 \\\n"
144
+ " --destination-properties \\\n"
145
+ " DestinationArn=arn:aws:s3:::my-guardduty-findings,\\\n"
146
+ " KmsKeyArn=arn:aws:kms:region:account:key/key-id\n\n"
147
+ "4. Set up EventBridge rule for notifications:\n"
148
+ "aws events put-rule \\\n"
149
+ " --name guardduty-findings \\\n"
150
+ " --event-pattern '{\n"
151
+ ' "source": ["aws.guardduty"],\n'
152
+ ' "detail-type": ["GuardDuty Finding"]\n'
153
+ " }'\n\n"
154
+ "# Add SNS target\n"
155
+ "aws events put-targets \\\n"
156
+ " --rule guardduty-findings \\\n"
157
+ " --targets Id=1,Arn=arn:aws:sns:region:account:security-alerts\n\n"
158
+ "Or use AWS Console:\n"
159
+ "1. Go to GuardDuty console\n"
160
+ "2. Click 'Get Started'\n"
161
+ "3. Click 'Enable GuardDuty'\n"
162
+ "4. Configure settings:\n"
163
+ " - Enable S3 Protection\n"
164
+ " - Enable EKS Protection (if applicable)\n"
165
+ " - Enable Malware Protection\n"
166
+ "5. Set up findings export:\n"
167
+ " - Go to Settings → Findings export options\n"
168
+ " - Configure S3 bucket for exports\n"
169
+ "6. Configure notifications:\n"
170
+ " - Go to EventBridge console\n"
171
+ " - Create rule for GuardDuty findings\n"
172
+ " - Add SNS topic as target\n\n"
173
+ "Best practices:\n"
174
+ "- Enable GuardDuty in all regions\n"
175
+ "- Use GuardDuty Organization for multi-account\n"
176
+ "- Configure automated responses (Lambda)\n"
177
+ "- Export findings to S3 for long-term storage\n"
178
+ "- Integrate with Security Hub\n"
179
+ "- Set up SNS/email notifications for high severity\n"
180
+ "- Review findings regularly (daily/weekly)\n"
181
+ "- Create suppression rules for known false positives\n"
182
+ "- Use Trusted IP lists for known safe IPs\n"
183
+ "- Use Threat IP lists for known malicious IPs\n"
184
+ "- Monitor GuardDuty coverage metrics\n\n"
185
+ "GuardDuty finding types:\n"
186
+ "Reconnaissance:\n"
187
+ "- Port scanning\n"
188
+ "- Unusual API calls\n"
189
+ "- Discovery attempts\n\n"
190
+ "Instance compromise:\n"
191
+ "- Cryptocurrency mining\n"
192
+ "- Backdoor communication\n"
193
+ "- Malware activity\n\n"
194
+ "Account compromise:\n"
195
+ "- Unusual behavior\n"
196
+ "- API calls from unusual locations\n"
197
+ "- Credential exfiltration\n\n"
198
+ "Bucket compromise:\n"
199
+ "- Suspicious S3 access\n"
200
+ "- Data exfiltration\n"
201
+ "- Policy changes\n\n"
202
+ "Cost considerations:\n"
203
+ "- Free 30-day trial\n"
204
+ "- Pricing based on:\n"
205
+ " • CloudTrail events analyzed\n"
206
+ " • VPC Flow Logs analyzed\n"
207
+ " • DNS logs analyzed\n"
208
+ " • S3 logs analyzed\n"
209
+ " • EKS logs analyzed\n"
210
+ "- Typically $4-5 per account per month\n"
211
+ "- Volume discounts available"
212
+ ),
213
+ evidence=None
214
+ )
215
+ result.add_finding(finding)
216
+ result.score = 0.0
217
+ result.passed = False
218
+ result.status = TestStatus.FAILED
219
+ result.metadata = {
220
+ "guardduty_enabled": False,
221
+ "message": "GuardDuty not enabled in region"
222
+ }
223
+ return result
224
+
225
+ # Get first detector (typically only one per region)
226
+ detector_id = detector_ids[0]
227
+ result.resources_scanned += 1
228
+
229
+ # Get detector details
230
+ self.logger.info("getting_guardduty_detector_details", detector_id=detector_id)
231
+ detector_response = guardduty_client.get_detector(DetectorId=detector_id)
232
+
233
+ status = detector_response.get("Status", "")
234
+ finding_publishing_frequency = detector_response.get("FindingPublishingFrequency", "")
235
+ data_sources = detector_response.get("DataSources", {})
236
+
237
+ # Check S3 protection
238
+ s3_logs = data_sources.get("S3Logs", {})
239
+ s3_protection_enabled = s3_logs.get("Status") == "ENABLED"
240
+
241
+ # Check Kubernetes (EKS) protection
242
+ kubernetes = data_sources.get("Kubernetes", {})
243
+ eks_audit_logs = kubernetes.get("AuditLogs", {})
244
+ eks_protection_enabled = eks_audit_logs.get("Status") == "ENABLED"
245
+
246
+ # Check Malware protection
247
+ malware_protection = data_sources.get("MalwareProtection", {})
248
+ scan_ec2 = malware_protection.get("ScanEc2InstanceWithFindings", {})
249
+ malware_protection_enabled = scan_ec2.get("EbsVolumes", {}).get("Status") == "ENABLED"
250
+
251
+ # Determine issues and calculate score
252
+ issues = []
253
+ severity = Severity.MEDIUM
254
+ score_points = 0 # Out of 100
255
+
256
+ # Check if detector is enabled (40 points)
257
+ if status == "ENABLED":
258
+ score_points += 40
259
+ else:
260
+ issues.append(f"GuardDuty detector is {status} (not ENABLED)")
261
+ severity = Severity.HIGH
262
+
263
+ # Check S3 protection (20 points)
264
+ if s3_protection_enabled:
265
+ score_points += 20
266
+ else:
267
+ issues.append("S3 Protection not enabled")
268
+
269
+ # Check EKS protection (20 points - if EKS is being used)
270
+ # Note: This is optional as not all accounts use EKS
271
+ if eks_protection_enabled:
272
+ score_points += 20
273
+ # Don't penalize if not enabled, as EKS might not be used
274
+
275
+ # Check Malware protection (20 points)
276
+ if malware_protection_enabled:
277
+ score_points += 20
278
+ else:
279
+ issues.append("Malware Protection not enabled")
280
+
281
+ # Create evidence
282
+ evidence = self.create_evidence(
283
+ resource_id=detector_id,
284
+ resource_type="guardduty_detector",
285
+ data={
286
+ "detector_id": detector_id,
287
+ "status": status,
288
+ "finding_publishing_frequency": finding_publishing_frequency,
289
+ "s3_protection_enabled": s3_protection_enabled,
290
+ "eks_protection_enabled": eks_protection_enabled,
291
+ "malware_protection_enabled": malware_protection_enabled,
292
+ "has_issues": len(issues) > 0,
293
+ "issues": issues,
294
+ "security_score": score_points,
295
+ }
296
+ )
297
+ result.add_evidence(evidence)
298
+
299
+ if len(issues) > 0:
300
+ # Create finding for GuardDuty configuration issues
301
+ finding = self.create_finding(
302
+ resource_id=detector_id,
303
+ resource_type="guardduty_detector",
304
+ severity=severity,
305
+ title="AWS GuardDuty has configuration issues",
306
+ description=f"AWS GuardDuty detector '{detector_id}' has configuration issues: "
307
+ f"{'; '.join(issues)}. GuardDuty should be fully enabled with all protection "
308
+ "features (S3, EKS, Malware) to provide comprehensive threat detection. "
309
+ "ISO 27001 A.8.16 requires comprehensive monitoring of security events.",
310
+ remediation=(
311
+ f"Improve GuardDuty detector '{detector_id}' configuration:\n\n"
312
+ "1. Ensure detector is enabled:\n"
313
+ f"aws guardduty update-detector \\\n"
314
+ f" --detector-id {detector_id} \\\n"
315
+ " --enable\n\n"
316
+ "2. Enable S3 Protection:\n"
317
+ f"aws guardduty update-detector \\\n"
318
+ f" --detector-id {detector_id} \\\n"
319
+ " --data-sources S3Logs={{Enable=true}}\n\n"
320
+ "3. Enable EKS Protection (if using EKS):\n"
321
+ f"aws guardduty update-detector \\\n"
322
+ f" --detector-id {detector_id} \\\n"
323
+ " --data-sources Kubernetes={{AuditLogs={{Enable=true}}}}\n\n"
324
+ "4. Enable Malware Protection:\n"
325
+ f"aws guardduty update-malware-protection-plan \\\n"
326
+ f" --detector-id {detector_id} \\\n"
327
+ " --enable\n\n"
328
+ "5. Configure findings frequency:\n"
329
+ f"aws guardduty update-detector \\\n"
330
+ f" --detector-id {detector_id} \\\n"
331
+ " --finding-publishing-frequency FIFTEEN_MINUTES\n\n"
332
+ "Or use AWS Console:\n"
333
+ "1. Go to GuardDuty console\n"
334
+ "2. Click Settings\n"
335
+ "3. Ensure 'Status' is Enabled\n"
336
+ "4. Enable protection features:\n"
337
+ " - S3 Protection: On\n"
338
+ " - EKS Protection: On (if using EKS)\n"
339
+ " - Malware Protection: On\n"
340
+ "5. Set findings publishing frequency\n"
341
+ "6. Click 'Save'\n\n"
342
+ "Additional recommendations:\n"
343
+ "- Review GuardDuty findings regularly\n"
344
+ "- Set up automated remediation with Lambda\n"
345
+ "- Export findings to S3 for analysis\n"
346
+ "- Integrate with SIEM tools\n"
347
+ "- Create CloudWatch alarms for high severity findings"
348
+ ),
349
+ evidence=evidence
350
+ )
351
+ result.add_finding(finding)
352
+
353
+ result.score = score_points
354
+ result.passed = score_points >= 80 # Require 80% for pass
355
+ result.status = TestStatus.PASSED if result.passed else TestStatus.FAILED
356
+
357
+ self.logger.warning(
358
+ "guardduty_has_issues",
359
+ detector_id=detector_id,
360
+ issues=issues,
361
+ score=score_points
362
+ )
363
+ else:
364
+ # GuardDuty is properly configured
365
+ result.score = 100.0
366
+ result.passed = True
367
+ result.status = TestStatus.PASSED
368
+
369
+ self.logger.info(
370
+ "guardduty_properly_configured",
371
+ detector_id=detector_id
372
+ )
373
+
374
+ # Add metadata
375
+ result.metadata = {
376
+ "guardduty_enabled": True,
377
+ "detector_id": detector_id,
378
+ "status": status,
379
+ "s3_protection": s3_protection_enabled,
380
+ "eks_protection": eks_protection_enabled,
381
+ "malware_protection": malware_protection_enabled,
382
+ "security_score": score_points,
383
+ "compliance_percentage": result.score,
384
+ }
385
+
386
+ self.logger.info(
387
+ "guardduty_enabled_test_completed",
388
+ detector_id=detector_id,
389
+ status=status,
390
+ score=result.score,
391
+ passed=result.passed
392
+ )
393
+
394
+ except ClientError as e:
395
+ error_code = e.response.get("Error", {}).get("Code")
396
+ self.logger.error("guardduty_enabled_test_error", error_code=error_code, error=str(e))
397
+ result.status = TestStatus.ERROR
398
+ result.passed = False
399
+ result.score = 0.0
400
+ result.error_message = f"AWS API Error: {error_code} - {str(e)}"
401
+
402
+ except Exception as e:
403
+ self.logger.error("guardduty_enabled_test_error", error=str(e))
404
+ result.status = TestStatus.ERROR
405
+ result.passed = False
406
+ result.score = 0.0
407
+ result.error_message = str(e)
408
+
409
+ return result
410
+
411
+
412
+ # ============================================================================
413
+ # CONVENIENCE FUNCTION
414
+ # ============================================================================
415
+
416
+
417
+ def run_guardduty_enabled_test(connector: AWSConnector) -> TestResult:
418
+ """Run AWS GuardDuty enabled compliance test.
419
+
420
+ Convenience function for running the test.
421
+
422
+ Args:
423
+ connector: AWS connector
424
+
425
+ Returns:
426
+ TestResult
427
+
428
+ Example:
429
+ >>> from complio.connectors.aws.client import AWSConnector
430
+ >>> connector = AWSConnector("production", "us-east-1")
431
+ >>> connector.connect()
432
+ >>> result = run_guardduty_enabled_test(connector)
433
+ >>> print(f"Score: {result.score}%")
434
+ """
435
+ test = GuardDutyEnabledTest(connector)
436
+ return test.execute()