Como gerenciar notificações - AWS IoT Events

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Como gerenciar notificações

O AWS IoT Events usa uma função do Lambda para gerenciar notificações de alarme. Você pode usar a função do Lambda fornecida por AWS IoT Events ou criar uma nova.

Criação de uma função do Lambda

O AWS IoT Events fornece uma função do Lambda que permite que os alarmes enviem e recebam notificações por e-mail e SMS.

Requisitos

Os seguintes requisitos se aplicam ao criar uma função do Lambda para alarmes:

  • Se seu alarme enviar notificações por e-mail ou SMS, você deverá ter um perfil do IAM que permita o AWS Lambda trabalhar com o Amazon SES e o Amazon SNS.

    Exemplo de política:

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ses:GetIdentityVerificationAttributes", "ses:SendEmail", "ses:VerifyEmailIdentity" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "sns:Publish", "sns:OptInPhoneNumber", "sns:CheckIfPhoneNumberIsOptedOut" ], "Resource": "*" }, { "Effect": "Deny", "Action": [ "sns:Publish" ], "Resource": "arn:aws:sns:*:*:*" } ] }
  • Você deve escolher a mesma região AWS para AWS IoT Events e AWS Lambda. Para obter uma lista das regiões oferecem suporte, consulte Endpoints e cotas do AWS IoT Events e Endpoints e cotas do AWS Lambda no Referência geral da Amazon Web Services.

Implantar uma função do Lambda

Este tutorial usa um modelo AWS CloudFormation para implantar uma função do Lambda. Esse modelo cria automaticamente um perfil do IAM que permite que que a função do Lambda funcione com o Amazon SES e o Amazon SNS.

Veja a seguir como usar AWS Command Line Interface (AWS CLI) para criar uma pilha do CloudFormation.

  1. No terminal do seu dispositivo, execute aws --version para verificar se você instalou o AWS CLI. Para obter mais informações, consulte Instalar a AWS CLI no Guia do usuário da AWS Command Line Interface.

  2. Execute aws configure list para verificar se você configurou AWS CLI na região AWS que tem todos os seus recursos AWS para este tutorial. Para obter mais informações, consulte Configuração da AWS CLI no Guia do usuárioAWS Command Line Interface

  3. Baixe o modelo do CloudFormation, NotificationLambda.template.yaml.zip.

    nota

    Se você tiver dificuldade em baixar o arquivo, o modelo também está disponível no Modelo do CloudFormation.

  4. Descompacte o conteúdo e salve-o localmente como notificationLambda.template.yaml.

  5. Abra um terminal em seu dispositivo e navegue até o diretório em que você fez o download do arquivo notificationLambda.template.yaml.

  6. Para criar uma pilha do CloudFormation, execute o comando a seguir:

    aws cloudformation create-stack --stack-name notificationLambda-stack --template-body file://notificationLambda.template.yaml --capabilities CAPABILITY_IAM

Você pode modificar esse modelo do CloudFormation para personalizar a função do Lambda e seu comportamento.

nota

O AWS Lambda repete os erros de função duas vezes. Se a função não tiver capacidade suficiente para lidar com todas as solicitações em andamento, os eventos poderão ter de aguardar na fila por horas ou dias até serem enviados para a função. Você pode configurar uma fila de mensagens não entregues (DLQ) na função para capturar eventos que não foram processados com êxito. Para obter mais informações, consulte Invocação assíncrona no Guia do desenvolvedor do AWS Lambda.

Você também pode criar ou configurar a pilha no console do CloudFormation. Para mais informações, consulte Como trabalhar com pilhas no Guia do usuário do AWS CloudFormation.

Como criar uma função do Lambda personalizada

Você pode criar uma função do Lambda ou modificar a fornecida pelo AWS IoT Events.

Os seguintes requisitos se aplicam ao criar uma função do Lambda personalizada.

  • Adicione permissões que permitam que sua função do Lambda execute ações específicas e acesse recursos AWS.

  • Se você usar a função do Lambda fornecida pelo AWS IoT Events, certifique-se de escolher o runtime do Python 3.7.

Exemplo da função do Lambda:

import boto3 import json import logging import datetime logger = logging.getLogger() logger.setLevel(logging.INFO) ses = boto3.client('ses') sns = boto3.client('sns') def check_value(target): if target: return True return False # Check whether email is verified. Only verified emails are allowed to send emails to or from. def check_email(email): if not check_value(email): return False result = ses.get_identity_verification_attributes(Identities=[email]) attr = result['VerificationAttributes'] if (email not in attr or attr[email]['VerificationStatus'] != 'Success'): logging.info('Verification email for {} sent. You must have all the emails verified before sending email.'.format(email)) ses.verify_email_identity(EmailAddress=email) return False return True # Check whether the phone holder has opted out of receiving SMS messages from your account def check_phone_number(phone_number): try: result = sns.check_if_phone_number_is_opted_out(phoneNumber=phone_number) if (result['isOptedOut']): logger.info('phoneNumber {} is not opt in of receiving SMS messages. Phone number must be opt in first.'.format(phone_number)) return False return True except Exception as e: logging.error('Your phone number {} must be in E.164 format in SSO. Exception thrown: {}'.format(phone_number, e)) return False def check_emails(emails): result = True for email in emails: if not check_email(email): result = False return result def lambda_handler(event, context): logging.info('Received event: ' + json.dumps(event)) nep = json.loads(event.get('notificationEventPayload')) alarm_state = nep['alarmState'] default_msg = 'Alarm ' + alarm_state['stateName'] + '\n' timestamp = datetime.datetime.utcfromtimestamp(float(nep['stateUpdateTime'])/1000).strftime('%Y-%m-%d %H:%M:%S') alarm_msg = "{} {} {} at {} UTC ".format(nep['alarmModelName'], nep.get('keyValue', 'Singleton'), alarm_state['stateName'], timestamp) default_msg += 'Sev: ' + str(nep['severity']) + '\n' if (alarm_state['ruleEvaluation']): property = alarm_state['ruleEvaluation']['simpleRule']['inputProperty'] default_msg += 'Current Value: ' + str(property) + '\n' operator = alarm_state['ruleEvaluation']['simpleRule']['operator'] threshold = alarm_state['ruleEvaluation']['simpleRule']['threshold'] alarm_msg += '({} {} {})'.format(str(property), operator, str(threshold)) default_msg += alarm_msg + '\n' emails = event.get('emailConfigurations', []) logger.info('Start Sending Emails') for email in emails: from_adr = email.get('from') to_adrs = email.get('to', []) cc_adrs = email.get('cc', []) bcc_adrs = email.get('bcc', []) msg = default_msg + '\n' + email.get('additionalMessage', '') subject = email.get('subject', alarm_msg) fa_ver = check_email(from_adr) tas_ver = check_emails(to_adrs) ccas_ver = check_emails(cc_adrs) bccas_ver = check_emails(bcc_adrs) if (fa_ver and tas_ver and ccas_ver and bccas_ver): ses.send_email(Source=from_adr, Destination={'ToAddresses': to_adrs, 'CcAddresses': cc_adrs, 'BccAddresses': bcc_adrs}, Message={'Subject': {'Data': subject}, 'Body': {'Text': {'Data': msg}}}) logger.info('Emails have been sent') logger.info('Start Sending SNS message to SMS') sns_configs = event.get('smsConfigurations', []) for sns_config in sns_configs: sns_msg = default_msg + '\n' + sns_config.get('additionalMessage', '') phone_numbers = sns_config.get('phoneNumbers', []) sender_id = sns_config.get('senderId') for phone_number in phone_numbers: if check_phone_number(phone_number): if check_value(sender_id): sns.publish(PhoneNumber=phone_number, Message=sns_msg, MessageAttributes={'AWS.SNS.SMS.SenderID':{'DataType': 'String','StringValue': sender_id}}) else: sns.publish(PhoneNumber=phone_number, Message=sns_msg) logger.info('SNS messages have been sent')

Para obter mais informações, consulte O que é o AWS Lambda? no Guia do desenvolvedor do AWS Lambda.

Modelo do CloudFormation

Use o seguinte modelo do CloudFormation para criar sua função do Lambda.

AWSTemplateFormatVersion: '2010-09-09' Description: 'Notification Lambda for Alarm Model' Resources: NotificationLambdaRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole Path: "/" ManagedPolicyArns: - 'arn:aws:iam::aws:policy/AWSLambdaExecute' Policies: - PolicyName: "NotificationLambda" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "ses:GetIdentityVerificationAttributes" - "ses:SendEmail" - "ses:VerifyEmailIdentity" Resource: "*" - Effect: "Allow" Action: - "sns:Publish" - "sns:OptInPhoneNumber" - "sns:CheckIfPhoneNumberIsOptedOut" Resource: "*" - Effect: "Deny" Action: - "sns:Publish" Resource: "arn:aws:sns:*:*:*" NotificationLambdaFunction: Type: AWS::Lambda::Function Properties: Role: !GetAtt NotificationLambdaRole.Arn Runtime: python3.7 Handler: index.lambda_handler Timeout: 300 MemorySize: 3008 Code: ZipFile: | import boto3 import json import logging import datetime logger = logging.getLogger() logger.setLevel(logging.INFO) ses = boto3.client('ses') sns = boto3.client('sns') def check_value(target): if target: return True return False # Check whether email is verified. Only verified emails are allowed to send emails to or from. def check_email(email): if not check_value(email): return False result = ses.get_identity_verification_attributes(Identities=[email]) attr = result['VerificationAttributes'] if (email not in attr or attr[email]['VerificationStatus'] != 'Success'): logging.info('Verification email for {} sent. You must have all the emails verified before sending email.'.format(email)) ses.verify_email_identity(EmailAddress=email) return False return True # Check whether the phone holder has opted out of receiving SMS messages from your account def check_phone_number(phone_number): try: result = sns.check_if_phone_number_is_opted_out(phoneNumber=phone_number) if (result['isOptedOut']): logger.info('phoneNumber {} is not opt in of receiving SMS messages. Phone number must be opt in first.'.format(phone_number)) return False return True except Exception as e: logging.error('Your phone number {} must be in E.164 format in SSO. Exception thrown: {}'.format(phone_number, e)) return False def check_emails(emails): result = True for email in emails: if not check_email(email): result = False return result def lambda_handler(event, context): logging.info('Received event: ' + json.dumps(event)) nep = json.loads(event.get('notificationEventPayload')) alarm_state = nep['alarmState'] default_msg = 'Alarm ' + alarm_state['stateName'] + '\n' timestamp = datetime.datetime.utcfromtimestamp(float(nep['stateUpdateTime'])/1000).strftime('%Y-%m-%d %H:%M:%S') alarm_msg = "{} {} {} at {} UTC ".format(nep['alarmModelName'], nep.get('keyValue', 'Singleton'), alarm_state['stateName'], timestamp) default_msg += 'Sev: ' + str(nep['severity']) + '\n' if (alarm_state['ruleEvaluation']): property = alarm_state['ruleEvaluation']['simpleRule']['inputProperty'] default_msg += 'Current Value: ' + str(property) + '\n' operator = alarm_state['ruleEvaluation']['simpleRule']['operator'] threshold = alarm_state['ruleEvaluation']['simpleRule']['threshold'] alarm_msg += '({} {} {})'.format(str(property), operator, str(threshold)) default_msg += alarm_msg + '\n' emails = event.get('emailConfigurations', []) logger.info('Start Sending Emails') for email in emails: from_adr = email.get('from') to_adrs = email.get('to', []) cc_adrs = email.get('cc', []) bcc_adrs = email.get('bcc', []) msg = default_msg + '\n' + email.get('additionalMessage', '') subject = email.get('subject', alarm_msg) fa_ver = check_email(from_adr) tas_ver = check_emails(to_adrs) ccas_ver = check_emails(cc_adrs) bccas_ver = check_emails(bcc_adrs) if (fa_ver and tas_ver and ccas_ver and bccas_ver): ses.send_email(Source=from_adr, Destination={'ToAddresses': to_adrs, 'CcAddresses': cc_adrs, 'BccAddresses': bcc_adrs}, Message={'Subject': {'Data': subject}, 'Body': {'Text': {'Data': msg}}}) logger.info('Emails have been sent') logger.info('Start Sending SNS message to SMS') sns_configs = event.get('smsConfigurations', []) for sns_config in sns_configs: sns_msg = default_msg + '\n' + sns_config.get('additionalMessage', '') phone_numbers = sns_config.get('phoneNumbers', []) sender_id = sns_config.get('senderId') for phone_number in phone_numbers: if check_phone_number(phone_number): if check_value(sender_id): sns.publish(PhoneNumber=phone_number, Message=sns_msg, MessageAttributes={'AWS.SNS.SMS.SenderID':{'DataType': 'String','StringValue': sender_id}}) else: sns.publish(PhoneNumber=phone_number, Message=sns_msg) logger.info('SNS messages have been sent')