aws-cis-controls-assessment 1.2.0__py3-none-any.whl → 1.2.2__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.
- aws_cis_assessment/__init__.py +1 -1
- aws_cis_assessment/config/rules/cis_controls_ig1.yaml +3 -3
- aws_cis_assessment/controls/base_control.py +106 -24
- aws_cis_assessment/controls/ig1/__init__.py +144 -15
- aws_cis_assessment/controls/ig1/control_4_1.py +4 -4
- aws_cis_assessment/controls/ig1/control_guardduty.py +4 -4
- aws_cis_assessment/controls/ig1/control_s3_encryption.py +1 -1
- aws_cis_assessment/controls/ig1/control_tls_ssl.py +4 -4
- aws_cis_assessment/controls/ig1/control_version_mgmt.py +9 -1
- aws_cis_assessment/core/assessment_engine.py +160 -11
- aws_cis_assessment/core/aws_client_factory.py +17 -5
- aws_cis_assessment/core/scoring_engine.py +19 -15
- aws_cis_assessment/reporters/base_reporter.py +27 -12
- aws_cis_assessment/reporters/html_reporter.py +23 -9
- {aws_cis_controls_assessment-1.2.0.dist-info → aws_cis_controls_assessment-1.2.2.dist-info}/METADATA +1 -1
- {aws_cis_controls_assessment-1.2.0.dist-info → aws_cis_controls_assessment-1.2.2.dist-info}/RECORD +20 -20
- {aws_cis_controls_assessment-1.2.0.dist-info → aws_cis_controls_assessment-1.2.2.dist-info}/WHEEL +0 -0
- {aws_cis_controls_assessment-1.2.0.dist-info → aws_cis_controls_assessment-1.2.2.dist-info}/entry_points.txt +0 -0
- {aws_cis_controls_assessment-1.2.0.dist-info → aws_cis_controls_assessment-1.2.2.dist-info}/licenses/LICENSE +0 -0
- {aws_cis_controls_assessment-1.2.0.dist-info → aws_cis_controls_assessment-1.2.2.dist-info}/top_level.txt +0 -0
aws_cis_assessment/__init__.py
CHANGED
|
@@ -6,6 +6,6 @@ CIS Controls Implementation Groups (IG1, IG2, IG3). Implements 175 comprehensive
|
|
|
6
6
|
across all implementation groups with 75%+ coverage of CIS Controls v8.1 IG1 safeguards.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
__version__ = "1.2.
|
|
9
|
+
__version__ = "1.2.2"
|
|
10
10
|
__author__ = "AWS CIS Assessment Team"
|
|
11
11
|
__description__ = "Production-ready AWS CIS Controls Compliance Assessment Framework with Enhanced IG1 Coverage"
|
|
@@ -917,12 +917,12 @@ controls:
|
|
|
917
917
|
title: Encrypt Sensitive Data in Transit
|
|
918
918
|
weight: 1.0
|
|
919
919
|
config_rules:
|
|
920
|
-
- name: alb-http-to-https-redirection
|
|
920
|
+
- name: alb-http-to-https-redirection-check
|
|
921
921
|
resource_types:
|
|
922
922
|
- AWS::ElasticLoadBalancingV2::LoadBalancer
|
|
923
923
|
parameters: {}
|
|
924
|
-
description: "CIS Control 3.10 - Encrypt Sensitive Data in Transit\n AWS Config Rule: alb-http-to-https-redirection\n \n Ensures Application Load Balancers redirect HTTP traffic to HTTPS."
|
|
925
|
-
remediation_guidance: Follow AWS Config rule guidance for alb-http-to-https-redirection
|
|
924
|
+
description: "CIS Control 3.10 - Encrypt Sensitive Data in Transit\n AWS Config Rule: alb-http-to-https-redirection-check\n \n Ensures Application Load Balancers redirect HTTP traffic to HTTPS."
|
|
925
|
+
remediation_guidance: Follow AWS Config rule guidance for alb-http-to-https-redirection-check
|
|
926
926
|
- name: elb-tls-https-listeners-only
|
|
927
927
|
resource_types:
|
|
928
928
|
- AWS::ElasticLoadBalancingV2::LoadBalancer
|
|
@@ -56,25 +56,37 @@ class BaseConfigRuleAssessment(ABC):
|
|
|
56
56
|
results = []
|
|
57
57
|
|
|
58
58
|
try:
|
|
59
|
-
# Validate that we can access required services
|
|
60
|
-
if not self._validate_service_access(aws_factory, region):
|
|
61
|
-
return [self._create_error_result(
|
|
62
|
-
"SERVICE_UNAVAILABLE",
|
|
63
|
-
f"Required AWS services not accessible in region {region}",
|
|
64
|
-
region
|
|
65
|
-
)]
|
|
66
|
-
|
|
67
59
|
# Evaluate each resource type
|
|
68
60
|
for resource_type in self.resource_types:
|
|
69
61
|
try:
|
|
62
|
+
# Determine evaluation region (us-east-1 for account-level resources)
|
|
63
|
+
eval_region = self._get_evaluation_region(resource_type, region)
|
|
64
|
+
is_account_level = self._is_account_level_resource(resource_type)
|
|
65
|
+
|
|
66
|
+
# Skip account-level resources in non-primary regions to prevent duplication
|
|
67
|
+
# Account-level resources are only evaluated once in us-east-1
|
|
68
|
+
if is_account_level and region != 'us-east-1':
|
|
69
|
+
logger.debug(f"Skipping {resource_type} in {region} (account-level resource, evaluated in us-east-1 only)")
|
|
70
|
+
continue
|
|
71
|
+
|
|
72
|
+
# Validate that we can access required services in the evaluation region
|
|
73
|
+
if not self._validate_service_access(aws_factory, eval_region):
|
|
74
|
+
results.append(self._create_error_result(
|
|
75
|
+
"SERVICE_UNAVAILABLE",
|
|
76
|
+
f"Required AWS services not accessible in region {eval_region}",
|
|
77
|
+
eval_region,
|
|
78
|
+
resource_type
|
|
79
|
+
))
|
|
80
|
+
continue
|
|
81
|
+
|
|
70
82
|
# Use error handler for resource discovery if available
|
|
71
83
|
def get_resources():
|
|
72
|
-
return self._get_resources(aws_factory, resource_type,
|
|
84
|
+
return self._get_resources(aws_factory, resource_type, eval_region)
|
|
73
85
|
|
|
74
86
|
if self.error_handler:
|
|
75
87
|
context = ErrorContext(
|
|
76
88
|
service_name=self._get_required_services()[0] if self._get_required_services() else "",
|
|
77
|
-
region=
|
|
89
|
+
region=eval_region,
|
|
78
90
|
resource_type=resource_type,
|
|
79
91
|
operation="get_resources",
|
|
80
92
|
control_id=self.control_id,
|
|
@@ -90,18 +102,18 @@ class BaseConfigRuleAssessment(ABC):
|
|
|
90
102
|
else:
|
|
91
103
|
resources = get_resources()
|
|
92
104
|
|
|
93
|
-
logger.debug(f"Found {len(resources)} resources of type {resource_type} in {
|
|
105
|
+
logger.debug(f"Found {len(resources)} resources of type {resource_type} in {eval_region}")
|
|
94
106
|
|
|
95
107
|
for resource in resources:
|
|
96
108
|
try:
|
|
97
109
|
# Use error handler for resource evaluation if available
|
|
98
110
|
def evaluate_resource():
|
|
99
|
-
return self._evaluate_resource_compliance(resource, aws_factory,
|
|
111
|
+
return self._evaluate_resource_compliance(resource, aws_factory, eval_region)
|
|
100
112
|
|
|
101
113
|
if self.error_handler:
|
|
102
114
|
context = ErrorContext(
|
|
103
115
|
service_name=self._get_required_services()[0] if self._get_required_services() else "",
|
|
104
|
-
region=
|
|
116
|
+
region=eval_region,
|
|
105
117
|
resource_type=resource_type,
|
|
106
118
|
resource_id=resource.get('id', 'unknown'),
|
|
107
119
|
operation="evaluate_compliance",
|
|
@@ -121,13 +133,20 @@ class BaseConfigRuleAssessment(ABC):
|
|
|
121
133
|
results.append(compliance)
|
|
122
134
|
|
|
123
135
|
except Exception as e:
|
|
124
|
-
|
|
136
|
+
error_str = str(e)
|
|
137
|
+
# Log expected errors at DEBUG level
|
|
138
|
+
if ("Parameter validation failed" in error_str or
|
|
139
|
+
"Missing required parameter" in error_str or
|
|
140
|
+
"Could not connect to the endpoint URL" in error_str):
|
|
141
|
+
logger.debug(f"Expected error for resource {resource.get('id', 'unknown')}: {e}")
|
|
142
|
+
else:
|
|
143
|
+
logger.error(f"Error evaluating resource {resource.get('id', 'unknown')}: {e}")
|
|
125
144
|
|
|
126
145
|
# Handle error with error handler if available
|
|
127
146
|
if self.error_handler:
|
|
128
147
|
context = ErrorContext(
|
|
129
148
|
service_name=self._get_required_services()[0] if self._get_required_services() else "",
|
|
130
|
-
region=
|
|
149
|
+
region=eval_region,
|
|
131
150
|
resource_type=resource_type,
|
|
132
151
|
resource_id=resource.get('id', 'unknown'),
|
|
133
152
|
operation="evaluate_compliance",
|
|
@@ -139,19 +158,27 @@ class BaseConfigRuleAssessment(ABC):
|
|
|
139
158
|
results.append(self._create_error_result(
|
|
140
159
|
resource.get('id', 'unknown'),
|
|
141
160
|
f"Evaluation error: {str(e)}",
|
|
142
|
-
|
|
161
|
+
eval_region,
|
|
143
162
|
resource_type
|
|
144
163
|
))
|
|
145
164
|
|
|
146
165
|
except ClientError as e:
|
|
147
166
|
error_code = e.response.get('Error', {}).get('Code', '')
|
|
148
|
-
error_message =
|
|
167
|
+
error_message = str(e)
|
|
168
|
+
|
|
169
|
+
# Log parameter validation errors at DEBUG level (expected for some resources)
|
|
170
|
+
if 'Parameter' in error_code or 'parameter' in error_message.lower():
|
|
171
|
+
logger.debug(f"Parameter validation error for {resource_type} in {eval_region}: {e}")
|
|
172
|
+
elif error_code in ['AccessDenied', 'UnauthorizedOperation']:
|
|
173
|
+
logger.debug(f"Access denied for {resource_type} in {eval_region}")
|
|
174
|
+
else:
|
|
175
|
+
logger.error(f"AWS API error for {resource_type} in {eval_region}: {e}")
|
|
149
176
|
|
|
150
177
|
# Handle error with error handler if available
|
|
151
178
|
if self.error_handler:
|
|
152
179
|
context = ErrorContext(
|
|
153
180
|
service_name=self._get_required_services()[0] if self._get_required_services() else "",
|
|
154
|
-
region=
|
|
181
|
+
region=eval_region,
|
|
155
182
|
resource_type=resource_type,
|
|
156
183
|
operation="get_resources",
|
|
157
184
|
control_id=self.control_id,
|
|
@@ -163,25 +190,29 @@ class BaseConfigRuleAssessment(ABC):
|
|
|
163
190
|
results.append(self._create_error_result(
|
|
164
191
|
f"{resource_type}_PERMISSION_ERROR",
|
|
165
192
|
f"Insufficient permissions to evaluate {resource_type}",
|
|
166
|
-
|
|
193
|
+
eval_region,
|
|
167
194
|
resource_type
|
|
168
195
|
))
|
|
169
196
|
else:
|
|
170
197
|
results.append(self._create_error_result(
|
|
171
198
|
f"{resource_type}_API_ERROR",
|
|
172
|
-
error_message,
|
|
173
|
-
|
|
199
|
+
f"AWS API error: {error_message}",
|
|
200
|
+
eval_region,
|
|
174
201
|
resource_type
|
|
175
202
|
))
|
|
176
203
|
|
|
177
204
|
except Exception as e:
|
|
178
|
-
|
|
205
|
+
# Log parameter validation errors at DEBUG level (expected for some resources)
|
|
206
|
+
if "Parameter validation failed" in str(e) or "Missing required parameter" in str(e):
|
|
207
|
+
logger.debug(f"Parameter validation error for {resource_type} in {eval_region}: {e}")
|
|
208
|
+
else:
|
|
209
|
+
logger.error(f"Unexpected error evaluating {resource_type}: {e}")
|
|
179
210
|
|
|
180
211
|
# Handle error with error handler if available
|
|
181
212
|
if self.error_handler:
|
|
182
213
|
context = ErrorContext(
|
|
183
214
|
service_name=self._get_required_services()[0] if self._get_required_services() else "",
|
|
184
|
-
region=
|
|
215
|
+
region=eval_region,
|
|
185
216
|
resource_type=resource_type,
|
|
186
217
|
operation="evaluate_resource_type",
|
|
187
218
|
control_id=self.control_id,
|
|
@@ -192,7 +223,7 @@ class BaseConfigRuleAssessment(ABC):
|
|
|
192
223
|
results.append(self._create_error_result(
|
|
193
224
|
f"{resource_type}_UNKNOWN_ERROR",
|
|
194
225
|
f"Unexpected error: {str(e)}",
|
|
195
|
-
|
|
226
|
+
eval_region,
|
|
196
227
|
resource_type
|
|
197
228
|
))
|
|
198
229
|
|
|
@@ -298,6 +329,57 @@ class BaseConfigRuleAssessment(ABC):
|
|
|
298
329
|
|
|
299
330
|
return list(services)
|
|
300
331
|
|
|
332
|
+
def _is_account_level_resource(self, resource_type: str) -> bool:
|
|
333
|
+
"""Check if resource type is account-level (global).
|
|
334
|
+
|
|
335
|
+
Account-level resources should be evaluated in us-east-1 only once,
|
|
336
|
+
not per region. This prevents duplicate evaluations and region validation errors.
|
|
337
|
+
|
|
338
|
+
Args:
|
|
339
|
+
resource_type: AWS resource type (e.g., "AWS::::Account", "AWS::IAM::User")
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
True if resource is account-level/global
|
|
343
|
+
"""
|
|
344
|
+
# Explicit account-level marker
|
|
345
|
+
if resource_type == 'AWS::::Account':
|
|
346
|
+
return True
|
|
347
|
+
|
|
348
|
+
# Global services that should only be evaluated in us-east-1
|
|
349
|
+
global_service_prefixes = [
|
|
350
|
+
'AWS::IAM::', # IAM is global
|
|
351
|
+
'AWS::CloudFront::', # CloudFront is global
|
|
352
|
+
'AWS::Route53::', # Route53 is global
|
|
353
|
+
'AWS::Organizations::', # Organizations is global
|
|
354
|
+
]
|
|
355
|
+
|
|
356
|
+
for prefix in global_service_prefixes:
|
|
357
|
+
if resource_type.startswith(prefix):
|
|
358
|
+
return True
|
|
359
|
+
|
|
360
|
+
# S3 buckets are special - they're global but region-specific
|
|
361
|
+
# We handle them in controls by checking region == 'us-east-1'
|
|
362
|
+
|
|
363
|
+
return False
|
|
364
|
+
|
|
365
|
+
def _get_evaluation_region(self, resource_type: str, requested_region: str) -> str:
|
|
366
|
+
"""Determine which region to use for resource evaluation.
|
|
367
|
+
|
|
368
|
+
Account-level and global resources must be evaluated in us-east-1
|
|
369
|
+
to avoid region validation errors and ensure proper API access.
|
|
370
|
+
|
|
371
|
+
Args:
|
|
372
|
+
resource_type: AWS resource type
|
|
373
|
+
requested_region: Region requested for evaluation
|
|
374
|
+
|
|
375
|
+
Returns:
|
|
376
|
+
Region to use (us-east-1 for account-level, requested_region otherwise)
|
|
377
|
+
"""
|
|
378
|
+
if self._is_account_level_resource(resource_type):
|
|
379
|
+
return 'us-east-1'
|
|
380
|
+
return requested_region
|
|
381
|
+
|
|
382
|
+
|
|
301
383
|
def _create_error_result(self, resource_id: str, error_message: str, region: str, resource_type: str = "Unknown") -> ComplianceResult:
|
|
302
384
|
"""Create a ComplianceResult for error conditions.
|
|
303
385
|
|
|
@@ -61,13 +61,8 @@ from .control_data_protection import (
|
|
|
61
61
|
)
|
|
62
62
|
|
|
63
63
|
from .control_network_security import (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
EC2InstancesInVPCAssessment,
|
|
67
|
-
EMRMasterNoPublicIPAssessment,
|
|
68
|
-
LambdaFunctionPublicAccessProhibitedAssessment,
|
|
69
|
-
SageMakerNotebookNoDirectInternetAccessAssessment,
|
|
70
|
-
SubnetAutoAssignPublicIPDisabledAssessment
|
|
64
|
+
NetworkFirewallDeployedAssessment,
|
|
65
|
+
Route53ResolverFirewallEnabledAssessment
|
|
71
66
|
)
|
|
72
67
|
|
|
73
68
|
from .control_iam_governance import (
|
|
@@ -143,6 +138,85 @@ from .control_instance_optimization import (
|
|
|
143
138
|
EBSOptimizedInstanceAssessment
|
|
144
139
|
)
|
|
145
140
|
|
|
141
|
+
# Phase 1-4: CIS Controls v8.1 IG1 Expansion
|
|
142
|
+
from .control_guardduty import GuardDutyEnabledAssessment
|
|
143
|
+
from .control_inspector import InspectorEnabledAssessment
|
|
144
|
+
from .control_macie import MacieEnabledAssessment
|
|
145
|
+
from .control_access_analyzer import IAMAccessAnalyzerEnabledAssessment
|
|
146
|
+
from .control_vpc_flow_logs import VPCFlowLogsEnabledAssessment
|
|
147
|
+
from .control_elb_logging import ELBLoggingEnabledAssessment
|
|
148
|
+
from .control_cloudfront_logging import CloudFrontLoggingEnabledAssessment
|
|
149
|
+
from .control_waf_logging import WAFLoggingEnabledAssessment
|
|
150
|
+
from .control_ebs_encryption import EBSEncryptionByDefaultAssessment
|
|
151
|
+
from .control_rds_encryption import RDSStorageEncryptedAssessment
|
|
152
|
+
from .control_efs_encryption import EFSEncryptedCheckAssessment
|
|
153
|
+
from .control_dynamodb_encryption import DynamoDBTableEncryptedKMSAssessment
|
|
154
|
+
from .control_s3_encryption import S3DefaultEncryptionKMSAssessment
|
|
155
|
+
from .control_patch_management import (
|
|
156
|
+
SSMPatchManagerEnabledAssessment,
|
|
157
|
+
SSMPatchBaselineConfiguredAssessment,
|
|
158
|
+
EC2PatchComplianceStatusAssessment
|
|
159
|
+
)
|
|
160
|
+
from .control_access_control import (
|
|
161
|
+
SSOEnabledCheckAssessment,
|
|
162
|
+
IdentityCenterConfiguredAssessment
|
|
163
|
+
)
|
|
164
|
+
from .control_mfa import (
|
|
165
|
+
IAMAdminMFARequiredAssessment,
|
|
166
|
+
CognitoMFAEnabledAssessment,
|
|
167
|
+
VPNMFAEnabledAssessment
|
|
168
|
+
)
|
|
169
|
+
from .control_tls_ssl import (
|
|
170
|
+
ALBHTTPToHTTPSRedirectionAssessment,
|
|
171
|
+
ELBTLSHTTPSListenersOnlyAssessment,
|
|
172
|
+
RDSSSLConnectionRequiredAssessment,
|
|
173
|
+
APIGatewaySSLEnabledAssessment,
|
|
174
|
+
RedshiftRequireTLSSSLAssessment
|
|
175
|
+
)
|
|
176
|
+
from .control_messaging_encryption import (
|
|
177
|
+
SNSEncryptedKMSAssessment,
|
|
178
|
+
SQSQueueEncryptedAssessment,
|
|
179
|
+
CloudTrailS3DataEventsEnabledAssessment
|
|
180
|
+
)
|
|
181
|
+
from .control_inventory import (
|
|
182
|
+
SSMInventoryEnabledAssessment,
|
|
183
|
+
ConfigEnabledAllRegionsAssessment,
|
|
184
|
+
AMIInventoryTrackingAssessment,
|
|
185
|
+
LambdaRuntimeInventoryAssessment,
|
|
186
|
+
IAMUserInventoryCheckAssessment
|
|
187
|
+
)
|
|
188
|
+
from .control_configuration_mgmt import (
|
|
189
|
+
ConfigConformancePackDeployedAssessment,
|
|
190
|
+
SecurityHubStandardsEnabledAssessment,
|
|
191
|
+
AssetTaggingComplianceAssessment,
|
|
192
|
+
InspectorAssessmentEnabledAssessment
|
|
193
|
+
)
|
|
194
|
+
from .control_version_mgmt import (
|
|
195
|
+
EC2OSVersionSupportedAssessment,
|
|
196
|
+
RDSEngineVersionSupportedAssessment,
|
|
197
|
+
LambdaRuntimeSupportedAssessment
|
|
198
|
+
)
|
|
199
|
+
from .control_access_asset_mgmt import (
|
|
200
|
+
IAMUserLastAccessCheckAssessment,
|
|
201
|
+
SSMSessionManagerEnabledAssessment,
|
|
202
|
+
UnauthorizedAssetDetectionAssessment
|
|
203
|
+
)
|
|
204
|
+
from .control_data_classification import (
|
|
205
|
+
DataClassificationTaggingAssessment,
|
|
206
|
+
S3BucketClassificationTagsAssessment
|
|
207
|
+
)
|
|
208
|
+
from .control_network_security import (
|
|
209
|
+
NetworkFirewallDeployedAssessment,
|
|
210
|
+
Route53ResolverFirewallEnabledAssessment
|
|
211
|
+
)
|
|
212
|
+
from .control_backup_security import (
|
|
213
|
+
BackupVaultEncryptionEnabledAssessment,
|
|
214
|
+
BackupCrossRegionCopyEnabledAssessment,
|
|
215
|
+
BackupVaultLockEnabledAssessment,
|
|
216
|
+
Route53QueryLoggingEnabledAssessment,
|
|
217
|
+
RDSBackupRetentionCheckAssessment
|
|
218
|
+
)
|
|
219
|
+
|
|
146
220
|
__all__ = [
|
|
147
221
|
# Control 1.1 - Asset Inventory
|
|
148
222
|
'EIPAttachedAssessment',
|
|
@@ -171,13 +245,6 @@ __all__ = [
|
|
|
171
245
|
'RDSInstancePublicAccessCheckAssessment',
|
|
172
246
|
'RedshiftClusterPublicAccessCheckAssessment',
|
|
173
247
|
'S3BucketLevelPublicAccessProhibitedAssessment',
|
|
174
|
-
'DMSReplicationNotPublicAssessment',
|
|
175
|
-
'ElasticsearchInVPCOnlyAssessment',
|
|
176
|
-
'EC2InstancesInVPCAssessment',
|
|
177
|
-
'EMRMasterNoPublicIPAssessment',
|
|
178
|
-
'LambdaFunctionPublicAccessProhibitedAssessment',
|
|
179
|
-
'SageMakerNotebookNoDirectInternetAccessAssessment',
|
|
180
|
-
'SubnetAutoAssignPublicIPDisabledAssessment',
|
|
181
248
|
'IAMGroupHasUsersCheckAssessment',
|
|
182
249
|
'IAMPolicyNoStatementsWithFullAccessAssessment',
|
|
183
250
|
'IAMUserNoPoliciesCheckAssessment',
|
|
@@ -252,5 +319,67 @@ __all__ = [
|
|
|
252
319
|
'S3BucketPublicWriteProhibitedAssessment',
|
|
253
320
|
|
|
254
321
|
# Instance Optimization
|
|
255
|
-
'EBSOptimizedInstanceAssessment'
|
|
322
|
+
'EBSOptimizedInstanceAssessment',
|
|
323
|
+
|
|
324
|
+
# Phase 1-4: CIS Controls v8.1 IG1 Expansion (50 new rules)
|
|
325
|
+
# Phase 1 - Quick Wins (13 rules)
|
|
326
|
+
'GuardDutyEnabledAssessment',
|
|
327
|
+
'InspectorEnabledAssessment',
|
|
328
|
+
'MacieEnabledAssessment',
|
|
329
|
+
'IAMAccessAnalyzerEnabledAssessment',
|
|
330
|
+
'VPCFlowLogsEnabledAssessment',
|
|
331
|
+
'ELBLoggingEnabledAssessment',
|
|
332
|
+
'CloudFrontLoggingEnabledAssessment',
|
|
333
|
+
'WAFLoggingEnabledAssessment',
|
|
334
|
+
'EBSEncryptionByDefaultAssessment',
|
|
335
|
+
'RDSStorageEncryptedAssessment',
|
|
336
|
+
'EFSEncryptedCheckAssessment',
|
|
337
|
+
'DynamoDBTableEncryptedKMSAssessment',
|
|
338
|
+
'S3DefaultEncryptionKMSAssessment',
|
|
339
|
+
|
|
340
|
+
# Phase 2 - Core Security (15 rules)
|
|
341
|
+
'SSMPatchManagerEnabledAssessment',
|
|
342
|
+
'SSMPatchBaselineConfiguredAssessment',
|
|
343
|
+
'EC2PatchComplianceStatusAssessment',
|
|
344
|
+
'SSOEnabledCheckAssessment',
|
|
345
|
+
'IdentityCenterConfiguredAssessment',
|
|
346
|
+
'IAMAdminMFARequiredAssessment',
|
|
347
|
+
'CognitoMFAEnabledAssessment',
|
|
348
|
+
'VPNMFAEnabledAssessment',
|
|
349
|
+
'ALBHTTPToHTTPSRedirectionAssessment',
|
|
350
|
+
'ELBTLSHTTPSListenersOnlyAssessment',
|
|
351
|
+
'RDSSSLConnectionRequiredAssessment',
|
|
352
|
+
'APIGatewaySSLEnabledAssessment',
|
|
353
|
+
'RedshiftRequireTLSSSLAssessment',
|
|
354
|
+
'SNSEncryptedKMSAssessment',
|
|
355
|
+
'SQSQueueEncryptedAssessment',
|
|
356
|
+
'CloudTrailS3DataEventsEnabledAssessment',
|
|
357
|
+
|
|
358
|
+
# Phase 3 - Advanced (15 rules)
|
|
359
|
+
'SSMInventoryEnabledAssessment',
|
|
360
|
+
'ConfigEnabledAllRegionsAssessment',
|
|
361
|
+
'AMIInventoryTrackingAssessment',
|
|
362
|
+
'LambdaRuntimeInventoryAssessment',
|
|
363
|
+
'IAMUserInventoryCheckAssessment',
|
|
364
|
+
'ConfigConformancePackDeployedAssessment',
|
|
365
|
+
'SecurityHubStandardsEnabledAssessment',
|
|
366
|
+
'AssetTaggingComplianceAssessment',
|
|
367
|
+
'InspectorAssessmentEnabledAssessment',
|
|
368
|
+
'EC2OSVersionSupportedAssessment',
|
|
369
|
+
'RDSEngineVersionSupportedAssessment',
|
|
370
|
+
'LambdaRuntimeSupportedAssessment',
|
|
371
|
+
'IAMUserLastAccessCheckAssessment',
|
|
372
|
+
'SSMSessionManagerEnabledAssessment',
|
|
373
|
+
'UnauthorizedAssetDetectionAssessment',
|
|
374
|
+
|
|
375
|
+
# Phase 4 - Enhanced (7 rules)
|
|
376
|
+
'DataClassificationTaggingAssessment',
|
|
377
|
+
'S3BucketClassificationTagsAssessment',
|
|
378
|
+
'NetworkFirewallDeployedAssessment',
|
|
379
|
+
'Route53ResolverFirewallEnabledAssessment',
|
|
380
|
+
'BackupVaultEncryptionEnabledAssessment',
|
|
381
|
+
'BackupCrossRegionCopyEnabledAssessment',
|
|
382
|
+
'BackupVaultLockEnabledAssessment',
|
|
383
|
+
'Route53QueryLoggingEnabledAssessment',
|
|
384
|
+
'RDSBackupRetentionCheckAssessment'
|
|
256
385
|
]
|
|
@@ -28,8 +28,8 @@ class AccountPartOfOrganizationsAssessment(BaseConfigRuleAssessment):
|
|
|
28
28
|
return []
|
|
29
29
|
|
|
30
30
|
try:
|
|
31
|
-
# Get account information
|
|
32
|
-
sts_client = aws_factory.get_client('sts', region)
|
|
31
|
+
# Get account information (use allow_global_region for account-level resources)
|
|
32
|
+
sts_client = aws_factory.get_client('sts', region, allow_global_region=True)
|
|
33
33
|
|
|
34
34
|
response = aws_factory.aws_api_call_with_retry(
|
|
35
35
|
lambda: sts_client.get_caller_identity()
|
|
@@ -55,8 +55,8 @@ class AccountPartOfOrganizationsAssessment(BaseConfigRuleAssessment):
|
|
|
55
55
|
account_id = resource.get('AccountId', 'unknown')
|
|
56
56
|
|
|
57
57
|
try:
|
|
58
|
-
# Check if account is part of an organization
|
|
59
|
-
organizations_client = aws_factory.get_client('organizations', region)
|
|
58
|
+
# Check if account is part of an organization (use allow_global_region for account-level resources)
|
|
59
|
+
organizations_client = aws_factory.get_client('organizations', region, allow_global_region=True)
|
|
60
60
|
|
|
61
61
|
# Try to describe the organization
|
|
62
62
|
response = aws_factory.aws_api_call_with_retry(
|
|
@@ -16,8 +16,8 @@ logger = logging.getLogger(__name__)
|
|
|
16
16
|
|
|
17
17
|
class GuardDutyEnabledAssessment(BaseConfigRuleAssessment):
|
|
18
18
|
"""
|
|
19
|
-
CIS Control
|
|
20
|
-
AWS Config Rule: guardduty-enabled
|
|
19
|
+
CIS Control 6.2 - Establish and Maintain a Secure Network Architecture
|
|
20
|
+
AWS Config Rule: guardduty-enabled-centralized
|
|
21
21
|
|
|
22
22
|
Ensures GuardDuty is enabled for threat detection and malware defense.
|
|
23
23
|
GuardDuty provides intelligent threat detection by analyzing VPC Flow Logs,
|
|
@@ -26,8 +26,8 @@ class GuardDutyEnabledAssessment(BaseConfigRuleAssessment):
|
|
|
26
26
|
|
|
27
27
|
def __init__(self):
|
|
28
28
|
super().__init__(
|
|
29
|
-
rule_name="guardduty-enabled",
|
|
30
|
-
control_id="
|
|
29
|
+
rule_name="guardduty-enabled-centralized",
|
|
30
|
+
control_id="6.2",
|
|
31
31
|
resource_types=["AWS::GuardDuty::Detector"]
|
|
32
32
|
)
|
|
33
33
|
|
|
@@ -304,7 +304,7 @@ class S3DefaultEncryptionKMSAssessment(BaseConfigRuleAssessment):
|
|
|
304
304
|
' "Rules": [{',
|
|
305
305
|
' "ApplyServerSideEncryptionByDefault": {',
|
|
306
306
|
' "SSEAlgorithm": "aws:kms",',
|
|
307
|
-
' "KMSMasterKeyID": "'
|
|
307
|
+
' "KMSMasterKeyID": "'"$KMS_KEY_ID"'"',
|
|
308
308
|
" },",
|
|
309
309
|
' "BucketKeyEnabled": true',
|
|
310
310
|
" }]",
|
|
@@ -16,16 +16,16 @@ logger = logging.getLogger(__name__)
|
|
|
16
16
|
|
|
17
17
|
class ALBHTTPToHTTPSRedirectionAssessment(BaseConfigRuleAssessment):
|
|
18
18
|
"""
|
|
19
|
-
CIS Control
|
|
20
|
-
AWS Config Rule: alb-http-to-https-redirection
|
|
19
|
+
CIS Control 3.10 - Encrypt Sensitive Data in Transit
|
|
20
|
+
AWS Config Rule: alb-http-to-https-redirection-check
|
|
21
21
|
|
|
22
22
|
Ensures Application Load Balancers redirect HTTP traffic to HTTPS.
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
def __init__(self):
|
|
26
26
|
super().__init__(
|
|
27
|
-
rule_name="alb-http-to-https-redirection",
|
|
28
|
-
control_id="
|
|
27
|
+
rule_name="alb-http-to-https-redirection-check",
|
|
28
|
+
control_id="3.10",
|
|
29
29
|
resource_types=["AWS::ElasticLoadBalancingV2::LoadBalancer"]
|
|
30
30
|
)
|
|
31
31
|
|
|
@@ -58,7 +58,15 @@ class EC2OSVersionSupportedAssessment(BaseConfigRuleAssessment):
|
|
|
58
58
|
return instances
|
|
59
59
|
|
|
60
60
|
except ClientError as e:
|
|
61
|
-
|
|
61
|
+
error_code = e.response.get('Error', {}).get('Code', '')
|
|
62
|
+
# Log parameter validation errors at DEBUG level (expected for some resources)
|
|
63
|
+
if 'Parameter' in error_code or 'parameter' in str(e).lower():
|
|
64
|
+
logger.debug(f"Parameter validation issue retrieving instance information in {region}: {e}")
|
|
65
|
+
else:
|
|
66
|
+
logger.error(f"Error retrieving instance information in {region}: {e}")
|
|
67
|
+
return []
|
|
68
|
+
except Exception as e:
|
|
69
|
+
logger.error(f"Unexpected error retrieving instance information in {region}: {e}")
|
|
62
70
|
return []
|
|
63
71
|
|
|
64
72
|
def _check_version_support(self, platform_name: str, platform_version: str) -> bool:
|
|
@@ -59,10 +59,8 @@ from aws_cis_assessment.controls.ig1.control_data_protection import (
|
|
|
59
59
|
S3BucketLevelPublicAccessProhibitedAssessment
|
|
60
60
|
)
|
|
61
61
|
from aws_cis_assessment.controls.ig1.control_network_security import (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
LambdaFunctionPublicAccessProhibitedAssessment, SageMakerNotebookNoDirectInternetAccessAssessment,
|
|
65
|
-
SubnetAutoAssignPublicIPDisabledAssessment
|
|
62
|
+
NetworkFirewallDeployedAssessment,
|
|
63
|
+
Route53ResolverFirewallEnabledAssessment
|
|
66
64
|
)
|
|
67
65
|
from aws_cis_assessment.controls.ig1.control_iam_governance import (
|
|
68
66
|
IAMGroupHasUsersCheckAssessment, IAMPolicyNoStatementsWithFullAccessAssessment,
|
|
@@ -106,6 +104,82 @@ from aws_cis_assessment.controls.ig1.control_s3_enhancements import (
|
|
|
106
104
|
from aws_cis_assessment.controls.ig1.control_instance_optimization import (
|
|
107
105
|
EBSOptimizedInstanceAssessment
|
|
108
106
|
)
|
|
107
|
+
|
|
108
|
+
# Phase 1-4: CIS Controls v8.1 IG1 Expansion (50 new rules)
|
|
109
|
+
from aws_cis_assessment.controls.ig1.control_guardduty import GuardDutyEnabledAssessment
|
|
110
|
+
from aws_cis_assessment.controls.ig1.control_inspector import InspectorEnabledAssessment
|
|
111
|
+
from aws_cis_assessment.controls.ig1.control_macie import MacieEnabledAssessment
|
|
112
|
+
from aws_cis_assessment.controls.ig1.control_access_analyzer import IAMAccessAnalyzerEnabledAssessment
|
|
113
|
+
from aws_cis_assessment.controls.ig1.control_vpc_flow_logs import VPCFlowLogsEnabledAssessment
|
|
114
|
+
from aws_cis_assessment.controls.ig1.control_elb_logging import ELBLoggingEnabledAssessment
|
|
115
|
+
from aws_cis_assessment.controls.ig1.control_cloudfront_logging import CloudFrontLoggingEnabledAssessment
|
|
116
|
+
from aws_cis_assessment.controls.ig1.control_waf_logging import WAFLoggingEnabledAssessment
|
|
117
|
+
from aws_cis_assessment.controls.ig1.control_ebs_encryption import EBSEncryptionByDefaultAssessment
|
|
118
|
+
from aws_cis_assessment.controls.ig1.control_rds_encryption import RDSStorageEncryptedAssessment as RDSStorageEncryptedIG1Assessment
|
|
119
|
+
from aws_cis_assessment.controls.ig1.control_efs_encryption import EFSEncryptedCheckAssessment
|
|
120
|
+
from aws_cis_assessment.controls.ig1.control_dynamodb_encryption import DynamoDBTableEncryptedKMSAssessment as DynamoDBTableEncryptedKMSIG1Assessment
|
|
121
|
+
from aws_cis_assessment.controls.ig1.control_s3_encryption import S3DefaultEncryptionKMSAssessment as S3DefaultEncryptionKMSIG1Assessment
|
|
122
|
+
from aws_cis_assessment.controls.ig1.control_patch_management import (
|
|
123
|
+
SSMPatchManagerEnabledAssessment,
|
|
124
|
+
SSMPatchBaselineConfiguredAssessment,
|
|
125
|
+
EC2PatchComplianceStatusAssessment
|
|
126
|
+
)
|
|
127
|
+
from aws_cis_assessment.controls.ig1.control_access_control import (
|
|
128
|
+
SSOEnabledCheckAssessment,
|
|
129
|
+
IdentityCenterConfiguredAssessment
|
|
130
|
+
)
|
|
131
|
+
from aws_cis_assessment.controls.ig1.control_mfa import (
|
|
132
|
+
IAMAdminMFARequiredAssessment,
|
|
133
|
+
CognitoMFAEnabledAssessment,
|
|
134
|
+
VPNMFAEnabledAssessment
|
|
135
|
+
)
|
|
136
|
+
from aws_cis_assessment.controls.ig1.control_tls_ssl import (
|
|
137
|
+
ALBHTTPToHTTPSRedirectionAssessment as ALBHTTPToHTTPSRedirectionIG1Assessment,
|
|
138
|
+
ELBTLSHTTPSListenersOnlyAssessment as ELBTLSHTTPSListenersOnlyIG1Assessment,
|
|
139
|
+
RDSSSLConnectionRequiredAssessment,
|
|
140
|
+
APIGatewaySSLEnabledAssessment as APIGatewaySSLEnabledIG1Assessment,
|
|
141
|
+
RedshiftRequireTLSSSLAssessment as RedshiftRequireTLSSSLIG1Assessment
|
|
142
|
+
)
|
|
143
|
+
from aws_cis_assessment.controls.ig1.control_messaging_encryption import (
|
|
144
|
+
SNSEncryptedKMSAssessment,
|
|
145
|
+
SQSQueueEncryptedAssessment,
|
|
146
|
+
CloudTrailS3DataEventsEnabledAssessment
|
|
147
|
+
)
|
|
148
|
+
from aws_cis_assessment.controls.ig1.control_inventory import (
|
|
149
|
+
SSMInventoryEnabledAssessment,
|
|
150
|
+
ConfigEnabledAllRegionsAssessment,
|
|
151
|
+
AMIInventoryTrackingAssessment,
|
|
152
|
+
LambdaRuntimeInventoryAssessment,
|
|
153
|
+
IAMUserInventoryCheckAssessment
|
|
154
|
+
)
|
|
155
|
+
from aws_cis_assessment.controls.ig1.control_configuration_mgmt import (
|
|
156
|
+
ConfigConformancePackDeployedAssessment,
|
|
157
|
+
SecurityHubStandardsEnabledAssessment,
|
|
158
|
+
AssetTaggingComplianceAssessment,
|
|
159
|
+
InspectorAssessmentEnabledAssessment
|
|
160
|
+
)
|
|
161
|
+
from aws_cis_assessment.controls.ig1.control_version_mgmt import (
|
|
162
|
+
EC2OSVersionSupportedAssessment,
|
|
163
|
+
RDSEngineVersionSupportedAssessment,
|
|
164
|
+
LambdaRuntimeSupportedAssessment
|
|
165
|
+
)
|
|
166
|
+
from aws_cis_assessment.controls.ig1.control_access_asset_mgmt import (
|
|
167
|
+
IAMUserLastAccessCheckAssessment,
|
|
168
|
+
SSMSessionManagerEnabledAssessment,
|
|
169
|
+
UnauthorizedAssetDetectionAssessment
|
|
170
|
+
)
|
|
171
|
+
from aws_cis_assessment.controls.ig1.control_data_classification import (
|
|
172
|
+
DataClassificationTaggingAssessment,
|
|
173
|
+
S3BucketClassificationTagsAssessment
|
|
174
|
+
)
|
|
175
|
+
from aws_cis_assessment.controls.ig1.control_backup_security import (
|
|
176
|
+
BackupVaultEncryptionEnabledAssessment,
|
|
177
|
+
BackupCrossRegionCopyEnabledAssessment,
|
|
178
|
+
BackupVaultLockEnabledAssessment,
|
|
179
|
+
Route53QueryLoggingEnabledAssessment,
|
|
180
|
+
RDSBackupRetentionCheckAssessment
|
|
181
|
+
)
|
|
182
|
+
|
|
109
183
|
from aws_cis_assessment.controls.ig2.control_3_10 import (
|
|
110
184
|
APIGatewaySSLEnabledAssessment, ALBHTTPToHTTPSRedirectionAssessment,
|
|
111
185
|
ELBTLSHTTPSListenersOnlyAssessment, S3BucketSSLRequestsOnlyAssessment,
|
|
@@ -379,13 +453,6 @@ class AssessmentEngine:
|
|
|
379
453
|
'rds-instance-public-access-check': RDSInstancePublicAccessCheckAssessment(),
|
|
380
454
|
'redshift-cluster-public-access-check': RedshiftClusterPublicAccessCheckAssessment(),
|
|
381
455
|
's3-bucket-level-public-access-prohibited': S3BucketLevelPublicAccessProhibitedAssessment(),
|
|
382
|
-
'dms-replication-not-public': DMSReplicationNotPublicAssessment(),
|
|
383
|
-
'elasticsearch-in-vpc-only': ElasticsearchInVPCOnlyAssessment(),
|
|
384
|
-
'ec2-instances-in-vpc': EC2InstancesInVPCAssessment(),
|
|
385
|
-
'emr-master-no-public-ip': EMRMasterNoPublicIPAssessment(),
|
|
386
|
-
'lambda-function-public-access-prohibited': LambdaFunctionPublicAccessProhibitedAssessment(),
|
|
387
|
-
'sagemaker-notebook-no-direct-internet-access': SageMakerNotebookNoDirectInternetAccessAssessment(),
|
|
388
|
-
'subnet-auto-assign-public-ip-disabled': SubnetAutoAssignPublicIPDisabledAssessment(),
|
|
389
456
|
'iam-group-has-users-check': IAMGroupHasUsersCheckAssessment(),
|
|
390
457
|
'iam-policy-no-statements-with-full-access': IAMPolicyNoStatementsWithFullAccessAssessment(),
|
|
391
458
|
'iam-user-no-policies-check': IAMUserNoPoliciesCheckAssessment(),
|
|
@@ -458,6 +525,88 @@ class AssessmentEngine:
|
|
|
458
525
|
|
|
459
526
|
# Instance Optimization
|
|
460
527
|
'ebs-optimized-instance': EBSOptimizedInstanceAssessment(),
|
|
528
|
+
|
|
529
|
+
# Phase 1-4: CIS Controls v8.1 IG1 Expansion (50 new rules)
|
|
530
|
+
# Phase 1 - Quick Wins: Security Services (4 rules)
|
|
531
|
+
'guardduty-enabled-centralized': GuardDutyEnabledAssessment(),
|
|
532
|
+
'inspector-enabled': InspectorEnabledAssessment(),
|
|
533
|
+
'macie-enabled': MacieEnabledAssessment(),
|
|
534
|
+
'iam-access-analyzer-enabled': IAMAccessAnalyzerEnabledAssessment(),
|
|
535
|
+
|
|
536
|
+
# Phase 1 - Quick Wins: Logging (4 rules)
|
|
537
|
+
'vpc-flow-logs-enabled': VPCFlowLogsEnabledAssessment(),
|
|
538
|
+
'elb-logging-enabled': ELBLoggingEnabledAssessment(),
|
|
539
|
+
'cloudfront-accesslogs-enabled': CloudFrontLoggingEnabledAssessment(),
|
|
540
|
+
'wafv2-logging-enabled': WAFLoggingEnabledAssessment(),
|
|
541
|
+
|
|
542
|
+
# Phase 1 - Quick Wins: Encryption (5 rules)
|
|
543
|
+
'ebs-encryption-by-default': EBSEncryptionByDefaultAssessment(),
|
|
544
|
+
'rds-storage-encrypted-ig1': RDSStorageEncryptedIG1Assessment(),
|
|
545
|
+
'efs-encrypted-check-ig1': EFSEncryptedCheckAssessment(),
|
|
546
|
+
'dynamodb-table-encrypted-kms-ig1': DynamoDBTableEncryptedKMSIG1Assessment(),
|
|
547
|
+
's3-default-encryption-kms-ig1': S3DefaultEncryptionKMSIG1Assessment(),
|
|
548
|
+
|
|
549
|
+
# Phase 2 - Core Security: Patch Management (3 rules)
|
|
550
|
+
'ssm-patch-manager-enabled': SSMPatchManagerEnabledAssessment(),
|
|
551
|
+
'ssm-patch-baseline-configured': SSMPatchBaselineConfiguredAssessment(),
|
|
552
|
+
'ec2-patch-compliance-status': EC2PatchComplianceStatusAssessment(),
|
|
553
|
+
|
|
554
|
+
# Phase 2 - Core Security: Access Control (5 rules)
|
|
555
|
+
'sso-enabled-check': SSOEnabledCheckAssessment(),
|
|
556
|
+
'identity-center-configured': IdentityCenterConfiguredAssessment(),
|
|
557
|
+
'iam-admin-mfa-required': IAMAdminMFARequiredAssessment(),
|
|
558
|
+
'cognito-mfa-enabled': CognitoMFAEnabledAssessment(),
|
|
559
|
+
'vpn-mfa-enabled': VPNMFAEnabledAssessment(),
|
|
560
|
+
|
|
561
|
+
# Phase 2 - Core Security: TLS/SSL (5 rules)
|
|
562
|
+
'alb-http-to-https-redirection-check': ALBHTTPToHTTPSRedirectionIG1Assessment(),
|
|
563
|
+
'elb-tls-https-listeners-only-ig1': ELBTLSHTTPSListenersOnlyIG1Assessment(),
|
|
564
|
+
'rds-ssl-connection-required': RDSSSLConnectionRequiredAssessment(),
|
|
565
|
+
'api-gateway-ssl-enabled-ig1': APIGatewaySSLEnabledIG1Assessment(),
|
|
566
|
+
'redshift-require-tls-ssl-ig1': RedshiftRequireTLSSSLIG1Assessment(),
|
|
567
|
+
|
|
568
|
+
# Phase 2 - Core Security: Additional Encryption (3 rules)
|
|
569
|
+
'sns-encrypted-kms': SNSEncryptedKMSAssessment(),
|
|
570
|
+
'sqs-queue-encrypted': SQSQueueEncryptedAssessment(),
|
|
571
|
+
'cloudtrail-s3-dataevents-enabled': CloudTrailS3DataEventsEnabledAssessment(),
|
|
572
|
+
|
|
573
|
+
# Phase 3 - Advanced: Inventory (5 rules)
|
|
574
|
+
'ssm-inventory-enabled': SSMInventoryEnabledAssessment(),
|
|
575
|
+
'config-enabled-all-regions': ConfigEnabledAllRegionsAssessment(),
|
|
576
|
+
'ami-inventory-tracking': AMIInventoryTrackingAssessment(),
|
|
577
|
+
'lambda-runtime-inventory': LambdaRuntimeInventoryAssessment(),
|
|
578
|
+
'iam-user-inventory-check': IAMUserInventoryCheckAssessment(),
|
|
579
|
+
|
|
580
|
+
# Phase 3 - Advanced: Configuration Management (4 rules)
|
|
581
|
+
'config-conformance-pack-deployed': ConfigConformancePackDeployedAssessment(),
|
|
582
|
+
'securityhub-standards-enabled': SecurityHubStandardsEnabledAssessment(),
|
|
583
|
+
'asset-tagging-compliance': AssetTaggingComplianceAssessment(),
|
|
584
|
+
'inspector-assessment-enabled': InspectorAssessmentEnabledAssessment(),
|
|
585
|
+
|
|
586
|
+
# Phase 3 - Advanced: Version Management (3 rules)
|
|
587
|
+
'ec2-os-version-supported': EC2OSVersionSupportedAssessment(),
|
|
588
|
+
'rds-engine-version-supported': RDSEngineVersionSupportedAssessment(),
|
|
589
|
+
'lambda-runtime-supported': LambdaRuntimeSupportedAssessment(),
|
|
590
|
+
|
|
591
|
+
# Phase 3 - Advanced: Access/Asset Management (3 rules)
|
|
592
|
+
'iam-user-last-access-check': IAMUserLastAccessCheckAssessment(),
|
|
593
|
+
'ssm-session-manager-enabled': SSMSessionManagerEnabledAssessment(),
|
|
594
|
+
'unauthorized-asset-detection': UnauthorizedAssetDetectionAssessment(),
|
|
595
|
+
|
|
596
|
+
# Phase 4 - Enhanced: Data Classification (2 rules)
|
|
597
|
+
'data-classification-tagging': DataClassificationTaggingAssessment(),
|
|
598
|
+
's3-bucket-classification-tags': S3BucketClassificationTagsAssessment(),
|
|
599
|
+
|
|
600
|
+
# Phase 4 - Enhanced: Network Security (2 rules)
|
|
601
|
+
'network-firewall-deployed': NetworkFirewallDeployedAssessment(),
|
|
602
|
+
'route53-resolver-firewall-enabled': Route53ResolverFirewallEnabledAssessment(),
|
|
603
|
+
|
|
604
|
+
# Phase 4 - Enhanced: Backup Security (5 rules)
|
|
605
|
+
'backup-vault-encryption-enabled': BackupVaultEncryptionEnabledAssessment(),
|
|
606
|
+
'backup-cross-region-copy-enabled': BackupCrossRegionCopyEnabledAssessment(),
|
|
607
|
+
'backup-vault-lock-enabled': BackupVaultLockEnabledAssessment(),
|
|
608
|
+
'route53-query-logging-enabled': Route53QueryLoggingEnabledAssessment(),
|
|
609
|
+
'rds-backup-retention-check': RDSBackupRetentionCheckAssessment(),
|
|
461
610
|
},
|
|
462
611
|
'IG2': {
|
|
463
612
|
# Control 3.10 - Encryption in Transit
|
|
@@ -69,24 +69,32 @@ class AWSClientFactory:
|
|
|
69
69
|
logger.error(f"Failed to initialize AWS session: {e}")
|
|
70
70
|
raise
|
|
71
71
|
|
|
72
|
-
def get_client(self, service_name: str, region: Optional[str] = None
|
|
72
|
+
def get_client(self, service_name: str, region: Optional[str] = None,
|
|
73
|
+
allow_global_region: bool = False) -> boto3.client:
|
|
73
74
|
"""Get AWS service client for specified service and region.
|
|
74
75
|
|
|
75
76
|
Args:
|
|
76
77
|
service_name: AWS service name (e.g., 'ec2', 'iam', 's3')
|
|
77
78
|
region: AWS region. If None, uses first region from regions list.
|
|
79
|
+
allow_global_region: If True, allows us-east-1 even if not in regions list.
|
|
80
|
+
This is used for account-level and global resources that
|
|
81
|
+
must be evaluated in us-east-1 regardless of configured regions.
|
|
78
82
|
|
|
79
83
|
Returns:
|
|
80
84
|
Boto3 client for the specified service
|
|
81
85
|
|
|
82
86
|
Raises:
|
|
83
|
-
ValueError: If region is not in supported regions list
|
|
87
|
+
ValueError: If region is not in supported regions list (unless allow_global_region=True for us-east-1)
|
|
84
88
|
ClientError: If client creation fails
|
|
85
89
|
"""
|
|
86
90
|
if region is None:
|
|
87
91
|
region = self.regions[0]
|
|
88
92
|
|
|
89
|
-
if
|
|
93
|
+
# Allow us-east-1 for global/account-level resources even if not in regions list
|
|
94
|
+
if allow_global_region and region == 'us-east-1':
|
|
95
|
+
# us-east-1 is allowed for global resources
|
|
96
|
+
logger.debug(f"Allowing global region us-east-1 for {service_name} (not in configured regions)")
|
|
97
|
+
elif region not in self.regions:
|
|
90
98
|
raise ValueError(f"Region {region} not in supported regions: {self.regions}")
|
|
91
99
|
|
|
92
100
|
# Create cache key
|
|
@@ -283,8 +291,12 @@ class AWSClientFactory:
|
|
|
283
291
|
raise
|
|
284
292
|
|
|
285
293
|
except Exception as e:
|
|
286
|
-
#
|
|
287
|
-
|
|
294
|
+
# Log connection errors at DEBUG level (expected for cross-region S3 buckets)
|
|
295
|
+
error_str = str(e)
|
|
296
|
+
if "Could not connect to the endpoint URL" in error_str or "Connection" in error_str:
|
|
297
|
+
logger.debug(f"Connection error in AWS API call (may be cross-region resource): {e}")
|
|
298
|
+
else:
|
|
299
|
+
logger.error(f"Non-retryable error in AWS API call: {e}")
|
|
288
300
|
raise
|
|
289
301
|
|
|
290
302
|
# This should never be reached due to the raise in the loop
|
|
@@ -463,22 +463,26 @@ class ScoringEngine:
|
|
|
463
463
|
'IG3': 153 # Cumulative
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
#
|
|
467
|
-
#
|
|
468
|
-
safeguard_coverage = {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
'
|
|
479
|
-
|
|
466
|
+
# Dynamically count implemented rules from actual assessment data
|
|
467
|
+
# This replaces hardcoded values to ensure accuracy
|
|
468
|
+
safeguard_coverage = {}
|
|
469
|
+
|
|
470
|
+
for ig_name, ig_score in ig_scores.items():
|
|
471
|
+
if ig_name not in total_safeguards:
|
|
472
|
+
continue
|
|
473
|
+
|
|
474
|
+
# Count unique config rules across all controls in this IG
|
|
475
|
+
unique_rules = set()
|
|
476
|
+
for control_score in ig_score.control_scores.values():
|
|
477
|
+
# Each control may evaluate multiple config rules
|
|
478
|
+
if hasattr(control_score, 'config_rules_evaluated'):
|
|
479
|
+
unique_rules.update(control_score.config_rules_evaluated)
|
|
480
|
+
|
|
481
|
+
# Store the actual count of rules
|
|
482
|
+
safeguard_coverage[ig_name] = {
|
|
483
|
+
'covered': 42 if ig_name == 'IG1' else (30 if ig_name == 'IG2' else 15), # Safeguards covered (estimated)
|
|
484
|
+
'rules': len(unique_rules) # Actual rule count from assessment
|
|
480
485
|
}
|
|
481
|
-
}
|
|
482
486
|
|
|
483
487
|
coverage_metrics = {}
|
|
484
488
|
|
|
@@ -80,21 +80,36 @@ class ReportGenerator(ABC):
|
|
|
80
80
|
Returns:
|
|
81
81
|
Dictionary containing standardized report data
|
|
82
82
|
"""
|
|
83
|
-
# Calculate additional metrics
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
# Calculate additional metrics - deduplicate resources across IGs
|
|
84
|
+
# Since IG2 includes IG1 and IG3 includes IG1+IG2, we need to count unique resources
|
|
85
|
+
# Use IG1 as the source of truth since it contains all unique evaluations
|
|
86
|
+
# (controls in higher IGs are the same controls, just evaluated again)
|
|
87
|
+
|
|
88
|
+
# Collect unique resources by (resource_id, resource_type, region, config_rule_name)
|
|
89
|
+
unique_resources = {}
|
|
90
|
+
|
|
91
|
+
for ig_name, ig_score in assessment_result.ig_scores.items():
|
|
92
|
+
for control_id, control in ig_score.control_scores.items():
|
|
93
|
+
for finding in control.findings:
|
|
94
|
+
# Create unique key for each resource evaluation
|
|
95
|
+
resource_key = (
|
|
96
|
+
finding.resource_id,
|
|
97
|
+
finding.resource_type,
|
|
98
|
+
finding.region,
|
|
99
|
+
finding.config_rule_name
|
|
100
|
+
)
|
|
101
|
+
# Store the finding (last one wins, but they should be identical)
|
|
102
|
+
unique_resources[resource_key] = finding
|
|
103
|
+
|
|
104
|
+
# Now count from unique resources
|
|
105
|
+
total_resources = len(unique_resources)
|
|
89
106
|
total_compliant = sum(
|
|
90
|
-
|
|
91
|
-
|
|
107
|
+
1 for finding in unique_resources.values()
|
|
108
|
+
if finding.compliance_status.value == 'COMPLIANT'
|
|
92
109
|
)
|
|
93
|
-
|
|
94
110
|
total_non_compliant = sum(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
for ig in assessment_result.ig_scores.values()
|
|
111
|
+
1 for finding in unique_resources.values()
|
|
112
|
+
if finding.compliance_status.value == 'NON_COMPLIANT'
|
|
98
113
|
)
|
|
99
114
|
|
|
100
115
|
# Prepare standardized data structure
|
|
@@ -1861,7 +1861,7 @@ class HTMLReporter(ReportGenerator):
|
|
|
1861
1861
|
<span>{ig_value:.1f}%</span>
|
|
1862
1862
|
</div>
|
|
1863
1863
|
<div class="progress-container">
|
|
1864
|
-
<div class="progress-bar {ig_status}" data-width="{ig_value}">
|
|
1864
|
+
<div class="progress-bar {ig_status}" data-width="{self._get_display_width(ig_value)}">
|
|
1865
1865
|
<span class="progress-text">{ig_value:.1f}%</span>
|
|
1866
1866
|
</div>
|
|
1867
1867
|
</div>
|
|
@@ -1959,7 +1959,7 @@ class HTMLReporter(ReportGenerator):
|
|
|
1959
1959
|
</div>
|
|
1960
1960
|
{inheritance_indicator}
|
|
1961
1961
|
<div class="progress-container">
|
|
1962
|
-
<div class="progress-bar {status_class}" data-width="{control_data['compliance_percentage']}">
|
|
1962
|
+
<div class="progress-bar {status_class}" data-width="{self._get_display_width(control_data['compliance_percentage'])}">
|
|
1963
1963
|
<span class="progress-text">{control_data['compliance_percentage']:.1f}%</span>
|
|
1964
1964
|
</div>
|
|
1965
1965
|
</div>
|
|
@@ -2188,6 +2188,20 @@ class HTMLReporter(ReportGenerator):
|
|
|
2188
2188
|
else:
|
|
2189
2189
|
return "#e74c3c" # Red
|
|
2190
2190
|
|
|
2191
|
+
def _get_display_width(self, actual_percentage: float) -> float:
|
|
2192
|
+
"""Calculate display width for progress bars.
|
|
2193
|
+
|
|
2194
|
+
Ensures minimum 5% width for visibility when actual percentage is 0%.
|
|
2195
|
+
This prevents progress bars from being invisible for non-compliant controls.
|
|
2196
|
+
|
|
2197
|
+
Args:
|
|
2198
|
+
actual_percentage: Actual compliance percentage (0-100)
|
|
2199
|
+
|
|
2200
|
+
Returns:
|
|
2201
|
+
Display width with minimum 5% for visibility
|
|
2202
|
+
"""
|
|
2203
|
+
return max(5.0, actual_percentage)
|
|
2204
|
+
|
|
2191
2205
|
def _get_status_class(self, compliance_percentage: float) -> str:
|
|
2192
2206
|
"""Get CSS status class based on compliance percentage."""
|
|
2193
2207
|
if compliance_percentage >= 95.0:
|
|
@@ -2302,9 +2316,9 @@ class HTMLReporter(ReportGenerator):
|
|
|
2302
2316
|
have higher impact on the overall score.
|
|
2303
2317
|
</p>
|
|
2304
2318
|
<ul class="comparison-features">
|
|
2305
|
-
<li
|
|
2306
|
-
<li
|
|
2307
|
-
<li
|
|
2319
|
+
<li>Prioritizes critical security controls</li>
|
|
2320
|
+
<li>Prevents resource count skew</li>
|
|
2321
|
+
<li>Guides remediation priorities</li>
|
|
2308
2322
|
</ul>
|
|
2309
2323
|
</div>
|
|
2310
2324
|
|
|
@@ -2316,9 +2330,9 @@ class HTMLReporter(ReportGenerator):
|
|
|
2316
2330
|
All rules treated equally regardless of security criticality.
|
|
2317
2331
|
</p>
|
|
2318
2332
|
<ul class="comparison-features">
|
|
2319
|
-
<li
|
|
2320
|
-
<li
|
|
2321
|
-
<li
|
|
2333
|
+
<li>Simple and straightforward</li>
|
|
2334
|
+
<li>Easy to audit</li>
|
|
2335
|
+
<li>Resource-level tracking</li>
|
|
2322
2336
|
</ul>
|
|
2323
2337
|
</div>
|
|
2324
2338
|
</div>
|
|
@@ -2724,7 +2738,7 @@ class HTMLReporter(ReportGenerator):
|
|
|
2724
2738
|
type_compliance = (stats["compliant"] / stats["total"] * 100) if stats["total"] > 0 else 0
|
|
2725
2739
|
status_class = self._get_status_class(type_compliance)
|
|
2726
2740
|
# Ensure minimum width of 5% for visibility when compliance is 0%
|
|
2727
|
-
display_width =
|
|
2741
|
+
display_width = self._get_display_width(type_compliance)
|
|
2728
2742
|
|
|
2729
2743
|
resource_type_breakdown += f"""
|
|
2730
2744
|
<div class="resource-type-stat">
|
{aws_cis_controls_assessment-1.2.0.dist-info → aws_cis_controls_assessment-1.2.2.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aws-cis-controls-assessment
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Production-ready AWS CIS Controls compliance assessment framework with 175 comprehensive rules and 75%+ IG1 coverage
|
|
5
5
|
Author-email: AWS CIS Assessment Team <security@example.com>
|
|
6
6
|
Maintainer-email: AWS CIS Assessment Team <security@example.com>
|
{aws_cis_controls_assessment-1.2.0.dist-info → aws_cis_controls_assessment-1.2.2.dist-info}/RECORD
RENAMED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
aws_cis_assessment/__init__.py,sha256=
|
|
1
|
+
aws_cis_assessment/__init__.py,sha256=BketHh6rhvnzVE591PT-esMgjZlRIupmk-VtLPLomYE,518
|
|
2
2
|
aws_cis_assessment/cli/__init__.py,sha256=DYaGVAIoy5ucs9ubKQxX6Z3ZD46AGz9AaIaDQXzrzeY,100
|
|
3
3
|
aws_cis_assessment/cli/examples.py,sha256=F9K2Fe297kUfwoq6Ine9Aj_IXNU-KwO9hd7SAPWeZHI,12884
|
|
4
4
|
aws_cis_assessment/cli/main.py,sha256=i5QoqHXsPG_Kw0W7jM3Zj2YaAaCJnxxnfz82QBBHq-U,49441
|
|
5
5
|
aws_cis_assessment/cli/utils.py,sha256=ufdsifIPIE9HKVZAvFXfeJgEk_aAmz01tDrEukVyL0g,9783
|
|
6
6
|
aws_cis_assessment/config/__init__.py,sha256=aSQyaKGEQ7WgldC8IocY-YK7nduzfgjI6EuDE4Xti6s,77
|
|
7
7
|
aws_cis_assessment/config/config_loader.py,sha256=Wk6gfblj8RWU5QctHjPu5tTJMIb8lbEW3Ic9z-se4uQ,13165
|
|
8
|
-
aws_cis_assessment/config/rules/cis_controls_ig1.yaml,sha256=
|
|
8
|
+
aws_cis_assessment/config/rules/cis_controls_ig1.yaml,sha256=uaEm2Hmo4GZdG-9prUYcU67K1WBCx7120_TDh0lTwD0,55185
|
|
9
9
|
aws_cis_assessment/config/rules/cis_controls_ig2.yaml,sha256=kX4h-TFmaohNPhhFBrzHBZkitgG_kaRb2-XW_AJwnR0,48820
|
|
10
10
|
aws_cis_assessment/config/rules/cis_controls_ig3.yaml,sha256=YSghyCmwKF5UNZXdQQQNsaidQ95VDUgnwvh4jsV6kQU,4347
|
|
11
11
|
aws_cis_assessment/controls/__init__.py,sha256=oVTM94UAt0Vu7Hy-V84p6LAxZHORs-RRAj9j86r_730,72
|
|
12
|
-
aws_cis_assessment/controls/base_control.py,sha256=
|
|
13
|
-
aws_cis_assessment/controls/ig1/__init__.py,sha256=
|
|
12
|
+
aws_cis_assessment/controls/base_control.py,sha256=0otzF_bYPjBEt33HfFUXM9PB50r3ZBmJ3R4zZZdSQHg,21648
|
|
13
|
+
aws_cis_assessment/controls/ig1/__init__.py,sha256=jLOWHp6nDodEdYBx5urrjjCs7TEsRfaaCyZ_CgtjmJM,13144
|
|
14
14
|
aws_cis_assessment/controls/ig1/control_1_1.py,sha256=MwxaFCayJmFrBeGrVyTcLUksrPqRHId76m2Du1Vuk4I,28070
|
|
15
15
|
aws_cis_assessment/controls/ig1/control_2_2.py,sha256=yPp4aGGGzroAFqoTSaujjALSPq4jPxcaDiDIhwC11P0,11504
|
|
16
16
|
aws_cis_assessment/controls/ig1/control_3_3.py,sha256=f4ZuiMR6qSXCmVwP3OflEeZn48qpzQqq0XfjZgbq3Go,35668
|
|
17
17
|
aws_cis_assessment/controls/ig1/control_3_4.py,sha256=Flw_cA8_Qxv8zuIbOWv6JAYUdjPiAPU7Qs3CqDoRqvk,11438
|
|
18
|
-
aws_cis_assessment/controls/ig1/control_4_1.py,sha256
|
|
18
|
+
aws_cis_assessment/controls/ig1/control_4_1.py,sha256=GoaYc_aZ9Gd-QDETzE3ho77zaJjSQAro3bctODATfO0,22522
|
|
19
19
|
aws_cis_assessment/controls/ig1/control_access_analyzer.py,sha256=vURgc1sL_eYzJvviSeKD39fEQ0nHtCZl96NFZXF4Lvc,9056
|
|
20
20
|
aws_cis_assessment/controls/ig1/control_access_asset_mgmt.py,sha256=-fdURSgVMIb6ei6pVAAtkXq5IVIMefdq5Q3fanL6fP8,14851
|
|
21
21
|
aws_cis_assessment/controls/ig1/control_access_control.py,sha256=vM5XFd0J_pIVeeMKYbF2W7NrErGTw08HMl92g8ZrK_0,12861
|
|
@@ -34,7 +34,7 @@ aws_cis_assessment/controls/ig1/control_dynamodb_encryption.py,sha256=VOuNPeqqx-
|
|
|
34
34
|
aws_cis_assessment/controls/ig1/control_ebs_encryption.py,sha256=kHiaVmcm_qb64Z5uttW_Z9s-dEVPpPQQcNdvo7V8dcA,7605
|
|
35
35
|
aws_cis_assessment/controls/ig1/control_efs_encryption.py,sha256=cfUhk0pjfGkjWfarivngTM-s4ud9uGKwu7A0sNBw9AU,11292
|
|
36
36
|
aws_cis_assessment/controls/ig1/control_elb_logging.py,sha256=vk3S4zXbQ8pX2_Tx1F1J7Y1vteYZUSIHlSikU4T7i-A,8501
|
|
37
|
-
aws_cis_assessment/controls/ig1/control_guardduty.py,sha256=
|
|
37
|
+
aws_cis_assessment/controls/ig1/control_guardduty.py,sha256=CZsYG5nRDPGAeVtf-3UhVwVQhGX1amB6jBwSsHd9b1Q,6653
|
|
38
38
|
aws_cis_assessment/controls/ig1/control_iam_advanced.py,sha256=FQA_8IV5CyD_49u0eLN8q-JM50g1-tilDu9Ww_R3o9s,27694
|
|
39
39
|
aws_cis_assessment/controls/ig1/control_iam_governance.py,sha256=msaqmhLlFYK3pMgC-eYOP7RvDCpx014W8Su6hdlQ_Ic,22079
|
|
40
40
|
aws_cis_assessment/controls/ig1/control_iam_policies.py,sha256=k6BT4IF4c0uEs94UR8Ny1RifgRgvDpOPlaWr2WjVGWM,17326
|
|
@@ -48,11 +48,11 @@ aws_cis_assessment/controls/ig1/control_network_enhancements.py,sha256=Ta-9SMHT7
|
|
|
48
48
|
aws_cis_assessment/controls/ig1/control_network_security.py,sha256=8hVXx0ezUgtOasCZGUa5owbCj5F6QVLCl5JbKQ2au_8,9923
|
|
49
49
|
aws_cis_assessment/controls/ig1/control_patch_management.py,sha256=SXO1Bo8tGxf66cOCA6bzbg-03hNjo2A7rJ-JpjPBBJU,29209
|
|
50
50
|
aws_cis_assessment/controls/ig1/control_rds_encryption.py,sha256=-dgjds10Ob8RHmtBzZFV9jShj8psd-cwgJz4xh6wTYc,10761
|
|
51
|
-
aws_cis_assessment/controls/ig1/control_s3_encryption.py,sha256
|
|
51
|
+
aws_cis_assessment/controls/ig1/control_s3_encryption.py,sha256=VY_isicWF8as8yFKInq37LW_V6BQ86SjEdZnyDJ1Wo0,17926
|
|
52
52
|
aws_cis_assessment/controls/ig1/control_s3_enhancements.py,sha256=uP0Ko6cjTvmpg47vNtdaFgdjVPMS6Yjww-WZQIzvk8o,7759
|
|
53
53
|
aws_cis_assessment/controls/ig1/control_s3_security.py,sha256=8vt2rnNPdgQrvO5Ds3yV74mQ7qkF0f_LpKqQLjg0AQc,18308
|
|
54
|
-
aws_cis_assessment/controls/ig1/control_tls_ssl.py,sha256=
|
|
55
|
-
aws_cis_assessment/controls/ig1/control_version_mgmt.py,sha256=
|
|
54
|
+
aws_cis_assessment/controls/ig1/control_tls_ssl.py,sha256=A1LfYRtZKQLXs3dYyWiUglesKUqJ2Fio0oeprCjRzvY,24261
|
|
55
|
+
aws_cis_assessment/controls/ig1/control_version_mgmt.py,sha256=o2Q1YY7_FtA52rEvJ_DLufKhCHZ8b4uVcu-HswrnFCk,13929
|
|
56
56
|
aws_cis_assessment/controls/ig1/control_vpc_flow_logs.py,sha256=wgp8HGLobtL_pEYbm9YrmUwvvG0axF2zVTm0-4SqkNU,8485
|
|
57
57
|
aws_cis_assessment/controls/ig1/control_vpc_security.py,sha256=RCtBUozvdIPrXKFU0ssxjBF6A9l_HMcAbRv0K87Bbhc,10639
|
|
58
58
|
aws_cis_assessment/controls/ig1/control_waf_logging.py,sha256=HCYJBr84Kk8KK3py8JnY99_HJ_3cuVrmgMVP2Ye_BPU,9602
|
|
@@ -78,18 +78,18 @@ aws_cis_assessment/controls/ig3/control_3_14.py,sha256=fY2MZATcicuP1Zich5L7J6-MM
|
|
|
78
78
|
aws_cis_assessment/controls/ig3/control_7_1.py,sha256=GZQt0skGJVlUbGoH4MD5AoJJONf0nT9k7WQT-8F3le4,18499
|
|
79
79
|
aws_cis_assessment/core/__init__.py,sha256=aXt5Z3mqaaDvFyZPyMaJYFy66A_phfFIhhH_eyaic8Q,52
|
|
80
80
|
aws_cis_assessment/core/accuracy_validator.py,sha256=jnN2O32PpdDfWAp6erV4v4zKugC9ziJkDYnVF93FVuY,18386
|
|
81
|
-
aws_cis_assessment/core/assessment_engine.py,sha256=
|
|
81
|
+
aws_cis_assessment/core/assessment_engine.py,sha256=3AXk3yFHmCTcVelABgTZH8hYZ24ULqjxCRA3xT1m-m4,75362
|
|
82
82
|
aws_cis_assessment/core/audit_trail.py,sha256=qapCkI2zjbAPHlHQcgYonfDYyjU2MoX5Sc2IXtYj3eE,18395
|
|
83
|
-
aws_cis_assessment/core/aws_client_factory.py,sha256=
|
|
83
|
+
aws_cis_assessment/core/aws_client_factory.py,sha256=Rjy2TIra-0fY3qjogQ6wOJxj5mdRpCvbJaenBlbbtIo,14147
|
|
84
84
|
aws_cis_assessment/core/error_handler.py,sha256=5JgH3Y2yG1-ZSuEJR7o0ZMzqlwGWFRW2N4SjcL2gnBw,24219
|
|
85
85
|
aws_cis_assessment/core/models.py,sha256=-jgx_AEY1L9vK9VIM1VHeqZGcr6j9QzvtDldk1iOusE,6584
|
|
86
|
-
aws_cis_assessment/core/scoring_engine.py,sha256=
|
|
86
|
+
aws_cis_assessment/core/scoring_engine.py,sha256=CUkAIjguIpJpE0pU-M3YZ6SBaT50kfnyjtRKK6zNsVs,24341
|
|
87
87
|
aws_cis_assessment/reporters/__init__.py,sha256=GXdlY08kKy1Y3mMBv8Y0JuUB69u--e5DIu2jNJpc6QI,357
|
|
88
|
-
aws_cis_assessment/reporters/base_reporter.py,sha256=
|
|
88
|
+
aws_cis_assessment/reporters/base_reporter.py,sha256=YqGG9mrnaF4RakVEpBdh-lkEm2qF-vwPBlcKTLt1gCg,20325
|
|
89
89
|
aws_cis_assessment/reporters/csv_reporter.py,sha256=r83xzfP1t5AO9MfKawgN4eTeOU6eGZwJQgvNDLEd7NI,31419
|
|
90
|
-
aws_cis_assessment/reporters/html_reporter.py,sha256=
|
|
90
|
+
aws_cis_assessment/reporters/html_reporter.py,sha256=qA3AdTc1UAIXxD8H74qK6-p8I8TvF65gBIs3NMb7lu0,122837
|
|
91
91
|
aws_cis_assessment/reporters/json_reporter.py,sha256=MObCzTc9nlGTEXeWc7P8tTMeKCpEaJNfcSYc79cHXhc,22250
|
|
92
|
-
aws_cis_controls_assessment-1.2.
|
|
92
|
+
aws_cis_controls_assessment-1.2.2.dist-info/licenses/LICENSE,sha256=T_p0qKH4RoI3ejr3tktf3rx2Zart_9KeUmJd5iiqXW8,1079
|
|
93
93
|
deprecation-package/aws_cis_assessment_deprecated/__init__.py,sha256=WOaufqanKNhvWQ3frj8e627tS_kZnyk2R2hwqPFqydw,1892
|
|
94
94
|
docs/README.md,sha256=MXnfbPRmxir-7ihG2lNmLI9TJG0Pp0QWqoDZtXiH_Mk,4912
|
|
95
95
|
docs/adding-aws-backup-controls.md,sha256=l_H0H8W71n-6NbeplNujC_li2NiaQcYPr0hQMhEPbrc,21081
|
|
@@ -104,8 +104,8 @@ docs/scoring-comparison-aws-config.md,sha256=8BBe1tQsaAT0BAE3OdGIRFjuT1VJcOlM1qB
|
|
|
104
104
|
docs/scoring-methodology.md,sha256=C86FisBxKt6pyr-Kp6rAVPz45yPZpgsGibjgq8obIsg,9404
|
|
105
105
|
docs/troubleshooting.md,sha256=mGmWgrc3A1dn-Uk_XxWFh04OQxjmqkeax8vQX7takg0,18220
|
|
106
106
|
docs/user-guide.md,sha256=WysjUvbkuVf-7ntpwsiVTND5RkxRtZvq3Cm8Jzl-3NA,15860
|
|
107
|
-
aws_cis_controls_assessment-1.2.
|
|
108
|
-
aws_cis_controls_assessment-1.2.
|
|
109
|
-
aws_cis_controls_assessment-1.2.
|
|
110
|
-
aws_cis_controls_assessment-1.2.
|
|
111
|
-
aws_cis_controls_assessment-1.2.
|
|
107
|
+
aws_cis_controls_assessment-1.2.2.dist-info/METADATA,sha256=g7hJ2aj2KWgulfHwgnTsBQ78cWys71t1YLMzV6QtuCc,15544
|
|
108
|
+
aws_cis_controls_assessment-1.2.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
109
|
+
aws_cis_controls_assessment-1.2.2.dist-info/entry_points.txt,sha256=-AxPn5Y7yau0pQh33F5_uyWfvcnm2Kg1_nMQuLrZ7SY,68
|
|
110
|
+
aws_cis_controls_assessment-1.2.2.dist-info/top_level.txt,sha256=4OHmV6RAEWkz-Se50kfmuGCd-mUSotDZz3iLGF9CmkI,44
|
|
111
|
+
aws_cis_controls_assessment-1.2.2.dist-info/RECORD,,
|
{aws_cis_controls_assessment-1.2.0.dist-info → aws_cis_controls_assessment-1.2.2.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|