Skip to content

Commit

Permalink
feat: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
RubenMakandra committed Jan 7, 2025
1 parent 5a6cb74 commit fa7defe
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 27 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ We recommend protecting the `main` branch and to allow new code pushes only via

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.7.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.40.0 |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.6.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.55.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.40.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 4.55.0 |

## Modules

Expand All @@ -67,7 +67,7 @@ No modules.
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_cloudfront"></a> [cloudfront](#input\_cloudfront) | The name of the s3 bucket containing the cloudfront logs. Creates a db and saved cloudfront queries if set. | `string` | `null` | no |
| <a name="input_cloudtrail"></a> [cloudtrail](#input\_cloudtrail) | Configuration for cloudtrail. Creates a db and saved cloudfront queries if bucket\_name is set. Only set prefix if you configured one in your cloudtrail | <pre>object({<br/> bucket_name = optional(string)<br/> prefix = optional(string)<br/> })</pre> | `{}` | no |
| <a name="input_cloudtrail"></a> [cloudtrail](#input\_cloudtrail) | Configuration for cloudtrail. Creates a db and saved cloudfront queries if bucket\_name is set. Only set prefix if you configured one in your cloudtrail | <pre>object({<br/> bucket_name = string<br/> prefix = optional(string)<br/> })</pre> | <pre>{<br/> "bucket_name": null<br/>}</pre> | no |
| <a name="input_query_bucket_name"></a> [query\_bucket\_name](#input\_query\_bucket\_name) | The name of the bucket to save the query into. | `string` | n/a | yes |
| <a name="input_ses"></a> [ses](#input\_ses) | The name of the s3 bucket containing the ses logs. Creates a db and saved ses queries if set | `string` | `null` | no |

Expand Down
21 changes: 12 additions & 9 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
locals {
named_queries = {
cloudfront = var.cloudfront != null ? {
cloudfront_create_log_table = "Create the table for CloudFront logs",
cloudfront_log_yesterday_today = "Show requests to CloudFront yesterday and today",
cloudfront_log_yesterday_today_for_ip = "Show requests to CloudFront from a given IP yesterday and today"
cloudfront_create_log_table = "Creates the table for CloudFront logs",
cloudfront_log_yesterday_today = "Shows requests to CloudFront yesterday and today",
cloudfront_log_yesterday_today_for_ip = "Shows requests to CloudFront from a given IP yesterday and today"
cloudfront_logs_for_specific_distribution = "Shows requests to a given cloudfront distribution, with optional filter for date, status code or ssl_protocol"
} : {}
cloudtrail = var.cloudtrail.bucket_name != null ? {
cloudtrail_create_log_table = "Create the table for CloudTrail logs",
cloudtrail_create_log_table = "Creates the table for CloudTrail logs",
cloudtrail_console_login = "Displays console login events, ordered by date"
} : {}
ses = var.ses != null ? {
ses_create_log_table = "Create the table for SES logs"
ses_bounce_ratio = "Displays bounced email as % of send emails"
ses_create_log_table = "Creates the table for SES logs"
ses_daily_bounced_and_send_mails = "Displays bounced and send mails for each day"
ses_formatted_mails = "Displays only the most relevant information per email, optional filter for event type"
ses_daily_not_suppressed_bounces = "Displays amount of bounced emails per day, filtering out bounces caused by addresses being on the suppression list"
} : {}
Expand Down Expand Up @@ -53,7 +53,8 @@ resource "aws_athena_database" "ses" {
}

resource "aws_athena_named_query" "cloudfront" {
for_each = local.named_queries.cloudfront
for_each = local.named_queries.cloudfront

name = replace(each.key, "_", "-")
database = aws_athena_database.cloudfront[0].name
description = each.value
Expand All @@ -66,7 +67,8 @@ resource "aws_athena_named_query" "cloudfront" {
}

resource "aws_athena_named_query" "cloudtrail" {
for_each = local.named_queries.cloudtrail
for_each = local.named_queries.cloudtrail

name = replace(each.key, "_", "-")
database = aws_athena_database.cloudtrail[0].name
description = each.value
Expand All @@ -80,7 +82,8 @@ resource "aws_athena_named_query" "cloudtrail" {
}

resource "aws_athena_named_query" "ses" {
for_each = local.named_queries.ses
for_each = local.named_queries.ses

name = replace(each.key, "_", "-")
database = aws_athena_database.ses[0].name
description = each.value
Expand Down
4 changes: 2 additions & 2 deletions queries/cloudfront_logs_for_specific_distribution.sql.tftpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
SELECT * FROM cloudfront.cloudfront_logs
WHERE host='https://$CLOUDFRONT_NAME.cloudfront.net'
WHERE host='$DISTRIBUTION_DOMAIN_NAME' -- without protocol, e.g. a1a1aaaaaa1a1a.cloudfront.net
-- AND "date" BETWEEN DATE '2023-08-10' AND DATE '2023-08-11' --date is a reserved word and needs to be doublequoted
-- AND status=200
-- AND ssl_protocol=TLSv1.2
-- AND ssl_protocol='TLSv1.2'
LIMIT 100;
2 changes: 1 addition & 1 deletion queries/cloudtrail_console_login.sql.tftpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
select useridentity.username, sourceipaddress, eventtime, additionaleventdata
select useridentity, sourceipaddress, eventtime, additionaleventdata
from cloudtrail.cloudtrail_logs
where eventname = 'ConsoleLogin'
order by date(from_iso8601_timestamp(eventtime)) desc
2 changes: 1 addition & 1 deletion queries/ses_create_log_table.sql.tftpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CREATE EXTERNAL TABLE IF NOT EXISTS ses (
CREATE EXTERNAL TABLE IF NOT EXISTS ses_logs (
eventType string,
complaint struct < arrivaldate: string,
complainedrecipients: array < struct < emailaddress: string >>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
select bounces.date, bounces, send, ((bounces * 1.0)/(send * 1.0) * 100 ) as "% bounces"
select bounces.date, bounces, send
from
( select
date(from_iso8601_timestamp(mail.timestamp)) as date, count(*) as bounces from ses.ses_bounce_logs where eventtype='Bounce'and bounce.bouncedrecipients[1].diagnosticcode not like '%Amazon SES did not send the message to this address%'
date(from_iso8601_timestamp(mail.timestamp)) as date, count(*) as bounces from ses.ses_logs where eventtype='Bounce'and bounce.bouncedrecipients[1].diagnosticcode not like '%Amazon SES did not send the message to this address%'
GROUP BY date(from_iso8601_timestamp(mail.timestamp)) order by date(from_iso8601_timestamp(mail.timestamp)) desc) bounces

inner join
( select
date(from_iso8601_timestamp(mail.timestamp)) as date, count(*) as send from ses.ses_bounce_logs where eventtype='Send'
date(from_iso8601_timestamp(mail.timestamp)) as date, count(*) as send from ses.ses_logs where eventtype='Send'
GROUP BY date(from_iso8601_timestamp(mail.timestamp)) order by date(from_iso8601_timestamp(mail.timestamp)) desc) send
ON
bounces.date = send.date
bounces.date = send.date
2 changes: 1 addition & 1 deletion queries/ses_daily_not_suppressed_bounces.sql.tftpl
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
select
date(from_iso8601_timestamp(mail.timestamp)) as date, count(*) as bounces from ses.ses_bounce_logs where eventtype='Bounce'and bounce.bouncedrecipients[1].diagnosticcode not like '%Amazon SES did not send the message to this address%'
date(from_iso8601_timestamp(mail.timestamp)) as date, count(*) as bounces from ses.ses_logs where eventtype='Bounce'and bounce.bouncedrecipients[1].diagnosticcode not like '%Amazon SES did not send the message to this address%'
GROUP BY date(from_iso8601_timestamp(mail.timestamp)) order by date(from_iso8601_timestamp(mail.timestamp)) desc
2 changes: 1 addition & 1 deletion queries/ses_formatted_mails.sql.tftpl
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
select mail.timestamp, mail.source, mail.destination, bounce.bouncedrecipients[1].diagnosticcode as diagnosticcode from ses.ses_bounce_logs
select mail.timestamp, mail.source, mail.destination, bounce.bouncedrecipients[1].diagnosticcode as diagnosticcode from ses.ses_logs
-- where eventtype='Bounce' -- or any other event type
39 changes: 39 additions & 0 deletions tests/test_input_parsing_cloudfront.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
mock_provider "aws" {}

run "dont_create_resources_without_input" {
variables {
query_bucket_name = "test"
}
assert {
condition = length(local.named_queries.cloudfront) == 0
error_message = "local.named_queries.cloudfront should have 0 elements, but has ${length(local.named_queries.cloudfront)}"
}
assert {
condition = length(aws_athena_database.cloudfront) == 0
error_message = "aws_athena_database.cloudfront should have 0 instances, but has ${length(aws_athena_database.cloudfront)}"
}
assert {
condition = length(aws_athena_named_query.cloudfront) == 0
error_message = "aws_athena_named_query.cloudfront should have 0 instances, but has ${length(aws_athena_database.cloudfront)}"
}
}

run "create_resources_with_correct_input" {
variables {
query_bucket_name = "test"
cloudfront = "cloudfront-bucket"
}

assert {
condition = length(local.named_queries.cloudfront) != 0
error_message = "local.named_queries.cloudfront should not have 0 elements"
}
assert {
condition = length(aws_athena_database.cloudfront) == 1
error_message = "aws_athena_database.cloudfront should have 1 instance, but has ${length(aws_athena_database.cloudfront)}"
}
assert {
condition = length(aws_athena_named_query.cloudfront) != 0
error_message = "aws_athena_named_query.cloudfront should not have 0 element"
}
}
41 changes: 41 additions & 0 deletions tests/test_input_parsing_cloudtrail.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
mock_provider "aws" {}

run "dont_create_resources_without_input" {
variables {
query_bucket_name = "test"
}
assert {
condition = length(local.named_queries.cloudtrail) == 0
error_message = "local.named_queries.cloudtrail should have 0 elements, but has ${length(local.named_queries.cloudtrail)}"
}
assert {
condition = length(aws_athena_database.cloudtrail) == 0
error_message = "aws_athena_database.cloudtrail should have 0 instances, but has ${length(aws_athena_database.cloudtrail)}"
}
assert {
condition = length(aws_athena_named_query.cloudtrail) == 0
error_message = "aws_athena_named_query.cloudtrail should have 0 instances, but has ${length(aws_athena_database.cloudtrail)}"
}
}

run "create_resources_with_correct_input" {
variables {
query_bucket_name = "test"
cloudtrail = {
bucket_name = "cloudtrail-bucket"
}
}

assert {
condition = length(local.named_queries.cloudtrail) != 0
error_message = "local.named_queries.cloudtrail should not have 0 elements"
}
assert {
condition = length(aws_athena_database.cloudtrail) == 1
error_message = "aws_athena_database.cloudtrail should have 1 instance, but has ${length(aws_athena_database.cloudtrail)}"
}
assert {
condition = length(aws_athena_named_query.cloudtrail) != 0
error_message = "aws_athena_named_query.cloudtrail should not have 0 element"
}
}
39 changes: 39 additions & 0 deletions tests/test_input_parsing_ses.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
mock_provider "aws" {}

run "dont_create_resources_without_input" {
variables {
query_bucket_name = "test"
}
assert {
condition = length(local.named_queries.ses) == 0
error_message = "local.named_queries.ses should have 0 elements, but has ${length(local.named_queries.ses)}"
}
assert {
condition = length(aws_athena_database.ses) == 0
error_message = "aws_athena_database.ses should have 0 instances, but has ${length(aws_athena_database.ses)}"
}
assert {
condition = length(aws_athena_named_query.ses) == 0
error_message = "aws_athena_named_query.ses should have 0 instances, but has ${length(aws_athena_database.ses)}"
}
}

run "create_resources_with_correct_input" {
variables {
query_bucket_name = "test"
ses = "ses-bucket"
}

assert {
condition = length(local.named_queries.ses) != 0
error_message = "local.named_queries.ses should not have 0 elements"
}
assert {
condition = length(aws_athena_database.ses) == 1
error_message = "aws_athena_database.ses should have 1 instance, but has ${length(aws_athena_database.ses)}"
}
assert {
condition = length(aws_athena_named_query.ses) != 0
error_message = "aws_athena_named_query.ses should not have 0 element"
}
}
6 changes: 4 additions & 2 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ variable "cloudfront" {
variable "cloudtrail" {
description = "Configuration for cloudtrail. Creates a db and saved cloudfront queries if bucket_name is set. Only set prefix if you configured one in your cloudtrail"
type = object({
bucket_name = optional(string)
bucket_name = string
prefix = optional(string)
})
default = {}
default = {
bucket_name = null
}
}

variable "ses" {
Expand Down
4 changes: 2 additions & 2 deletions versions.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
terraform {
required_version = ">= 1.7.0"
required_version = ">= 1.6.0"
required_providers {
aws = {
version = ">= 5.40.0"
version = ">= 4.55.0"
}
}
}

0 comments on commit fa7defe

Please sign in to comment.