Skip to content

Commit

Permalink
Add CloudWatch Opsgenie alerts SNS
Browse files Browse the repository at this point in the history
* This creates an SNS topic in the default region, and us-east-1, to
  allow CloudWatch to send alerts to Opsgenie.
* The SNS endpoint must first be configured in Opsgenie (https://support.atlassian.com/opsgenie/docs/integrate-opsgenie-with-incoming-amazon-sns/)
  and provided in the variable `cloudwatch_opsgenie_alerts_sns_endpoint`
  • Loading branch information
Stretch96 committed Oct 17, 2023
1 parent 4f060c2 commit e18fefe
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 0 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ for dxw's Dalmatian hosting platform.
|------|---------|
| <a name="provider_archive"></a> [archive](#provider\_archive) | 2.4.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.21.0 |
| <a name="provider_aws.useast1"></a> [aws.useast1](#provider\_aws.useast1) | 5.21.0 |

## Modules

Expand All @@ -42,6 +43,10 @@ for dxw's Dalmatian hosting platform.
| [aws_iam_role.cloudwatch_slack_alerts_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.cloudtrail_cloudwatch_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.cloudtrail_cloudwatch_logs_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_kms_alias.cloudwatch_opsgenie_alerts_sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource |
| [aws_kms_alias.cloudwatch_opsgenie_alerts_sns_us_east_1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource |
| [aws_kms_key.cloudwatch_opsgenie_alerts_sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
| [aws_kms_key.cloudwatch_opsgenie_alerts_sns_us_east_1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
| [aws_lambda_function.cloudwatch_slack_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource |
| [aws_lambda_permission.cloudwatch_slack_alerts_sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource |
| [aws_s3_bucket.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource |
Expand All @@ -50,8 +55,14 @@ for dxw's Dalmatian hosting platform.
| [aws_s3_bucket_public_access_block.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource |
| [aws_s3_bucket_server_side_encryption_configuration.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource |
| [aws_s3_bucket_versioning.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource |
| [aws_sns_topic.cloudwatch_opsgenie_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource |
| [aws_sns_topic.cloudwatch_opsgenie_alerts_us_east_1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource |
| [aws_sns_topic.cloudwatch_slack_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource |
| [aws_sns_topic_policy.sns_cloudwatch_opsgenie_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource |
| [aws_sns_topic_policy.sns_cloudwatch_opsgenie_alerts_us_east_1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource |
| [aws_sns_topic_policy.sns_cloudwatch_slack_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource |
| [aws_sns_topic_subscription.cloudwatch_opsgenie_alerts_subscription](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource |
| [aws_sns_topic_subscription.cloudwatch_opsgenie_alerts_subscription_us_east_1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource |
| [aws_sns_topic_subscription.cloudwatch_slack_alerts_lambda_subscription](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource |
| [archive_file.cloudwatch_slack_alerts_lambda](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
Expand All @@ -63,9 +74,12 @@ for dxw's Dalmatian hosting platform.
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | AWS region in which to launch resources | `string` | n/a | yes |
| <a name="input_cloudtrail_log_prefix"></a> [cloudtrail\_log\_prefix](#input\_cloudtrail\_log\_prefix) | Cloudtrail log prefix | `string` | n/a | yes |
| <a name="input_cloudtrail_log_retention"></a> [cloudtrail\_log\_retention](#input\_cloudtrail\_log\_retention) | Cloudtrail log retention in days. Set to 0 to keep all logs. | `number` | n/a | yes |
| <a name="input_cloudwatch_opsgenie_alerts_sns_endpoint"></a> [cloudwatch\_opsgenie\_alerts\_sns\_endpoint](#input\_cloudwatch\_opsgenie\_alerts\_sns\_endpoint) | The Opsgenie SNS endpoint. https://support.atlassian.com/opsgenie/docs/integrate-opsgenie-with-incoming-amazon-sns/ | `string` | n/a | yes |
| <a name="input_cloudwatch_opsgenie_alerts_sns_kms_encryption"></a> [cloudwatch\_opsgenie\_alerts\_sns\_kms\_encryption](#input\_cloudwatch\_opsgenie\_alerts\_sns\_kms\_encryption) | Use KMS encryption with the Opsgenie Alerts SNS topic | `bool` | n/a | yes |
| <a name="input_cloudwatch_slack_alerts_channel"></a> [cloudwatch\_slack\_alerts\_channel](#input\_cloudwatch\_slack\_alerts\_channel) | The Slack channel for CloudWatch alerts | `string` | n/a | yes |
| <a name="input_cloudwatch_slack_alerts_hook_url"></a> [cloudwatch\_slack\_alerts\_hook\_url](#input\_cloudwatch\_slack\_alerts\_hook\_url) | The Slack webhook URL for CloudWatch alerts | `string` | n/a | yes |
| <a name="input_enable_cloudtrail"></a> [enable\_cloudtrail](#input\_enable\_cloudtrail) | Enable Cloudtrail | `bool` | n/a | yes |
| <a name="input_enable_cloudwatch_opsgenie_alerts"></a> [enable\_cloudwatch\_opsgenie\_alerts](#input\_enable\_cloudwatch\_opsgenie\_alerts) | Enable CloudWatch Opsgenie alerts. This creates an SNS topic to which alerts and pipelines can send messages, which are then sent to the Opsgenie SNS endpoint. | `bool` | n/a | yes |
| <a name="input_enable_cloudwatch_slack_alerts"></a> [enable\_cloudwatch\_slack\_alerts](#input\_enable\_cloudwatch\_slack\_alerts) | Enable CloudWatch Slack alerts. This creates an SNS topic to which alerts and pipelines can send messages, which are then picked up by a Lambda function that forwards them to a Slack webhook. | `bool` | n/a | yes |
| <a name="input_enable_s3_tfvars"></a> [enable\_s3\_tfvars](#input\_enable\_s3\_tfvars) | enable\_s3\_tfvars | `bool` | n/a | yes |
| <a name="input_project_name"></a> [project\_name](#input\_project\_name) | Project name to be used as a prefix for all resources | `string` | n/a | yes |
Expand Down
116 changes: 116 additions & 0 deletions cloudwatch-opsgenie-alerts-sns.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
resource "aws_kms_key" "cloudwatch_opsgenie_alerts_sns" {
count = local.cloudwatch_opsgenie_alerts_sns_kms_encryption ? 1 : 0

description = "This key is used to encrypt data in SNS for the CloudWatch Opsgenie Alerts (${local.project_name})"
deletion_window_in_days = 10
enable_key_rotation = true

policy = templatefile(
"${path.module}/policies/kms-key-policy-sns-topic.json.tpl",
{
services = jsonencode(["cloudwatch.amazonaws.com"]),
sns_topic_arn = "arn:aws:sns:${local.aws_region}:${local.aws_account_id}:${local.project_name}-cloudwatch-opsgenie-alerts"
}
)
}

resource "aws_kms_alias" "cloudwatch_opsgenie_alerts_sns" {
count = local.cloudwatch_opsgenie_alerts_sns_kms_encryption ? 1 : 0

name = "alias/${local.project_name}-cloudwatch-opsgenie-alerts-sns"
target_key_id = aws_kms_key.cloudwatch_opsgenie_alerts_sns[0].key_id
}

resource "aws_sns_topic" "cloudwatch_opsgenie_alerts" {
count = local.enable_cloudwatch_opsgenie_alerts ? 1 : 0

name = "${local.project_name}-cloudwatch-opsgenie-alerts"
kms_master_key_id = local.cloudwatch_opsgenie_alerts_sns_kms_encryption ? aws_kms_alias.cloudwatch_opsgenie_alerts_sns[0].name : null
}

resource "aws_kms_key" "cloudwatch_opsgenie_alerts_sns_us_east_1" {
count = local.cloudwatch_opsgenie_alerts_sns_kms_encryption ? 1 : 0

provider = aws.useast1

description = "This key is used to encrypt data in SNS for the CloudWatch Opsgenie Alerts (${local.project_name})"
deletion_window_in_days = 10
enable_key_rotation = true

policy = templatefile(
"${path.module}/policies/kms-key-policy-sns-topic.json.tpl",
{
services = jsonencode(["cloudwatch.amazonaws.com"]),
sns_topic_arn = "arn:aws:sns:us-east-1:${local.aws_account_id}:${local.project_name}-cloudwatch-opsgenie-alerts"
}
)
}

resource "aws_kms_alias" "cloudwatch_opsgenie_alerts_sns_us_east_1" {
count = local.cloudwatch_opsgenie_alerts_sns_kms_encryption ? 1 : 0

provider = aws.useast1

name = "alias/${local.project_name}-cloudwatch-opsgenie-alerts-sns"
target_key_id = aws_kms_key.cloudwatch_opsgenie_alerts_sns_us_east_1[0].key_id
}


resource "aws_sns_topic" "cloudwatch_opsgenie_alerts_us_east_1" {
count = local.enable_cloudwatch_opsgenie_alerts ? 1 : 0

provider = aws.useast1

name = "${local.project_name}-cloudwatch-opsgenie-alerts"
kms_master_key_id = local.cloudwatch_opsgenie_alerts_sns_kms_encryption ? aws_kms_alias.cloudwatch_opsgenie_alerts_sns_us_east_1[0].name : null
}

resource "aws_sns_topic_policy" "sns_cloudwatch_opsgenie_alerts" {
count = local.enable_cloudwatch_opsgenie_alerts ? 1 : 0

arn = aws_sns_topic.cloudwatch_opsgenie_alerts[0].arn
policy = templatefile(
"${path.root}/policies/sns-events-policy.json.tpl",
{
sns_arn = aws_sns_topic.cloudwatch_opsgenie_alerts[0].arn
aws_account_id = local.aws_account_id
}
)
}

resource "aws_sns_topic_policy" "sns_cloudwatch_opsgenie_alerts_us_east_1" {
count = local.enable_cloudwatch_opsgenie_alerts ? 1 : 0

provider = aws.useast1

arn = aws_sns_topic.cloudwatch_opsgenie_alerts_us_east_1[0].arn
policy = templatefile(
"${path.root}/policies/sns-events-policy.json.tpl",
{
sns_arn = aws_sns_topic.cloudwatch_opsgenie_alerts_us_east_1[0].arn
aws_account_id = local.aws_account_id
}
)
}

resource "aws_sns_topic_subscription" "cloudwatch_opsgenie_alerts_subscription" {
count = local.enable_cloudwatch_opsgenie_alerts ? 1 : 0

topic_arn = aws_sns_topic.cloudwatch_opsgenie_alerts[0].arn
protocol = "https"
endpoint = local.cloudwatch_opsgenie_alerts_sns_endpoint
endpoint_auto_confirms = true
confirmation_timeout_in_minutes = 10
}

resource "aws_sns_topic_subscription" "cloudwatch_opsgenie_alerts_subscription_us_east_1" {
count = local.enable_cloudwatch_opsgenie_alerts ? 1 : 0

provider = aws.useast1

topic_arn = aws_sns_topic.cloudwatch_opsgenie_alerts_us_east_1[0].arn
protocol = "https"
endpoint = local.cloudwatch_opsgenie_alerts_sns_endpoint
endpoint_auto_confirms = true
confirmation_timeout_in_minutes = 10
}
4 changes: 4 additions & 0 deletions locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ locals {
cloudwatch_slack_alerts_hook_url = var.cloudwatch_slack_alerts_hook_url
cloudwatch_slack_alerts_channel = var.cloudwatch_slack_alerts_channel

enable_cloudwatch_opsgenie_alerts = var.enable_cloudwatch_opsgenie_alerts
cloudwatch_opsgenie_alerts_sns_kms_encryption = var.cloudwatch_opsgenie_alerts_sns_kms_encryption && local.enable_cloudwatch_opsgenie_alerts
cloudwatch_opsgenie_alerts_sns_endpoint = var.cloudwatch_opsgenie_alerts_sns_endpoint

default_tags = {
Project = local.project_name,
}
Expand Down
16 changes: 16 additions & 0 deletions policies/kms-key-policy-sns-topic.json.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"Effect": "Allow",
"Principal": {
"Service": ${services}
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:EncryptionContext:aws:sns:topicArn": "${sns_topic_arn}"
}
}
}
9 changes: 9 additions & 0 deletions providers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,12 @@ provider "aws" {
tags = local.default_tags
}
}

provider "aws" {
region = "us-east-1"
alias = "useast1"

default_tags {
tags = local.default_tags
}
}
15 changes: 15 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,18 @@ variable "cloudwatch_slack_alerts_channel" {
description = "The Slack channel for CloudWatch alerts"
type = string
}

variable "enable_cloudwatch_opsgenie_alerts" {
description = "Enable CloudWatch Opsgenie alerts. This creates an SNS topic to which alerts and pipelines can send messages, which are then sent to the Opsgenie SNS endpoint."
type = bool
}

variable "cloudwatch_opsgenie_alerts_sns_endpoint" {
description = "The Opsgenie SNS endpoint. https://support.atlassian.com/opsgenie/docs/integrate-opsgenie-with-incoming-amazon-sns/"
type = string
}

variable "cloudwatch_opsgenie_alerts_sns_kms_encryption" {
description = "Use KMS encryption with the Opsgenie Alerts SNS topic"
type = bool
}

0 comments on commit e18fefe

Please sign in to comment.