diff --git a/README.md b/README.md
index 9f10588..5bf4b6b 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@ for dxw's Dalmatian hosting platform.
|------|---------|
| [archive](#provider\_archive) | 2.4.0 |
| [aws](#provider\_aws) | 5.21.0 |
+| [aws.useast1](#provider\_aws.useast1) | 5.21.0 |
## Modules
@@ -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 |
@@ -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 |
@@ -63,9 +74,12 @@ for dxw's Dalmatian hosting platform.
| [aws\_region](#input\_aws\_region) | AWS region in which to launch resources | `string` | n/a | yes |
| [cloudtrail\_log\_prefix](#input\_cloudtrail\_log\_prefix) | Cloudtrail log prefix | `string` | n/a | yes |
| [cloudtrail\_log\_retention](#input\_cloudtrail\_log\_retention) | Cloudtrail log retention in days. Set to 0 to keep all logs. | `number` | n/a | yes |
+| [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 |
+| [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 |
| [cloudwatch\_slack\_alerts\_channel](#input\_cloudwatch\_slack\_alerts\_channel) | The Slack channel for CloudWatch alerts | `string` | n/a | yes |
| [cloudwatch\_slack\_alerts\_hook\_url](#input\_cloudwatch\_slack\_alerts\_hook\_url) | The Slack webhook URL for CloudWatch alerts | `string` | n/a | yes |
| [enable\_cloudtrail](#input\_enable\_cloudtrail) | Enable Cloudtrail | `bool` | n/a | yes |
+| [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 |
| [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 |
| [enable\_s3\_tfvars](#input\_enable\_s3\_tfvars) | enable\_s3\_tfvars | `bool` | n/a | yes |
| [project\_name](#input\_project\_name) | Project name to be used as a prefix for all resources | `string` | n/a | yes |
diff --git a/cloudwatch-opsgenie-alerts-sns.tf b/cloudwatch-opsgenie-alerts-sns.tf
new file mode 100644
index 0000000..3107ae6
--- /dev/null
+++ b/cloudwatch-opsgenie-alerts-sns.tf
@@ -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
+}
diff --git a/locals.tf b/locals.tf
index b408cb4..130881a 100644
--- a/locals.tf
+++ b/locals.tf
@@ -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,
}
diff --git a/policies/kms-key-policy-sns-topic.json.tpl b/policies/kms-key-policy-sns-topic.json.tpl
new file mode 100644
index 0000000..803a942
--- /dev/null
+++ b/policies/kms-key-policy-sns-topic.json.tpl
@@ -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}"
+ }
+ }
+}
diff --git a/providers.tf b/providers.tf
index 899804b..3bada62 100644
--- a/providers.tf
+++ b/providers.tf
@@ -5,3 +5,12 @@ provider "aws" {
tags = local.default_tags
}
}
+
+provider "aws" {
+ region = "us-east-1"
+ alias = "useast1"
+
+ default_tags {
+ tags = local.default_tags
+ }
+}
diff --git a/variables.tf b/variables.tf
index e0f6080..21155e5 100644
--- a/variables.tf
+++ b/variables.tf
@@ -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
+}