krz/aws-summary-report

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

Commit 7e57be6f39

7e57be6f395763145985a28aa6de43aa88f3029f

parent: f398469aab

Verified · cmc

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

fix: convert README.org to README.md

Layout: unified · split

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