Initial commit
This commit is contained in:
commit
5db67720fd
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.vscode
|
||||||
|
__pycache__
|
||||||
|
venv
|
||||||
|
env
|
||||||
|
|
||||||
|
bp.json
|
628
bp-base.json
Normal file
628
bp-base.json
Normal file
@ -0,0 +1,628 @@
|
|||||||
|
{
|
||||||
|
"ALB": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"alb-http-drop-invalid-header-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"alb-waf-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"elb-cross-zone-load-balancing-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"elb-deletion-protection-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"elb-logging-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"API GW": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"api-gwv2-access-logs-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"api-gwv2-authorization-type-configured": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"api-gw-associated-with-waf": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"api-gw-cache-enabled-and-encrypted": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"api-gw-execution-logging-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"api-gw-xray-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"RDS": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"aurora-last-backup-recovery-point-created": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"aurora-mysql-backtracking-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"db-instance-backup-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"rds-cluster-auto-minor-version-upgrade-enable": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"rds-cluster-default-admin-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"rds-cluster-deletion-protection-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"rds-cluster-encrypted-at-rest": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"rds-cluster-iam-authentication-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"rds-cluster-multi-az-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"rds-db-security-group-not-allowed": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"rds-enhanced-monitoring-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"rds-instance-deletion-protection-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"rds-instance-public-access-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"rds-logging-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"rds-snapshot-encrypted": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ASG": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"autoscaling-group-elb-healthcheck-required": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"autoscaling-multiple-az": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"EC2": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"autoscaling-launch-template": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ec2-ebs-encryption-by-default": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ec2-imdsv2-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ec2-instance-detailed-monitoring-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ec2-instance-managed-by-systems-manager": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ec2-instance-profile-attached": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ec2-no-amazon-key-pair": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"ec2-stopped-instance": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ec2-token-hop-limit-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"CloudFront": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"cloudfront-accesslogs-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"cloudfront-associated-with-waf": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"cloudfront-default-root-object-configured": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"cloudfront-no-deprecated-ssl-protocols": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"cloudfront-s3-origin-access-control-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"cloudfront-viewer-policy-https": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"KMS": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"cmk-backing-key-rotation-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"CodeSeries": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"codebuild-project-environment-privileged-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"codebuild-project-logging-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"codedeploy-auto-rollback-monitor-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"CloudWatch": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"cw-loggroup-retention-period-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"cloudwatch-alarm-settings-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DocDB": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"docdb-cluster-audit-logging-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"docdb-cluster-backup-retention-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"docdb-cluster-deletion-protection-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"docdb-cluster-encrypted": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DynamoDB": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"dynamodb-autoscaling-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"dynamodb-last-backup-recovery-point-created": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"dynamodb-pitr-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"dynamodb-table-deletion-protection-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"dynamodb-table-encrypted-kms": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"dynamodb-table-encryption-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ECR": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"ecr-private-image-scanning-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ecr-private-lifecycle-policy-configured": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ecr-private-tag-immutability-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ecr-kms-encryption-1": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ECS": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"ecs-awsvpc-networking-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ecs-containers-nonprivileged": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ecs-containers-readonly-access": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ecs-container-insights-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ecs-fargate-latest-platform-version": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ecs-task-definition-log-configuration": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"ecs-task-definition-memory-hard-limit": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"ecs-task-definition-nonroot-user": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"EFS": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"efs-access-point-enforce-root-directory": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"efs-access-point-enforce-user-identity": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"efs-automatic-backups-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"efs-encrypted-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"efs-mount-target-public-accessible": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"EKS": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"eks-cluster-logging-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"eks-cluster-secrets-encrypted": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"eks-endpoint-no-public-access": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"eks-secrets-encrypted": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ElastiCache": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"elasticache-auto-minor-version-upgrade-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"elasticache-redis-cluster-automatic-backup-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"elasticache-repl-grp-auto-failover-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"elasticache-repl-grp-encrypted-at-rest": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"elasticache-repl-grp-encrypted-in-transit": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"elasticache-subnet-group-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IAM": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"iam-policy-no-statements-with-admin-access": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"iam-policy-no-statements-with-full-access": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"iam-role-managed-policy-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Lambda": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"lambda-dlq-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"lambda-function-public-access-prohibited": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"lambda-function-settings-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"lambda-inside-vpc": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Tags": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"required-tags": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Route53": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"route53-query-logging-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"S3": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"s3-access-point-in-vpc-only": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"s3-bucket-default-lock-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"s3-bucket-level-public-access-prohibited": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"s3-bucket-logging-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"s3-bucket-ssl-requests-only": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"s3-bucket-versioning-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"s3-default-encryption-kms": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"s3-event-notifications-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"s3-last-backup-recovery-point-created": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"s3-lifecycle-policy-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Secrets Manager": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"secretsmanager-rotation-enabled-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"secretsmanager-scheduled-rotation-success-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"secretsmanager-secret-periodic-rotation": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Security Hub": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"securityhub-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SNS": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"sns-encrypted-kms": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"sns-topic-message-delivery-notification-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"VPC": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"ec2-transit-gateway-auto-vpc-attach-disabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"restricted-ssh": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"restricted-common-ports": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"subnet-auto-assign-public-ip-disabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 1
|
||||||
|
},
|
||||||
|
"vpc-default-security-group-closed": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"vpc-flow-logs-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"vpc-network-acl-unused-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"vpc-peering-dns-resolution-check": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"vpc-sg-open-only-to-authorized-ports": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"WAFv2": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"wafv2-logging-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"wafv2-rulegroup-logging-enabled": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"wafv2-rulegroup-not-empty": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
},
|
||||||
|
"wafv2-webacl-not-empty": {
|
||||||
|
"enabled": true,
|
||||||
|
"level": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
93
main.py
Normal file
93
main.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import json
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
from PyInquirer import prompt, style_from_dict, Token
|
||||||
|
from colorama import Style, Fore
|
||||||
|
|
||||||
|
from utils import *
|
||||||
|
import services
|
||||||
|
|
||||||
|
custom_style_2 = style_from_dict(
|
||||||
|
{
|
||||||
|
Token.Separator: "#6C6C6C",
|
||||||
|
Token.QuestionMark: "#FF9D00 bold",
|
||||||
|
# Token.Selected: '', # default
|
||||||
|
Token.Selected: "#5F819D",
|
||||||
|
Token.Pointer: "#FF9D00 bold",
|
||||||
|
Token.Instruction: "", # default
|
||||||
|
Token.Answer: "#5F819D bold",
|
||||||
|
Token.Question: "",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ask_services_to_enable(bp):
|
||||||
|
cli_questions = [
|
||||||
|
{
|
||||||
|
"type": "checkbox",
|
||||||
|
"message": "Select AWS Services to inspect",
|
||||||
|
"name": "services",
|
||||||
|
"choices": [
|
||||||
|
{"name": k, "checked": bool(v["enabled"])} for k, v in bp.items()
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
answers = prompt(questions=cli_questions, style=custom_style_2)
|
||||||
|
for service in bp.keys():
|
||||||
|
bp[service]["enabled"] = service in answers["services"]
|
||||||
|
return bp
|
||||||
|
|
||||||
|
|
||||||
|
def perform_bp_rules_check(bp):
|
||||||
|
for service_name, service in bp.items():
|
||||||
|
if not service["enabled"]:
|
||||||
|
continue
|
||||||
|
if service_name == "Lambda":
|
||||||
|
service_name = "_lambda"
|
||||||
|
|
||||||
|
module = getattr(services, convert_snake_case(service_name))
|
||||||
|
for rule_name, rule in service["rules"].items():
|
||||||
|
if not rule["enabled"]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
rule["result"] = getattr(module, convert_snake_case(rule_name))()
|
||||||
|
return bp
|
||||||
|
|
||||||
|
|
||||||
|
def show_bp_result(bp):
|
||||||
|
for service_name, service in bp.items():
|
||||||
|
if not service["enabled"]:
|
||||||
|
continue
|
||||||
|
print(f"{'=' * 25} {service_name + ' ':=<30}")
|
||||||
|
|
||||||
|
for rule_name, rule in service["rules"].items():
|
||||||
|
if not rule["enabled"]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if rule["result"].passed:
|
||||||
|
style = Style.DIM
|
||||||
|
color = Fore.GREEN
|
||||||
|
mark = "✅"
|
||||||
|
elif rule["level"] == 2 and not rule["result"].passed:
|
||||||
|
style = Style.BRIGHT
|
||||||
|
color = Fore.RED
|
||||||
|
mark = "❌"
|
||||||
|
elif rule["level"] == 1 and not rule["result"].passed:
|
||||||
|
style = Style.NORMAL
|
||||||
|
color = Fore.LIGHTRED_EX
|
||||||
|
mark = "❕"
|
||||||
|
|
||||||
|
print(f"{style}{rule_name:50}{Style.RESET_ALL} - {color}{mark}{Fore.RESET}")
|
||||||
|
for resource in rule["result"].non_compliant_resources:
|
||||||
|
print(f" - {color}{resource}{Fore.RESET}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
bp = load_bp_from_file()
|
||||||
|
bp = ask_services_to_enable(bp)
|
||||||
|
save_bp_to_file(bp)
|
||||||
|
|
||||||
|
bp = perform_bp_rules_check(bp)
|
||||||
|
show_bp_result(bp)
|
7
models.py
Normal file
7
models.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class RuleCheckResult(BaseModel):
|
||||||
|
passed: bool
|
||||||
|
compliant_resources: list[str]
|
||||||
|
non_compliant_resources: list[str]
|
17
requirements.txt
Normal file
17
requirements.txt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
annotated-types==0.7.0
|
||||||
|
boto3==1.34.153
|
||||||
|
botocore==1.34.153
|
||||||
|
colorama==0.4.6
|
||||||
|
jmespath==1.0.1
|
||||||
|
prompt-toolkit==1.0.14
|
||||||
|
pydantic==2.8.2
|
||||||
|
pydantic_core==2.20.1
|
||||||
|
Pygments==2.18.0
|
||||||
|
PyInquirer==1.0.3
|
||||||
|
python-dateutil==2.9.0.post0
|
||||||
|
regex==2024.7.24
|
||||||
|
s3transfer==0.10.2
|
||||||
|
six==1.16.0
|
||||||
|
typing_extensions==4.12.2
|
||||||
|
urllib3==1.26.19
|
||||||
|
wcwidth==0.2.13
|
28
services/__init__.py
Normal file
28
services/__init__.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from . import (
|
||||||
|
alb,
|
||||||
|
api_gw,
|
||||||
|
rds,
|
||||||
|
asg,
|
||||||
|
ec2,
|
||||||
|
cloudfront,
|
||||||
|
kms,
|
||||||
|
codeseries,
|
||||||
|
cloudwatch,
|
||||||
|
docdb,
|
||||||
|
dynamodb,
|
||||||
|
ecr,
|
||||||
|
ecs,
|
||||||
|
efs,
|
||||||
|
eks,
|
||||||
|
elasticache,
|
||||||
|
iam,
|
||||||
|
_lambda,
|
||||||
|
tags,
|
||||||
|
route53,
|
||||||
|
s3,
|
||||||
|
secrets_manager,
|
||||||
|
security_hub,
|
||||||
|
sns,
|
||||||
|
vpc,
|
||||||
|
wafv2,
|
||||||
|
)
|
29
services/_lambda.py
Normal file
29
services/_lambda.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def lambda_dlq_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def lambda_function_public_access_prohibited():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def lambda_function_settings_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def lambda_inside_vpc():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
37
services/alb.py
Normal file
37
services/alb.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def alb_http_drop_invalid_header_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False,
|
||||||
|
compliant_resources=[],
|
||||||
|
non_compliant_resources=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def alb_waf_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def elb_cross_zone_load_balancing_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def elb_deletion_protection_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def elb_logging_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
41
services/api_gw.py
Normal file
41
services/api_gw.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def api_gwv2_access_logs_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def api_gwv2_authorization_type_configured():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def api_gw_associated_with_waf():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def api_gw_cache_enabled_and_encrypted():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def api_gw_execution_logging_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def api_gw_xray_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
17
services/asg.py
Normal file
17
services/asg.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def autoscaling_group_elb_healthcheck_required():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def autoscaling_multiple_az():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
41
services/cloudfront.py
Normal file
41
services/cloudfront.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def cloudfront_accesslogs_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def cloudfront_associated_with_waf():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def cloudfront_default_root_object_configured():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def cloudfront_no_deprecated_ssl_protocols():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def cloudfront_s3_origin_access_control_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def cloudfront_viewer_policy_https():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
17
services/cloudwatch.py
Normal file
17
services/cloudwatch.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def cw_loggroup_retention_period_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def cloudwatch_alarm_settings_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
23
services/codeseries.py
Normal file
23
services/codeseries.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def codebuild_project_environment_privileged_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def codebuild_project_logging_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def codedeploy_auto_rollback_monitor_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
29
services/docdb.py
Normal file
29
services/docdb.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def docdb_cluster_audit_logging_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def docdb_cluster_backup_retention_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def docdb_cluster_deletion_protection_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def docdb_cluster_encrypted():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
41
services/dynamodb.py
Normal file
41
services/dynamodb.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def dynamodb_autoscaling_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def dynamodb_last_backup_recovery_point_created():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def dynamodb_pitr_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def dynamodb_table_deletion_protection_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def dynamodb_table_encrypted_kms():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def dynamodb_table_encryption_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
59
services/ec2.py
Normal file
59
services/ec2.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def autoscaling_launch_template():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ec2_ebs_encryption_by_default():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ec2_imdsv2_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ec2_instance_detailed_monitoring_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ec2_instance_managed_by_systems_manager():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ec2_instance_profile_attached():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ec2_no_amazon_key_pair():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ec2_stopped_instance():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ec2_token_hop_limit_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
29
services/ecr.py
Normal file
29
services/ecr.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def ecr_private_image_scanning_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ecr_private_lifecycle_policy_configured():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ecr_private_tag_immutability_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ecr_kms_encryption_1():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
53
services/ecs.py
Normal file
53
services/ecs.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def ecs_awsvpc_networking_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ecs_containers_nonprivileged():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ecs_containers_readonly_access():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ecs_container_insights_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ecs_fargate_latest_platform_version():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ecs_task_definition_log_configuration():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ecs_task_definition_memory_hard_limit():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ecs_task_definition_nonroot_user():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
35
services/efs.py
Normal file
35
services/efs.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def efs_access_point_enforce_root_directory():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def efs_access_point_enforce_user_identity():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def efs_automatic_backups_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def efs_encrypted_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def efs_mount_target_public_accessible():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
29
services/eks.py
Normal file
29
services/eks.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def eks_cluster_logging_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def eks_cluster_secrets_encrypted():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def eks_endpoint_no_public_access():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def eks_secrets_encrypted():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
41
services/elasticache.py
Normal file
41
services/elasticache.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def elasticache_auto_minor_version_upgrade_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def elasticache_redis_cluster_automatic_backup_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def elasticache_repl_grp_auto_failover_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def elasticache_repl_grp_encrypted_at_rest():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def elasticache_repl_grp_encrypted_in_transit():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def elasticache_subnet_group_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
23
services/iam.py
Normal file
23
services/iam.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def iam_policy_no_statements_with_admin_access():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def iam_policy_no_statements_with_full_access():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def iam_role_managed_policy_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
11
services/kms.py
Normal file
11
services/kms.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def cmk_backing_key_rotation_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
95
services/rds.py
Normal file
95
services/rds.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def aurora_last_backup_recovery_point_created():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def aurora_mysql_backtracking_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def db_instance_backup_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_cluster_auto_minor_version_upgrade_enable():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_cluster_default_admin_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_cluster_deletion_protection_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_cluster_encrypted_at_rest():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_cluster_iam_authentication_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_cluster_multi_az_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_db_security_group_not_allowed():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_enhanced_monitoring_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_instance_deletion_protection_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_instance_public_access_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_logging_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def rds_snapshot_encrypted():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
11
services/route53.py
Normal file
11
services/route53.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def route53_query_logging_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
65
services/s3.py
Normal file
65
services/s3.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def s3_access_point_in_vpc_only():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def s3_bucket_default_lock_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def s3_bucket_level_public_access_prohibited():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def s3_bucket_logging_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def s3_bucket_ssl_requests_only():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def s3_bucket_versioning_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def s3_default_encryption_kms():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def s3_event_notifications_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def s3_last_backup_recovery_point_created():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def s3_lifecycle_policy_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
23
services/secrets_manager.py
Normal file
23
services/secrets_manager.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def secretsmanager_rotation_enabled_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def secretsmanager_scheduled_rotation_success_check():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def secretsmanager_secret_periodic_rotation():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
11
services/security_hub.py
Normal file
11
services/security_hub.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def securityhub_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
17
services/sns.py
Normal file
17
services/sns.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def sns_encrypted_kms():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def sns_topic_message_delivery_notification_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
11
services/tags.py
Normal file
11
services/tags.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def required_tags():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
257
services/vpc.py
Normal file
257
services/vpc.py
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
from pprint import pprint
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
ec2 = boto3.client("ec2")
|
||||||
|
|
||||||
|
|
||||||
|
def ec2_transit_gateway_auto_vpc_attach_disabled():
|
||||||
|
response = ec2.describe_transit_gateways()
|
||||||
|
|
||||||
|
non_compliant_resources = [
|
||||||
|
resource["TransitGatewayArn"]
|
||||||
|
for resource in filter(
|
||||||
|
lambda x: x["Options"]["AutoAcceptSharedAttachments"] == "enable",
|
||||||
|
response["TransitGateways"],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
compliant_resources = list(
|
||||||
|
set([resource["TransitGatewayArn"] for resource in response["TransitGateways"]])
|
||||||
|
- set(non_compliant_resources)
|
||||||
|
)
|
||||||
|
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=not non_compliant_resources,
|
||||||
|
compliant_resources=compliant_resources,
|
||||||
|
non_compliant_resources=non_compliant_resources,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def restricted_ssh():
|
||||||
|
response = ec2.describe_security_group_rules()
|
||||||
|
|
||||||
|
non_compliant_resources = [
|
||||||
|
f'{resource["GroupId"]} / {resource["SecurityGroupRuleId"]}'
|
||||||
|
for resource in filter(
|
||||||
|
lambda x: x["IsEgress"] == False
|
||||||
|
and x["FromPort"] <= 22
|
||||||
|
and x["ToPort"] >= 22
|
||||||
|
and x.get("CidrIpv4") == "0.0.0.0/0",
|
||||||
|
response["SecurityGroupRules"],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
compliant_resources = list(
|
||||||
|
set(
|
||||||
|
[
|
||||||
|
f'{resource["GroupId"]} / {resource["SecurityGroupRuleId"]}'
|
||||||
|
for resource in response["SecurityGroupRules"]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
- set(non_compliant_resources)
|
||||||
|
)
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=not non_compliant_resources,
|
||||||
|
compliant_resources=compliant_resources,
|
||||||
|
non_compliant_resources=non_compliant_resources,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def restricted_common_ports():
|
||||||
|
common_ports = [
|
||||||
|
22, # SSH
|
||||||
|
80, # HTTP
|
||||||
|
3306, # MySQL
|
||||||
|
3389, # RDP
|
||||||
|
5432, # PostgreSQL
|
||||||
|
6379, # Redis
|
||||||
|
11211, # Memcached
|
||||||
|
]
|
||||||
|
response = ec2.describe_security_group_rules()
|
||||||
|
|
||||||
|
non_compliant_resources = [
|
||||||
|
f'{resource["GroupId"]} / {resource["SecurityGroupRuleId"]}'
|
||||||
|
for resource in filter(
|
||||||
|
lambda x: x["IsEgress"] == False
|
||||||
|
and x["FromPort"] in common_ports
|
||||||
|
and x["ToPort"] in common_ports
|
||||||
|
and x.get("PrefixListId") is None,
|
||||||
|
response["SecurityGroupRules"],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
compliant_resources = list(
|
||||||
|
set(
|
||||||
|
f'{resource["GroupId"]} / {resource["SecurityGroupRuleId"]}'
|
||||||
|
for resource in response["SecurityGroupRules"]
|
||||||
|
)
|
||||||
|
- set(non_compliant_resources)
|
||||||
|
)
|
||||||
|
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=not non_compliant_resources,
|
||||||
|
compliant_resources=compliant_resources,
|
||||||
|
non_compliant_resources=non_compliant_resources,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def subnet_auto_assign_public_ip_disabled():
|
||||||
|
response = ec2.describe_subnets()
|
||||||
|
|
||||||
|
non_compliant_resources = [
|
||||||
|
resource["SubnetId"]
|
||||||
|
for resource in filter(lambda x: x["MapPublicIpOnLaunch"], response["Subnets"])
|
||||||
|
]
|
||||||
|
|
||||||
|
compliant_resources = list(
|
||||||
|
set(resource["SubnetId"] for resource in response["Subnets"])
|
||||||
|
- set(non_compliant_resources)
|
||||||
|
)
|
||||||
|
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=not non_compliant_resources,
|
||||||
|
compliant_resources=compliant_resources,
|
||||||
|
non_compliant_resources=non_compliant_resources,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def vpc_default_security_group_closed():
|
||||||
|
response = ec2.describe_security_groups(
|
||||||
|
Filters=[{"Name": "group-name", "Values": ["default"]}]
|
||||||
|
)
|
||||||
|
|
||||||
|
non_compliant_resources = [
|
||||||
|
resource["GroupId"]
|
||||||
|
for resource in filter(
|
||||||
|
lambda x: x["IpPermissions"] or x["IpPermissionsEgress"],
|
||||||
|
response["SecurityGroups"],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
compliant_resources = list(
|
||||||
|
set(resource["GroupId"] for resource in response["SecurityGroups"])
|
||||||
|
- set(non_compliant_resources)
|
||||||
|
)
|
||||||
|
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=not non_compliant_resources,
|
||||||
|
compliant_resources=compliant_resources,
|
||||||
|
non_compliant_resources=non_compliant_resources,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def vpc_flow_logs_enabled():
|
||||||
|
response = ec2.describe_flow_logs()
|
||||||
|
flow_log_enabled_vpcs = [
|
||||||
|
resource["ResourceId"] for resource in response["FlowLogs"]
|
||||||
|
]
|
||||||
|
|
||||||
|
response = ec2.describe_vpcs()
|
||||||
|
|
||||||
|
non_compliant_resources = [
|
||||||
|
resource["VpcId"]
|
||||||
|
for resource in filter(
|
||||||
|
lambda x: x["VpcId"] not in flow_log_enabled_vpcs, response["Vpcs"]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
compliant_resources = list(
|
||||||
|
set(resource["VpcId"] for resource in response["Vpcs"])
|
||||||
|
- set(non_compliant_resources)
|
||||||
|
)
|
||||||
|
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=not non_compliant_resources,
|
||||||
|
compliant_resources=compliant_resources,
|
||||||
|
non_compliant_resources=non_compliant_resources,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def vpc_network_acl_unused_check():
|
||||||
|
response = ec2.describe_network_acls()
|
||||||
|
|
||||||
|
non_compliant_resources = [
|
||||||
|
resource["NetworkAclId"]
|
||||||
|
for resource in filter(lambda x: not x["Associations"], response["NetworkAcls"])
|
||||||
|
]
|
||||||
|
|
||||||
|
compliant_resources = list(
|
||||||
|
set(resource["NetworkAclId"] for resource in response["NetworkAcls"])
|
||||||
|
- set(non_compliant_resources)
|
||||||
|
)
|
||||||
|
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=not non_compliant_resources,
|
||||||
|
compliant_resources=compliant_resources,
|
||||||
|
non_compliant_resources=non_compliant_resources,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def vpc_peering_dns_resolution_check():
|
||||||
|
response = ec2.describe_vpc_peering_connections()
|
||||||
|
|
||||||
|
non_compliant_resources = [
|
||||||
|
resource["VpcPeeringConnectionId"]
|
||||||
|
for resource in filter(
|
||||||
|
lambda x: x["Status"]["Code"] not in ["deleted", "deleting"]
|
||||||
|
and (
|
||||||
|
not x["AccepterVpcInfo"].get("PeeringOptions")
|
||||||
|
or not x["AccepterVpcInfo"]["PeeringOptions"][
|
||||||
|
"AllowDnsResolutionFromRemoteVpc"
|
||||||
|
]
|
||||||
|
or not x["RequesterVpcInfo"]["PeeringOptions"][
|
||||||
|
"AllowDnsResolutionFromRemoteVpc"
|
||||||
|
]
|
||||||
|
),
|
||||||
|
response["VpcPeeringConnections"],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
compliant_resources = list(
|
||||||
|
set(
|
||||||
|
resource["VpcPeeringConnectionId"]
|
||||||
|
for resource in response["VpcPeeringConnections"]
|
||||||
|
)
|
||||||
|
- set(non_compliant_resources)
|
||||||
|
)
|
||||||
|
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=not non_compliant_resources,
|
||||||
|
compliant_resources=compliant_resources,
|
||||||
|
non_compliant_resources=non_compliant_resources,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def vpc_sg_open_only_to_authorized_ports():
|
||||||
|
response = ec2.describe_security_group_rules()
|
||||||
|
|
||||||
|
authorized_port = [
|
||||||
|
# 80
|
||||||
|
]
|
||||||
|
|
||||||
|
non_compliant_resources = [
|
||||||
|
f'{resource["GroupId"]} / {resource["SecurityGroupRuleId"]}'
|
||||||
|
for resource in filter(
|
||||||
|
lambda x: x["IsEgress"] == False
|
||||||
|
and (x.get("CidrIpv4") == "0.0.0.0/0" or x.get("CidrIpv6") == "::/0")
|
||||||
|
and x["FromPort"] not in authorized_port
|
||||||
|
and x["ToPort"] not in authorized_port,
|
||||||
|
response["SecurityGroupRules"],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
compliant_resources = list(
|
||||||
|
set(
|
||||||
|
f'{resource["GroupId"]} / {resource["SecurityGroupRuleId"]}'
|
||||||
|
for resource in response["SecurityGroupRules"]
|
||||||
|
)
|
||||||
|
- set(non_compliant_resources)
|
||||||
|
)
|
||||||
|
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=not non_compliant_resources,
|
||||||
|
compliant_resources=compliant_resources,
|
||||||
|
non_compliant_resources=non_compliant_resources,
|
||||||
|
)
|
29
services/wafv2.py
Normal file
29
services/wafv2.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
|
||||||
|
|
||||||
|
def wafv2_logging_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def wafv2_rulegroup_logging_enabled():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def wafv2_rulegroup_not_empty():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def wafv2_webacl_not_empty():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
68
utils.py
Normal file
68
utils.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import json
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
def load_bp_from_file(filepath="bp.json"):
|
||||||
|
try:
|
||||||
|
with open(filepath, "r") as f:
|
||||||
|
content = "".join(f.readlines())
|
||||||
|
except FileNotFoundError:
|
||||||
|
shutil.copy("bp-base.json", filepath)
|
||||||
|
with open(filepath, "r") as f:
|
||||||
|
content = "".join(f.readlines())
|
||||||
|
|
||||||
|
return json.loads(content)
|
||||||
|
|
||||||
|
|
||||||
|
def save_bp_to_file(bp, filepath="bp.json"):
|
||||||
|
with open(filepath, "w") as f:
|
||||||
|
f.write(json.dumps(bp, indent=2))
|
||||||
|
|
||||||
|
|
||||||
|
def convert_snake_case(text):
|
||||||
|
return text.lower().replace(" ", "_").replace("-", "_")
|
||||||
|
|
||||||
|
|
||||||
|
def convert_bp_to_snake_case(bp):
|
||||||
|
bp = {
|
||||||
|
service_name.lower().replace(" ", "_"): value
|
||||||
|
for service_name, value in bp.items()
|
||||||
|
}
|
||||||
|
for v in bp.values():
|
||||||
|
v["rules"] = {
|
||||||
|
rule_name.lower().replace("-", "_"): rule
|
||||||
|
for rule_name, rule in v["rules"].items()
|
||||||
|
}
|
||||||
|
return bp
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
bp = load_bp_from_file()
|
||||||
|
rules = [
|
||||||
|
(
|
||||||
|
k.lower().replace(" ", "_"),
|
||||||
|
list(map(lambda x: x.replace("-", "_"), v["rules"].keys())),
|
||||||
|
)
|
||||||
|
for k, v in bp.items()
|
||||||
|
]
|
||||||
|
print(json.dumps(rules, indent=2))
|
||||||
|
for rule in rules:
|
||||||
|
file_name = rule[0]
|
||||||
|
rule_names = rule[1]
|
||||||
|
file_template = f"""from models import RuleCheckResult
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
|
||||||
|
# client = boto3.client("")
|
||||||
|
"""
|
||||||
|
with open(f"services/{file_name}.py", "w") as f:
|
||||||
|
f.write(file_template)
|
||||||
|
for rule_name in rule_names:
|
||||||
|
function_template = f"""
|
||||||
|
|
||||||
|
def {rule_name}():
|
||||||
|
return RuleCheckResult(
|
||||||
|
passed=False, compliant_resources=[], non_compliant_resources=[]
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
f.write(function_template)
|
Loading…
Reference in New Issue
Block a user