feat(aws): send notifications to slack channels

This commit is contained in:
Michele Cereda
2025-02-03 23:20:08 +01:00
parent b0b3caebd0
commit 8b626edc28
9 changed files with 530 additions and 2 deletions

View File

@@ -13,5 +13,7 @@ MD033: # no-inline-html
- br
- code
- details
- i
- summary
- sup
- u

View File

@@ -105,6 +105,8 @@ One can can rapidly remapping addresses to other instances in one's account and
| [S3] | Storage |
| [Sagemaker] | Machine learning |
| [Security Hub] | Aggregator for security findings |
| [SNS] | Pub/sub message delivery |
| [SQS] | Queues |
[Service icons][aws icons] are publicly available for diagrams and such.
Public service IP address ranges are [available in JSON form][aws public ip address ranges now available in json form]
@@ -510,6 +512,8 @@ machine if not.
[route53]: route53.md
[s3]: s3.md
[sagemaker]: sagemaker.md
[sns]: sns.md
[sqs]: sqs.md
<!-- Upstream -->
[access aws services through aws privatelink]: https://docs.aws.amazon.com/vpc/latest/privatelink/privatelink-access-aws-services.html

View File

@@ -0,0 +1,81 @@
# Chatbot
Enables using messaging program chat rooms to monitor, and respond to, operational events in AWS by processing service
notifications from SNS and forwarding them to chat rooms like Slack channels.
One can also run AWS CLI commands in chat channels using Chatbot.
1. [TL;DR](#tldr)
1. [Further readings](#further-readings)
1. [Sources](#sources)
## TL;DR
Chatbot has **no** additional charge, minimum fees nor upfront commitments.<br/>
One will pay for the underlying services (SNS, SQS, CloudWatch, …).
Supports Amazon Chime, Microsoft Teams, and [Slack] at the time of writing.
<!-- Uncomment if used
<details>
<summary>Setup</summary>
```sh
```
</details>
-->
<details>
<summary>Usage</summary>
```sh
# List Slack workspaces.
aws chatbot describe-slack-workspaces
aws chatbot describe-slack-workspaces --query 'SlackWorkspaces'
# Show Slack channel configurations.
aws chatbot describe-slack-channel-configurations
aws chatbot describe-slack-channel-configurations --query 'SlackChannelConfigurations'
```
</details>
<!-- Uncomment if used
<details>
<summary>Real world use cases</summary>
```sh
```
</details>
-->
## Further readings
- [Website]
- [Documentation]
- [Slack]
- [SNS]
### Sources
- [What is AWS Chatbot?]
<!--
Reference
═╬═Time══
-->
<!-- In-article sections -->
<!-- Knowledge base -->
[slack]: ../../slack.md
[sns]: sns.md
<!-- Files -->
<!-- Upstream -->
[documentation]: https://docs.aws.amazon.com/chatbot/
[website]: https://aws.amazon.com/chatbot/
[what is aws chatbot?]: https://docs.aws.amazon.com/chatbot/latest/adminguide/what-is.html
<!-- Others -->

View File

@@ -0,0 +1,187 @@
# Simple Notification Service
Managed pub/sub message delivery service.
1. [TL;DR](#tldr)
1. [Connect a Slack channel to SNS](#connect-a-slack-channel-to-sns)
1. [Further readings](#further-readings)
1. [Sources](#sources)
## TL;DR
_Publishers_ (or _producers_) send messages to a _topic_.<br/>
Topics are logical access points acting as communication channels for multiple _endpoints_ like SQS, emails, lambda,
and others.
SNS can be also used to send notifications to HTTP(S) endpoints such as Webhook URLs.<br/>
Anyway, SNS does **not** support sending requests using JSON key-value pairs, which some webhooks require (i.e. Slack).
_Subscribers_ (or _consumers_) subscribe to the topic and receive published messages using a supported endpoint type.
<details>
<summary><i>Standard</i> topics</summary>
- Do **not** enforce strict message ordering, grouping, **nor** deduplication.<br/>
Consumers of the queue may receive messages out of order, and more than once.
- Support **all** delivery protocols.
</details>
<details style="padding-bottom: 1em">
<summary><i>FIFO</i> topics</summary>
- Integrate with FIFO queues in [SQS].
- **Do** enforce strict message ordering, grouping, and deduplication.<br/>
They always deliver messages to subscribed [SQS] queues in the **exact** order in which the messages are published to
the topic, and **only once**.
- **Do** ensure strict message ordering, message grouping, and deduplication.
- Allowing FIFO and standard queues to subscribe for message processing.
</details>
By default, only the topic's owner can publish or subscribe to the topic.<br/>
Configure additional access permissions by expanding the topic's Access policy.
<!-- Uncomment if used
<details>
<summary>Setup</summary>
```sh
```
</details>
-->
<details>
<summary>Usage</summary>
```sh
# List topics.
aws sns list-topics
# Get information about topics.
aws sns get-topic-attributes --topic-arn 'arn:aws:sns:eu-west-1:012345678901:aSucculentTopic'
# List subscriptions.
aws sns list-subscriptions
aws sns list-subscriptions --query 'Subscriptions'
aws sns list-subscriptions-by-topic --topic-arn 'arn:aws:sns:eu-west-1:012345678901:aSucculentTopic'
# Get information about subscriptions.
aws sns get-subscription-attributes \
--subscription-arn 'arn:aws:sns:eu-west-1:012345678901:aSucculentTopic:abcdef01-2345-6789-abcd-ef0123456789'
```
</details>
<!-- Uncomment if used
<details>
<summary>Real world use cases</summary>
```sh
```
</details>
-->
## Connect a Slack channel to SNS
Refer [How to Connect AWS SNS to Slack using Webhooks: Easy Step-by-Step Explanation].
SNS does **not** currently support integrating directly with third-party applications.<br/>
Leverage [Slack's incoming webhooks] or create a [Chatbot] configuration for the destination Slack channel.
<details>
<summary>Webhook</summary>
SNS does **not** currently support sending requests using JSON key-value pairs, and Slack's webhooks require JSON
requests to include a message string as the value of the `text` key.<br/>
To solve this, use a Lambda function to modify the SNS message's body JSON document for the webhook endpoint.
Procedure:
1. Ensure the existence of a [Slack incoming webhook][slack's incoming webhooks] to send requests to.
1. Create a topic.<br/>
The _standard_ type is usually enough.
1. Create a Lambda function.<br/>
And test it works.
1. Add a topic trigger to the function.
<details>
<details>
<summary>Chatbot</summary>
1. Ensure the existence of a [Slack incoming webhook][slack's incoming webhooks] to send requests to.
1. Create a topic.<br/>
The _standard_ type is usually enough.
1. Create a IAM Role for the Chatbot configuration to use.
<details>
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "chatbot.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
```
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Autogenerated-AWS-Chatbot-NotificationsOnly-Policy",
"Effect": "Allow",
"Action": [
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*"
],
"Resource": "*"
}
]
}
```
</details>
1. Create a Chatbot configuration for the destination Slack channel.
<details>
## Further readings
- [SQS]
### Sources
- [What is Amazon SNS?]
- [How To Set Up A Slack Channel To Be An AWS SNS Subscriber]
- [How to Connect AWS SNS to Slack using Webhooks: Easy Step-by-Step Explanation]
<!--
Reference
═╬═Time══
-->
<!-- In-article sections -->
<!-- Knowledge base -->
[chatbot]: chatbot.md
[sqs]: sqs.md
[slack's incoming webhooks]: ../../slack.md#incoming-webhooks
<!-- Files -->
<!-- Upstream -->
[what is amazon sns?]: https://docs.aws.amazon.com/sns/latest/dg/welcome.html
<!-- Others -->
[how to set up a slack channel to be an aws sns subscriber]: https://medium.com/cohealo-engineering/how-set-up-a-slack-channel-to-be-an-aws-sns-subscriber-63b4d57ad3ea
[how to connect aws sns to slack using webhooks: easy step-by-step explanation]: https://hevodata.com/learn/sns-to-slack/

View File

@@ -0,0 +1,62 @@
# Simple Queue Service
Managed queues.
1. [TL;DR](#tldr)
1. [Further readings](#further-readings)
1. [Sources](#sources)
## TL;DR
<!-- Uncomment if used
<details>
<summary>Setup</summary>
```sh
```
</details>
-->
<!-- Uncomment if used
<details>
<summary>Usage</summary>
```sh
```
</details>
-->
<!-- Uncomment if used
<details>
<summary>Real world use cases</summary>
```sh
```
</details>
-->
## Further readings
- [SNS]
### Sources
- [What is Amazon Simple Queue Service?]
<!--
Reference
═╬═Time══
-->
<!-- In-article sections -->
<!-- Knowledge base -->
[sns]: sns.md
<!-- Files -->
<!-- Upstream -->
[what is amazon simple queue service?]: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html
<!-- Others -->

View File

@@ -3,6 +3,8 @@
1. [TL;DR](#tldr)
1. [Add custom emoji](#add-custom-emoji)
1. [Give aliases to existing emojis](#give-aliases-to-existing-emojis)
1. [Apps](#apps)
1. [Incoming webhooks](#incoming-webhooks)
1. [Further readings](#further-readings)
1. [Sources](#sources)
@@ -23,8 +25,8 @@ mas install '803453959'
```sh
# Send notifications to channels
curl -X POST -H 'Content-type: application/json' \
--data '{"text": "Staging DB restore completed successfully"}' \
curl -X 'POST' -H 'Content-type: application/json' \
--data '{"text": "Hello, World!"}' \
'https://hooks.slack.com/services/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'
```
@@ -57,15 +59,38 @@ Check out [slackmojis] for some common reactions.
1. Choose the image.
1. Give it an alias.
## Apps
Direct links:
- [Create a new App](https://api.slack.com/apps?new_app=1).
## Incoming webhooks
Refer [Sending messages using incoming webhooks] and [Setting Up Slack Webhook URL Simplified 101].
1. Enable Incoming Webhooks for a Slack app.<br/>
_Features__Incoming Webhooks__Activate Incoming Webhooks_.
1. Create a new Webhook URL and authorize it (or request authorization for it).
1. Install the app in the workspace.
1. Send a test request to the webhook.
```sh
curl -X 'POST' -H 'Content-type: application/json' \
'https://hooks.slack.com/services/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' --data '{"text": "Hello, World!"}'
```
## Further readings
- [Website]
- [Sending messages using incoming webhooks]
- [Posting messages using curl]
### Sources
- [Slackmojis]
- [Slack Notifications for Ansible Tower (AWX)]
- [Setting Up Slack Webhook URL Simplified 101]
<!--
Reference
@@ -77,8 +102,10 @@ Check out [slackmojis] for some common reactions.
<!-- Files -->
<!-- Upstream -->
[posting messages using curl]: https://api.slack.com/tutorials/tracks/posting-messages-with-curl
[sending messages using incoming webhooks]: https://api.slack.com/messaging/webhooks
[website]: https://slack.com/
<!-- Others -->
[setting up slack webhook url simplified 101]: https://hevodata.com/learn/slack-webhook-url/
[slack notifications for ansible tower (awx)]: https://mpolinowski.github.io/docs/DevOps/Ansible/2021-04-30-ansible-tower-slack-notifications/2021-04-30/
[slackmojis]: https://slackmojis.com/

View File

@@ -24,6 +24,34 @@ aws autoscaling cancel-instance-refresh --auto-scaling-group-name 'ProductionSer
aws autoscaling rollback-instance-refresh --auto-scaling-group-name 'ProductionServers'
###
# Chatbot
# ------------------
###
# List Slack workspaces
aws chatbot describe-slack-workspaces
aws chatbot describe-slack-workspaces --query 'SlackWorkspaces'
# Show Slack channel configurations
aws chatbot describe-slack-channel-configurations
aws chatbot describe-slack-channel-configurations --query 'SlackChannelConfigurations'
###
# CloudWatch
# ------------------
###
# List available metrics
aws cloudwatch list-metrics --namespace 'AWS/EC2'
aws cloudwatch list-metrics --namespace 'AWS/EC2' --metric-name 'CPUUtilization'
aws cloudwatch list-metrics --namespace 'AWS/EC2' --dimensions 'Name=InstanceId,Value=i-1234567890abcdef0' --query 'Metrics[].MetricName'
# Show alarms information
aws cloudwatch describe-alarms-for-metric --metric-name 'CPUUtilization' --namespace 'AWS/EC2' --dimensions 'Name=InstanceId,Value=i-1234567890abcdef0'
###
# Cognito
# ------------------
@@ -347,3 +375,23 @@ aws s3api list-objects-v2 --bucket 'backup'
aws s3api list-objects-v2 --bucket 'backup' --query "Contents[?LastModified>='2022-01-05T08:05:37+00:00'].Key"
aws s3api list-buckets --output 'text' --query 'Buckets[].Name' | xargs -pn '1' aws s3api list-multipart-uploads --bucket
###
# SNS
# ------------------
###
# List topics
aws sns list-topics
# Get information about topics
aws sns get-topic-attributes --topic-arn 'arn:aws:sns:eu-west-1:012345678901:aSucculentTopic'
# List subscriptions
aws sns list-subscriptions
aws sns list-subscriptions --query 'Subscriptions'
aws sns list-subscriptions-by-topic --topic-arn 'arn:aws:sns:eu-west-1:012345678901:aSucculentTopic'
# Get information about subscriptions
aws sns get-subscription-attributes --subscription-arn 'arn:aws:sns:eu-west-1:012345678901:aSucculentTopic:abcdef01-2345-6789-abcd-ef0123456789'

View File

@@ -0,0 +1,116 @@
import * as aws from "@pulumi/aws";
const instance_output = new aws.ec2.getInstanceOutput({
filters: [{
name: "tag:Name",
values: [ "instance-name-tag" ],
}],
});
const iamRole = new aws.iam.Role(
"awsChatbot",
{
name: "AWSChatbotRole",
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: {
Service: "chatbot.amazonaws.com",
},
Action: "sts:AssumeRole",
}],
}),
},
);
new aws.iam.RolePolicy(
"awsChatbot",
{
name: "AllowRoleFunctions",
description: "NotificationsOnly policy for AWS-Chatbot",
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*",
],
"Resource": "*",
}],
}),
},
);
const notifications_snsTopic = new aws.sns.Topic(
"notifications",
{ name: "notifications" },
);
new aws.sns.TopicSubscription(
// FIXME: requires manual confirmation from email
"notifications-email",
{
topic: notifications_snsTopic.arn,
protocol: "email",
endpoint: "infra@example.org",
},
);
new aws.chatbot.SlackChannelConfiguration(
"notifications-channel",
{
configurationName: "Notifications2Channel",
slackTeamId: "T00000000",
slackChannelId: "C0000000000",
snsTopicArns: [ notifications_snsTopic.arn ],
iamRoleArn: iamRole.arn,
guardrailPolicyArns: [ "arn:aws:iam::aws:policy/ReadOnlyAccess" ],
},
);
new aws.cloudwatch.MetricAlarm(
"prometheusServer_systemStatus",
{
name: "PrometheusServer_SystemStatus",
alarmDescription: "Notify and recover when the System status check fails 5 consecutive times over 5 minutes.",
namespace: "AWS/EC2",
dimensions: {
InstanceId: instance_output.id,
},
metricName: "StatusCheckFailed_System",
statistic: "Maximum",
unit: "Count",
comparisonOperator: "GreaterThanOrEqualToThreshold",
threshold: 1,
evaluationPeriods: 5,
period: 60,
alarmActions: [
notifications_snsTopic.arn,
"arn:aws:automate:eu-west-1:ec2:recover",
],
},
);
new aws.cloudwatch.MetricAlarm(
"prometheusServer_instanceStatus",
{
name: "PrometheusServer_instanceStatus",
alarmDescription: "Notify and reboot when the Instance status check fails 5 consecutive times over 5 minutes.",
namespace: "AWS/EC2",
dimensions: {
InstanceId: instance_output.id,
},
metricName: "StatusCheckFailed_Instance",
statistic: "Maximum",
unit: "Count",
comparisonOperator: "GreaterThanOrEqualToThreshold",
threshold: 1,
evaluationPeriods: 5,
period: 60,
alarmActions: [
notifications_snsTopic.arn,
"arn:aws:swf:eu-west-1:012345678901:action/actions/AWS_EC2.InstanceId.Reboot/1.0",
],
},
);

View File

@@ -87,3 +87,4 @@ pulumi import 'aws:ec2/securityGroup:SecurityGroup' 'internalOps' 'sg-0123456789
pulumi import 'aws:iam/user:User' 'jimmy' 'jimmy' --generate-code='false'
pulumi import 'aws:route53/record:Record' 'hoppscotch' 'ZGG4442BC3E8M_hoppscotch.example.org_A'
pulumi import 'aws:cloudwatch/metricAlarm:MetricAlarm' 'prometheus-ec2-CPUUtilization' 'prometheus-ec2-CPUUtilization-drc5644'
pulumi import 'aws:chatbot/slackChannelConfiguration:SlackChannelConfiguration' 'alarms' 'arn:aws:chatbot::012345678901:chat-configuration/slack-channel/alarms'