krz/aws-summary-report

Automated AWS summary reports, straight to your inbox. automation aws email reporting

Commit f398469aab

f398469aab82fd36868b13afe8c92d9ad076e225

parent: 0ac3e4788a

Verified · cmc

cmc <hello@cleberg.net> · 2025-08-02 17:50 UTC

fix: convert README.org to README.md

Layout: unified · split

README.md added +249
@@ -0,0 +1,249 @@
1# Overview
2
3This project is a Python-based tool that sends a daily plaintext email
4summarizing key AWS environment metrics and alerts. It is modular,
5configurable, and intended for solo or small-team AWS accounts that want
6automated visibility into infrastructure health, security, and cost.
7
8# Features
9
10- ✅ Daily billing breakdown (Cost Explorer)
11- ✅ New Security Hub findings
12- ✅ Route 53 health check status
13- ✅ CloudWatch alarms triggered in the last 24 hours
14- ✅ S3 bucket access/encryption audit
15- ✅ Expiring ACM certificates (next 30 days)
16- ✅ AWS Config non-compliant resources
17- ✅ CloudFront distribution changes (last 48h)
18- ✅ WAF blocked request summary (regional)
19
20The program is configured to be modular and accept new sections to the
21report as needed. To create a new section, simply create the
22`new_section.py` script inside the `sections/` directory and update the
23`sections` variable inside the `config.toml` file.
24
25# Directory Structure
26
27 .
28 ├── README.org ; This file
29 ├── config.toml ; Configuration (AWS profile, region, etc.)
30 ├── email_formatter.py ; Utility to format email body
31 ├── main.py ; Main entry point for report generation
32 ├── pyproject.toml ; Project metadata and dependencies
33 ├── utils.py ; Shared utility functions
34 ├── sections/ ; Modular report generators
35 │ ├── acm.py ; ACM expiring certs
36 │ ├── cloudfront.py ; CloudFront changes
37 │ ├── cloudwatch.py ; Alarms
38 │ ├── config.py ; Config compliance
39 │ ├── costexplorer.py ; Billing
40 │ ├── route53.py ; Health checks
41 │ ├── s3.py ; Bucket audit
42 │ └── securityhub.py ; Findings
43
44# Usage
45
46## 1. Configure
47
48Edit `config.toml` to configure your AWS, email, and report options:
49
50``` toml
51[aws]
52profile = "default"
53region = "us-east-1"
54
55[email]
56from = "you@example.com"
57to = ["you@example.com"]
58subject = "Daily AWS Report"
59
60[recipients]
61emails = [
62 "you@example.com"
63]
64
65[report]
66sections = [
67 "acm"
68]
69```
70
71If you do not already have an AWS profile (e.g., `default`), then you
72will need to install the AWS CLI and configure a profile first:
73
74``` bash
75aws configure --profile default
76```
77
78## 2. Run
79
80Use Python to run the report and send the email:
81
82``` bash
83python main.py
84```
85
86Or, if you're using [uv](https://github.com/astral-sh/uv) (which will
87auto-install dependencies and create a virtual environment):
88
89``` bash
90uv run main.py
91```
92
93Emails are plaintext with ASCII-formatted tables (via `tabulate`).
94
95<figure>
96<img src="./screenshots/uv.png" />
97<figcaption>UV Run</figcaption>
98</figure>
99
100# Installation
101
102## Dependencies
103
104Python 3.11+ is recommended. Install dependencies using:
105
106``` bash
107pip install -r requirements.txt
108# or if you're using uv:
109uv sync
110```
111
112You may need to install:
113
114- `boto3`
115- `tabulate`
116
117## AWS Permissions
118
119Ensure your IAM user or role has read access to:
120
121- Cost Explorer
122- Security Hub
123- S3, CloudFront, CloudWatch
124- Route 53, ACM, Config, WAF
125- SES (if sending emails from within AWS)
126
127# Customizing Sections
128
129Each section is defined in a file under `sections/` and implements a:
130
131``` python
132def get_section(config) -> str:
133 ...
134```
135
136You can add, remove, or modify these sections in `config.toml`.
137
138# Example Output
139
140Here's an example of the output in plain text format.
141
142 Expiring TLS Certificates:
143 No certs expiring in the next 30 days.
144
145 CloudFront Changes:
146 No distributions changed in the last 48h.
147
148 CloudWatch Alarms:
149 No alarms triggered in the last 24h.
150
151 AWS Config Non-Compliant Resources:
152 [https://eu-west-1.console.aws.amazon.com/config/home#/resources?complianceType=NON_COMPLIANT]
153 ┌───────────────────────────────────────┬────────────────────────┐
154 │ Resource Type │ Resource ID │
155 ├───────────────────────────────────────┼────────────────────────┤
156 │ AWS::::Account │ <account-id> │
157 ├───────────────────────────────────────┼────────────────────────┤
158 │ AWS::EC2::VPC │ vpc-<id> │
159 ├───────────────────────────────────────┼────────────────────────┤
160 │ AWS::EC2::Subnet │ subnet-<id> │
161 ├───────────────────────────────────────┼────────────────────────┤
162 │ AWS::EC2::Subnet │ subnet-<id> │
163 ├───────────────────────────────────────┼────────────────────────┤
164 │ AWS::EC2::Subnet │ subnet-<id> │
165 ├───────────────────────────────────────┼────────────────────────┤
166 │ AWS::EC2::VPCBlockPublicAccessOptions │ <account-id> │
167 ├───────────────────────────────────────┼────────────────────────┤
168 │ AWS::EC2::SecurityGroup │ sg-<id> │
169 ├───────────────────────────────────────┼────────────────────────┤
170 │ AWS::S3::Bucket │ example-cf-logs │
171 ├───────────────────────────────────────┼────────────────────────┤
172 │ AWS::S3::Bucket │ img.example.com │
173 └───────────────────────────────────────┴────────────────────────┘
174
175 AWS Billing Report for 2025-06-18
176 [https://eu-west-1.console.aws.amazon.com/costmanagement/]
177 ┌────────────────────────────────────┬────────┐
178 │ Service │ Cost │
179 ├────────────────────────────────────┼────────┤
180 │ AWS CloudShell │ $0.00 │
181 │ AWS Config │ $0.17 │
182 │ AWS Glue │ $0.00 │
183 │ AWS HealthImaging │ $0.00 │
184 │ AWS Key Management Service │ $0.00 │
185 │ AWS Migration Hub Refactor Spaces │ $0.00 │
186 │ AWS Secrets Manager │ $0.00 │
187 │ AWS Security Hub │ $0.00 │
188 │ AWS Service Catalog │ $0.00 │
189 │ AWS WAF │ $0.29 │
190 │ Amazon CloudFront │ $0.00 │
191 │ Amazon GuardDuty │ $0.00 │
192 │ Amazon Location Service │ $0.00 │
193 │ Amazon Route 53 │ $0.01 │
194 │ Amazon Simple Notification Service │ $0.00 │
195 │ Amazon Simple Queue Service │ $0.00 │
196 │ Amazon Simple Storage Service │ $0.00 │
197 │ AmazonCloudWatch │ $0.00 │
198 │ CloudWatch Events │ $0.00 │
199 ├────────────────────────────────────┼────────┤
200 │ TOTAL │ $0.47 │
201 └────────────────────────────────────┴────────┘
202
203 Note: Costs are estimated and may change.
204
205 Route 53 Health Checks:
206 [https://eu-west-1.console.aws.amazon.com/route53/v2/healthchecks/home]
207 ┌────────────────────┬──────────┐
208 │ Domain │ Status │
209 ├────────────────────┼──────────┤
210 │ img.example.com │ HEALTHY │
211 └────────────────────┴──────────┘
212
213 S3 Bucket Access Summary:
214 [https://eu-west-1.console.aws.amazon.com/s3/home]
215 ┌──────────────────────────────────────────────┬────────┬────────────┐
216 │ Bucket │ Public │ Encrypted │
217 ├──────────────────────────────────────────────┼────────┼────────────┤
218 │ aws-cloudtrail-logs-<account-id>-<suffix> │ No │ Yes │
219 │ example-cf-logs │ No │ Yes │
220 │ img.example.com │ No │ Yes │
221 └──────────────────────────────────────────────┴────────┴────────────┘
222
223 AWS Security Hub Findings (Last 24h): 18 new finding(s)
224 [https://eu-west-1.console.aws.amazon.com/securityhub/home?region=eu-west-1#/findings]
225 ┌───────────────┬────────────────────────────────────────────────────┬──────────────┬────────────────────────────────┐
226 │ Severity │ Title │ Product │ Resource │
227 ├───────────────┼────────────────────────────────────────────────────┼──────────────┼────────────────────────────────┤
228 │ INFORMATIONAL │ S3 buckets should have server access logging │ Security Hub │ arn:aws:s3:::img.example.com │
229 │ INFORMATIONAL │ S3 buckets should require requests to use HTTPS │ Security Hub │ arn:aws:s3:::img.example.com │
230 │ INFORMATIONAL │ S3 buckets should have lifecycle configuration │ Security Hub │ arn:aws:s3:::img.example.com │
231 │ INFORMATIONAL │ S3 buckets should block public access │ Security Hub │ arn:aws:s3:::example-cf-logs │
232 │ INFORMATIONAL │ ACLs should not be used to manage user access │ Security Hub │ arn:aws:s3:::img.example.com │
233 │ INFORMATIONAL │ EC2 subnets shouldn't auto-assign public IPs │ Security Hub │ arn:aws:ec2:eu-west-1:<acct> │
234 │ INFORMATIONAL │ VPC block public access should be enabled │ Security Hub │ arn:aws:ec2:eu-west-1:<acct> │
235 │ INFORMATIONAL │ S3 bucket policies should restrict public access │ Security Hub │ arn:aws:s3:::img.example.com │
236 │ INFORMATIONAL │ Unused network ACLs should be removed │ Security Hub │ arn:aws:ec2:eu-west-1:<acct> │
237 │ INFORMATIONAL │ RSA certs should use 2048-bit+ key lengths │ Security Hub │ arn:aws:acm:eu-west-1:<acct> │
238 │ INFORMATIONAL │ Athena workgroups should enable logging │ Security Hub │ arn:aws:athena:eu-west-1:<acct>│
239 └───────────────┴────────────────────────────────────────────────────┴──────────────┴────────────────────────────────┘
240
241# License
242
243Refer to the LICENSE file for information on the GPL v3 license.
244
245# Future Improvements
246
247- [ ] Email attachment support (e.g., CSV or HTML export)
248- [ ] Slack or Teams notification integration
249- [ ] Cloud deployment (Lambda, Step Functions)
aws-summary/README.md added +238
@@ -0,0 +1,238 @@
1# Overview
2
3This project is a Python-based tool that sends a daily plaintext email
4summarizing key AWS environment metrics and alerts. It is modular,
5configurable, and intended for solo or small-team AWS accounts that want
6automated visibility into infrastructure health, security, and cost.
7
8# Features
9
10- ✅ Daily billing breakdown (Cost Explorer)
11- ✅ New Security Hub findings
12- ✅ Route 53 health check status
13- ✅ CloudWatch alarms triggered in the last 24 hours
14- ✅ S3 bucket access/encryption audit
15- ✅ Expiring ACM certificates (next 30 days)
16- ✅ AWS Config non-compliant resources
17- ✅ CloudFront distribution changes (last 48h)
18- ✅ WAF blocked request summary (regional)
19
20The program is configured to be modular and accept new sections to the
21report as needed. To create a new section, simply create the
22`new_section.py` script inside the `sections/` directory and update the
23`sections` variable inside the `config.toml` file.
24
25# Directory Structure
26
27 .
28 ├── README.org ; This file
29 ├── config.toml ; Configuration (AWS profile, region, etc.)
30 ├── email_formatter.py ; Utility to format email body
31 ├── main.py ; Main entry point for report generation
32 ├── pyproject.toml ; Project metadata and dependencies
33 ├── utils.py ; Shared utility functions
34 ├── sections/ ; Modular report generators
35 ├── acm.py ; ACM expiring certs
36 ├── cloudfront.py ; CloudFront changes
37 ├── cloudwatch.py ; Alarms
38 ├── config.py ; Config compliance
39 ├── costexplorer.py ; Billing
40 ├── route53.py ; Health checks
41 ├── s3.py ; Bucket audit
42 └── securityhub.py ; Findings
43
44# Usage
45
46## 1. Configure
47
48Edit `config.toml` to configure your AWS, email, and report options:
49
50``` toml
51[aws]
52profile = "default"
53region = "us-east-1"
54
55[email]
56from = "you@example.com"
57to = ["you@example.com"]
58subject = "Daily AWS Report"
59
60[recipients]
61emails = [
62 "you@example.com"
63]
64
65[report]
66sections = [
67 "acm"
68]
69```
70
71## 2. Run
72
73Use Python to run the report and send the email:
74
75``` bash
76python main.py
77```
78
79Or, if you're using [uv](https://github.com/astral-sh/uv) (which will
80auto-install dependencies and create a virtual environment):
81
82``` bash
83uv main.py
84```
85
86Emails are plaintext with ASCII-formatted tables (via `tabulate`).
87
88# Installation
89
90## Dependencies
91
92Python 3.11+ is recommended. Install dependencies using:
93
94``` bash
95pip install -r requirements.txt
96# or if you're using uv:
97uv sync
98```
99
100You may need to install:
101
102- `boto3`
103- `tabulate`
104
105## AWS Permissions
106
107Ensure your IAM user or role has read access to:
108
109- Cost Explorer
110- Security Hub
111- S3, CloudFront, CloudWatch
112- Route 53, ACM, Config, WAF
113- SES (if sending emails from within AWS)
114
115# Customizing Sections
116
117Each section is defined in a file under `sections/` and implements a:
118
119``` python
120def get_section(config) -> str:
121 ...
122```
123
124You can add, remove, or modify these sections and control their order in
125`main.py`.
126
127# Example Output
128
129Here is an example of the output produced by the program.
130
131 Expiring TLS Certificates:
132 No certs expiring in the next 30 days.
133
134 CloudFront Changes:
135 No distributions changed in the last 48h.
136
137 CloudWatch Alarms:
138 No alarms triggered in the last 24h.
139
140 AWS Config Non-Compliant Resources:
141 [https://eu-west-1.console.aws.amazon.com/config/home#/resources?complianceType=NON_COMPLIANT]
142 ┌───────────────────────────────────────┬────────────────────────┐
143 │ Resource Type │ Resource ID │
144 ├───────────────────────────────────────┼────────────────────────┤
145 │ AWS::::Account │ <account-id> │
146 ├───────────────────────────────────────┼────────────────────────┤
147 │ AWS::EC2::VPC │ vpc-<id> │
148 ├───────────────────────────────────────┼────────────────────────┤
149 │ AWS::EC2::Subnet │ subnet-<id> │
150 ├───────────────────────────────────────┼────────────────────────┤
151 │ AWS::EC2::Subnet │ subnet-<id> │
152 ├───────────────────────────────────────┼────────────────────────┤
153 │ AWS::EC2::Subnet │ subnet-<id> │
154 ├───────────────────────────────────────┼────────────────────────┤
155 │ AWS::EC2::VPCBlockPublicAccessOptions │ <account-id> │
156 ├───────────────────────────────────────┼────────────────────────┤
157 │ AWS::EC2::SecurityGroup │ sg-<id> │
158 ├───────────────────────────────────────┼────────────────────────┤
159 │ AWS::S3::Bucket │ example-cf-logs │
160 ├───────────────────────────────────────┼────────────────────────┤
161 │ AWS::S3::Bucket │ img.example.com │
162 └───────────────────────────────────────┴────────────────────────┘
163
164 AWS Billing Report for 2025-06-18
165 [https://eu-west-1.console.aws.amazon.com/costmanagement/]
166 ┌────────────────────────────────────┬────────┐
167 │ Service │ Cost │
168 ├────────────────────────────────────┼────────┤
169 │ AWS CloudShell │ $0.00 │
170 │ AWS Config │ $0.17 │
171 │ AWS Glue │ $0.00 │
172 │ AWS HealthImaging │ $0.00 │
173 │ AWS Key Management Service │ $0.00 │
174 │ AWS Migration Hub Refactor Spaces │ $0.00 │
175 │ AWS Secrets Manager │ $0.00 │
176 │ AWS Security Hub │ $0.00 │
177 │ AWS Service Catalog │ $0.00 │
178 │ AWS WAF │ $0.29 │
179 │ Amazon CloudFront │ $0.00 │
180 │ Amazon GuardDuty │ $0.00 │
181 │ Amazon Location Service │ $0.00 │
182 │ Amazon Route 53 │ $0.01 │
183 │ Amazon Simple Notification Service │ $0.00 │
184 │ Amazon Simple Queue Service │ $0.00 │
185 │ Amazon Simple Storage Service │ $0.00 │
186 │ AmazonCloudWatch │ $0.00 │
187 │ CloudWatch Events │ $0.00 │
188 ├────────────────────────────────────┼────────┤
189 │ TOTAL │ $0.47 │
190 └────────────────────────────────────┴────────┘
191
192 Note: Costs are estimated and may change.
193
194 Route 53 Health Checks:
195 [https://eu-west-1.console.aws.amazon.com/route53/v2/healthchecks/home]
196 ┌────────────────────┬──────────┐
197 │ Domain │ Status │
198 ├────────────────────┼──────────┤
199 │ img.example.com │ HEALTHY │
200 └────────────────────┴──────────┘
201
202 S3 Bucket Access Summary:
203 [https://eu-west-1.console.aws.amazon.com/s3/home]
204 ┌──────────────────────────────────────────────┬────────┬────────────┐
205 │ Bucket │ Public │ Encrypted │
206 ├──────────────────────────────────────────────┼────────┼────────────┤
207 │ aws-cloudtrail-logs-<account-id>-<suffix> │ No │ Yes │
208 │ example-cf-logs │ No │ Yes │
209 │ img.example.com │ No │ Yes │
210 └──────────────────────────────────────────────┴────────┴────────────┘
211
212 AWS Security Hub Findings (Last 24h): 18 new finding(s)
213 [https://eu-west-1.console.aws.amazon.com/securityhub/home?region=eu-west-1#/findings]
214 ┌───────────────┬────────────────────────────────────────────────────┬──────────────┬────────────────────────────────┐
215 │ Severity │ Title │ Product │ Resource │
216 ├───────────────┼────────────────────────────────────────────────────┼──────────────┼────────────────────────────────┤
217 │ INFORMATIONAL │ S3 buckets should have server access logging │ Security Hub │ arn:aws:s3:::img.example.com │
218 │ INFORMATIONAL │ S3 buckets should require requests to use HTTPS │ Security Hub │ arn:aws:s3:::img.example.com │
219 │ INFORMATIONAL │ S3 buckets should have lifecycle configuration │ Security Hub │ arn:aws:s3:::img.example.com │
220 │ INFORMATIONAL │ S3 buckets should block public access │ Security Hub │ arn:aws:s3:::example-cf-logs │
221 │ INFORMATIONAL │ ACLs should not be used to manage user access │ Security Hub │ arn:aws:s3:::img.example.com │
222 │ INFORMATIONAL │ EC2 subnets shouldn't auto-assign public IPs │ Security Hub │ arn:aws:ec2:eu-west-1:<acct> │
223 │ INFORMATIONAL │ VPC block public access should be enabled │ Security Hub │ arn:aws:ec2:eu-west-1:<acct> │
224 │ INFORMATIONAL │ S3 bucket policies should restrict public access │ Security Hub │ arn:aws:s3:::img.example.com │
225 │ INFORMATIONAL │ Unused network ACLs should be removed │ Security Hub │ arn:aws:ec2:eu-west-1:<acct> │
226 │ INFORMATIONAL │ RSA certs should use 2048-bit+ key lengths │ Security Hub │ arn:aws:acm:eu-west-1:<acct> │
227 │ INFORMATIONAL │ Athena workgroups should enable logging │ Security Hub │ arn:aws:athena:eu-west-1:<acct>│
228 └───────────────┴────────────────────────────────────────────────────┴──────────────┴────────────────────────────────┘
229
230# License
231
232Refer to the LICENSE file.
233
234# Future Improvements
235
236- [ ] Email attachment support (e.g., CSV or HTML export)
237- [ ] Slack or Teams notification integration
238- [ ] Cloud deployment (Lambda, Step Functions)