aws-cis-controls-assessment 1.1.4__py3-none-any.whl → 1.2.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.
Files changed (40) hide show
  1. aws_cis_assessment/__init__.py +4 -4
  2. aws_cis_assessment/config/rules/cis_controls_ig1.yaml +365 -2
  3. aws_cis_assessment/controls/ig1/control_access_analyzer.py +198 -0
  4. aws_cis_assessment/controls/ig1/control_access_asset_mgmt.py +360 -0
  5. aws_cis_assessment/controls/ig1/control_access_control.py +323 -0
  6. aws_cis_assessment/controls/ig1/control_backup_security.py +579 -0
  7. aws_cis_assessment/controls/ig1/control_cloudfront_logging.py +215 -0
  8. aws_cis_assessment/controls/ig1/control_configuration_mgmt.py +407 -0
  9. aws_cis_assessment/controls/ig1/control_data_classification.py +255 -0
  10. aws_cis_assessment/controls/ig1/control_dynamodb_encryption.py +279 -0
  11. aws_cis_assessment/controls/ig1/control_ebs_encryption.py +177 -0
  12. aws_cis_assessment/controls/ig1/control_efs_encryption.py +243 -0
  13. aws_cis_assessment/controls/ig1/control_elb_logging.py +195 -0
  14. aws_cis_assessment/controls/ig1/control_guardduty.py +156 -0
  15. aws_cis_assessment/controls/ig1/control_inspector.py +184 -0
  16. aws_cis_assessment/controls/ig1/control_inventory.py +511 -0
  17. aws_cis_assessment/controls/ig1/control_macie.py +165 -0
  18. aws_cis_assessment/controls/ig1/control_messaging_encryption.py +419 -0
  19. aws_cis_assessment/controls/ig1/control_mfa.py +485 -0
  20. aws_cis_assessment/controls/ig1/control_network_security.py +194 -619
  21. aws_cis_assessment/controls/ig1/control_patch_management.py +626 -0
  22. aws_cis_assessment/controls/ig1/control_rds_encryption.py +228 -0
  23. aws_cis_assessment/controls/ig1/control_s3_encryption.py +383 -0
  24. aws_cis_assessment/controls/ig1/control_tls_ssl.py +556 -0
  25. aws_cis_assessment/controls/ig1/control_version_mgmt.py +329 -0
  26. aws_cis_assessment/controls/ig1/control_vpc_flow_logs.py +205 -0
  27. aws_cis_assessment/controls/ig1/control_waf_logging.py +226 -0
  28. aws_cis_assessment/core/models.py +20 -1
  29. aws_cis_assessment/core/scoring_engine.py +98 -1
  30. aws_cis_assessment/reporters/base_reporter.py +31 -1
  31. aws_cis_assessment/reporters/html_reporter.py +163 -0
  32. aws_cis_controls_assessment-1.2.0.dist-info/METADATA +320 -0
  33. {aws_cis_controls_assessment-1.1.4.dist-info → aws_cis_controls_assessment-1.2.0.dist-info}/RECORD +39 -15
  34. docs/developer-guide.md +204 -5
  35. docs/user-guide.md +137 -4
  36. aws_cis_controls_assessment-1.1.4.dist-info/METADATA +0 -404
  37. {aws_cis_controls_assessment-1.1.4.dist-info → aws_cis_controls_assessment-1.2.0.dist-info}/WHEEL +0 -0
  38. {aws_cis_controls_assessment-1.1.4.dist-info → aws_cis_controls_assessment-1.2.0.dist-info}/entry_points.txt +0 -0
  39. {aws_cis_controls_assessment-1.1.4.dist-info → aws_cis_controls_assessment-1.2.0.dist-info}/licenses/LICENSE +0 -0
  40. {aws_cis_controls_assessment-1.1.4.dist-info → aws_cis_controls_assessment-1.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,329 @@
1
+ """
2
+ CIS Control 2.2 - Version Management
3
+ Ensures software versions are current and supported.
4
+ """
5
+
6
+ import logging
7
+ from typing import List, Dict, Any
8
+ from botocore.exceptions import ClientError
9
+
10
+ from aws_cis_assessment.controls.base_control import BaseConfigRuleAssessment
11
+ from aws_cis_assessment.core.models import ComplianceResult, ComplianceStatus
12
+ from aws_cis_assessment.core.aws_client_factory import AWSClientFactory
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class EC2OSVersionSupportedAssessment(BaseConfigRuleAssessment):
18
+ """
19
+ CIS Control 2.2 - Ensure Authorized Software is Currently Supported
20
+ AWS Config Rule: ec2-os-version-supported
21
+
22
+ Ensures EC2 instances run supported operating system versions.
23
+ """
24
+
25
+ def __init__(self):
26
+ super().__init__(
27
+ rule_name="ec2-os-version-supported",
28
+ control_id="2.2",
29
+ resource_types=["AWS::EC2::Instance"]
30
+ )
31
+
32
+ def _get_resources(self, aws_factory: AWSClientFactory, resource_type: str, region: str) -> List[Dict[str, Any]]:
33
+ """Get EC2 instances with OS information."""
34
+ if resource_type != "AWS::EC2::Instance":
35
+ return []
36
+
37
+ try:
38
+ ssm_client = aws_factory.get_client('ssm', region)
39
+
40
+ # Get instance information from SSM
41
+ response = ssm_client.describe_instance_information()
42
+ instances = []
43
+
44
+ for instance in response.get('InstanceInformationList', []):
45
+ platform_name = instance.get('PlatformName', 'Unknown')
46
+ platform_version = instance.get('PlatformVersion', 'Unknown')
47
+
48
+ # Simple heuristic for supported versions
49
+ is_supported = self._check_version_support(platform_name, platform_version)
50
+
51
+ instances.append({
52
+ 'InstanceId': instance.get('InstanceId'),
53
+ 'PlatformName': platform_name,
54
+ 'PlatformVersion': platform_version,
55
+ 'IsSupported': is_supported
56
+ })
57
+
58
+ return instances
59
+
60
+ except ClientError as e:
61
+ logger.error(f"Error retrieving instance information in {region}: {e}")
62
+ return []
63
+
64
+ def _check_version_support(self, platform_name: str, platform_version: str) -> bool:
65
+ """Check if OS version is supported (simplified logic)."""
66
+ # This is a simplified check - in production, maintain a list of EOL versions
67
+ deprecated_keywords = ['2008', '2012', 'centos 6', 'ubuntu 14', 'ubuntu 16']
68
+ platform_lower = f"{platform_name} {platform_version}".lower()
69
+
70
+ return not any(keyword in platform_lower for keyword in deprecated_keywords)
71
+
72
+ def _evaluate_resource_compliance(
73
+ self,
74
+ resource: Dict[str, Any],
75
+ aws_factory: AWSClientFactory,
76
+ region: str
77
+ ) -> ComplianceResult:
78
+ """Evaluate if EC2 instance runs supported OS version."""
79
+ instance_id = resource.get('InstanceId', 'unknown')
80
+ platform_name = resource.get('PlatformName', 'Unknown')
81
+ platform_version = resource.get('PlatformVersion', 'Unknown')
82
+ is_supported = resource.get('IsSupported', True)
83
+
84
+ if is_supported:
85
+ evaluation_reason = f"Instance {instance_id} runs supported OS: {platform_name} {platform_version}"
86
+ compliance_status = ComplianceStatus.COMPLIANT
87
+ else:
88
+ evaluation_reason = f"Instance {instance_id} runs unsupported OS: {platform_name} {platform_version}"
89
+ compliance_status = ComplianceStatus.NON_COMPLIANT
90
+
91
+ return ComplianceResult(
92
+ resource_id=instance_id,
93
+ resource_type="AWS::EC2::Instance",
94
+ compliance_status=compliance_status,
95
+ evaluation_reason=evaluation_reason,
96
+ config_rule_name=self.rule_name,
97
+ region=region
98
+ )
99
+
100
+ def _get_rule_remediation_steps(self) -> List[str]:
101
+ """Get remediation steps for OS version support."""
102
+ return [
103
+ "1. Identify instances with unsupported OS:",
104
+ " aws ssm describe-instance-information \\",
105
+ " --query 'InstanceInformationList[].{ID:InstanceId,OS:PlatformName,Version:PlatformVersion}'",
106
+ "",
107
+ "2. Plan migration to supported OS versions",
108
+ "3. Create new instances with supported OS",
109
+ "4. Migrate workloads to new instances",
110
+ "5. Decommission old instances",
111
+ "",
112
+ "Priority: HIGH - Security risk with unsupported OS",
113
+ "Effort: High - Requires migration planning",
114
+ "",
115
+ "AWS Documentation:",
116
+ "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html"
117
+ ]
118
+
119
+
120
+ class RDSEngineVersionSupportedAssessment(BaseConfigRuleAssessment):
121
+ """
122
+ CIS Control 2.2 - Ensure Authorized Software is Currently Supported
123
+ AWS Config Rule: rds-engine-version-supported
124
+
125
+ Ensures RDS instances run supported database engine versions.
126
+ """
127
+
128
+ def __init__(self):
129
+ super().__init__(
130
+ rule_name="rds-engine-version-supported",
131
+ control_id="2.2",
132
+ resource_types=["AWS::RDS::DBInstance"]
133
+ )
134
+
135
+ def _get_resources(self, aws_factory: AWSClientFactory, resource_type: str, region: str) -> List[Dict[str, Any]]:
136
+ """Get RDS instances with engine version information."""
137
+ if resource_type != "AWS::RDS::DBInstance":
138
+ return []
139
+
140
+ try:
141
+ rds_client = aws_factory.get_client('rds', region)
142
+
143
+ response = rds_client.describe_db_instances()
144
+ instances = []
145
+
146
+ for db in response.get('DBInstances', []):
147
+ engine = db.get('Engine')
148
+ engine_version = db.get('EngineVersion')
149
+
150
+ # Check if version is deprecated
151
+ try:
152
+ versions_response = rds_client.describe_db_engine_versions(
153
+ Engine=engine,
154
+ EngineVersion=engine_version
155
+ )
156
+
157
+ if versions_response.get('DBEngineVersions'):
158
+ version_info = versions_response['DBEngineVersions'][0]
159
+ is_deprecated = version_info.get('Status') == 'deprecated'
160
+ else:
161
+ is_deprecated = False
162
+ except ClientError:
163
+ is_deprecated = False
164
+
165
+ instances.append({
166
+ 'DBInstanceIdentifier': db.get('DBInstanceIdentifier'),
167
+ 'Engine': engine,
168
+ 'EngineVersion': engine_version,
169
+ 'IsDeprecated': is_deprecated
170
+ })
171
+
172
+ return instances
173
+
174
+ except ClientError as e:
175
+ logger.error(f"Error retrieving RDS instances in {region}: {e}")
176
+ return []
177
+
178
+ def _evaluate_resource_compliance(
179
+ self,
180
+ resource: Dict[str, Any],
181
+ aws_factory: AWSClientFactory,
182
+ region: str
183
+ ) -> ComplianceResult:
184
+ """Evaluate if RDS instance runs supported engine version."""
185
+ db_id = resource.get('DBInstanceIdentifier', 'unknown')
186
+ engine = resource.get('Engine', 'unknown')
187
+ engine_version = resource.get('EngineVersion', 'unknown')
188
+ is_deprecated = resource.get('IsDeprecated', False)
189
+
190
+ if not is_deprecated:
191
+ evaluation_reason = f"RDS instance {db_id} runs supported {engine} version {engine_version}"
192
+ compliance_status = ComplianceStatus.COMPLIANT
193
+ else:
194
+ evaluation_reason = f"RDS instance {db_id} runs deprecated {engine} version {engine_version}"
195
+ compliance_status = ComplianceStatus.NON_COMPLIANT
196
+
197
+ return ComplianceResult(
198
+ resource_id=db_id,
199
+ resource_type="AWS::RDS::DBInstance",
200
+ compliance_status=compliance_status,
201
+ evaluation_reason=evaluation_reason,
202
+ config_rule_name=self.rule_name,
203
+ region=region
204
+ )
205
+
206
+ def _get_rule_remediation_steps(self) -> List[str]:
207
+ """Get remediation steps for RDS version support."""
208
+ return [
209
+ "1. Check for available engine versions:",
210
+ " aws rds describe-db-engine-versions \\",
211
+ " --engine <engine-name> \\",
212
+ " --query 'DBEngineVersions[?Status!=`deprecated`]'",
213
+ "",
214
+ "2. Upgrade RDS instance:",
215
+ " aws rds modify-db-instance \\",
216
+ " --db-instance-identifier <db-id> \\",
217
+ " --engine-version <new-version> \\",
218
+ " --apply-immediately",
219
+ "",
220
+ "3. Test application compatibility before upgrading",
221
+ "",
222
+ "Priority: HIGH - Deprecated versions lack security updates",
223
+ "Effort: Medium - Requires testing and maintenance window",
224
+ "",
225
+ "AWS Documentation:",
226
+ "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.Upgrading.html"
227
+ ]
228
+
229
+
230
+ class LambdaRuntimeSupportedAssessment(BaseConfigRuleAssessment):
231
+ """
232
+ CIS Control 2.2 - Ensure Authorized Software is Currently Supported
233
+ AWS Config Rule: lambda-runtime-supported
234
+
235
+ Ensures Lambda functions use supported runtimes.
236
+ """
237
+
238
+ def __init__(self):
239
+ super().__init__(
240
+ rule_name="lambda-runtime-supported",
241
+ control_id="2.2",
242
+ resource_types=["AWS::Lambda::Function"]
243
+ )
244
+
245
+ def _get_resources(self, aws_factory: AWSClientFactory, resource_type: str, region: str) -> List[Dict[str, Any]]:
246
+ """Get Lambda functions with runtime information."""
247
+ if resource_type != "AWS::Lambda::Function":
248
+ return []
249
+
250
+ try:
251
+ lambda_client = aws_factory.get_client('lambda', region)
252
+ functions = []
253
+
254
+ # Deprecated runtimes as of 2026
255
+ deprecated_runtimes = [
256
+ 'python2.7', 'python3.6', 'python3.7',
257
+ 'nodejs10.x', 'nodejs12.x', 'nodejs14.x',
258
+ 'ruby2.5', 'ruby2.7',
259
+ 'dotnetcore2.1', 'dotnetcore3.1',
260
+ 'go1.x'
261
+ ]
262
+
263
+ paginator = lambda_client.get_paginator('list_functions')
264
+ for page in paginator.paginate():
265
+ for func in page.get('Functions', []):
266
+ runtime = func.get('Runtime', 'unknown')
267
+ is_deprecated = runtime in deprecated_runtimes
268
+
269
+ functions.append({
270
+ 'FunctionName': func.get('FunctionName'),
271
+ 'FunctionArn': func.get('FunctionArn'),
272
+ 'Runtime': runtime,
273
+ 'IsDeprecated': is_deprecated
274
+ })
275
+
276
+ return functions
277
+
278
+ except ClientError as e:
279
+ logger.error(f"Error retrieving Lambda functions in {region}: {e}")
280
+ return []
281
+
282
+ def _evaluate_resource_compliance(
283
+ self,
284
+ resource: Dict[str, Any],
285
+ aws_factory: AWSClientFactory,
286
+ region: str
287
+ ) -> ComplianceResult:
288
+ """Evaluate if Lambda function uses supported runtime."""
289
+ function_name = resource.get('FunctionName', 'unknown')
290
+ runtime = resource.get('Runtime', 'unknown')
291
+ is_deprecated = resource.get('IsDeprecated', False)
292
+
293
+ if not is_deprecated:
294
+ evaluation_reason = f"Lambda function {function_name} uses supported runtime: {runtime}"
295
+ compliance_status = ComplianceStatus.COMPLIANT
296
+ else:
297
+ evaluation_reason = f"Lambda function {function_name} uses deprecated runtime: {runtime}"
298
+ compliance_status = ComplianceStatus.NON_COMPLIANT
299
+
300
+ return ComplianceResult(
301
+ resource_id=resource.get('FunctionArn', function_name),
302
+ resource_type="AWS::Lambda::Function",
303
+ compliance_status=compliance_status,
304
+ evaluation_reason=evaluation_reason,
305
+ config_rule_name=self.rule_name,
306
+ region=region
307
+ )
308
+
309
+ def _get_rule_remediation_steps(self) -> List[str]:
310
+ """Get remediation steps for Lambda runtime support."""
311
+ return [
312
+ "1. List functions with deprecated runtimes:",
313
+ " aws lambda list-functions \\",
314
+ " --query 'Functions[?Runtime==`python3.7`].FunctionName'",
315
+ "",
316
+ "2. Update function runtime:",
317
+ " aws lambda update-function-configuration \\",
318
+ " --function-name <function-name> \\",
319
+ " --runtime python3.11",
320
+ "",
321
+ "3. Test function after runtime update",
322
+ "4. Update deployment packages if needed",
323
+ "",
324
+ "Priority: HIGH - Deprecated runtimes lose security support",
325
+ "Effort: Medium - Requires testing and code updates",
326
+ "",
327
+ "AWS Documentation:",
328
+ "https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html"
329
+ ]
@@ -0,0 +1,205 @@
1
+ """
2
+ CIS Control 8.2 - VPC Flow Logs
3
+ Ensures VPC Flow Logs are enabled for network traffic visibility.
4
+ """
5
+
6
+ import logging
7
+ from typing import List, Dict, Any
8
+ from botocore.exceptions import ClientError
9
+
10
+ from aws_cis_assessment.controls.base_control import BaseConfigRuleAssessment
11
+ from aws_cis_assessment.core.models import ComplianceResult, ComplianceStatus
12
+ from aws_cis_assessment.core.aws_client_factory import AWSClientFactory
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class VPCFlowLogsEnabledAssessment(BaseConfigRuleAssessment):
18
+ """
19
+ CIS Control 8.2 - Collect Audit Logs
20
+ AWS Config Rule: vpc-flow-logs-enabled
21
+
22
+ Ensures VPC Flow Logs are enabled for network traffic monitoring.
23
+ Flow Logs capture information about IP traffic going to and from
24
+ network interfaces in VPCs, essential for security analysis and troubleshooting.
25
+ """
26
+
27
+ def __init__(self):
28
+ super().__init__(
29
+ rule_name="vpc-flow-logs-enabled",
30
+ control_id="8.2",
31
+ resource_types=["AWS::EC2::VPC"]
32
+ )
33
+
34
+ def _get_resources(self, aws_factory: AWSClientFactory, resource_type: str, region: str) -> List[Dict[str, Any]]:
35
+ """Get VPCs and their Flow Logs configuration."""
36
+ if resource_type != "AWS::EC2::VPC":
37
+ return []
38
+
39
+ try:
40
+ ec2_client = aws_factory.get_client('ec2', region)
41
+
42
+ # Get all VPCs
43
+ vpcs_response = ec2_client.describe_vpcs()
44
+ vpcs = vpcs_response.get('Vpcs', [])
45
+
46
+ if not vpcs:
47
+ return []
48
+
49
+ # Get all Flow Logs
50
+ flow_logs_response = ec2_client.describe_flow_logs()
51
+ flow_logs = flow_logs_response.get('FlowLogs', [])
52
+
53
+ # Create a mapping of VPC ID to Flow Logs
54
+ vpc_flow_logs = {}
55
+ for flow_log in flow_logs:
56
+ resource_id = flow_log.get('ResourceId', '')
57
+ if resource_id.startswith('vpc-'):
58
+ if resource_id not in vpc_flow_logs:
59
+ vpc_flow_logs[resource_id] = []
60
+ vpc_flow_logs[resource_id].append(flow_log)
61
+
62
+ # Build resource list with Flow Log status
63
+ vpc_resources = []
64
+ for vpc in vpcs:
65
+ vpc_id = vpc.get('VpcId', '')
66
+ vpc_flow_log_list = vpc_flow_logs.get(vpc_id, [])
67
+
68
+ # Check if any active Flow Logs exist
69
+ active_flow_logs = [
70
+ fl for fl in vpc_flow_log_list
71
+ if fl.get('FlowLogStatus') == 'ACTIVE'
72
+ ]
73
+
74
+ vpc_resources.append({
75
+ 'VpcId': vpc_id,
76
+ 'IsDefault': vpc.get('IsDefault', False),
77
+ 'CidrBlock': vpc.get('CidrBlock', ''),
78
+ 'State': vpc.get('State', ''),
79
+ 'Region': region,
80
+ 'FlowLogs': active_flow_logs,
81
+ 'HasActiveFlowLogs': len(active_flow_logs) > 0,
82
+ 'Tags': vpc.get('Tags', [])
83
+ })
84
+
85
+ return vpc_resources
86
+
87
+ except ClientError as e:
88
+ error_code = e.response.get('Error', {}).get('Code', '')
89
+ if error_code == 'UnauthorizedOperation':
90
+ logger.warning(f"Access denied to describe VPCs/Flow Logs in {region}")
91
+ else:
92
+ logger.error(f"Error describing VPCs/Flow Logs in {region}: {e}")
93
+ return []
94
+
95
+ def _evaluate_resource_compliance(
96
+ self,
97
+ resource: Dict[str, Any],
98
+ aws_factory: AWSClientFactory,
99
+ region: str
100
+ ) -> ComplianceResult:
101
+ """Evaluate if VPC has Flow Logs enabled."""
102
+ vpc_id = resource.get('VpcId', '')
103
+ has_flow_logs = resource.get('HasActiveFlowLogs', False)
104
+ flow_logs = resource.get('FlowLogs', [])
105
+ is_default = resource.get('IsDefault', False)
106
+
107
+ # Check if VPC has active Flow Logs
108
+ is_compliant = has_flow_logs
109
+
110
+ if is_compliant:
111
+ # Provide details about the Flow Logs
112
+ flow_log_details = []
113
+ for fl in flow_logs:
114
+ destination = fl.get('LogDestinationType', 'unknown')
115
+ traffic_type = fl.get('TrafficType', 'unknown')
116
+ flow_log_details.append(f"{traffic_type} to {destination}")
117
+
118
+ evaluation_reason = (
119
+ f"VPC {vpc_id} has {len(flow_logs)} active Flow Log(s) enabled: "
120
+ f"{', '.join(flow_log_details)}"
121
+ )
122
+ if is_default:
123
+ evaluation_reason += " (Default VPC)"
124
+
125
+ compliance_status = ComplianceStatus.COMPLIANT
126
+ else:
127
+ evaluation_reason = f"VPC {vpc_id} does not have Flow Logs enabled."
128
+ if is_default:
129
+ evaluation_reason += " (Default VPC - should be monitored)"
130
+ compliance_status = ComplianceStatus.NON_COMPLIANT
131
+
132
+ return ComplianceResult(
133
+ resource_id=vpc_id,
134
+ resource_type="AWS::EC2::VPC",
135
+ compliance_status=compliance_status,
136
+ evaluation_reason=evaluation_reason,
137
+ config_rule_name=self.rule_name,
138
+ region=region
139
+ )
140
+
141
+ def _get_rule_remediation_steps(self) -> List[str]:
142
+ """Get remediation steps for enabling VPC Flow Logs."""
143
+ return [
144
+ "1. Enable VPC Flow Logs in the AWS Console:",
145
+ " - Navigate to VPC service",
146
+ " - Select the VPC",
147
+ " - Click 'Actions' > 'Create flow log'",
148
+ " - Configure:",
149
+ " * Filter: ALL (captures accepted and rejected traffic)",
150
+ " * Destination: CloudWatch Logs or S3",
151
+ " * IAM role: Create or select role with permissions",
152
+ " - Click 'Create flow log'",
153
+ "",
154
+ "2. Enable Flow Logs using AWS CLI (CloudWatch Logs):",
155
+ " # Create IAM role first (one-time setup)",
156
+ " aws iam create-role \\",
157
+ " --role-name VPCFlowLogsRole \\",
158
+ " --assume-role-policy-document file://trust-policy.json",
159
+ "",
160
+ " # Create Flow Log",
161
+ " aws ec2 create-flow-logs \\",
162
+ " --resource-type VPC \\",
163
+ " --resource-ids <vpc-id> \\",
164
+ " --traffic-type ALL \\",
165
+ " --log-destination-type cloud-watch-logs \\",
166
+ " --log-group-name /aws/vpc/flowlogs \\",
167
+ " --deliver-logs-permission-arn <role-arn> \\",
168
+ " --region <region>",
169
+ "",
170
+ "3. Enable Flow Logs using AWS CLI (S3):",
171
+ " aws ec2 create-flow-logs \\",
172
+ " --resource-type VPC \\",
173
+ " --resource-ids <vpc-id> \\",
174
+ " --traffic-type ALL \\",
175
+ " --log-destination-type s3 \\",
176
+ " --log-destination arn:aws:s3:::<bucket-name> \\",
177
+ " --region <region>",
178
+ "",
179
+ "4. Best practices:",
180
+ " - Enable for ALL traffic (not just ACCEPT or REJECT)",
181
+ " - Use S3 for cost-effective long-term storage",
182
+ " - Use CloudWatch Logs for real-time analysis and alerting",
183
+ " - Set appropriate log retention (30-90 days minimum)",
184
+ " - Enable for all VPCs, including default VPC",
185
+ "",
186
+ "5. Analyze Flow Logs:",
187
+ " - Use CloudWatch Insights for queries",
188
+ " - Use Athena for S3-based logs",
189
+ " - Look for:",
190
+ " * Rejected traffic (potential attacks)",
191
+ " * Unusual traffic patterns",
192
+ " * Data exfiltration attempts",
193
+ " * Unauthorized access attempts",
194
+ "",
195
+ "6. Cost optimization:",
196
+ " - Flow Logs incur charges for data ingestion and storage",
197
+ " - Use sampling if full capture is too expensive",
198
+ " - Archive old logs to S3 Glacier",
199
+ "",
200
+ "Priority: HIGH - Network visibility is essential for security",
201
+ "Effort: Low - Can be enabled in minutes per VPC",
202
+ "",
203
+ "AWS Documentation:",
204
+ "https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html"
205
+ ]