我可以在我们以外的地方发送一条关于云观察警报的短信吗?

时间:2016-01-07 00:13:38

标签: javascript amazon-web-services amazon-sns amazon-cloudwatch aws-lambda

看起来AWS不提供SMS作为美国东部以外的SNS主题订阅者的协议。我希望连接我的CloudWatch警报并在出现故障时收到短信,但无法将其发送到短信。

有没有办法做到这一点?

3 个答案:

答案 0 :(得分:9)

是<!/强>

经过一番挖掘,我能够让它发挥作用。它比仅选择一个主题或输入一个警报要复杂一点,但效果很好!

解决方案的关键是使用AWS的lambda函数!

数据流是这样的:

> Alarm triggered
>  -> Push notification to SNS
>  -> SNS posts to lambda
>  -> lambda reposts to SNS on us-east-1
>  -> subscriber receives message

只是服务:

> CloudWatch Alarm   (us-west-2) 
>  -> SNS            (us-west-2) 
>  -> Lambda         (us-west-2)
>  -> SNS            (us-east-1)
>  -> SMS subscriber (us-east-1)

我不会过多地谈论设置SNS或设置lambda,你可以浏览已经存在的示例。但是,我将分享我为执行此操作而编写的lambda代码。您可以使用发布消息到主题功能来测试它。

console.log('Loading function');

var Aws = require('aws-sdk');

var usEastSns = new Aws.SNS({
    accessKeyId: "ENTER YOUR ACCESS KEY HERE",
    secretAccessKey: "ENTER YOUR SECRET KEY HERE",
    region: "us-east-1",
    logger: console
});

exports.snsProxy = function(event, context) {
    var message = event.Records[0].Sns;
    console.log("received message: ", message);
    var newMessage = buildNewMessage(message);
    console.log("publishing: ", newMessage);
    usEastSns.publish(newMessage, function(err, data) {
        if (err) {
            console.log(err, err.stack); // an error occurred
        } else {
            // It's important that we succeed in the callback
            // otherwise it seems to succeed without sending
            console.log(data);           
            context.succeed(message);    
        }
    })
};

function buildNewMessage(message) {
    // For some reason the message that gets sent in the event
    // does not contain the same interface as what the library
    // expects so it needs to be created
    return {
        TargetArn: "ENTER YOUR ARN IN US EAST HERE",
        Message: message.Message,
        Subject: message.Subject,
        MessageAttributes: collectAttr(message.MessageAttributes)
    };
}

function collectAttr(attrs) {
    var newAttrs = {};
    for (var attr in attrs) {
        newAttrs[attr] ={
            DataType: attrs[attr].Type,
            StringValue: attrs[attr].Value
        }
    }
    return newAttrs;
}

除了已经在lambda函数中的aws-sdk之外,这不需要任何其他库。如果您不想要它,可以随意省略控制台日志记录,但它对调试很有用。

如果您使用测试功能,它可能会失败。我相信这是因为回调永远不会发生。

请记住,lambda不应该在us-east-1上,因为它会在你正在使用的任何地区被触发。

指向教程的链接:

SNS发布api:

http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SNS.html#publish-property

如何在lambda中使用node.js:

http://docs.aws.amazon.com/lambda/latest/dg/programming-model.html

关于使用其他aws函数的非常棒的教程:

http://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html

答案 1 :(得分:0)

这是一个更现代/简洁的类似解决方案,利用新的Node 8.10环境变量:

const AWS = require('aws-sdk');
const TARGET_ARN = process.env.TARGET_ARN;
var sns = new AWS.SNS({
    region: "us-east-1"
});

exports.handler = async (event) => {
    const message = event.Records[0].Sns;
    return await forwardMessage(message);
};

function forwardMessage(message) {
    const messageToForward = {
        TargetArn: TARGET_ARN,
        Message: message.Message,
        Subject: message.Subject
    };

    return sns.publish(messageToForward).promise();
}

答案 2 :(得分:0)

在us-east-1之外,您在协议下拉列表中找不到任何类似于SMS的协议

Subscription Creation under SNS

AWS没有提供适当的解决方案,但是您可以为此做一些修改

要实现此解决方案,我使用的是 AWS Lambda ,但是如果您有一些HTTP端点(任何类型的API),那么您也可以使用它,基本步骤是相同的​​。

  • 在SNS部分下创建主题
  • 创建一个订阅,并将订阅附加到在第1点中创建的主题
  • 转到Lambda服务并创建一个如下所示的Lambda


import json
import boto3
import os


ACCESS_KEY = os.environ.get("ACCESS_KEY", "<your key>")
ACCESS_SECRET = os.environ.get("ACCESS_SECRET", "<your-secret>")
AWS_REGION = os.environ.get("AWS_REGION_NAME", "<your-regoin>")

def execute_sms_service(event, context):
    message = json.loads(event['Records'][0]['Sns']['Message'])
    alarm_name = message['AlarmName']
    alarm_description = message['AlarmDescription']

    recipient_numbers = [<recipient number list>]
    sender_id = <sender_id>
    message = 'Alarm Name: {}\nAlarm Description:{}\n\n '.format(alarm_name, alarm_description)

    sns = boto3.client('sns', aws_access_key_id=ACCESS_KEY,
                   aws_secret_access_key=ACCESS_SECRET,
                   region_name=AWS_REGION)
    for number in recipient_numbers:
        response = sns.publish(
            PhoneNumber=number,
            Message=message,
            MessageAttributes={
                'AWS.SNS.SMS.SenderID': {'DataType': 'String',
                                     'StringValue': sender_id},
                'AWS.SNS.SMS.SMSType': {'DataType': 'String',
                                    'StringValue': 'Promotional'}
            }
        )
        print(response)
  • 创建AWS Lambda之后,请检查lambda是否正常运行,然后将此lambda附加到第二点创建的Subscription协议中。
  • 创建警报并配置将通知发送到在第一点创建的主题的操作

希望这会有所帮助,如果对上述过程有疑问,请发表评论。