# Overview
This project is a Python-based tool that sends a daily plaintext email
summarizing key AWS environment metrics and alerts. It is modular,
configurable, and intended for solo or small-team AWS accounts that want
automated visibility into infrastructure health, security, and cost.
# Features
- ✅ Daily billing breakdown (Cost Explorer)
- ✅ New Security Hub findings
- ✅ Route 53 health check status
- ✅ CloudWatch alarms triggered in the last 24 hours
- ✅ S3 bucket access/encryption audit
- ✅ Expiring ACM certificates (next 30 days)
- ✅ AWS Config non-compliant resources
- ✅ CloudFront distribution changes (last 48h)
- ✅ WAF blocked request summary (regional)
The program is configured to be modular and accept new sections to the
report as needed. To create a new section, simply create the
`new_section.py` script inside the `sections/` directory and update the
`sections` variable inside the `config.toml` file.
# Directory Structure
.
├── README.org ; This file
├── config.toml ; Configuration (AWS profile, region, etc.)
├── email_formatter.py ; Utility to format email body
├── main.py ; Main entry point for report generation
├── pyproject.toml ; Project metadata and dependencies
├── utils.py ; Shared utility functions
├── sections/ ; Modular report generators
│ ├── acm.py ; ACM expiring certs
│ ├── cloudfront.py ; CloudFront changes
│ ├── cloudwatch.py ; Alarms
│ ├── config.py ; Config compliance
│ ├── costexplorer.py ; Billing
│ ├── route53.py ; Health checks
│ ├── s3.py ; Bucket audit
│ └── securityhub.py ; Findings
# Usage
## 1. Configure
Edit `config.toml` to configure your AWS, email, and report options:
``` toml
[aws]
profile = "default"
region = "us-east-1"
[email]
from = "you@example.com"
to = ["you@example.com"]
subject = "Daily AWS Report"
[recipients]
emails = [
"you@example.com"
]
[report]
sections = [
"acm"
]
```
If you do not already have an AWS profile (e.g., `default`), then you
will need to install the AWS CLI and configure a profile first:
``` bash
aws configure --profile default
```
## 2. Run
Use Python to run the report and send the email:
``` bash
python main.py
```
Or, if you're using [uv](https://github.com/astral-sh/uv) (which will
auto-install dependencies and create a virtual environment):
``` bash
uv run main.py
```
Emails are plaintext with ASCII-formatted tables (via `tabulate`).
UV Run
# Installation
## Dependencies
Python 3.11+ is recommended. Install dependencies using:
``` bash
pip install -r requirements.txt
# or if you're using uv:
uv sync
```
You may need to install:
- `boto3`
- `tabulate`
## AWS Permissions
Ensure your IAM user or role has read access to:
- Cost Explorer
- Security Hub
- S3, CloudFront, CloudWatch
- Route 53, ACM, Config, WAF
- SES (if sending emails from within AWS)
# Customizing Sections
Each section is defined in a file under `sections/` and implements a:
``` python
def get_section(config) -> str:
...
```
You can add, remove, or modify these sections in `config.toml`.
# Example Output
Here's an example of the output in plain text format.
Expiring TLS Certificates:
No certs expiring in the next 30 days.
CloudFront Changes:
No distributions changed in the last 48h.
CloudWatch Alarms:
No alarms triggered in the last 24h.
AWS Config Non-Compliant Resources:
[https://eu-west-1.console.aws.amazon.com/config/home#/resources?complianceType=NON_COMPLIANT]
┌───────────────────────────────────────┬────────────────────────┐
│ Resource Type │ Resource ID │
├───────────────────────────────────────┼────────────────────────┤
│ AWS::::Account │ │
├───────────────────────────────────────┼────────────────────────┤
│ AWS::EC2::VPC │ vpc- │
├───────────────────────────────────────┼────────────────────────┤
│ AWS::EC2::Subnet │ subnet- │
├───────────────────────────────────────┼────────────────────────┤
│ AWS::EC2::Subnet │ subnet- │
├───────────────────────────────────────┼────────────────────────┤
│ AWS::EC2::Subnet │ subnet- │
├───────────────────────────────────────┼────────────────────────┤
│ AWS::EC2::VPCBlockPublicAccessOptions │ │
├───────────────────────────────────────┼────────────────────────┤
│ AWS::EC2::SecurityGroup │ sg- │
├───────────────────────────────────────┼────────────────────────┤
│ AWS::S3::Bucket │ example-cf-logs │
├───────────────────────────────────────┼────────────────────────┤
│ AWS::S3::Bucket │ img.example.com │
└───────────────────────────────────────┴────────────────────────┘
AWS Billing Report for 2025-06-18
[https://eu-west-1.console.aws.amazon.com/costmanagement/]
┌────────────────────────────────────┬────────┐
│ Service │ Cost │
├────────────────────────────────────┼────────┤
│ AWS CloudShell │ $0.00 │
│ AWS Config │ $0.17 │
│ AWS Glue │ $0.00 │
│ AWS HealthImaging │ $0.00 │
│ AWS Key Management Service │ $0.00 │
│ AWS Migration Hub Refactor Spaces │ $0.00 │
│ AWS Secrets Manager │ $0.00 │
│ AWS Security Hub │ $0.00 │
│ AWS Service Catalog │ $0.00 │
│ AWS WAF │ $0.29 │
│ Amazon CloudFront │ $0.00 │
│ Amazon GuardDuty │ $0.00 │
│ Amazon Location Service │ $0.00 │
│ Amazon Route 53 │ $0.01 │
│ Amazon Simple Notification Service │ $0.00 │
│ Amazon Simple Queue Service │ $0.00 │
│ Amazon Simple Storage Service │ $0.00 │
│ AmazonCloudWatch │ $0.00 │
│ CloudWatch Events │ $0.00 │
├────────────────────────────────────┼────────┤
│ TOTAL │ $0.47 │
└────────────────────────────────────┴────────┘
Note: Costs are estimated and may change.
Route 53 Health Checks:
[https://eu-west-1.console.aws.amazon.com/route53/v2/healthchecks/home]
┌────────────────────┬──────────┐
│ Domain │ Status │
├────────────────────┼──────────┤
│ img.example.com │ HEALTHY │
└────────────────────┴──────────┘
S3 Bucket Access Summary:
[https://eu-west-1.console.aws.amazon.com/s3/home]
┌──────────────────────────────────────────────┬────────┬────────────┐
│ Bucket │ Public │ Encrypted │
├──────────────────────────────────────────────┼────────┼────────────┤
│ aws-cloudtrail-logs-- │ No │ Yes │
│ example-cf-logs │ No │ Yes │
│ img.example.com │ No │ Yes │
└──────────────────────────────────────────────┴────────┴────────────┘
AWS Security Hub Findings (Last 24h): 18 new finding(s)
[https://eu-west-1.console.aws.amazon.com/securityhub/home?region=eu-west-1#/findings]
┌───────────────┬────────────────────────────────────────────────────┬──────────────┬────────────────────────────────┐
│ Severity │ Title │ Product │ Resource │
├───────────────┼────────────────────────────────────────────────────┼──────────────┼────────────────────────────────┤
│ INFORMATIONAL │ S3 buckets should have server access logging │ Security Hub │ arn:aws:s3:::img.example.com │
│ INFORMATIONAL │ S3 buckets should require requests to use HTTPS │ Security Hub │ arn:aws:s3:::img.example.com │
│ INFORMATIONAL │ S3 buckets should have lifecycle configuration │ Security Hub │ arn:aws:s3:::img.example.com │
│ INFORMATIONAL │ S3 buckets should block public access │ Security Hub │ arn:aws:s3:::example-cf-logs │
│ INFORMATIONAL │ ACLs should not be used to manage user access │ Security Hub │ arn:aws:s3:::img.example.com │
│ INFORMATIONAL │ EC2 subnets shouldn't auto-assign public IPs │ Security Hub │ arn:aws:ec2:eu-west-1: │
│ INFORMATIONAL │ VPC block public access should be enabled │ Security Hub │ arn:aws:ec2:eu-west-1: │
│ INFORMATIONAL │ S3 bucket policies should restrict public access │ Security Hub │ arn:aws:s3:::img.example.com │
│ INFORMATIONAL │ Unused network ACLs should be removed │ Security Hub │ arn:aws:ec2:eu-west-1: │
│ INFORMATIONAL │ RSA certs should use 2048-bit+ key lengths │ Security Hub │ arn:aws:acm:eu-west-1: │
│ INFORMATIONAL │ Athena workgroups should enable logging │ Security Hub │ arn:aws:athena:eu-west-1:│
└───────────────┴────────────────────────────────────────────────────┴──────────────┴────────────────────────────────┘
# License
Refer to the LICENSE file for information on the GPL v3 license.
# Future Improvements
- [ ] Email attachment support (e.g., CSV or HTML export)
- [ ] Slack or Teams notification integration
- [ ] Cloud deployment (Lambda, Step Functions)