aws-cis-controls-assessment 1.0.8__py3-none-any.whl → 1.0.10__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 +94 -1
- aws_cis_assessment/config/rules/cis_controls_ig2.yaml +83 -1
- aws_cis_assessment/controls/ig1/__init__.py +17 -0
- aws_cis_assessment/controls/ig1/control_aws_backup_service.py +1276 -0
- aws_cis_assessment/controls/ig2/__init__.py +12 -0
- aws_cis_assessment/controls/ig2/control_aws_backup_ig2.py +23 -0
- aws_cis_assessment/core/assessment_engine.py +24 -0
- aws_cis_assessment/core/models.py +1 -0
- aws_cis_assessment/core/scoring_engine.py +30 -0
- aws_cis_assessment/reporters/base_reporter.py +2 -0
- aws_cis_assessment/reporters/html_reporter.py +279 -7
- {aws_cis_controls_assessment-1.0.8.dist-info → aws_cis_controls_assessment-1.0.10.dist-info}/METADATA +57 -10
- {aws_cis_controls_assessment-1.0.8.dist-info → aws_cis_controls_assessment-1.0.10.dist-info}/RECORD +30 -24
- docs/README.md +14 -3
- docs/adding-aws-backup-controls.md +562 -0
- docs/assessment-logic.md +291 -3
- docs/cli-reference.md +1 -1
- docs/config-rule-mappings.md +46 -5
- docs/developer-guide.md +312 -3
- docs/dual-scoring-implementation.md +303 -0
- docs/installation.md +2 -2
- docs/scoring-comparison-aws-config.md +379 -0
- docs/scoring-methodology.md +350 -0
- docs/troubleshooting.md +211 -2
- docs/user-guide.md +47 -2
- {aws_cis_controls_assessment-1.0.8.dist-info → aws_cis_controls_assessment-1.0.10.dist-info}/WHEEL +0 -0
- {aws_cis_controls_assessment-1.0.8.dist-info → aws_cis_controls_assessment-1.0.10.dist-info}/entry_points.txt +0 -0
- {aws_cis_controls_assessment-1.0.8.dist-info → aws_cis_controls_assessment-1.0.10.dist-info}/licenses/LICENSE +0 -0
- {aws_cis_controls_assessment-1.0.8.dist-info → aws_cis_controls_assessment-1.0.10.dist-info}/top_level.txt +0 -0
|
@@ -92,6 +92,13 @@ from .control_remaining_rules import (
|
|
|
92
92
|
AuditLogPolicyExistsAssessment
|
|
93
93
|
)
|
|
94
94
|
|
|
95
|
+
# Import AWS Backup IG2 controls
|
|
96
|
+
from .control_aws_backup_ig2 import (
|
|
97
|
+
BackupVaultLockCheckAssessment,
|
|
98
|
+
BackupReportPlanExistsCheckAssessment,
|
|
99
|
+
BackupRestoreTestingPlanExistsCheckAssessment
|
|
100
|
+
)
|
|
101
|
+
|
|
95
102
|
__all__ = [
|
|
96
103
|
# Control 3.10 - Encrypt Sensitive Data in Transit
|
|
97
104
|
'APIGatewaySSLEnabledAssessment',
|
|
@@ -165,6 +172,11 @@ __all__ = [
|
|
|
165
172
|
'RestrictedCommonPortsAssessment',
|
|
166
173
|
'AuditLogPolicyExistsAssessment',
|
|
167
174
|
|
|
175
|
+
# AWS Backup IG2 Controls
|
|
176
|
+
'BackupVaultLockCheckAssessment',
|
|
177
|
+
'BackupReportPlanExistsCheckAssessment',
|
|
178
|
+
'BackupRestoreTestingPlanExistsCheckAssessment',
|
|
179
|
+
|
|
168
180
|
# Control 5.2 - Use Unique Passwords
|
|
169
181
|
'MFAEnabledForIAMConsoleAccessAssessment',
|
|
170
182
|
'RootAccountMFAEnabledAssessment',
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""AWS Backup Service Controls for IG2 - Advanced backup infrastructure assessment.
|
|
2
|
+
|
|
3
|
+
This module implements IG2-level AWS Backup service controls that assess
|
|
4
|
+
advanced backup capabilities like vault lock, reporting, and restore testing.
|
|
5
|
+
|
|
6
|
+
Controls:
|
|
7
|
+
- backup-vault-lock-check: Verifies vault lock (ransomware protection)
|
|
8
|
+
- backup-report-plan-exists-check: Validates backup compliance reporting
|
|
9
|
+
- backup-restore-testing-plan-exists-check: Ensures backups are recoverable
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# Import the IG2 controls from the IG1 module since they're all in the same file
|
|
13
|
+
from aws_cis_assessment.controls.ig1.control_aws_backup_service import (
|
|
14
|
+
BackupVaultLockCheckAssessment,
|
|
15
|
+
BackupReportPlanExistsCheckAssessment,
|
|
16
|
+
BackupRestoreTestingPlanExistsCheckAssessment
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
'BackupVaultLockCheckAssessment',
|
|
21
|
+
'BackupReportPlanExistsCheckAssessment',
|
|
22
|
+
'BackupRestoreTestingPlanExistsCheckAssessment'
|
|
23
|
+
]
|
|
@@ -95,6 +95,11 @@ from aws_cis_assessment.controls.ig1.control_backup_recovery import (
|
|
|
95
95
|
DBInstanceBackupEnabledAssessment, RedshiftBackupEnabledAssessment, DynamoDBPITREnabledAssessment,
|
|
96
96
|
ElastiCacheRedisClusterAutomaticBackupCheckAssessment, S3BucketReplicationEnabledAssessment
|
|
97
97
|
)
|
|
98
|
+
from aws_cis_assessment.controls.ig1.control_aws_backup_service import (
|
|
99
|
+
BackupPlanMinFrequencyAndMinRetentionCheckAssessment,
|
|
100
|
+
BackupVaultAccessPolicyCheckAssessment,
|
|
101
|
+
BackupSelectionResourceCoverageCheckAssessment
|
|
102
|
+
)
|
|
98
103
|
from aws_cis_assessment.controls.ig1.control_s3_enhancements import (
|
|
99
104
|
S3AccountLevelPublicAccessBlocksPeriodicAssessment, S3BucketPublicWriteProhibitedAssessment
|
|
100
105
|
)
|
|
@@ -151,6 +156,11 @@ from aws_cis_assessment.controls.ig2.control_remaining_rules import (
|
|
|
151
156
|
RedshiftEnhancedVPCRoutingEnabledAssessment, RestrictedCommonPortsAssessment,
|
|
152
157
|
AuditLogPolicyExistsAssessment
|
|
153
158
|
)
|
|
159
|
+
from aws_cis_assessment.controls.ig2.control_aws_backup_ig2 import (
|
|
160
|
+
BackupVaultLockCheckAssessment,
|
|
161
|
+
BackupReportPlanExistsCheckAssessment,
|
|
162
|
+
BackupRestoreTestingPlanExistsCheckAssessment
|
|
163
|
+
)
|
|
154
164
|
from aws_cis_assessment.controls.ig3.control_3_14 import (
|
|
155
165
|
APIGatewayExecutionLoggingEnabledAssessment, CloudTrailS3DataEventsEnabledAssessment,
|
|
156
166
|
MultiRegionCloudTrailEnabledAssessment, CloudTrailCloudWatchLogsEnabledAssessment
|
|
@@ -412,6 +422,11 @@ class AssessmentEngine:
|
|
|
412
422
|
'elasticache-redis-cluster-automatic-backup-check': ElastiCacheRedisClusterAutomaticBackupCheckAssessment(),
|
|
413
423
|
's3-bucket-replication-enabled': S3BucketReplicationEnabledAssessment(),
|
|
414
424
|
|
|
425
|
+
# AWS Backup Service Controls (IG1)
|
|
426
|
+
'backup-plan-min-frequency-and-min-retention-check': BackupPlanMinFrequencyAndMinRetentionCheckAssessment(),
|
|
427
|
+
'backup-vault-access-policy-check': BackupVaultAccessPolicyCheckAssessment(),
|
|
428
|
+
'backup-selection-resource-coverage-check': BackupSelectionResourceCoverageCheckAssessment(),
|
|
429
|
+
|
|
415
430
|
# S3 Security Enhancements
|
|
416
431
|
's3-account-level-public-access-blocks-periodic': S3AccountLevelPublicAccessBlocksPeriodicAssessment(),
|
|
417
432
|
's3-bucket-public-write-prohibited': S3BucketPublicWriteProhibitedAssessment(),
|
|
@@ -488,6 +503,11 @@ class AssessmentEngine:
|
|
|
488
503
|
'redshift-enhanced-vpc-routing-enabled': RedshiftEnhancedVPCRoutingEnabledAssessment(),
|
|
489
504
|
'restricted-common-ports': RestrictedCommonPortsAssessment(),
|
|
490
505
|
'audit-log-policy-exists (Process check)': AuditLogPolicyExistsAssessment(),
|
|
506
|
+
|
|
507
|
+
# AWS Backup Service Controls (IG2)
|
|
508
|
+
'backup-vault-lock-check': BackupVaultLockCheckAssessment(),
|
|
509
|
+
'backup-report-plan-exists-check': BackupReportPlanExistsCheckAssessment(),
|
|
510
|
+
'backup-restore-testing-plan-exists-check': BackupRestoreTestingPlanExistsCheckAssessment(),
|
|
491
511
|
},
|
|
492
512
|
'IG3': {
|
|
493
513
|
# Control 3.14 - Sensitive Data Logging
|
|
@@ -702,12 +722,16 @@ class AssessmentEngine:
|
|
|
702
722
|
# Calculate overall score using scoring engine
|
|
703
723
|
overall_score = self.scoring_engine.calculate_overall_score(ig_scores)
|
|
704
724
|
|
|
725
|
+
# Calculate AWS Config-style unweighted score
|
|
726
|
+
aws_config_score = self.scoring_engine.calculate_aws_config_style_score(ig_scores)
|
|
727
|
+
|
|
705
728
|
# Create final assessment result
|
|
706
729
|
assessment_result = AssessmentResult(
|
|
707
730
|
account_id=account_id,
|
|
708
731
|
regions_assessed=self.aws_factory.regions.copy(),
|
|
709
732
|
timestamp=datetime.now(),
|
|
710
733
|
overall_score=overall_score,
|
|
734
|
+
aws_config_score=aws_config_score, # Add AWS Config score
|
|
711
735
|
ig_scores=ig_scores,
|
|
712
736
|
total_resources_evaluated=len(all_results),
|
|
713
737
|
assessment_duration=self.progress.elapsed_time
|
|
@@ -126,6 +126,7 @@ class AssessmentResult:
|
|
|
126
126
|
regions_assessed: List[str]
|
|
127
127
|
timestamp: datetime
|
|
128
128
|
overall_score: float
|
|
129
|
+
aws_config_score: float = 0.0 # AWS Config Conformance Pack style score
|
|
129
130
|
ig_scores: Dict[str, IGScore] = field(default_factory=dict)
|
|
130
131
|
total_resources_evaluated: int = 0
|
|
131
132
|
assessment_duration: Optional[timedelta] = None
|
|
@@ -47,6 +47,36 @@ class ScoringEngine:
|
|
|
47
47
|
|
|
48
48
|
logger.info("ScoringEngine initialized with control and IG weights")
|
|
49
49
|
|
|
50
|
+
def calculate_aws_config_style_score(self, ig_scores: Dict[str, IGScore]) -> float:
|
|
51
|
+
"""Calculate compliance score using AWS Config Conformance Pack approach.
|
|
52
|
+
|
|
53
|
+
This is a simple unweighted calculation:
|
|
54
|
+
Score = Total Compliant Resources / Total Resources
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
ig_scores: Dictionary of IG scores
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Unweighted compliance percentage (0-100)
|
|
61
|
+
"""
|
|
62
|
+
total_compliant = 0
|
|
63
|
+
total_resources = 0
|
|
64
|
+
|
|
65
|
+
# Sum all compliant and total resources across all IGs and controls
|
|
66
|
+
for ig_score in ig_scores.values():
|
|
67
|
+
for control_score in ig_score.control_scores.values():
|
|
68
|
+
total_compliant += control_score.compliant_resources
|
|
69
|
+
total_resources += control_score.total_resources
|
|
70
|
+
|
|
71
|
+
if total_resources > 0:
|
|
72
|
+
aws_config_score = (total_compliant / total_resources) * 100
|
|
73
|
+
else:
|
|
74
|
+
aws_config_score = 0.0
|
|
75
|
+
|
|
76
|
+
logger.info(f"AWS Config style score: {aws_config_score:.1f}% "
|
|
77
|
+
f"({total_compliant}/{total_resources} resources compliant)")
|
|
78
|
+
return aws_config_score
|
|
79
|
+
|
|
50
80
|
def calculate_control_score(self, control_id: str, rule_results: List[ComplianceResult],
|
|
51
81
|
control_title: str = "", implementation_group: str = "") -> ControlScore:
|
|
52
82
|
"""Calculate compliance score for individual CIS Control.
|
|
@@ -110,6 +110,8 @@ class ReportGenerator(ABC):
|
|
|
110
110
|
},
|
|
111
111
|
'executive_summary': {
|
|
112
112
|
'overall_compliance_percentage': compliance_summary.overall_compliance_percentage,
|
|
113
|
+
'aws_config_style_score': assessment_result.aws_config_score, # Add AWS Config score
|
|
114
|
+
'score_difference': compliance_summary.overall_compliance_percentage - assessment_result.aws_config_score, # Show difference
|
|
113
115
|
'ig1_compliance_percentage': compliance_summary.ig1_compliance_percentage,
|
|
114
116
|
'ig2_compliance_percentage': compliance_summary.ig2_compliance_percentage,
|
|
115
117
|
'ig3_compliance_percentage': compliance_summary.ig3_compliance_percentage,
|
|
@@ -962,6 +962,171 @@ class HTMLReporter(ReportGenerator):
|
|
|
962
962
|
}
|
|
963
963
|
}
|
|
964
964
|
|
|
965
|
+
/* Score Comparison Styles */
|
|
966
|
+
.score-comparison-section {
|
|
967
|
+
background: white;
|
|
968
|
+
border-radius: 8px;
|
|
969
|
+
padding: 25px;
|
|
970
|
+
margin-bottom: 30px;
|
|
971
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
.comparison-grid {
|
|
975
|
+
display: grid;
|
|
976
|
+
grid-template-columns: 1fr 1fr;
|
|
977
|
+
gap: 20px;
|
|
978
|
+
margin-bottom: 20px;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
.comparison-card {
|
|
982
|
+
background: #f8f9fa;
|
|
983
|
+
border-radius: 8px;
|
|
984
|
+
padding: 20px;
|
|
985
|
+
border: 2px solid #e9ecef;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
.comparison-card h4 {
|
|
989
|
+
margin: 0 0 15px 0;
|
|
990
|
+
color: #2c3e50;
|
|
991
|
+
font-size: 1.1em;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
.comparison-value {
|
|
995
|
+
font-size: 2.5em;
|
|
996
|
+
font-weight: bold;
|
|
997
|
+
margin: 10px 0;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
.comparison-card.weighted .comparison-value {
|
|
1001
|
+
color: #3498db;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
.comparison-card.aws-config .comparison-value {
|
|
1005
|
+
color: #9b59b6;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.comparison-features {
|
|
1009
|
+
list-style: none;
|
|
1010
|
+
padding: 0;
|
|
1011
|
+
margin: 15px 0 0 0;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
.comparison-features li {
|
|
1015
|
+
padding: 5px 0;
|
|
1016
|
+
color: #666;
|
|
1017
|
+
font-size: 0.9em;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
.comparison-features li:before {
|
|
1021
|
+
content: "✓ ";
|
|
1022
|
+
color: #27ae60;
|
|
1023
|
+
font-weight: bold;
|
|
1024
|
+
margin-right: 5px;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
.score-difference {
|
|
1028
|
+
background: #fff3cd;
|
|
1029
|
+
border: 1px solid #ffc107;
|
|
1030
|
+
border-radius: 8px;
|
|
1031
|
+
padding: 15px;
|
|
1032
|
+
margin-top: 20px;
|
|
1033
|
+
display: flex;
|
|
1034
|
+
align-items: center;
|
|
1035
|
+
gap: 15px;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
.diff-icon {
|
|
1039
|
+
font-size: 2em;
|
|
1040
|
+
flex-shrink: 0;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
.diff-content {
|
|
1044
|
+
flex-grow: 1;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
.diff-content strong {
|
|
1048
|
+
display: block;
|
|
1049
|
+
margin-bottom: 5px;
|
|
1050
|
+
color: #856404;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.diff-content p {
|
|
1054
|
+
margin: 0;
|
|
1055
|
+
color: #856404;
|
|
1056
|
+
font-size: 0.9em;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.score-difference.neutral {
|
|
1060
|
+
background: #d1ecf1;
|
|
1061
|
+
border-color: #17a2b8;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
.score-difference.neutral .diff-content strong,
|
|
1065
|
+
.score-difference.neutral .diff-content p {
|
|
1066
|
+
color: #0c5460;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
.score-difference.warning {
|
|
1070
|
+
background: #fff3cd;
|
|
1071
|
+
border-color: #ffc107;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
.score-difference.warning .diff-content strong,
|
|
1075
|
+
.score-difference.warning .diff-content p {
|
|
1076
|
+
color: #856404;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
.score-difference.positive {
|
|
1080
|
+
background: #d4edda;
|
|
1081
|
+
border-color: #28a745;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
.score-difference.positive .diff-content strong,
|
|
1085
|
+
.score-difference.positive .diff-content p {
|
|
1086
|
+
color: #155724;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
.methodology-note {
|
|
1090
|
+
background: #e7f3ff;
|
|
1091
|
+
border-left: 4px solid #3498db;
|
|
1092
|
+
padding: 15px;
|
|
1093
|
+
margin-top: 20px;
|
|
1094
|
+
border-radius: 4px;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
.methodology-note h5 {
|
|
1098
|
+
margin: 0 0 10px 0;
|
|
1099
|
+
color: #2c3e50;
|
|
1100
|
+
font-size: 1em;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
.methodology-note p {
|
|
1104
|
+
margin: 5px 0;
|
|
1105
|
+
color: #555;
|
|
1106
|
+
font-size: 0.9em;
|
|
1107
|
+
line-height: 1.6;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
.methodology-note a {
|
|
1111
|
+
color: #3498db;
|
|
1112
|
+
text-decoration: none;
|
|
1113
|
+
font-weight: 500;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
.methodology-note a:hover {
|
|
1117
|
+
text-decoration: underline;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
@media (max-width: 768px) {
|
|
1121
|
+
.comparison-grid {
|
|
1122
|
+
grid-template-columns: 1fr;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
.comparison-value {
|
|
1126
|
+
font-size: 2em;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
|
|
965
1130
|
/* Print styles */
|
|
966
1131
|
@media print {
|
|
967
1132
|
.navigation {
|
|
@@ -1300,6 +1465,18 @@ class HTMLReporter(ReportGenerator):
|
|
|
1300
1465
|
a.click();
|
|
1301
1466
|
window.URL.revokeObjectURL(url);
|
|
1302
1467
|
}}
|
|
1468
|
+
|
|
1469
|
+
// Toggle scoring details
|
|
1470
|
+
function toggleScoringDetails() {{
|
|
1471
|
+
const detailsSection = document.getElementById('scoringDetails');
|
|
1472
|
+
if (detailsSection) {{
|
|
1473
|
+
if (detailsSection.style.display === 'none') {{
|
|
1474
|
+
detailsSection.style.display = 'block';
|
|
1475
|
+
}} else {{
|
|
1476
|
+
detailsSection.style.display = 'none';
|
|
1477
|
+
}}
|
|
1478
|
+
}}
|
|
1479
|
+
}}
|
|
1303
1480
|
"""
|
|
1304
1481
|
|
|
1305
1482
|
def _generate_header(self, html_data: Dict[str, Any]) -> str:
|
|
@@ -1362,14 +1539,22 @@ class HTMLReporter(ReportGenerator):
|
|
|
1362
1539
|
|
|
1363
1540
|
# Generate metric cards
|
|
1364
1541
|
overall_status = self._get_status_class(exec_summary.get("overall_compliance_percentage", 0))
|
|
1542
|
+
aws_config_score = exec_summary.get('aws_config_style_score', 0)
|
|
1543
|
+
score_diff = exec_summary.get('score_difference', 0)
|
|
1365
1544
|
|
|
1366
1545
|
metric_cards = f"""
|
|
1367
1546
|
<div class="metric-card {overall_status}">
|
|
1368
1547
|
<div class="metric-value">{exec_summary.get('overall_compliance_percentage', 0):.1f}%</div>
|
|
1369
|
-
<div class="metric-label">
|
|
1548
|
+
<div class="metric-label">Weighted Compliance Score</div>
|
|
1370
1549
|
<div class="metric-trend trend-stable">Grade: {exec_summary.get('compliance_grade', 'N/A')}</div>
|
|
1371
1550
|
</div>
|
|
1372
1551
|
|
|
1552
|
+
<div class="metric-card">
|
|
1553
|
+
<div class="metric-value">{aws_config_score:.1f}%</div>
|
|
1554
|
+
<div class="metric-label">AWS Config Style Score</div>
|
|
1555
|
+
<div class="metric-trend trend-stable">Unweighted</div>
|
|
1556
|
+
</div>
|
|
1557
|
+
|
|
1373
1558
|
<div class="metric-card">
|
|
1374
1559
|
<div class="metric-value">{exec_summary.get('total_resources', 0):,}</div>
|
|
1375
1560
|
<div class="metric-label">Resources Evaluated</div>
|
|
@@ -1381,14 +1566,15 @@ class HTMLReporter(ReportGenerator):
|
|
|
1381
1566
|
<div class="metric-label">Compliant Resources</div>
|
|
1382
1567
|
<div class="metric-trend trend-up">{(exec_summary.get('compliant_resources', 0) / max(exec_summary.get('total_resources', 1), 1) * 100):.1f}% of total</div>
|
|
1383
1568
|
</div>
|
|
1384
|
-
|
|
1385
|
-
<div class="metric-card">
|
|
1386
|
-
<div class="metric-value">{exec_summary.get('non_compliant_resources', 0):,}</div>
|
|
1387
|
-
<div class="metric-label">Non-Compliant Resources</div>
|
|
1388
|
-
<div class="metric-trend trend-down">Require attention</div>
|
|
1389
|
-
</div>
|
|
1390
1569
|
"""
|
|
1391
1570
|
|
|
1571
|
+
# Add scoring comparison section
|
|
1572
|
+
score_comparison = self._generate_score_comparison_section(
|
|
1573
|
+
exec_summary.get('overall_compliance_percentage', 0),
|
|
1574
|
+
aws_config_score,
|
|
1575
|
+
score_diff
|
|
1576
|
+
)
|
|
1577
|
+
|
|
1392
1578
|
# Generate IG progress bars
|
|
1393
1579
|
ig_progress = ""
|
|
1394
1580
|
for ig in ['ig1', 'ig2', 'ig3']:
|
|
@@ -1435,6 +1621,8 @@ class HTMLReporter(ReportGenerator):
|
|
|
1435
1621
|
{metric_cards}
|
|
1436
1622
|
</div>
|
|
1437
1623
|
|
|
1624
|
+
{score_comparison}
|
|
1625
|
+
|
|
1438
1626
|
<div class="ig-progress-section">
|
|
1439
1627
|
<h3>Implementation Groups Progress</h3>
|
|
1440
1628
|
{ig_progress}
|
|
@@ -1910,6 +2098,90 @@ class HTMLReporter(ReportGenerator):
|
|
|
1910
2098
|
display_findings.append(display_finding)
|
|
1911
2099
|
return display_findings
|
|
1912
2100
|
|
|
2101
|
+
def _generate_score_comparison_section(self, weighted_score: float,
|
|
2102
|
+
aws_config_score: float,
|
|
2103
|
+
score_diff: float) -> str:
|
|
2104
|
+
"""Generate scoring methodology comparison section.
|
|
2105
|
+
|
|
2106
|
+
Args:
|
|
2107
|
+
weighted_score: Our weighted compliance score
|
|
2108
|
+
aws_config_score: AWS Config Conformance Pack style score
|
|
2109
|
+
score_diff: Difference between the two scores
|
|
2110
|
+
|
|
2111
|
+
Returns:
|
|
2112
|
+
HTML section comparing the two scoring approaches
|
|
2113
|
+
"""
|
|
2114
|
+
# Determine interpretation based on difference
|
|
2115
|
+
if abs(score_diff) < 1.0:
|
|
2116
|
+
interpretation = "Both scoring approaches show similar results, indicating balanced compliance across all control priorities."
|
|
2117
|
+
icon = "ℹ️"
|
|
2118
|
+
diff_class = "neutral"
|
|
2119
|
+
elif score_diff < 0:
|
|
2120
|
+
# Weighted score is lower
|
|
2121
|
+
interpretation = f"The weighted score is {abs(score_diff):.1f}% lower, indicating critical security controls need attention despite good overall resource compliance."
|
|
2122
|
+
icon = "⚠️"
|
|
2123
|
+
diff_class = "warning"
|
|
2124
|
+
else:
|
|
2125
|
+
# Weighted score is higher
|
|
2126
|
+
interpretation = f"The weighted score is {score_diff:.1f}% higher, indicating strong performance in critical security controls despite some gaps in less critical areas."
|
|
2127
|
+
icon = "✓"
|
|
2128
|
+
diff_class = "positive"
|
|
2129
|
+
|
|
2130
|
+
return f"""
|
|
2131
|
+
<div class="score-comparison-section">
|
|
2132
|
+
<h3>Scoring Methodology Comparison</h3>
|
|
2133
|
+
<div class="comparison-grid">
|
|
2134
|
+
<div class="comparison-card">
|
|
2135
|
+
<h4>Weighted Score (Our Approach)</h4>
|
|
2136
|
+
<div class="comparison-value">{weighted_score:.1f}%</div>
|
|
2137
|
+
<p class="comparison-description">
|
|
2138
|
+
Uses risk-based weighting where critical controls (encryption, access control)
|
|
2139
|
+
have higher impact on the overall score. Reflects actual security posture.
|
|
2140
|
+
</p>
|
|
2141
|
+
<ul class="comparison-features">
|
|
2142
|
+
<li>✓ Prioritizes critical security controls</li>
|
|
2143
|
+
<li>✓ Prevents resource count skew</li>
|
|
2144
|
+
<li>✓ Guides remediation priorities</li>
|
|
2145
|
+
</ul>
|
|
2146
|
+
</div>
|
|
2147
|
+
|
|
2148
|
+
<div class="comparison-card">
|
|
2149
|
+
<h4>AWS Config Style Score</h4>
|
|
2150
|
+
<div class="comparison-value">{aws_config_score:.1f}%</div>
|
|
2151
|
+
<p class="comparison-description">
|
|
2152
|
+
Simple unweighted calculation: compliant resources divided by total resources.
|
|
2153
|
+
All rules treated equally regardless of security criticality.
|
|
2154
|
+
</p>
|
|
2155
|
+
<ul class="comparison-features">
|
|
2156
|
+
<li>✓ Simple and straightforward</li>
|
|
2157
|
+
<li>✓ Easy to audit</li>
|
|
2158
|
+
<li>✓ Resource-level tracking</li>
|
|
2159
|
+
</ul>
|
|
2160
|
+
</div>
|
|
2161
|
+
</div>
|
|
2162
|
+
|
|
2163
|
+
<div class="score-difference {diff_class}">
|
|
2164
|
+
<span class="diff-icon">{icon}</span>
|
|
2165
|
+
<div class="diff-content">
|
|
2166
|
+
<strong>Score Difference: {score_diff:+.1f}%</strong>
|
|
2167
|
+
<p>{interpretation}</p>
|
|
2168
|
+
</div>
|
|
2169
|
+
</div>
|
|
2170
|
+
|
|
2171
|
+
<div class="methodology-note">
|
|
2172
|
+
<strong>Which score should I use?</strong>
|
|
2173
|
+
<ul>
|
|
2174
|
+
<li><strong>Weighted Score:</strong> Use for security decision-making, risk prioritization, and remediation planning</li>
|
|
2175
|
+
<li><strong>AWS Config Style:</strong> Use for compliance reporting, audits, and simple stakeholder communication</li>
|
|
2176
|
+
<li><strong>Both:</strong> Track both metrics for comprehensive security program management</li>
|
|
2177
|
+
</ul>
|
|
2178
|
+
<p>
|
|
2179
|
+
<a href="#" onclick="toggleScoringDetails(); return false;">Learn more about scoring methodologies →</a>
|
|
2180
|
+
</p>
|
|
2181
|
+
</div>
|
|
2182
|
+
</div>
|
|
2183
|
+
"""
|
|
2184
|
+
|
|
1913
2185
|
def set_chart_options(self, include_charts: bool = True) -> None:
|
|
1914
2186
|
"""Configure chart inclusion options.
|
|
1915
2187
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aws-cis-controls-assessment
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.10
|
|
4
4
|
Summary: Production-ready AWS CIS Controls compliance assessment framework with 145 comprehensive rules
|
|
5
5
|
Author-email: AWS CIS Assessment Team <security@example.com>
|
|
6
6
|
Maintainer-email: AWS CIS Assessment Team <security@example.com>
|
|
@@ -57,18 +57,20 @@ Dynamic: license-file
|
|
|
57
57
|
|
|
58
58
|
# AWS CIS Controls Compliance Assessment Framework
|
|
59
59
|
|
|
60
|
-
A production-ready, enterprise-grade framework for evaluating AWS account configurations against CIS Controls Implementation Groups (IG1, IG2, IG3) using AWS Config rule specifications. **100% CIS Controls coverage achieved** with
|
|
60
|
+
A production-ready, enterprise-grade framework for evaluating AWS account configurations against CIS Controls Implementation Groups (IG1, IG2, IG3) using AWS Config rule specifications. **100% CIS Controls coverage achieved** with 133 implemented rules plus 5 bonus security enhancements.
|
|
61
61
|
|
|
62
62
|
> **Production Status**: This framework is production-ready and actively deployed in enterprise environments. It provides comprehensive point-in-time compliance assessments while we recommend [AWS Config](https://aws.amazon.com/config/) for ongoing continuous compliance monitoring and automated remediation.
|
|
63
63
|
|
|
64
64
|
## 🎯 Key Features
|
|
65
65
|
|
|
66
|
-
- **✅ Complete Coverage**:
|
|
66
|
+
- **✅ Complete Coverage**: 137/137 CIS Controls rules implemented (100% coverage)
|
|
67
|
+
- **✅ Dual Scoring System**: Both weighted and AWS Config-style scoring methodologies
|
|
67
68
|
- **✅ Enterprise Ready**: Production-tested with enterprise-grade architecture
|
|
68
69
|
- **✅ Performance Optimized**: Handles large-scale assessments efficiently
|
|
69
70
|
- **✅ Multi-Format Reports**: JSON, HTML, and CSV with detailed remediation guidance
|
|
70
71
|
- **✅ No AWS Config Required**: Direct AWS API calls based on Config rule specifications
|
|
71
72
|
- **✅ Bonus Security Rules**: 5 additional security enhancements beyond CIS requirements
|
|
73
|
+
- **✅ AWS Backup Controls**: 6 comprehensive backup infrastructure controls (3 IG1 + 3 IG2)
|
|
72
74
|
|
|
73
75
|
## 🚀 Quick Start
|
|
74
76
|
|
|
@@ -87,7 +89,7 @@ pip install -e .
|
|
|
87
89
|
### Basic Usage
|
|
88
90
|
|
|
89
91
|
```bash
|
|
90
|
-
# Run complete assessment (all
|
|
92
|
+
# Run complete assessment (all 142 rules) - defaults to us-east-1
|
|
91
93
|
aws-cis-assess assess --aws-profile my-aws-profile
|
|
92
94
|
|
|
93
95
|
# Assess multiple regions
|
|
@@ -108,19 +110,19 @@ aws-cis-assess assess --output-format json
|
|
|
108
110
|
|
|
109
111
|
## 📊 Implementation Groups Coverage
|
|
110
112
|
|
|
111
|
-
### IG1 - Essential Cyber Hygiene (
|
|
113
|
+
### IG1 - Essential Cyber Hygiene (96 Rules) ✅
|
|
112
114
|
**100% Coverage Achieved**
|
|
113
115
|
- Asset Inventory and Management (6 rules)
|
|
114
116
|
- Identity and Access Management (15 rules)
|
|
115
117
|
- Data Protection and Encryption (8 rules)
|
|
116
118
|
- Network Security Controls (20 rules)
|
|
117
119
|
- Logging and Monitoring (13 rules)
|
|
118
|
-
- Backup and Recovery (
|
|
120
|
+
- Backup and Recovery (17 rules) - **NEW: 6 AWS Backup service controls added (3 IG1 + 3 IG2)**
|
|
119
121
|
- Security Services Integration (5 rules)
|
|
120
122
|
- Configuration Management (9 rules)
|
|
121
123
|
- Vulnerability Management (5 rules)
|
|
122
124
|
|
|
123
|
-
### IG2 - Enhanced Security (+
|
|
125
|
+
### IG2 - Enhanced Security (+40 Rules) ✅
|
|
124
126
|
**100% Coverage Achieved**
|
|
125
127
|
- Advanced Encryption at Rest (6 rules)
|
|
126
128
|
- Certificate Management (2 rules)
|
|
@@ -131,6 +133,7 @@ aws-cis-assess assess --output-format json
|
|
|
131
133
|
- Network Segmentation (5 rules)
|
|
132
134
|
- Auto-scaling Security (1 rule)
|
|
133
135
|
- Enhanced Access Controls (8 rules)
|
|
136
|
+
- AWS Backup Advanced Controls (3 rules) - **NEW: Vault lock, reporting, restore testing**
|
|
134
137
|
|
|
135
138
|
### IG3 - Advanced Security (+1 Rule) ✅
|
|
136
139
|
**100% Coverage Achieved**
|
|
@@ -150,7 +153,7 @@ aws-cis-assess assess --output-format json
|
|
|
150
153
|
|
|
151
154
|
### Core Components
|
|
152
155
|
- **Assessment Engine**: Orchestrates compliance evaluations across all AWS regions
|
|
153
|
-
- **Control Assessments**:
|
|
156
|
+
- **Control Assessments**: 138 individual rule implementations with robust error handling
|
|
154
157
|
- **Scoring Engine**: Calculates compliance scores and generates executive metrics
|
|
155
158
|
- **Reporting System**: Multi-format output with detailed remediation guidance
|
|
156
159
|
- **Resource Management**: Optimized for enterprise-scale deployments with memory management
|
|
@@ -208,6 +211,9 @@ aws-cis-assess assess --output-format json
|
|
|
208
211
|
- **[Installation Guide](docs/installation.md)**: Detailed installation instructions and requirements
|
|
209
212
|
- **[User Guide](docs/user-guide.md)**: Comprehensive user manual and best practices
|
|
210
213
|
- **[CLI Reference](docs/cli-reference.md)**: Complete command-line interface documentation
|
|
214
|
+
- **[Dual Scoring Guide](docs/dual-scoring-implementation.md)**: Weighted vs AWS Config scoring methodologies
|
|
215
|
+
- **[Scoring Methodology](docs/scoring-methodology.md)**: Detailed explanation of weighted scoring
|
|
216
|
+
- **[AWS Config Comparison](docs/scoring-comparison-aws-config.md)**: Comparison with AWS Config approach
|
|
211
217
|
- **[Troubleshooting Guide](docs/troubleshooting.md)**: Common issues and solutions
|
|
212
218
|
- **[Developer Guide](docs/developer-guide.md)**: Development and contribution guidelines
|
|
213
219
|
|
|
@@ -243,7 +249,48 @@ MIT License - see [LICENSE](LICENSE) file for details.
|
|
|
243
249
|
|
|
244
250
|
---
|
|
245
251
|
|
|
246
|
-
**Framework Version**: 1.0.
|
|
247
|
-
**CIS Controls Coverage**:
|
|
252
|
+
**Framework Version**: 1.0.10 (in development)
|
|
253
|
+
**CIS Controls Coverage**: 137/137 rules (100%) + 5 bonus rules
|
|
248
254
|
**Production Status**: ✅ Ready for immediate enterprise deployment
|
|
249
255
|
**Last Updated**: January 2026
|
|
256
|
+
|
|
257
|
+
## 🆕 What's New in Version 1.0.10
|
|
258
|
+
|
|
259
|
+
### AWS Backup Service Controls
|
|
260
|
+
Six new controls added to assess AWS Backup infrastructure:
|
|
261
|
+
|
|
262
|
+
**IG1 Controls (3)**:
|
|
263
|
+
1. **backup-plan-min-frequency-and-min-retention-check** - Validates backup plans have appropriate frequency and retention policies
|
|
264
|
+
- Ensures backup plans have at least one rule defined
|
|
265
|
+
- Validates schedule expressions (cron or rate)
|
|
266
|
+
- Checks retention periods meet minimum requirements (default: 7 days)
|
|
267
|
+
- Validates lifecycle policies for cold storage transitions
|
|
268
|
+
|
|
269
|
+
2. **backup-vault-access-policy-check** - Ensures backup vaults have secure access policies
|
|
270
|
+
- Detects publicly accessible backup vaults
|
|
271
|
+
- Identifies overly permissive access policies
|
|
272
|
+
- Warns about dangerous permissions (DeleteBackupVault, DeleteRecoveryPoint)
|
|
273
|
+
- Validates principle of least privilege
|
|
274
|
+
|
|
275
|
+
3. **backup-selection-resource-coverage-check** - Validates backup plans cover critical resources
|
|
276
|
+
- Ensures backup plans have at least one selection
|
|
277
|
+
- Validates selections target specific resources or use tags
|
|
278
|
+
- Checks that selections are not empty
|
|
279
|
+
|
|
280
|
+
**IG2 Controls (3)**:
|
|
281
|
+
4. **backup-vault-lock-check** - Verifies vault lock for ransomware protection
|
|
282
|
+
- Ensures critical vaults have Vault Lock enabled
|
|
283
|
+
- Validates immutable backup configuration (WORM)
|
|
284
|
+
- Checks minimum and maximum retention periods
|
|
285
|
+
|
|
286
|
+
5. **backup-report-plan-exists-check** - Validates backup compliance reporting
|
|
287
|
+
- Ensures at least one report plan exists
|
|
288
|
+
- Validates report delivery configuration
|
|
289
|
+
- Checks for active report generation
|
|
290
|
+
|
|
291
|
+
6. **backup-restore-testing-plan-exists-check** - Ensures backups are recoverable
|
|
292
|
+
- Validates restore testing plans exist
|
|
293
|
+
- Checks testing schedules are configured
|
|
294
|
+
- Ensures backups are actually tested for recoverability
|
|
295
|
+
|
|
296
|
+
These controls complement the existing 12 resource-specific backup controls by assessing the centralized AWS Backup service infrastructure itself. Total backup controls: 17 (12 resource-specific + 5 service-level). See [AWS Backup Controls Guide](docs/adding-aws-backup-controls.md) for detailed documentation.
|