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
docs/developer-guide.md
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
# Developer Guide
|
|
2
2
|
|
|
3
|
-
This guide covers extending and customizing the AWS CIS Controls Compliance Assessment Framework - a production-ready, enterprise-grade solution with
|
|
3
|
+
This guide covers extending and customizing the AWS CIS Controls Compliance Assessment Framework - a production-ready, enterprise-grade solution with 138 implemented rules (133 CIS Controls + 5 bonus security enhancements).
|
|
4
4
|
|
|
5
5
|
## Production Framework Status
|
|
6
6
|
|
|
7
7
|
**✅ Complete Implementation**
|
|
8
8
|
- 100% CIS Controls coverage across all Implementation Groups
|
|
9
|
-
-
|
|
9
|
+
- 138 total rules implemented (133 CIS + 5 bonus)
|
|
10
10
|
- Production-tested architecture with comprehensive error handling
|
|
11
11
|
- Enterprise-grade performance and scalability
|
|
12
12
|
- Ready for immediate deployment and customization
|
|
13
|
+
- **NEW:** AWS Backup service controls for infrastructure assessment
|
|
13
14
|
|
|
14
15
|
## Table of Contents
|
|
15
16
|
|
|
@@ -855,4 +856,312 @@ Common utility functions are available in various modules:
|
|
|
855
856
|
|
|
856
857
|
- `aws_cis_assessment.cli.utils`: CLI utilities
|
|
857
858
|
- `aws_cis_assessment.core.utils`: Core utilities
|
|
858
|
-
- `aws_cis_assessment.reporters.utils`: Reporting utilities
|
|
859
|
+
- `aws_cis_assessment.reporters.utils`: Reporting utilities
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
## AWS Backup Controls Example (New in v1.0.10)
|
|
863
|
+
|
|
864
|
+
### Overview
|
|
865
|
+
|
|
866
|
+
The AWS Backup service controls demonstrate best practices for implementing service-level assessments. These controls assess the backup infrastructure itself, complementing resource-specific backup controls.
|
|
867
|
+
|
|
868
|
+
### Implementation Example
|
|
869
|
+
|
|
870
|
+
```python
|
|
871
|
+
# aws_cis_assessment/controls/ig1/control_aws_backup_service.py
|
|
872
|
+
from typing import Dict, List, Any
|
|
873
|
+
import logging
|
|
874
|
+
import json
|
|
875
|
+
from botocore.exceptions import ClientError
|
|
876
|
+
|
|
877
|
+
from aws_cis_assessment.controls.base_control import BaseConfigRuleAssessment
|
|
878
|
+
from aws_cis_assessment.core.models import ComplianceResult, ComplianceStatus
|
|
879
|
+
from aws_cis_assessment.core.aws_client_factory import AWSClientFactory
|
|
880
|
+
|
|
881
|
+
logger = logging.getLogger(__name__)
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
class BackupPlanMinFrequencyAndMinRetentionCheckAssessment(BaseConfigRuleAssessment):
|
|
885
|
+
"""Assessment for backup-plan-min-frequency-and-min-retention-check Config rule.
|
|
886
|
+
|
|
887
|
+
Validates that AWS Backup plans have appropriate backup frequency and retention
|
|
888
|
+
policies to ensure data protection and recovery capabilities.
|
|
889
|
+
"""
|
|
890
|
+
|
|
891
|
+
def __init__(self, min_retention_days: int = 7):
|
|
892
|
+
"""Initialize backup plan assessment.
|
|
893
|
+
|
|
894
|
+
Args:
|
|
895
|
+
min_retention_days: Minimum retention period in days (default: 7)
|
|
896
|
+
"""
|
|
897
|
+
super().__init__(
|
|
898
|
+
rule_name="backup-plan-min-frequency-and-min-retention-check",
|
|
899
|
+
control_id="11.2",
|
|
900
|
+
resource_types=["AWS::Backup::BackupPlan"]
|
|
901
|
+
)
|
|
902
|
+
self.min_retention_days = min_retention_days
|
|
903
|
+
|
|
904
|
+
def _get_resources(self, aws_factory: AWSClientFactory,
|
|
905
|
+
resource_type: str, region: str) -> List[Dict[str, Any]]:
|
|
906
|
+
"""Get all AWS Backup plans in the region."""
|
|
907
|
+
if resource_type != "AWS::Backup::BackupPlan":
|
|
908
|
+
return []
|
|
909
|
+
|
|
910
|
+
try:
|
|
911
|
+
backup_client = aws_factory.get_client('backup', region)
|
|
912
|
+
|
|
913
|
+
# List all backup plans
|
|
914
|
+
response = aws_factory.aws_api_call_with_retry(
|
|
915
|
+
lambda: backup_client.list_backup_plans()
|
|
916
|
+
)
|
|
917
|
+
|
|
918
|
+
plans = []
|
|
919
|
+
for plan in response.get('BackupPlansList', []):
|
|
920
|
+
plan_id = plan.get('BackupPlanId')
|
|
921
|
+
plan_name = plan.get('BackupPlanName')
|
|
922
|
+
|
|
923
|
+
try:
|
|
924
|
+
# Get detailed plan information including rules
|
|
925
|
+
plan_details = aws_factory.aws_api_call_with_retry(
|
|
926
|
+
lambda: backup_client.get_backup_plan(BackupPlanId=plan_id)
|
|
927
|
+
)
|
|
928
|
+
|
|
929
|
+
plans.append({
|
|
930
|
+
'BackupPlanId': plan_id,
|
|
931
|
+
'BackupPlanName': plan_name,
|
|
932
|
+
'BackupPlan': plan_details.get('BackupPlan'),
|
|
933
|
+
'BackupPlanArn': plan_details.get('BackupPlanArn'),
|
|
934
|
+
'VersionId': plan.get('VersionId'),
|
|
935
|
+
'CreationDate': plan.get('CreationDate')
|
|
936
|
+
})
|
|
937
|
+
|
|
938
|
+
except ClientError as e:
|
|
939
|
+
logger.warning(f"Could not get details for backup plan {plan_name}: {e}")
|
|
940
|
+
# Include plan with minimal info
|
|
941
|
+
plans.append({
|
|
942
|
+
'BackupPlanId': plan_id,
|
|
943
|
+
'BackupPlanName': plan_name,
|
|
944
|
+
'BackupPlan': None,
|
|
945
|
+
'Error': str(e)
|
|
946
|
+
})
|
|
947
|
+
|
|
948
|
+
logger.info(f"Retrieved {len(plans)} backup plan(s) in region {region}")
|
|
949
|
+
return plans
|
|
950
|
+
|
|
951
|
+
except ClientError as e:
|
|
952
|
+
if e.response.get('Error', {}).get('Code') in ['AccessDenied', 'UnauthorizedOperation']:
|
|
953
|
+
logger.warning(f"Insufficient permissions to list backup plans in region {region}")
|
|
954
|
+
return []
|
|
955
|
+
logger.error(f"Error retrieving backup plans in region {region}: {e}")
|
|
956
|
+
raise
|
|
957
|
+
|
|
958
|
+
def _evaluate_resource_compliance(self, resource: Dict[str, Any],
|
|
959
|
+
aws_factory: AWSClientFactory,
|
|
960
|
+
region: str) -> ComplianceResult:
|
|
961
|
+
"""Evaluate if backup plan has appropriate frequency and retention."""
|
|
962
|
+
plan_id = resource.get('BackupPlanId', 'unknown')
|
|
963
|
+
plan_name = resource.get('BackupPlanName', 'unknown')
|
|
964
|
+
backup_plan = resource.get('BackupPlan')
|
|
965
|
+
|
|
966
|
+
# Check if plan details were retrieved
|
|
967
|
+
if backup_plan is None:
|
|
968
|
+
error_msg = resource.get('Error', 'Unknown error')
|
|
969
|
+
return ComplianceResult(
|
|
970
|
+
resource_id=plan_id,
|
|
971
|
+
resource_type="AWS::Backup::BackupPlan",
|
|
972
|
+
compliance_status=ComplianceStatus.ERROR,
|
|
973
|
+
evaluation_reason=f"Could not retrieve backup plan details: {error_msg}",
|
|
974
|
+
config_rule_name=self.rule_name,
|
|
975
|
+
region=region
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
# Check backup rules
|
|
979
|
+
rules = backup_plan.get('Rules', [])
|
|
980
|
+
|
|
981
|
+
if not rules:
|
|
982
|
+
return ComplianceResult(
|
|
983
|
+
resource_id=plan_id,
|
|
984
|
+
resource_type="AWS::Backup::BackupPlan",
|
|
985
|
+
compliance_status=ComplianceStatus.NON_COMPLIANT,
|
|
986
|
+
evaluation_reason=f"Backup plan '{plan_name}' has no backup rules defined",
|
|
987
|
+
config_rule_name=self.rule_name,
|
|
988
|
+
region=region
|
|
989
|
+
)
|
|
990
|
+
|
|
991
|
+
# Validate each rule
|
|
992
|
+
compliant_rules = 0
|
|
993
|
+
issues = []
|
|
994
|
+
|
|
995
|
+
for rule in rules:
|
|
996
|
+
rule_name = rule.get('RuleName', 'unnamed')
|
|
997
|
+
schedule = rule.get('ScheduleExpression', '')
|
|
998
|
+
lifecycle = rule.get('Lifecycle', {})
|
|
999
|
+
|
|
1000
|
+
# Check schedule expression
|
|
1001
|
+
if not schedule:
|
|
1002
|
+
issues.append(f"Rule '{rule_name}' has no schedule expression")
|
|
1003
|
+
continue
|
|
1004
|
+
|
|
1005
|
+
# Validate schedule format (cron or rate expression)
|
|
1006
|
+
has_valid_schedule = self._validate_schedule_expression(schedule)
|
|
1007
|
+
if not has_valid_schedule:
|
|
1008
|
+
issues.append(f"Rule '{rule_name}' has invalid schedule expression: {schedule}")
|
|
1009
|
+
|
|
1010
|
+
# Check retention period
|
|
1011
|
+
delete_after_days = lifecycle.get('DeleteAfterDays')
|
|
1012
|
+
move_to_cold_storage_after_days = lifecycle.get('MoveToColdStorageAfterDays')
|
|
1013
|
+
|
|
1014
|
+
if delete_after_days is None:
|
|
1015
|
+
issues.append(f"Rule '{rule_name}' has no retention period defined")
|
|
1016
|
+
elif delete_after_days < self.min_retention_days:
|
|
1017
|
+
issues.append(
|
|
1018
|
+
f"Rule '{rule_name}' has insufficient retention "
|
|
1019
|
+
f"({delete_after_days} days, minimum: {self.min_retention_days} days)"
|
|
1020
|
+
)
|
|
1021
|
+
else:
|
|
1022
|
+
# Check cold storage configuration if present
|
|
1023
|
+
if move_to_cold_storage_after_days is not None:
|
|
1024
|
+
if move_to_cold_storage_after_days >= delete_after_days:
|
|
1025
|
+
issues.append(
|
|
1026
|
+
f"Rule '{rule_name}' has invalid lifecycle: "
|
|
1027
|
+
f"cold storage transition ({move_to_cold_storage_after_days} days) "
|
|
1028
|
+
f"must be before deletion ({delete_after_days} days)"
|
|
1029
|
+
)
|
|
1030
|
+
else:
|
|
1031
|
+
# Rule is compliant
|
|
1032
|
+
if has_valid_schedule:
|
|
1033
|
+
compliant_rules += 1
|
|
1034
|
+
else:
|
|
1035
|
+
# No cold storage, just check schedule and retention
|
|
1036
|
+
if has_valid_schedule:
|
|
1037
|
+
compliant_rules += 1
|
|
1038
|
+
|
|
1039
|
+
# Determine overall compliance
|
|
1040
|
+
if compliant_rules == len(rules) and not issues:
|
|
1041
|
+
compliance_status = ComplianceStatus.COMPLIANT
|
|
1042
|
+
evaluation_reason = (
|
|
1043
|
+
f"Backup plan '{plan_name}' has {len(rules)} compliant rule(s) "
|
|
1044
|
+
f"with valid schedules and retention >= {self.min_retention_days} days"
|
|
1045
|
+
)
|
|
1046
|
+
elif compliant_rules > 0:
|
|
1047
|
+
compliance_status = ComplianceStatus.NON_COMPLIANT
|
|
1048
|
+
evaluation_reason = (
|
|
1049
|
+
f"Backup plan '{plan_name}' has {compliant_rules}/{len(rules)} compliant rules. "
|
|
1050
|
+
f"Issues: {'; '.join(issues)}"
|
|
1051
|
+
)
|
|
1052
|
+
else:
|
|
1053
|
+
compliance_status = ComplianceStatus.NON_COMPLIANT
|
|
1054
|
+
evaluation_reason = (
|
|
1055
|
+
f"Backup plan '{plan_name}' has no compliant rules. "
|
|
1056
|
+
f"Issues: {'; '.join(issues)}"
|
|
1057
|
+
)
|
|
1058
|
+
|
|
1059
|
+
return ComplianceResult(
|
|
1060
|
+
resource_id=plan_id,
|
|
1061
|
+
resource_type="AWS::Backup::BackupPlan",
|
|
1062
|
+
compliance_status=compliance_status,
|
|
1063
|
+
evaluation_reason=evaluation_reason,
|
|
1064
|
+
config_rule_name=self.rule_name,
|
|
1065
|
+
region=region
|
|
1066
|
+
)
|
|
1067
|
+
|
|
1068
|
+
def _validate_schedule_expression(self, schedule: str) -> bool:
|
|
1069
|
+
"""Validate AWS Backup schedule expression format."""
|
|
1070
|
+
if not schedule:
|
|
1071
|
+
return False
|
|
1072
|
+
|
|
1073
|
+
schedule_lower = schedule.lower().strip()
|
|
1074
|
+
|
|
1075
|
+
# Check for cron expression
|
|
1076
|
+
if schedule_lower.startswith('cron(') and schedule_lower.endswith(')'):
|
|
1077
|
+
return True
|
|
1078
|
+
|
|
1079
|
+
# Check for rate expression
|
|
1080
|
+
if schedule_lower.startswith('rate(') and schedule_lower.endswith(')'):
|
|
1081
|
+
return True
|
|
1082
|
+
|
|
1083
|
+
return False
|
|
1084
|
+
```
|
|
1085
|
+
|
|
1086
|
+
### Key Implementation Patterns
|
|
1087
|
+
|
|
1088
|
+
1. **Configurable Parameters**: The `min_retention_days` parameter allows customization
|
|
1089
|
+
2. **Comprehensive Error Handling**: Gracefully handles access denied and missing resources
|
|
1090
|
+
3. **Detailed Evaluation**: Provides specific reasons for non-compliance
|
|
1091
|
+
4. **Validation Logic**: Validates schedule expressions and lifecycle policies
|
|
1092
|
+
5. **Logging**: Appropriate logging for troubleshooting
|
|
1093
|
+
|
|
1094
|
+
### Testing Example
|
|
1095
|
+
|
|
1096
|
+
```python
|
|
1097
|
+
# tests/test_aws_backup_service_controls.py
|
|
1098
|
+
import pytest
|
|
1099
|
+
from unittest.mock import Mock
|
|
1100
|
+
from botocore.exceptions import ClientError
|
|
1101
|
+
|
|
1102
|
+
from aws_cis_assessment.controls.ig1.control_aws_backup_service import (
|
|
1103
|
+
BackupPlanMinFrequencyAndMinRetentionCheckAssessment
|
|
1104
|
+
)
|
|
1105
|
+
from aws_cis_assessment.core.models import ComplianceStatus
|
|
1106
|
+
|
|
1107
|
+
class TestBackupPlanMinFrequencyAndMinRetentionCheckAssessment:
|
|
1108
|
+
|
|
1109
|
+
def test_compliant_plan(self):
|
|
1110
|
+
"""Test evaluation of compliant backup plan."""
|
|
1111
|
+
assessment = BackupPlanMinFrequencyAndMinRetentionCheckAssessment()
|
|
1112
|
+
aws_factory = Mock()
|
|
1113
|
+
|
|
1114
|
+
resource = {
|
|
1115
|
+
'BackupPlanId': 'plan-123',
|
|
1116
|
+
'BackupPlanName': 'daily-backup',
|
|
1117
|
+
'BackupPlan': {
|
|
1118
|
+
'Rules': [{
|
|
1119
|
+
'RuleName': 'daily-rule',
|
|
1120
|
+
'ScheduleExpression': 'cron(0 5 * * ? *)',
|
|
1121
|
+
'Lifecycle': {'DeleteAfterDays': 30}
|
|
1122
|
+
}]
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
result = assessment._evaluate_resource_compliance(resource, aws_factory, "us-east-1")
|
|
1127
|
+
|
|
1128
|
+
assert result.compliance_status == ComplianceStatus.COMPLIANT
|
|
1129
|
+
assert 'compliant rule(s)' in result.evaluation_reason
|
|
1130
|
+
assert result.resource_id == 'plan-123'
|
|
1131
|
+
|
|
1132
|
+
def test_plan_insufficient_retention(self):
|
|
1133
|
+
"""Test evaluation of backup plan with insufficient retention."""
|
|
1134
|
+
assessment = BackupPlanMinFrequencyAndMinRetentionCheckAssessment()
|
|
1135
|
+
aws_factory = Mock()
|
|
1136
|
+
|
|
1137
|
+
resource = {
|
|
1138
|
+
'BackupPlanId': 'plan-123',
|
|
1139
|
+
'BackupPlanName': 'short-retention',
|
|
1140
|
+
'BackupPlan': {
|
|
1141
|
+
'Rules': [{
|
|
1142
|
+
'RuleName': 'short-rule',
|
|
1143
|
+
'ScheduleExpression': 'cron(0 5 * * ? *)',
|
|
1144
|
+
'Lifecycle': {'DeleteAfterDays': 3} # Less than minimum 7 days
|
|
1145
|
+
}]
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
result = assessment._evaluate_resource_compliance(resource, aws_factory, "us-east-1")
|
|
1150
|
+
|
|
1151
|
+
assert result.compliance_status == ComplianceStatus.NON_COMPLIANT
|
|
1152
|
+
assert 'insufficient retention' in result.evaluation_reason
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
### Documentation
|
|
1156
|
+
|
|
1157
|
+
For complete documentation on AWS Backup controls, see:
|
|
1158
|
+
- [AWS Backup Controls Implementation Guide](adding-aws-backup-controls.md)
|
|
1159
|
+
- [AWS Backup Controls Summary](../AWS_BACKUP_CONTROLS_IMPLEMENTATION_SUMMARY.md)
|
|
1160
|
+
|
|
1161
|
+
### Benefits of This Approach
|
|
1162
|
+
|
|
1163
|
+
1. **Hybrid Model**: Combines resource-specific and service-level assessments
|
|
1164
|
+
2. **Comprehensive Coverage**: Validates both resource protection and infrastructure security
|
|
1165
|
+
3. **Flexible**: Works for organizations using AWS Backup or service-native backups
|
|
1166
|
+
4. **Extensible**: Easy to add more AWS Backup controls (vault lock, restore testing, etc.)
|
|
1167
|
+
5. **Production-Ready**: Full error handling, logging, and testing
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# Dual Scoring Implementation Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The AWS CIS Assessment tool now provides **two scoring methodologies** in all reports:
|
|
6
|
+
|
|
7
|
+
1. **Weighted Score** (Default) - Risk-based scoring that prioritizes critical security controls
|
|
8
|
+
2. **AWS Config Style Score** - Simple unweighted calculation matching AWS Config Conformance Packs
|
|
9
|
+
|
|
10
|
+
Both scores are calculated automatically and displayed side-by-side in all report formats (JSON, CSV, HTML).
|
|
11
|
+
|
|
12
|
+
## Implementation Details
|
|
13
|
+
|
|
14
|
+
### Architecture
|
|
15
|
+
|
|
16
|
+
The dual scoring system is implemented across multiple components:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
assessment_engine.py
|
|
20
|
+
↓
|
|
21
|
+
scoring_engine.py (calculates both scores)
|
|
22
|
+
↓
|
|
23
|
+
base_reporter.py (includes both in report data)
|
|
24
|
+
↓
|
|
25
|
+
json_reporter.py / html_reporter.py (displays both scores)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Key Components
|
|
29
|
+
|
|
30
|
+
#### 1. Scoring Engine (`aws_cis_assessment/core/scoring_engine.py`)
|
|
31
|
+
|
|
32
|
+
**New Method: `calculate_aws_config_style_score()`**
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
def calculate_aws_config_style_score(self, ig_scores: Dict[str, IGScore]) -> float:
|
|
36
|
+
"""Calculate compliance score using AWS Config Conformance Pack approach.
|
|
37
|
+
|
|
38
|
+
Formula: (Total Compliant Resources) / (Total Resources) × 100
|
|
39
|
+
|
|
40
|
+
This is a simple unweighted calculation where all rules are treated equally.
|
|
41
|
+
"""
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### 2. Assessment Result Model (`aws_cis_assessment/core/models.py`)
|
|
45
|
+
|
|
46
|
+
**Updated Field:**
|
|
47
|
+
```python
|
|
48
|
+
@dataclass
|
|
49
|
+
class AssessmentResult:
|
|
50
|
+
overall_score: float # Weighted score
|
|
51
|
+
aws_config_score: float = 0.0 # AWS Config style score
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### 3. Base Reporter (`aws_cis_assessment/reporters/base_reporter.py`)
|
|
55
|
+
|
|
56
|
+
**Enhanced Executive Summary:**
|
|
57
|
+
```python
|
|
58
|
+
'executive_summary': {
|
|
59
|
+
'overall_compliance_percentage': compliance_summary.overall_compliance_percentage,
|
|
60
|
+
'aws_config_style_score': assessment_result.aws_config_score,
|
|
61
|
+
'score_difference': compliance_summary.overall_compliance_percentage - assessment_result.aws_config_score,
|
|
62
|
+
# ... other fields
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
#### 4. HTML Reporter (`aws_cis_assessment/reporters/html_reporter.py`)
|
|
67
|
+
|
|
68
|
+
**New Features:**
|
|
69
|
+
- Score comparison section in executive dashboard
|
|
70
|
+
- Visual comparison cards showing both methodologies
|
|
71
|
+
- Difference indicator with interpretation
|
|
72
|
+
- CSS styles for score comparison UI
|
|
73
|
+
- JavaScript toggle function for methodology details
|
|
74
|
+
|
|
75
|
+
**New Method: `_generate_score_comparison_section()`**
|
|
76
|
+
|
|
77
|
+
Generates a comprehensive comparison showing:
|
|
78
|
+
- Both scores side-by-side
|
|
79
|
+
- Key features of each methodology
|
|
80
|
+
- Score difference with interpretation
|
|
81
|
+
- Guidance on when to use each score
|
|
82
|
+
|
|
83
|
+
## Report Output
|
|
84
|
+
|
|
85
|
+
### JSON Report
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"assessment_result": {
|
|
90
|
+
"overall_score": 65.5,
|
|
91
|
+
"aws_config_score": 65.0
|
|
92
|
+
},
|
|
93
|
+
"compliance_summary": {
|
|
94
|
+
"overall_compliance_percentage": 65.5
|
|
95
|
+
},
|
|
96
|
+
"executive_summary": {
|
|
97
|
+
"overall_compliance_percentage": 65.5,
|
|
98
|
+
"aws_config_style_score": 65.0,
|
|
99
|
+
"score_difference": 0.5
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### CSV Report
|
|
105
|
+
|
|
106
|
+
The summary CSV includes both scores:
|
|
107
|
+
```csv
|
|
108
|
+
Metric,Value
|
|
109
|
+
Overall Compliance (Weighted),65.5%
|
|
110
|
+
AWS Config Style Score,65.0%
|
|
111
|
+
Score Difference,+0.5%
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### HTML Report
|
|
115
|
+
|
|
116
|
+
The HTML report includes:
|
|
117
|
+
|
|
118
|
+
1. **Metric Cards** - Both scores displayed prominently in the dashboard
|
|
119
|
+
2. **Score Comparison Section** - Detailed side-by-side comparison
|
|
120
|
+
3. **Visual Indicators** - Color-coded difference interpretation
|
|
121
|
+
4. **Methodology Notes** - Guidance on when to use each score
|
|
122
|
+
|
|
123
|
+
## Score Interpretation
|
|
124
|
+
|
|
125
|
+
### When Scores Differ
|
|
126
|
+
|
|
127
|
+
The difference between the two scores provides valuable insights:
|
|
128
|
+
|
|
129
|
+
#### Weighted Score Higher (Positive Difference)
|
|
130
|
+
```
|
|
131
|
+
Weighted: 70.0%
|
|
132
|
+
AWS Config: 65.0%
|
|
133
|
+
Difference: +5.0%
|
|
134
|
+
```
|
|
135
|
+
**Interpretation:** Strong performance in critical security controls despite some gaps in less critical areas. Your most important security measures are in good shape.
|
|
136
|
+
|
|
137
|
+
#### Weighted Score Lower (Negative Difference)
|
|
138
|
+
```
|
|
139
|
+
Weighted: 60.0%
|
|
140
|
+
AWS Config: 65.0%
|
|
141
|
+
Difference: -5.0%
|
|
142
|
+
```
|
|
143
|
+
**Interpretation:** Critical security controls need attention despite good overall resource compliance. Focus remediation on high-priority controls.
|
|
144
|
+
|
|
145
|
+
#### Scores Similar (< 1% Difference)
|
|
146
|
+
```
|
|
147
|
+
Weighted: 65.5%
|
|
148
|
+
AWS Config: 65.2%
|
|
149
|
+
Difference: +0.3%
|
|
150
|
+
```
|
|
151
|
+
**Interpretation:** Balanced compliance across all control priorities. Both methodologies show similar results.
|
|
152
|
+
|
|
153
|
+
## Usage Recommendations
|
|
154
|
+
|
|
155
|
+
### Use Weighted Score For:
|
|
156
|
+
- **Security Decision-Making** - Prioritize remediation based on risk
|
|
157
|
+
- **Risk Assessment** - Understand actual security posture
|
|
158
|
+
- **Resource Allocation** - Focus efforts on critical controls
|
|
159
|
+
- **Executive Reporting** - Show security program effectiveness
|
|
160
|
+
|
|
161
|
+
### Use AWS Config Style Score For:
|
|
162
|
+
- **Compliance Audits** - Simple, auditable metric
|
|
163
|
+
- **Stakeholder Communication** - Easy to understand percentage
|
|
164
|
+
- **Trend Tracking** - Consistent with AWS Config reports
|
|
165
|
+
- **Regulatory Reporting** - Straightforward compliance metric
|
|
166
|
+
|
|
167
|
+
### Track Both For:
|
|
168
|
+
- **Comprehensive Security Program** - Full visibility into compliance
|
|
169
|
+
- **Balanced Perspective** - Understand both resource and risk views
|
|
170
|
+
- **Continuous Improvement** - Monitor progress from multiple angles
|
|
171
|
+
|
|
172
|
+
## API Usage
|
|
173
|
+
|
|
174
|
+
### Accessing Scores Programmatically
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
from aws_cis_assessment.core.assessment_engine import AssessmentEngine
|
|
178
|
+
|
|
179
|
+
# Run assessment
|
|
180
|
+
engine = AssessmentEngine(regions=['us-east-1'])
|
|
181
|
+
result = engine.run_assessment(['IG1', 'IG2', 'IG3'])
|
|
182
|
+
|
|
183
|
+
# Access both scores
|
|
184
|
+
weighted_score = result.overall_score
|
|
185
|
+
aws_config_score = result.aws_config_score
|
|
186
|
+
difference = weighted_score - aws_config_score
|
|
187
|
+
|
|
188
|
+
print(f"Weighted Score: {weighted_score:.1f}%")
|
|
189
|
+
print(f"AWS Config Score: {aws_config_score:.1f}%")
|
|
190
|
+
print(f"Difference: {difference:+.1f}%")
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Generating Reports with Both Scores
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
from aws_cis_assessment.reporters.html_reporter import HTMLReporter
|
|
197
|
+
from aws_cis_assessment.reporters.json_reporter import JSONReporter
|
|
198
|
+
|
|
199
|
+
# Both reporters automatically include both scores
|
|
200
|
+
html_reporter = HTMLReporter()
|
|
201
|
+
html_content = html_reporter.generate_report(result, summary)
|
|
202
|
+
|
|
203
|
+
json_reporter = JSONReporter()
|
|
204
|
+
json_content = json_reporter.generate_report(result, summary)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Testing
|
|
208
|
+
|
|
209
|
+
The dual scoring implementation includes comprehensive tests:
|
|
210
|
+
|
|
211
|
+
- **Unit Tests** - Scoring engine calculations
|
|
212
|
+
- **Integration Tests** - End-to-end report generation
|
|
213
|
+
- **Property Tests** - Score consistency and accuracy
|
|
214
|
+
- **Real Data Tests** - Validation with actual assessment data
|
|
215
|
+
|
|
216
|
+
Run tests:
|
|
217
|
+
```bash
|
|
218
|
+
pytest tests/test_html_reporter*.py -v
|
|
219
|
+
pytest tests/test_json_reporter*.py -v
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Migration Notes
|
|
223
|
+
|
|
224
|
+
### Backward Compatibility
|
|
225
|
+
|
|
226
|
+
The implementation is **fully backward compatible**:
|
|
227
|
+
|
|
228
|
+
- Existing reports continue to work
|
|
229
|
+
- No breaking changes to APIs
|
|
230
|
+
- All existing tests pass
|
|
231
|
+
- Legacy data structures supported
|
|
232
|
+
|
|
233
|
+
### Upgrading from Previous Versions
|
|
234
|
+
|
|
235
|
+
No action required! The dual scoring is automatically enabled:
|
|
236
|
+
|
|
237
|
+
1. Update to version 1.0.8+
|
|
238
|
+
2. Run assessments as usual
|
|
239
|
+
3. Both scores appear in all reports
|
|
240
|
+
|
|
241
|
+
## Technical Details
|
|
242
|
+
|
|
243
|
+
### Calculation Formulas
|
|
244
|
+
|
|
245
|
+
**Weighted Score:**
|
|
246
|
+
```
|
|
247
|
+
Score = Σ(IG_Weight × IG_Score) / Σ(IG_Weight)
|
|
248
|
+
|
|
249
|
+
Where:
|
|
250
|
+
- IG_Weight: 1.0 (IG1), 1.5 (IG2), 2.0 (IG3)
|
|
251
|
+
- IG_Score: Weighted average of control scores within IG
|
|
252
|
+
- Control weights: 1.0-1.5 based on criticality
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**AWS Config Style Score:**
|
|
256
|
+
```
|
|
257
|
+
Score = (Total Compliant Resources) / (Total Resources) × 100
|
|
258
|
+
|
|
259
|
+
Where:
|
|
260
|
+
- All resources weighted equally
|
|
261
|
+
- All controls weighted equally
|
|
262
|
+
- Simple percentage calculation
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Performance Impact
|
|
266
|
+
|
|
267
|
+
The dual scoring implementation has **minimal performance impact**:
|
|
268
|
+
|
|
269
|
+
- Additional calculation time: < 10ms
|
|
270
|
+
- Memory overhead: < 1KB per assessment
|
|
271
|
+
- No impact on AWS API calls
|
|
272
|
+
- Parallel calculation with existing scoring
|
|
273
|
+
|
|
274
|
+
## Future Enhancements
|
|
275
|
+
|
|
276
|
+
Potential future improvements:
|
|
277
|
+
|
|
278
|
+
1. **Custom Weighting** - Allow users to define custom control weights
|
|
279
|
+
2. **Historical Tracking** - Track both scores over time
|
|
280
|
+
3. **Comparative Analysis** - Compare scores across accounts/regions
|
|
281
|
+
4. **Score Predictions** - Estimate impact of remediation on both scores
|
|
282
|
+
5. **Export Options** - Additional export formats with both scores
|
|
283
|
+
|
|
284
|
+
## References
|
|
285
|
+
|
|
286
|
+
- [Scoring Methodology](scoring-methodology.md) - Detailed weighted scoring explanation
|
|
287
|
+
- [AWS Config Comparison](scoring-comparison-aws-config.md) - Comparison with AWS Config approach
|
|
288
|
+
- [User Guide](user-guide.md) - General usage instructions
|
|
289
|
+
- [API Documentation](developer-guide.md) - Developer reference
|
|
290
|
+
|
|
291
|
+
## Support
|
|
292
|
+
|
|
293
|
+
For questions or issues related to dual scoring:
|
|
294
|
+
|
|
295
|
+
1. Check the [Troubleshooting Guide](troubleshooting.md)
|
|
296
|
+
2. Review [GitHub Issues](https://github.com/your-repo/issues)
|
|
297
|
+
3. Contact the development team
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
**Version:** 1.0.8+
|
|
302
|
+
**Last Updated:** January 27, 2026
|
|
303
|
+
**Status:** Production Ready
|
docs/installation.md
CHANGED
|
@@ -7,7 +7,7 @@ This guide covers the installation and initial setup of the AWS CIS Controls Com
|
|
|
7
7
|
## Production Status
|
|
8
8
|
|
|
9
9
|
**✅ Ready for Enterprise Deployment**
|
|
10
|
-
- Complete implementation with
|
|
10
|
+
- Complete implementation with 138 AWS Config rules (133 CIS Controls + 5 bonus)
|
|
11
11
|
- 100% CIS Controls coverage across all Implementation Groups
|
|
12
12
|
- Production-tested architecture with comprehensive error handling
|
|
13
13
|
- Enterprise-grade performance and scalability
|
|
@@ -104,7 +104,7 @@ aws-cis-assess assess --aws-profile my-sso-profile
|
|
|
104
104
|
|
|
105
105
|
## Required IAM Permissions
|
|
106
106
|
|
|
107
|
-
The tool requires read-only permissions for various AWS services. Here's a comprehensive IAM policy that covers all
|
|
107
|
+
The tool requires read-only permissions for various AWS services. Here's a comprehensive IAM policy that covers all 138 assessments:
|
|
108
108
|
|
|
109
109
|
```json
|
|
110
110
|
{
|