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,460 @@
1
+ """
2
+ AWS EventBridge security monitoring rules compliance test.
3
+
4
+ Checks that EventBridge rules are configured for critical security events.
5
+
6
+ ISO 27001 Control: A.8.16 - Monitoring activities
7
+ Requirement: EventBridge rules should monitor critical security events
8
+
9
+ Example:
10
+ >>> from complio.connectors.aws.client import AWSConnector
11
+ >>> from complio.tests_library.logging.eventbridge_rules import EventBridgeRulesTest
12
+ >>>
13
+ >>> connector = AWSConnector("production", "us-east-1")
14
+ >>> connector.connect()
15
+ >>>
16
+ >>> test = EventBridgeRulesTest(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 EventBridgeRulesTest(ComplianceTest):
35
+ """Test for EventBridge security monitoring rules compliance.
36
+
37
+ Verifies that EventBridge rules are configured for critical security events:
38
+ - Rules for GuardDuty findings
39
+ - Rules for Security Hub findings
40
+ - Rules for AWS Config compliance changes
41
+ - Rules for CloudTrail security events
42
+ - Rules should have targets configured (SNS, Lambda, etc.)
43
+ - Rules should be enabled (not disabled)
44
+
45
+ Compliance Requirements:
46
+ - EventBridge rules for critical security services
47
+ - Rules have targets for notifications/remediation
48
+ - Rules are enabled and active
49
+ - Coverage for major security event sources
50
+
51
+ Scoring:
52
+ - Based on presence of security monitoring rules
53
+ - Checks for key event patterns
54
+ - Validates targets are configured
55
+
56
+ Example:
57
+ >>> test = EventBridgeRulesTest(connector)
58
+ >>> result = test.execute()
59
+ >>> for finding in result.findings:
60
+ ... print(f"{finding.resource_id}: {finding.title}")
61
+ """
62
+
63
+ # Critical security event sources to monitor
64
+ CRITICAL_EVENT_SOURCES = {
65
+ "aws.guardduty": "GuardDuty threat detection findings",
66
+ "aws.securityhub": "Security Hub aggregated findings",
67
+ "aws.config": "AWS Config compliance changes",
68
+ "aws.health": "AWS Health security events",
69
+ }
70
+
71
+ def __init__(self, connector: AWSConnector) -> None:
72
+ """Initialize EventBridge rules test.
73
+
74
+ Args:
75
+ connector: AWS connector instance
76
+ """
77
+ super().__init__(
78
+ test_id="eventbridge_rules",
79
+ test_name="EventBridge Security Rules Check",
80
+ description="Verify EventBridge rules are configured for critical security events",
81
+ control_id="A.8.16",
82
+ connector=connector,
83
+ scope="regional",
84
+ )
85
+
86
+ def _check_rule_event_pattern(self, event_pattern: str, source: str) -> bool:
87
+ """Check if event pattern matches a security event source.
88
+
89
+ Args:
90
+ event_pattern: JSON event pattern string
91
+ source: Event source to check for
92
+
93
+ Returns:
94
+ True if pattern includes the source
95
+ """
96
+ if not event_pattern:
97
+ return False
98
+
99
+ try:
100
+ import json
101
+ pattern = json.loads(event_pattern)
102
+
103
+ # Check if source is in the pattern
104
+ pattern_sources = pattern.get("source", [])
105
+ if isinstance(pattern_sources, str):
106
+ pattern_sources = [pattern_sources]
107
+
108
+ return source in pattern_sources
109
+
110
+ except (json.JSONDecodeError, TypeError):
111
+ return False
112
+
113
+ def execute(self) -> TestResult:
114
+ """Execute EventBridge security rules compliance test.
115
+
116
+ Returns:
117
+ TestResult with findings for missing or misconfigured rules
118
+
119
+ Example:
120
+ >>> test = EventBridgeRulesTest(connector)
121
+ >>> result = test.execute()
122
+ >>> print(result.score)
123
+ 75.0
124
+ """
125
+ result = TestResult(
126
+ test_id=self.test_id,
127
+ test_name=self.test_name,
128
+ status=TestStatus.PASSED,
129
+ passed=True,
130
+ score=100.0,
131
+ )
132
+
133
+ try:
134
+ # Get EventBridge client
135
+ events_client = self.connector.get_client("events")
136
+
137
+ # List all EventBridge rules
138
+ self.logger.info("listing_eventbridge_rules")
139
+ rules = []
140
+
141
+ paginator = events_client.get_paginator("list_rules")
142
+ for page in paginator.paginate():
143
+ rules.extend(page.get("Rules", []))
144
+
145
+ self.logger.info("eventbridge_rules_found", count=len(rules))
146
+
147
+ # Track which critical event sources have rules
148
+ sources_covered = {}
149
+ for source in self.CRITICAL_EVENT_SOURCES.keys():
150
+ sources_covered[source] = {
151
+ "has_rule": False,
152
+ "rules": [],
153
+ "has_targets": False
154
+ }
155
+
156
+ # Check each rule
157
+ for rule in rules:
158
+ rule_name = rule.get("Name", "")
159
+ rule_arn = rule.get("Arn", "")
160
+ rule_state = rule.get("State", "DISABLED")
161
+ event_pattern = rule.get("EventPattern", "")
162
+
163
+ result.resources_scanned += 1
164
+
165
+ # Check if rule is enabled
166
+ if rule_state != "ENABLED":
167
+ continue
168
+
169
+ # Check if rule monitors critical security events
170
+ for source in self.CRITICAL_EVENT_SOURCES.keys():
171
+ if self._check_rule_event_pattern(event_pattern, source):
172
+ sources_covered[source]["has_rule"] = True
173
+ sources_covered[source]["rules"].append(rule_name)
174
+
175
+ # Check if rule has targets
176
+ try:
177
+ targets_response = events_client.list_targets_by_rule(Rule=rule_name)
178
+ targets = targets_response.get("Targets", [])
179
+
180
+ if len(targets) > 0:
181
+ sources_covered[source]["has_targets"] = True
182
+
183
+ except ClientError as e:
184
+ self.logger.warning("error_checking_targets", rule=rule_name, error=str(e))
185
+
186
+ # Analyze coverage
187
+ issues = []
188
+ severity = Severity.MEDIUM
189
+ score_points = 0
190
+
191
+ # Calculate score based on coverage of critical sources
192
+ points_per_source = 100 / len(self.CRITICAL_EVENT_SOURCES)
193
+
194
+ for source, info in sources_covered.items():
195
+ source_name = self.CRITICAL_EVENT_SOURCES[source]
196
+
197
+ if info["has_rule"] and info["has_targets"]:
198
+ # Full coverage for this source
199
+ score_points += points_per_source
200
+ self.logger.debug(
201
+ "event_source_covered",
202
+ source=source,
203
+ rules=info["rules"]
204
+ )
205
+ elif info["has_rule"]:
206
+ # Rule exists but no targets
207
+ score_points += points_per_source * 0.5
208
+ issues.append(f"{source_name} has rules but no targets configured")
209
+ else:
210
+ # No rule for this source
211
+ issues.append(f"No EventBridge rule for {source_name}")
212
+ if source in ["aws.guardduty", "aws.securityhub"]:
213
+ severity = Severity.HIGH
214
+
215
+ # If no rules at all, this is more serious
216
+ if len(rules) == 0:
217
+ issues.insert(0, "No EventBridge rules configured")
218
+ severity = Severity.HIGH
219
+ score_points = 0
220
+
221
+ # Create evidence
222
+ evidence = self.create_evidence(
223
+ resource_id="eventbridge-security-rules",
224
+ resource_type="eventbridge_rules",
225
+ data={
226
+ "total_rules": len(rules),
227
+ "sources_coverage": sources_covered,
228
+ "has_issues": len(issues) > 0,
229
+ "issues": issues,
230
+ "security_score": score_points,
231
+ }
232
+ )
233
+ result.add_evidence(evidence)
234
+
235
+ if len(issues) > 0:
236
+ # Create finding for EventBridge rules issues
237
+ finding = self.create_finding(
238
+ resource_id="eventbridge-security-rules",
239
+ resource_type="eventbridge_rules",
240
+ severity=severity,
241
+ title="EventBridge security monitoring rules incomplete",
242
+ description=f"EventBridge security monitoring rules have coverage gaps: {'; '.join(issues)}. "
243
+ "EventBridge rules should be configured to monitor critical security events from "
244
+ "GuardDuty, Security Hub, Config, and other security services for timely "
245
+ "detection and response. ISO 27001 A.8.16 requires monitoring and alerting for "
246
+ "security events.",
247
+ remediation=(
248
+ "Configure EventBridge rules for security monitoring:\n\n"
249
+ "1. Create rule for GuardDuty findings:\n"
250
+ "aws events put-rule \\\n"
251
+ " --name guardduty-high-severity \\\n"
252
+ " --description 'Alert on high severity GuardDuty findings' \\\n"
253
+ " --event-pattern '{\n"
254
+ ' "source": ["aws.guardduty"],\n'
255
+ ' "detail-type": ["GuardDuty Finding"],\n'
256
+ ' "detail": {\n'
257
+ ' "severity": [7, 7.0, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, 8.9]\n'
258
+ ' }\n'
259
+ " }' \\\n"
260
+ " --state ENABLED\n\n"
261
+ "# Add SNS target\n"
262
+ "aws events put-targets \\\n"
263
+ " --rule guardduty-high-severity \\\n"
264
+ " --targets Id=1,Arn=arn:aws:sns:REGION:ACCOUNT:security-alerts\n\n"
265
+ "2. Create rule for Security Hub findings:\n"
266
+ "aws events put-rule \\\n"
267
+ " --name securityhub-critical-findings \\\n"
268
+ " --description 'Alert on critical Security Hub findings' \\\n"
269
+ " --event-pattern '{\n"
270
+ ' "source": ["aws.securityhub"],\n'
271
+ ' "detail-type": ["Security Hub Findings - Imported"],\n'
272
+ ' "detail": {\n'
273
+ ' "findings": {\n'
274
+ ' "Severity": {\n'
275
+ ' "Label": ["CRITICAL", "HIGH"]\n'
276
+ ' }\n'
277
+ ' }\n'
278
+ ' }\n'
279
+ " }' \\\n"
280
+ " --state ENABLED\n\n"
281
+ "# Add SNS target\n"
282
+ "aws events put-targets \\\n"
283
+ " --rule securityhub-critical-findings \\\n"
284
+ " --targets Id=1,Arn=arn:aws:sns:REGION:ACCOUNT:security-alerts\n\n"
285
+ "3. Create rule for Config compliance changes:\n"
286
+ "aws events put-rule \\\n"
287
+ " --name config-compliance-changes \\\n"
288
+ " --description 'Alert on Config compliance changes' \\\n"
289
+ " --event-pattern '{\n"
290
+ ' "source": ["aws.config"],\n'
291
+ ' "detail-type": ["Config Rules Compliance Change"],\n'
292
+ ' "detail": {\n'
293
+ ' "newEvaluationResult": {\n'
294
+ ' "complianceType": ["NON_COMPLIANT"]\n'
295
+ ' }\n'
296
+ ' }\n'
297
+ " }' \\\n"
298
+ " --state ENABLED\n\n"
299
+ "# Add SNS target\n"
300
+ "aws events put-targets \\\n"
301
+ " --rule config-compliance-changes \\\n"
302
+ " --targets Id=1,Arn=arn:aws:sns:REGION:ACCOUNT:compliance-alerts\n\n"
303
+ "4. Create rule for AWS Health events:\n"
304
+ "aws events put-rule \\\n"
305
+ " --name health-security-events \\\n"
306
+ " --description 'Alert on AWS Health security events' \\\n"
307
+ " --event-pattern '{\n"
308
+ ' "source": ["aws.health"],\n'
309
+ ' "detail-type": ["AWS Health Event"],\n'
310
+ ' "detail": {\n'
311
+ ' "service": ["SECURITY"],\n'
312
+ ' "eventTypeCategory": ["issue", "accountNotification"]\n'
313
+ ' }\n'
314
+ " }' \\\n"
315
+ " --state ENABLED\n\n"
316
+ "# Add SNS target\n"
317
+ "aws events put-targets \\\n"
318
+ " --rule health-security-events \\\n"
319
+ " --targets Id=1,Arn=arn:aws:sns:REGION:ACCOUNT:security-alerts\n\n"
320
+ "Or use AWS Console:\n"
321
+ "1. Go to Amazon EventBridge console\n"
322
+ "2. Click 'Rules' → 'Create rule'\n"
323
+ "3. Configure rule:\n"
324
+ " - Name: guardduty-high-severity\n"
325
+ " - Event bus: default\n"
326
+ " - Rule type: Rule with an event pattern\n"
327
+ "4. Build event pattern:\n"
328
+ " - Event source: AWS events\n"
329
+ " - Service: GuardDuty\n"
330
+ " - Event type: GuardDuty Finding\n"
331
+ " - Add condition: severity >= 7.0\n"
332
+ "5. Select targets:\n"
333
+ " - SNS topic (for notifications)\n"
334
+ " - Lambda function (for automated response)\n"
335
+ " - Step Functions (for workflows)\n"
336
+ "6. Click 'Create'\n"
337
+ "7. Repeat for other security services\n\n"
338
+ "Recommended target types:\n"
339
+ "SNS Topics:\n"
340
+ "- Email notifications to security team\n"
341
+ "- SMS for critical alerts\n"
342
+ "- Integration with PagerDuty/Slack\n\n"
343
+ "Lambda Functions:\n"
344
+ "- Automated remediation\n"
345
+ "- Ticket creation in JIRA/ServiceNow\n"
346
+ "- Custom notification formatting\n\n"
347
+ "SQS Queues:\n"
348
+ "- Buffering for processing\n"
349
+ "- Integration with external systems\n\n"
350
+ "Step Functions:\n"
351
+ "- Complex remediation workflows\n"
352
+ "- Approval processes\n\n"
353
+ "Best practices:\n"
354
+ "- Use descriptive rule names\n"
355
+ "- Filter events by severity\n"
356
+ "- Configure multiple targets for redundancy\n"
357
+ "- Test rules with sample events\n"
358
+ "- Monitor rule invocation metrics\n"
359
+ "- Use dead-letter queues for failed invocations\n"
360
+ "- Document response procedures\n"
361
+ "- Regularly review and update rules\n"
362
+ "- Use tags for rule organization\n"
363
+ "- Implement rate limiting for high-volume events\n\n"
364
+ "Additional security event patterns:\n"
365
+ "Root account usage:\n"
366
+ '{"source": ["aws.signin"], "detail": {"userIdentity": {"type": ["Root"]}}}\n\n'
367
+ "Console sign-in failures:\n"
368
+ '{"source": ["aws.signin"], "detail": {"eventName": ["ConsoleLogin"], "errorCode": ["Failed"]}}\n\n'
369
+ "S3 bucket policy changes:\n"
370
+ '{"source": ["aws.s3"], "detail": {"eventName": ["PutBucketPolicy", "DeleteBucketPolicy"]}}\n\n'
371
+ "IAM policy changes:\n"
372
+ '{"source": ["aws.iam"], "detail": {"eventName": ["CreatePolicy", "DeletePolicy", "AttachUserPolicy"]}}\n\n'
373
+ "Security group changes:\n"
374
+ '{"source": ["aws.ec2"], "detail": {"eventName": ["AuthorizeSecurityGroupIngress", "RevokeSecurityGroupIngress"]}}'
375
+ ),
376
+ evidence=evidence
377
+ )
378
+ result.add_finding(finding)
379
+
380
+ result.score = score_points
381
+ result.passed = score_points >= 70 # Require 70% coverage for pass
382
+ result.status = TestStatus.PASSED if result.passed else TestStatus.FAILED
383
+
384
+ self.logger.warning(
385
+ "eventbridge_rules_incomplete",
386
+ issues=issues,
387
+ score=score_points
388
+ )
389
+ else:
390
+ # All critical event sources have rules with targets
391
+ result.score = 100.0
392
+ result.passed = True
393
+ result.status = TestStatus.PASSED
394
+
395
+ self.logger.info(
396
+ "eventbridge_rules_complete",
397
+ total_rules=len(rules)
398
+ )
399
+
400
+ # Add metadata
401
+ result.metadata = {
402
+ "total_rules": len(rules),
403
+ "critical_sources": len(self.CRITICAL_EVENT_SOURCES),
404
+ "sources_covered": sum(1 for s in sources_covered.values() if s["has_rule"] and s["has_targets"]),
405
+ "sources_partial": sum(1 for s in sources_covered.values() if s["has_rule"] and not s["has_targets"]),
406
+ "sources_missing": sum(1 for s in sources_covered.values() if not s["has_rule"]),
407
+ "security_score": score_points,
408
+ "compliance_percentage": result.score,
409
+ }
410
+
411
+ self.logger.info(
412
+ "eventbridge_rules_test_completed",
413
+ total_rules=len(rules),
414
+ score=result.score,
415
+ passed=result.passed
416
+ )
417
+
418
+ except ClientError as e:
419
+ error_code = e.response.get("Error", {}).get("Code")
420
+ self.logger.error("eventbridge_rules_test_error", error_code=error_code, error=str(e))
421
+ result.status = TestStatus.ERROR
422
+ result.passed = False
423
+ result.score = 0.0
424
+ result.error_message = f"AWS API Error: {error_code} - {str(e)}"
425
+
426
+ except Exception as e:
427
+ self.logger.error("eventbridge_rules_test_error", error=str(e))
428
+ result.status = TestStatus.ERROR
429
+ result.passed = False
430
+ result.score = 0.0
431
+ result.error_message = str(e)
432
+
433
+ return result
434
+
435
+
436
+ # ============================================================================
437
+ # CONVENIENCE FUNCTION
438
+ # ============================================================================
439
+
440
+
441
+ def run_eventbridge_rules_test(connector: AWSConnector) -> TestResult:
442
+ """Run EventBridge security rules compliance test.
443
+
444
+ Convenience function for running the test.
445
+
446
+ Args:
447
+ connector: AWS connector
448
+
449
+ Returns:
450
+ TestResult
451
+
452
+ Example:
453
+ >>> from complio.connectors.aws.client import AWSConnector
454
+ >>> connector = AWSConnector("production", "us-east-1")
455
+ >>> connector.connect()
456
+ >>> result = run_eventbridge_rules_test(connector)
457
+ >>> print(f"Score: {result.score}%")
458
+ """
459
+ test = EventBridgeRulesTest(connector)
460
+ return test.execute()