aws-cis-controls-assessment 1.0.9__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. aws_cis_assessment/__init__.py +2 -2
  2. aws_cis_assessment/config/rules/cis_controls_ig1.yaml +94 -1
  3. aws_cis_assessment/config/rules/cis_controls_ig2.yaml +680 -1
  4. aws_cis_assessment/controls/ig1/__init__.py +17 -0
  5. aws_cis_assessment/controls/ig1/control_aws_backup_service.py +1276 -0
  6. aws_cis_assessment/controls/ig2/__init__.py +74 -1
  7. aws_cis_assessment/controls/ig2/control_4_5_6_access_configuration.py +2638 -0
  8. aws_cis_assessment/controls/ig2/control_8_audit_logging.py +984 -0
  9. aws_cis_assessment/controls/ig2/control_aws_backup_ig2.py +23 -0
  10. aws_cis_assessment/core/assessment_engine.py +74 -0
  11. aws_cis_assessment/reporters/html_reporter.py +197 -35
  12. {aws_cis_controls_assessment-1.0.9.dist-info → aws_cis_controls_assessment-1.1.0.dist-info}/METADATA +163 -12
  13. {aws_cis_controls_assessment-1.0.9.dist-info → aws_cis_controls_assessment-1.1.0.dist-info}/RECORD +26 -21
  14. docs/README.md +14 -3
  15. docs/adding-aws-backup-controls.md +562 -0
  16. docs/assessment-logic.md +291 -3
  17. docs/cli-reference.md +1 -1
  18. docs/config-rule-mappings.md +465 -7
  19. docs/developer-guide.md +312 -3
  20. docs/installation.md +2 -2
  21. docs/troubleshooting.md +211 -2
  22. docs/user-guide.md +47 -2
  23. {aws_cis_controls_assessment-1.0.9.dist-info → aws_cis_controls_assessment-1.1.0.dist-info}/WHEEL +0 -0
  24. {aws_cis_controls_assessment-1.0.9.dist-info → aws_cis_controls_assessment-1.1.0.dist-info}/entry_points.txt +0 -0
  25. {aws_cis_controls_assessment-1.0.9.dist-info → aws_cis_controls_assessment-1.1.0.dist-info}/licenses/LICENSE +0 -0
  26. {aws_cis_controls_assessment-1.0.9.dist-info → aws_cis_controls_assessment-1.1.0.dist-info}/top_level.txt +0 -0
docs/assessment-logic.md CHANGED
@@ -5,7 +5,7 @@ This document provides detailed information about the assessment logic used by t
5
5
  ## Production Framework Overview
6
6
 
7
7
  **✅ Complete Implementation Status**
8
- - 136 AWS Config rules implemented (131 CIS Controls + 5 bonus)
8
+ - 138 AWS Config rules implemented (133 CIS Controls + 5 bonus)
9
9
  - 100% coverage across all Implementation Groups (IG1, IG2, IG3)
10
10
  - Production-tested with enterprise-grade error handling
11
11
  - Optimized for large-scale enterprise deployments
@@ -25,7 +25,7 @@ This document provides detailed information about the assessment logic used by t
25
25
 
26
26
  The assessment tool evaluates AWS account configurations against CIS Controls using the same logic as AWS Config rules, but without requiring AWS Config to be enabled. Each assessment follows a standardized process while implementing control-specific evaluation logic.
27
27
 
28
- **Framework Scope**: 136 implemented rules covering all CIS Controls requirements plus 5 bonus security enhancements for additional value.
28
+ **Framework Scope**: 138 implemented rules covering all CIS Controls requirements plus 5 bonus security enhancements for additional value.
29
29
 
30
30
  ### Key Principles
31
31
 
@@ -763,4 +763,292 @@ def batch_evaluate_resources(self, resources, batch_size=50):
763
763
  return results
764
764
  ```
765
765
 
766
- This comprehensive assessment logic ensures accurate, efficient, and reliable evaluation of AWS resources against CIS Controls while maintaining compatibility with AWS Config rule specifications.
766
+ This comprehensive assessment logic ensures accurate, efficient, and reliable evaluation of AWS resources against CIS Controls while maintaining compatibility with AWS Config rule specifications.
767
+
768
+
769
+ ### AWS Backup Resources
770
+ ```python
771
+ def discover_backup_plans(self, backup_client, region):
772
+ """Discover AWS Backup plans in specific region."""
773
+ try:
774
+ paginator = backup_client.get_paginator('list_backup_plans')
775
+
776
+ backup_plans = []
777
+ for page in paginator.paginate():
778
+ for plan in page['BackupPlansList']:
779
+ try:
780
+ # Get detailed plan information
781
+ plan_details = backup_client.get_backup_plan(
782
+ BackupPlanId=plan['BackupPlanId']
783
+ )
784
+
785
+ backup_plans.append({
786
+ 'BackupPlanId': plan['BackupPlanId'],
787
+ 'BackupPlanName': plan['BackupPlanName'],
788
+ 'BackupPlanArn': plan['BackupPlanArn'],
789
+ 'CreationDate': plan['CreationDate'],
790
+ 'VersionId': plan['VersionId'],
791
+ 'Rules': plan_details['BackupPlan'].get('Rules', []),
792
+ 'Region': region
793
+ })
794
+
795
+ except ClientError as e:
796
+ # Skip plans we can't access
797
+ if e.response['Error']['Code'] in ['AccessDenied', 'ResourceNotFoundException']:
798
+ continue
799
+ raise
800
+
801
+ return backup_plans
802
+
803
+ except ClientError as e:
804
+ if e.response['Error']['Code'] == 'AccessDenied':
805
+ self.logger.warning(f"Insufficient permissions for Backup in {region}")
806
+ return []
807
+ raise
808
+
809
+ def discover_backup_vaults(self, backup_client, region):
810
+ """Discover AWS Backup vaults in specific region."""
811
+ try:
812
+ paginator = backup_client.get_paginator('list_backup_vaults')
813
+
814
+ backup_vaults = []
815
+ for page in paginator.paginate():
816
+ for vault in page['BackupVaultList']:
817
+ try:
818
+ # Get vault access policy if exists
819
+ try:
820
+ policy_response = backup_client.get_backup_vault_access_policy(
821
+ BackupVaultName=vault['BackupVaultName']
822
+ )
823
+ vault['Policy'] = policy_response.get('Policy')
824
+ except ClientError as e:
825
+ if e.response['Error']['Code'] == 'ResourceNotFoundException':
826
+ vault['Policy'] = None
827
+ else:
828
+ raise
829
+
830
+ backup_vaults.append({
831
+ 'BackupVaultName': vault['BackupVaultName'],
832
+ 'BackupVaultArn': vault['BackupVaultArn'],
833
+ 'CreationDate': vault['CreationDate'],
834
+ 'EncryptionKeyArn': vault.get('EncryptionKeyArn'),
835
+ 'NumberOfRecoveryPoints': vault.get('NumberOfRecoveryPoints', 0),
836
+ 'Policy': vault.get('Policy'),
837
+ 'Region': region
838
+ })
839
+
840
+ except ClientError as e:
841
+ if e.response['Error']['Code'] in ['AccessDenied', 'ResourceNotFoundException']:
842
+ continue
843
+ raise
844
+
845
+ return backup_vaults
846
+
847
+ except ClientError as e:
848
+ if e.response['Error']['Code'] == 'AccessDenied':
849
+ self.logger.warning(f"Insufficient permissions for Backup vaults in {region}")
850
+ return []
851
+ raise
852
+ ```
853
+
854
+ ## AWS Backup Controls Logic
855
+
856
+ ### Backup Plan Frequency and Retention Check
857
+
858
+ Evaluates backup plans to ensure they meet minimum frequency and retention requirements:
859
+
860
+ ```python
861
+ def evaluate_backup_plan_compliance(self, resource, aws_factory):
862
+ """Evaluate backup plan frequency and retention requirements."""
863
+ backup_plan_id = resource['BackupPlanId']
864
+ backup_plan_name = resource['BackupPlanName']
865
+ rules = resource.get('Rules', [])
866
+ region = resource['Region']
867
+
868
+ if not rules:
869
+ return ComplianceResult(
870
+ resource_id=backup_plan_id,
871
+ resource_type="AWS::Backup::BackupPlan",
872
+ compliance_status="NON_COMPLIANT",
873
+ evaluation_reason="Backup plan has no rules defined",
874
+ config_rule_name="backup-plan-min-frequency-and-min-retention-check",
875
+ region=region,
876
+ timestamp=datetime.now(),
877
+ remediation_guidance="Add backup rules with appropriate frequency and retention"
878
+ )
879
+
880
+ # Check each rule for compliance
881
+ non_compliant_rules = []
882
+
883
+ for rule in rules:
884
+ rule_name = rule.get('RuleName', 'Unnamed')
885
+
886
+ # Check frequency (schedule expression)
887
+ schedule = rule.get('ScheduleExpression', '')
888
+ if not self._meets_frequency_requirement(schedule):
889
+ non_compliant_rules.append(
890
+ f"{rule_name}: frequency does not meet minimum (daily)"
891
+ )
892
+
893
+ # Check retention (minimum 35 days / 5 weeks)
894
+ lifecycle = rule.get('Lifecycle', {})
895
+ delete_after_days = lifecycle.get('DeleteAfterDays')
896
+
897
+ if delete_after_days is None or delete_after_days < 35:
898
+ non_compliant_rules.append(
899
+ f"{rule_name}: retention {delete_after_days} days is less than minimum (35 days)"
900
+ )
901
+
902
+ if non_compliant_rules:
903
+ return ComplianceResult(
904
+ resource_id=backup_plan_id,
905
+ resource_type="AWS::Backup::BackupPlan",
906
+ compliance_status="NON_COMPLIANT",
907
+ evaluation_reason=f"Backup plan rules do not meet requirements: {'; '.join(non_compliant_rules)}",
908
+ config_rule_name="backup-plan-min-frequency-and-min-retention-check",
909
+ region=region,
910
+ timestamp=datetime.now(),
911
+ remediation_guidance="Update backup plan rules to meet minimum frequency (daily) and retention (35 days)"
912
+ )
913
+
914
+ return ComplianceResult(
915
+ resource_id=backup_plan_id,
916
+ resource_type="AWS::Backup::BackupPlan",
917
+ compliance_status="COMPLIANT",
918
+ evaluation_reason="Backup plan meets frequency and retention requirements",
919
+ config_rule_name="backup-plan-min-frequency-and-min-retention-check",
920
+ region=region,
921
+ timestamp=datetime.now()
922
+ )
923
+
924
+ def _meets_frequency_requirement(self, schedule_expression):
925
+ """Check if schedule expression meets minimum daily frequency."""
926
+ if not schedule_expression:
927
+ return False
928
+
929
+ # Check for rate expressions (e.g., "rate(1 day)")
930
+ if schedule_expression.startswith('rate('):
931
+ # Extract number and unit
932
+ match = re.match(r'rate\((\d+)\s+(hour|day|week)\)', schedule_expression)
933
+ if match:
934
+ value = int(match.group(1))
935
+ unit = match.group(2)
936
+
937
+ # Convert to hours for comparison
938
+ if unit == 'hour':
939
+ hours = value
940
+ elif unit == 'day':
941
+ hours = value * 24
942
+ elif unit == 'week':
943
+ hours = value * 24 * 7
944
+
945
+ # Must be at least daily (24 hours or less)
946
+ return hours <= 24
947
+
948
+ # Check for cron expressions (e.g., "cron(0 0 * * ? *)")
949
+ elif schedule_expression.startswith('cron('):
950
+ # Daily or more frequent cron patterns
951
+ # This is a simplified check - full cron parsing would be more complex
952
+ return True # Assume cron expressions are configured appropriately
953
+
954
+ return False
955
+ ```
956
+
957
+ ### Backup Vault Access Policy Check
958
+
959
+ Evaluates backup vault access policies to ensure they don't allow overly permissive access:
960
+
961
+ ```python
962
+ def evaluate_backup_vault_policy(self, resource, aws_factory):
963
+ """Evaluate backup vault access policy for security."""
964
+ vault_name = resource['BackupVaultName']
965
+ vault_arn = resource['BackupVaultArn']
966
+ policy = resource.get('Policy')
967
+ region = resource['Region']
968
+
969
+ # If no policy, vault is secure by default
970
+ if not policy:
971
+ return ComplianceResult(
972
+ resource_id=vault_arn,
973
+ resource_type="AWS::Backup::BackupVault",
974
+ compliance_status="COMPLIANT",
975
+ evaluation_reason="Backup vault has no access policy (secure by default)",
976
+ config_rule_name="backup-vault-access-policy-check",
977
+ region=region,
978
+ timestamp=datetime.now()
979
+ )
980
+
981
+ try:
982
+ # Parse policy JSON
983
+ policy_doc = json.loads(policy) if isinstance(policy, str) else policy
984
+
985
+ # Check for overly permissive principals
986
+ security_issues = []
987
+
988
+ for statement in policy_doc.get('Statement', []):
989
+ principal = statement.get('Principal', {})
990
+ effect = statement.get('Effect', '')
991
+
992
+ # Check for wildcard principals with Allow effect
993
+ if effect == 'Allow':
994
+ if principal == '*' or principal == {'AWS': '*'}:
995
+ security_issues.append("Policy allows access from any principal (*)")
996
+
997
+ # Check for overly broad actions
998
+ actions = statement.get('Action', [])
999
+ if isinstance(actions, str):
1000
+ actions = [actions]
1001
+
1002
+ if 'backup:*' in actions or '*' in actions:
1003
+ security_issues.append("Policy allows all backup actions (*)")
1004
+
1005
+ if security_issues:
1006
+ return ComplianceResult(
1007
+ resource_id=vault_arn,
1008
+ resource_type="AWS::Backup::BackupVault",
1009
+ compliance_status="NON_COMPLIANT",
1010
+ evaluation_reason=f"Backup vault policy has security issues: {'; '.join(security_issues)}",
1011
+ config_rule_name="backup-vault-access-policy-check",
1012
+ region=region,
1013
+ timestamp=datetime.now(),
1014
+ remediation_guidance="Update vault policy to restrict access to specific principals and actions"
1015
+ )
1016
+
1017
+ return ComplianceResult(
1018
+ resource_id=vault_arn,
1019
+ resource_type="AWS::Backup::BackupVault",
1020
+ compliance_status="COMPLIANT",
1021
+ evaluation_reason="Backup vault policy follows security best practices",
1022
+ config_rule_name="backup-vault-access-policy-check",
1023
+ region=region,
1024
+ timestamp=datetime.now()
1025
+ )
1026
+
1027
+ except (json.JSONDecodeError, KeyError) as e:
1028
+ return ComplianceResult(
1029
+ resource_id=vault_arn,
1030
+ resource_type="AWS::Backup::BackupVault",
1031
+ compliance_status="ERROR",
1032
+ evaluation_reason=f"Failed to parse vault policy: {str(e)}",
1033
+ config_rule_name="backup-vault-access-policy-check",
1034
+ region=region,
1035
+ timestamp=datetime.now(),
1036
+ remediation_guidance="Verify vault policy is valid JSON"
1037
+ )
1038
+ ```
1039
+
1040
+ ### Backup Controls Integration
1041
+
1042
+ The AWS Backup service-level controls complement the existing resource-specific backup controls:
1043
+
1044
+ **Resource-Specific Controls** (existing):
1045
+ - `backup-recovery-point-encrypted`: Validates individual recovery points are encrypted
1046
+ - `backup-recovery-point-minimum-retention-check`: Checks retention of recovery points
1047
+ - `backup-recovery-point-manual-deletion-disabled`: Ensures manual deletion is disabled
1048
+ - And 9 other resource-specific backup controls
1049
+
1050
+ **Service-Level Controls** (new):
1051
+ - `backup-plan-min-frequency-and-min-retention-check`: Validates backup plan policies
1052
+ - `backup-vault-access-policy-check`: Checks backup vault security
1053
+
1054
+ This hybrid approach provides comprehensive backup coverage at both the service configuration level and individual resource level.
docs/cli-reference.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # CLI Reference
2
2
 
3
- Complete command-line interface reference for the AWS CIS Controls Compliance Assessment Framework - a production-ready enterprise solution with 136 implemented rules (131 CIS Controls + 5 bonus security enhancements).
3
+ Complete command-line interface reference for the AWS CIS Controls Compliance Assessment Framework - a production-ready enterprise solution with 149 implemented rules (133 CIS Controls + 9 bonus security enhancements + 7 audit logging controls).
4
4
 
5
5
  ## Table of Contents
6
6