看起来AWS不提供SMS作为美国东部以外的SNS主题订阅者的协议。我希望连接我的CloudWatch警报并在出现故障时收到短信,但无法将其发送到短信。
有没有办法做到这一点?
答案 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)
AWS没有提供适当的解决方案,但是您可以为此做一些修改
要实现此解决方案,我使用的是 AWS Lambda ,但是如果您有一些HTTP端点(任何类型的API),那么您也可以使用它,基本步骤是相同的。
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)
希望这会有所帮助,如果对上述过程有疑问,请发表评论。