aws-cis-controls-assessment 1.1.3__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 +172 -11
  32. aws_cis_controls_assessment-1.2.0.dist-info/METADATA +320 -0
  33. {aws_cis_controls_assessment-1.1.3.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.3.dist-info/METADATA +0 -404
  37. {aws_cis_controls_assessment-1.1.3.dist-info → aws_cis_controls_assessment-1.2.0.dist-info}/WHEEL +0 -0
  38. {aws_cis_controls_assessment-1.1.3.dist-info → aws_cis_controls_assessment-1.2.0.dist-info}/entry_points.txt +0 -0
  39. {aws_cis_controls_assessment-1.1.3.dist-info → aws_cis_controls_assessment-1.2.0.dist-info}/licenses/LICENSE +0 -0
  40. {aws_cis_controls_assessment-1.1.3.dist-info → aws_cis_controls_assessment-1.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,156 @@
1
+ """
2
+ CIS Control 10.1 - GuardDuty Malware Defense
3
+ Ensures GuardDuty is enabled for threat detection and malware defense.
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 GuardDutyEnabledAssessment(BaseConfigRuleAssessment):
18
+ """
19
+ CIS Control 10.1 - Deploy and Maintain Anti-Malware Software
20
+ AWS Config Rule: guardduty-enabled
21
+
22
+ Ensures GuardDuty is enabled for threat detection and malware defense.
23
+ GuardDuty provides intelligent threat detection by analyzing VPC Flow Logs,
24
+ CloudTrail events, and DNS logs to identify malicious activity.
25
+ """
26
+
27
+ def __init__(self):
28
+ super().__init__(
29
+ rule_name="guardduty-enabled",
30
+ control_id="10.1",
31
+ resource_types=["AWS::GuardDuty::Detector"]
32
+ )
33
+
34
+ def _get_resources(self, aws_factory: AWSClientFactory, resource_type: str, region: str) -> List[Dict[str, Any]]:
35
+ """Get GuardDuty detector configuration for the region."""
36
+ if resource_type != "AWS::GuardDuty::Detector":
37
+ return []
38
+
39
+ try:
40
+ guardduty_client = aws_factory.get_client('guardduty', region)
41
+
42
+ # List all detectors in the region
43
+ response = guardduty_client.list_detectors()
44
+ detector_ids = response.get('DetectorIds', [])
45
+
46
+ if not detector_ids:
47
+ # No detector found - return a placeholder resource for non-compliance
48
+ return [{
49
+ 'DetectorId': 'none',
50
+ 'Status': 'DISABLED',
51
+ 'Region': region,
52
+ 'AccountId': aws_factory.get_account_info().get('account_id', 'unknown')
53
+ }]
54
+
55
+ # Get details for each detector
56
+ detectors = []
57
+ for detector_id in detector_ids:
58
+ try:
59
+ detector_response = guardduty_client.get_detector(DetectorId=detector_id)
60
+
61
+ detectors.append({
62
+ 'DetectorId': detector_id,
63
+ 'Status': detector_response.get('Status', 'UNKNOWN'),
64
+ 'FindingPublishingFrequency': detector_response.get('FindingPublishingFrequency', 'UNKNOWN'),
65
+ 'DataSources': detector_response.get('DataSources', {}),
66
+ 'Region': region,
67
+ 'AccountId': aws_factory.get_account_info().get('account_id', 'unknown')
68
+ })
69
+
70
+ except ClientError as e:
71
+ logger.warning(f"Error getting detector {detector_id} details: {e}")
72
+ continue
73
+
74
+ return detectors if detectors else [{
75
+ 'DetectorId': 'none',
76
+ 'Status': 'DISABLED',
77
+ 'Region': region,
78
+ 'AccountId': aws_factory.get_account_info().get('account_id', 'unknown')
79
+ }]
80
+
81
+ except ClientError as e:
82
+ error_code = e.response.get('Error', {}).get('Code', '')
83
+ if error_code == 'AccessDeniedException':
84
+ logger.warning(f"Access denied to GuardDuty in {region}")
85
+ else:
86
+ logger.error(f"Error listing GuardDuty detectors in {region}: {e}")
87
+ return []
88
+
89
+ def _evaluate_resource_compliance(
90
+ self,
91
+ resource: Dict[str, Any],
92
+ aws_factory: AWSClientFactory,
93
+ region: str
94
+ ) -> ComplianceResult:
95
+ """Evaluate if GuardDuty is enabled."""
96
+ detector_id = resource.get('DetectorId', 'none')
97
+ status = resource.get('Status', 'DISABLED')
98
+
99
+ # Check if GuardDuty is enabled
100
+ is_compliant = status == 'ENABLED'
101
+
102
+ if is_compliant:
103
+ evaluation_reason = (
104
+ f"GuardDuty detector {detector_id} is enabled in {region}. "
105
+ f"Finding publishing frequency: {resource.get('FindingPublishingFrequency', 'UNKNOWN')}"
106
+ )
107
+ compliance_status = ComplianceStatus.COMPLIANT
108
+ else:
109
+ if detector_id == 'none':
110
+ evaluation_reason = f"GuardDuty is not enabled in {region}. No detector found."
111
+ else:
112
+ evaluation_reason = f"GuardDuty detector {detector_id} is disabled in {region}."
113
+ compliance_status = ComplianceStatus.NON_COMPLIANT
114
+
115
+ return ComplianceResult(
116
+ resource_id=detector_id,
117
+ resource_type="AWS::GuardDuty::Detector",
118
+ compliance_status=compliance_status,
119
+ evaluation_reason=evaluation_reason,
120
+ config_rule_name=self.rule_name,
121
+ region=region
122
+ )
123
+
124
+ def _get_rule_remediation_steps(self) -> List[str]:
125
+ """Get remediation steps for enabling GuardDuty."""
126
+ return [
127
+ "1. Enable GuardDuty in the AWS Console:",
128
+ " - Navigate to GuardDuty service",
129
+ " - Click 'Get Started' or 'Enable GuardDuty'",
130
+ " - Review and accept the service terms",
131
+ " - Click 'Enable GuardDuty'",
132
+ "",
133
+ "2. Enable GuardDuty using AWS CLI:",
134
+ " aws guardduty create-detector --enable --region <region>",
135
+ "",
136
+ "3. Configure finding publishing frequency (optional):",
137
+ " aws guardduty update-detector \\",
138
+ " --detector-id <detector-id> \\",
139
+ " --finding-publishing-frequency FIFTEEN_MINUTES \\",
140
+ " --region <region>",
141
+ "",
142
+ "4. Enable additional data sources (recommended):",
143
+ " - S3 Protection: Monitors S3 data events",
144
+ " - EKS Protection: Monitors Kubernetes audit logs",
145
+ " - Malware Protection: Scans EBS volumes",
146
+ "",
147
+ "5. Set up notifications:",
148
+ " - Create an SNS topic for GuardDuty findings",
149
+ " - Configure EventBridge rules to route findings",
150
+ "",
151
+ "Priority: HIGH - GuardDuty provides critical threat detection",
152
+ "Effort: Low - Can be enabled in minutes",
153
+ "",
154
+ "AWS Documentation:",
155
+ "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_settingup.html"
156
+ ]
@@ -0,0 +1,184 @@
1
+ """
2
+ CIS Control 7.1 - Amazon Inspector Vulnerability Management
3
+ Ensures Amazon Inspector is enabled for vulnerability scanning.
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 InspectorEnabledAssessment(BaseConfigRuleAssessment):
18
+ """
19
+ CIS Control 7.1 - Establish and Maintain a Vulnerability Management Process
20
+ AWS Config Rule: inspector-enabled
21
+
22
+ Ensures Amazon Inspector v2 is enabled for automated vulnerability scanning.
23
+ Inspector scans EC2 instances, container images, and Lambda functions for
24
+ software vulnerabilities and network exposure.
25
+ """
26
+
27
+ def __init__(self):
28
+ super().__init__(
29
+ rule_name="inspector-enabled",
30
+ control_id="7.1",
31
+ resource_types=["AWS::Inspector::AssessmentTarget"]
32
+ )
33
+
34
+ def _get_resources(self, aws_factory: AWSClientFactory, resource_type: str, region: str) -> List[Dict[str, Any]]:
35
+ """Get Amazon Inspector configuration for the region."""
36
+ if resource_type != "AWS::Inspector::AssessmentTarget":
37
+ return []
38
+
39
+ try:
40
+ inspector_client = aws_factory.get_client('inspector2', region)
41
+
42
+ # Check if Inspector is enabled by getting account status
43
+ try:
44
+ status_response = inspector_client.batch_get_account_status(
45
+ accountIds=[aws_factory.get_account_info().get('account_id', '')]
46
+ )
47
+
48
+ accounts = status_response.get('accounts', [])
49
+ if not accounts:
50
+ # Inspector not enabled
51
+ return [{
52
+ 'InspectorId': 'none',
53
+ 'Status': 'DISABLED',
54
+ 'Region': region,
55
+ 'AccountId': aws_factory.get_account_info().get('account_id', 'unknown'),
56
+ 'ResourceTypes': []
57
+ }]
58
+
59
+ account_status = accounts[0]
60
+ state = account_status.get('state', {}).get('status', 'DISABLED')
61
+
62
+ # Get coverage statistics
63
+ coverage_response = inspector_client.list_coverage(
64
+ maxResults=1 # Just checking if any resources are covered
65
+ )
66
+
67
+ covered_resources = coverage_response.get('coveredResources', [])
68
+ has_coverage = len(covered_resources) > 0
69
+
70
+ # Get resource types being scanned
71
+ resource_state = account_status.get('resourceState', {})
72
+ enabled_resource_types = [
73
+ rt for rt, status in resource_state.items()
74
+ if status.get('status') == 'ENABLED'
75
+ ]
76
+
77
+ return [{
78
+ 'InspectorId': f"inspector-{region}",
79
+ 'Status': state,
80
+ 'Region': region,
81
+ 'AccountId': aws_factory.get_account_info().get('account_id', 'unknown'),
82
+ 'ResourceTypes': enabled_resource_types,
83
+ 'HasCoverage': has_coverage
84
+ }]
85
+
86
+ except ClientError as e:
87
+ error_code = e.response.get('Error', {}).get('Code', '')
88
+ if error_code == 'ResourceNotFoundException':
89
+ # Inspector not enabled
90
+ return [{
91
+ 'InspectorId': 'none',
92
+ 'Status': 'DISABLED',
93
+ 'Region': region,
94
+ 'AccountId': aws_factory.get_account_info().get('account_id', 'unknown'),
95
+ 'ResourceTypes': []
96
+ }]
97
+ raise
98
+
99
+ except ClientError as e:
100
+ error_code = e.response.get('Error', {}).get('Code', '')
101
+ if error_code == 'AccessDeniedException':
102
+ logger.warning(f"Access denied to Inspector in {region}")
103
+ else:
104
+ logger.error(f"Error checking Inspector status in {region}: {e}")
105
+ return []
106
+
107
+ def _evaluate_resource_compliance(
108
+ self,
109
+ resource: Dict[str, Any],
110
+ aws_factory: AWSClientFactory,
111
+ region: str
112
+ ) -> ComplianceResult:
113
+ """Evaluate if Amazon Inspector is enabled."""
114
+ inspector_id = resource.get('InspectorId', 'none')
115
+ status = resource.get('Status', 'DISABLED')
116
+ resource_types = resource.get('ResourceTypes', [])
117
+
118
+ # Check if Inspector is enabled
119
+ is_compliant = status == 'ENABLED' and len(resource_types) > 0
120
+
121
+ if is_compliant:
122
+ evaluation_reason = (
123
+ f"Amazon Inspector is enabled in {region}. "
124
+ f"Scanning resource types: {', '.join(resource_types)}"
125
+ )
126
+ compliance_status = ComplianceStatus.COMPLIANT
127
+ else:
128
+ if inspector_id == 'none' or status == 'DISABLED':
129
+ evaluation_reason = f"Amazon Inspector is not enabled in {region}."
130
+ elif len(resource_types) == 0:
131
+ evaluation_reason = f"Amazon Inspector is enabled but no resource types are being scanned in {region}."
132
+ else:
133
+ evaluation_reason = f"Amazon Inspector status is {status} in {region}."
134
+ compliance_status = ComplianceStatus.NON_COMPLIANT
135
+
136
+ return ComplianceResult(
137
+ resource_id=inspector_id,
138
+ resource_type="AWS::Inspector::AssessmentTarget",
139
+ compliance_status=compliance_status,
140
+ evaluation_reason=evaluation_reason,
141
+ config_rule_name=self.rule_name,
142
+ region=region
143
+ )
144
+
145
+ def _get_rule_remediation_steps(self) -> List[str]:
146
+ """Get remediation steps for enabling Amazon Inspector."""
147
+ return [
148
+ "1. Enable Amazon Inspector v2 in the AWS Console:",
149
+ " - Navigate to Amazon Inspector service",
150
+ " - Click 'Get Started' or 'Enable Inspector'",
151
+ " - Select resource types to scan:",
152
+ " * EC2 instances (for OS vulnerabilities)",
153
+ " * ECR container images (for container vulnerabilities)",
154
+ " * Lambda functions (for code vulnerabilities)",
155
+ " - Click 'Enable'",
156
+ "",
157
+ "2. Enable Inspector using AWS CLI:",
158
+ " aws inspector2 enable \\",
159
+ " --resource-types EC2 ECR LAMBDA \\",
160
+ " --region <region>",
161
+ "",
162
+ "3. Verify Inspector is scanning resources:",
163
+ " aws inspector2 list-coverage \\",
164
+ " --region <region>",
165
+ "",
166
+ "4. Configure finding aggregation (optional):",
167
+ " - Set up cross-region aggregation for centralized findings",
168
+ " - Configure finding suppression rules for false positives",
169
+ "",
170
+ "5. Set up notifications:",
171
+ " - Create EventBridge rules to route findings to SNS/Slack",
172
+ " - Configure Security Hub integration for centralized findings",
173
+ "",
174
+ "6. Review findings regularly:",
175
+ " - Critical and High severity findings should be addressed immediately",
176
+ " - Medium findings within 30 days",
177
+ " - Low findings within 90 days",
178
+ "",
179
+ "Priority: HIGH - Vulnerability scanning is critical for security",
180
+ "Effort: Low - Can be enabled in minutes, ongoing effort for remediation",
181
+ "",
182
+ "AWS Documentation:",
183
+ "https://docs.aws.amazon.com/inspector/latest/user/getting_started_tutorial.html"
184
+ ]