Skip to content

Commit

Permalink
Merge pull request #13 from DNXLabs/feature/refactor-awscc-teams-slack
Browse files Browse the repository at this point in the history
Refactoring with awscc
  • Loading branch information
adenot authored Jul 16, 2024
2 parents 4c6e3ba + f5f0dc8 commit 280c3f2
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 103 deletions.
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,26 @@ In addition you have the option to:
| Name | Version |
|------|---------|
| aws | n/a |
| awscc | n/a |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| alarm\_sns\_topic\_arns | ARN of SNS Topic(s) to connect to AWS Chatbot | `any` | n/a | yes |
| enabled | If true, will create aws chatboot and integrate to slack | `string` | `"false"` | no |
| account\_ids | list of accounts that can send notifications | `list` | `[]` | no |
| logging\_level | Specifies the logging level for this configuration. This property affects the log entries pushed to Amazon CloudWatch Logs. Logging levels include ERROR, INFO, or NONE. | `string` | `"ERROR"` | no |
| org\_name | Name for this organization | `any` | n/a | yes |
| slack\_channel\_id | Slack channel id to send budget notfication using AWS Chatbot | `string` | `""` | no |
| slack\_ids | Use to define additional slack channels. Format: [ { channel = xxx, workspace=xxx } | `any` | `{}` | no |
| slack\_workspace\_id | Slack workspace id to send budget notfication using AWS Chatbot | `string` | `""` | no |
| slack\_targets | Use to define additional slack channels. Format: [ { slack\_channel\_name=xxxx , slack\_channel\_id=xxx, slack\_workspace\_id=xxx }] | `any` | `[]` | no |
| tags | Specifies object tags key and value. This applies to all resources created by this module. | `map(string)` | <pre>{<br> "Terraform": true<br>}</pre> | no |
| teams\_targets | Use to define additional slack channels. Format: [ { team\_id=xxxx , teams\_channel\_id=xxx, teams\_tenant\_id=xxx }] | `any` | `[]` | no |
| workspace\_name | Description for the chat integration | `any` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| role\_arn | The ARN of the Chatbot role |
| role\_name | The name of the Chatbot role |
| slack\_arns | A map of the Chatbot Slack configurations ARNs |
| chatbot\_role\_arn | The ARN of the Chatbot role |
| chatbot\_role\_name | The name of the Chatbot role |

<!--- END_TF_DOCS --->

Expand Down
1 change: 1 addition & 0 deletions _data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data "aws_region" "current" {}
22 changes: 0 additions & 22 deletions _locals.tf
Original file line number Diff line number Diff line change
@@ -1,23 +1 @@

locals {

primary_name = "${var.org_name}-${var.workspace_name}"

primary_target = (var.slack_channel_id != "" && var.slack_workspace_id != "") ? {
(local.primary_name) = {
channel = var.slack_channel_id
workspace = var.slack_workspace_id
} } : {}

# Priority to primary target if names conflict

slack_targets = merge(var.slack_ids, local.primary_target)

# Outputs

stacks = (var.enabled ? aws_cloudformation_stack.tf_chatbot : {})
slack_arns = { for k, v in local.stacks : k => v.outputs.ConfigurationArn }
}

# For debugging only
#output stacks { value = local.stacks }
13 changes: 4 additions & 9 deletions _outputs.tf
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@

output "slack_arns" {
description = "A map of the Chatbot Slack configurations ARNs"
value = local.slack_arns
}

output "role_name" {
output chatbot_role_name {
description = "The name of the Chatbot role"
value = var.enabled ? aws_iam_role.chatbot[0].name : ""
value = try(awscc_iam_role.chatbot.role_name, "")
}

output "role_arn" {
output chatbot_role_arn {
description = "The ARN of the Chatbot role"
value = var.enabled ? aws_iam_role.chatbot[0].arn : ""
value = try(awscc_iam_role.chatbot.arn, "")
}
52 changes: 33 additions & 19 deletions _variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,38 @@ variable "org_name" {
variable "workspace_name" {
description = "Description for the chat integration"
}
variable "enabled" {
description = "If true, will create aws chatboot and integrate to slack"
default = "false"
}
variable "slack_channel_id" {
description = "Slack channel id to send budget notfication using AWS Chatbot"
default = ""
}
variable "slack_workspace_id" {
description = "Slack workspace id to send budget notfication using AWS Chatbot"
default = ""
}
# variable "enabled" {
# description = "If true, will create aws chatboot and integrate to slack/teams"
# default = false
# type = bool
# }
# variable "slack_channel_id" {
# description = "Slack channel id to send budget notfication using AWS Chatbot"
# default = ""
# }
# variable "slack_workspace_id" {
# description = "Slack workspace id to send budget notfication using AWS Chatbot"
# default = ""
# }


variable "slack_ids" {
description = "Use to define additional slack channels. Format: [ { channel = xxx, workspace=xxx }"
default = {}
variable "slack_targets" {
description = "Use to define additional slack channels. Format: [ { slack_channel_name=xxxx , slack_channel_id=xxx, slack_workspace_id=xxx }]"
default = []
type = any
}

variable "alarm_sns_topic_arns" {
description = "ARN of SNS Topic(s) to connect to AWS Chatbot"
# list of string (accept string for backwards compatibility)
type = any
variable "teams_targets" {
description = "Use to define additional slack channels. Format: [ { team_id=xxxx , teams_channel_id=xxx, teams_tenant_id=xxx }]"
default = []
type = any
}

# variable "alarm_sns_topic_arns" {
# description = "ARN of SNS Topic(s) to connect to AWS Chatbot"
# type = list
# default = []
# }

variable "tags" {
description = "Specifies object tags key and value. This applies to all resources created by this module."
Expand All @@ -42,3 +49,10 @@ variable "logging_level" {
description = "Specifies the logging level for this configuration. This property affects the log entries pushed to Amazon CloudWatch Logs. Logging levels include ERROR, INFO, or NONE."
default = "ERROR"
}

variable "account_ids" {
description = "list of accounts that can send notifications"
type = list
default = []
}

79 changes: 34 additions & 45 deletions chatbot.tf
Original file line number Diff line number Diff line change
@@ -1,52 +1,41 @@

# Note that the same configuration name cannot appear more than once, even in different slack
# workspaces.

resource "aws_cloudformation_stack" "tf_chatbot" {
for_each = var.enabled ? local.slack_targets : {}

name = "terraform-chatbot-${each.key}"

parameters = {
ConfigurationNameParam = each.key
IamRoleArnArnParam = aws_iam_role.chatbot.*.arn[0]
SnsTopicArnsParam = join(",", flatten([var.alarm_sns_topic_arns]))
SlackChannelIdParam = each.value.channel
SlackWorkspaceIdParam = each.value.workspace
LoggingLevelParam = var.logging_level
}
template_body = file("${path.module}/cf-chatbot.yml")
}

#--------------

resource "aws_iam_role" "chatbot" {
count = var.enabled ? 1 : 0
name = "${var.org_name}-${var.workspace_name}-chatbot-role"
assume_role_policy = data.aws_iam_policy_document.assume_role_chatbot.*.json[0]
tags = var.tags
resource "awscc_chatbot_slack_channel_configuration" "slack" {
for_each = {for config in var.slack_targets : config.slack_channel_name => config}

configuration_name = "slack-config-${each.value.slack_channel_name}"
iam_role_arn = awscc_iam_role.chatbot.arn
slack_channel_id = each.value.slack_channel_id
slack_workspace_id = each.value.slack_workspace_id
sns_topic_arns = [aws_sns_topic.chatbot[each.value.slack_channel_name].arn] #var.alarm_sns_topic_arns
logging_level = try(each.value.logging_level, "NONE")
}

#--------------
resource "awscc_chatbot_microsoft_teams_channel_configuration" "microsoft" {
for_each = {for config in var.teams_targets : config.teams_channel_name => config}

resource "aws_iam_role_policy_attachment" "chatbot_policy" {
count = var.enabled ? 1 : 0
role = aws_iam_role.chatbot.*.name[0]
policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
configuration_name = "teams-config-${each.value.teams_channel_name}"
iam_role_arn = awscc_iam_role.chatbot.arn
team_id = each.value.team_id
teams_channel_id = each.value.teams_channel_id
teams_tenant_id = each.value.teams_tenant_id
sns_topic_arns = [aws_sns_topic.chatbot[each.value.teams_channel_name].arn]
logging_level = try(each.value.logging_level, "NONE")
}

data "aws_iam_policy_document" "assume_role_chatbot" {
count = var.enabled ? 1 : 0
statement {

principals {
type = "Service"
identifiers = [
"chatbot.amazonaws.com"
]
}
actions = [
"sts:AssumeRole",
resource "awscc_iam_role" "chatbot" {
role_name = "chatBot-integration-role"
assume_role_policy_document = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "chatbot.amazonaws.com"
}
},
]
}
}
})
managed_policy_arns = ["arn:aws:iam::aws:policy/AWSResourceExplorerReadOnlyAccess", "arn:aws:iam::aws:policy/CloudWatchEventsReadOnlyAccess", "arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess"]
}
57 changes: 57 additions & 0 deletions sns.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
resource "aws_sns_topic" "chatbot" {
for_each = {for config in var.slack_targets : config.slack_channel_name => config}

name = "chatbot-${each.value.slack_channel_name}"
# kms_master_key_id = var.kms_key default key does not allow cloudwatch alarms to publish
tags = var.tags
}

resource "aws_sns_topic_policy" "alarms" {
for_each = {for config in var.slack_targets : config.slack_channel_name => config}
arn = aws_sns_topic.chatbot[each.value.slack_channel_name].arn
policy = data.aws_iam_policy_document.alarms_policy[each.value.slack_channel_name].json
}

data "aws_iam_policy_document" "alarms_policy" {
for_each = {for config in var.slack_targets : config.slack_channel_name => config}

policy_id = "allow-org-accounts"


statement {
actions = ["sns:Publish"]
effect = "Allow"
principals {
type = "Service"
identifiers = [ "cloudwatch.amazonaws.com","events.amazonaws.com"]
}
resources = [aws_sns_topic.chatbot[each.value.slack_channel_name].arn]
sid = "allow-cloudwatch-events"
}

statement {
actions = [
"SNS:GetTopicAttributes",
"SNS:SetTopicAttributes",
"SNS:AddPermission",
"SNS:RemovePermission",
"SNS:DeleteTopic",
"SNS:Subscribe",
"SNS:ListSubscriptionsByTopic",
"SNS:Publish",
"SNS:Receive"
]
effect = "Allow"
condition {
test = "StringEquals"
variable = "AWS:SourceOwner"
values = var.account_ids
}
principals {
type = "AWS"
identifiers = ["*"]
}
resources = [aws_sns_topic.chatbot[each.value.slack_channel_name].arn]
sid = "allow-org-accounts"
}
}

0 comments on commit 280c3f2

Please sign in to comment.