SNS de AWS y cómo publicar notificaciones con Node.JS

Cómo enviar notificaciones vía Node.JS a SNS de AWS usando el SDK de Javascript

En muchas ocasiones las aplicaciones o soluciones que desarrollamos necesitan enviar notificaciones a terceros en función de algún tipo de evento. Por ejemplo notificar a un conjunto de correos cuando se modifica o se genera un registro relevante, a veces esto es complejo de desarrollar pero con AWS SNS la vida se vuelve más fácil.

Estas notificaciones en general no son parte del modelo o solución en si, y necesitan abstraerse en un modelo distinto, como el modelo “publish/suscribe”, aquí es donde entra en escena AWS Simple Notificacion Service (SNS), un servicio escalable y completamente administrado por AWS, que permite implementar un modelo publish/suscribe con mucha facilidad, de esa forma se pueden enviar mensajes de texto (SMS), email, notificaciones push y otros tipos de mensaje a distintos targets en múltiples canales sin tener que lidiar con la complejidad de implementar todo eso.

En este post revisaremos como generar un tópico SNS y enviar mensajes desde un pequeño script para Node.js usando el SDK para Javascript de AWS, recuerda que en Octasquare somos arquitectos de soluciones certificados en AWS y podemos brindarte consultoría e implementación de soluciones en la nube

1 – Generar Tópico SNS

Para empezar, tenemos que dirigirnos a nuestra consola de administración de AWS y buscar el servicio SNS, luego en este, elegir la opción de “Topics” y “Create Topic”

crear topic SNS
SNS

Nota: Si van por FIFO solo permite como protocolo colas SQS, por lo que si queremos mandar email, SMS u otra cosa, deberemos usar el “Standard”

2 – Crear Usuario IAM (programático)

Dado que usaremos el SDK de AWS para Javascript, necesitamos crear un usuario programático que tendrá los permisos necesarios para realizar acciones sobre el servicio SNS

En la sección de IAM en la consola de AWS iremos a crear usuario

add user iam

En este caso usaremos un nombre genérico como “SNSUser”, pero recuerden que estos permisos se pueden agregar a un usuario ya existente (programático).

Los permisos a agregar el usuario son los siguientes:

add user IAM

Esto permitirá que el usuario “SNSUSer” tenga todos los permisos sobre el servicio de SNS, con ello se podrán generar suscripciones y hacer publicaciones frente a un tópico

3 – Guardar Credenciales en entorno de Node.js

Finalizando el paso anterior, la consola de AWS nos entrega los datos del usuario creado, como su “Access Key Id” y “Secret Access Key”, es importante que estos datos se traspasen al entorno donde se ejecutará la aplicación Node.js, una forma de hacerlo es vía este pequeño script para linux

touch ~/.aws/credentials
echo '[sns_profile]' >> ~/.aws/credentials
echo 'aws_access_key_id = <YOUR_ACCESS_KEY_ID>' >> ~/.aws/credentials # The access key ID from the IAM user
echo 'aws_secret_access_key = <YOUR_SECRET_ACCESS_KEY>' >> ~/.aws/credentials # The secret access key from the IAM user
echo 'region = <YOUR_AWS_REGION>' # From the regions page, examples include: us-east-1, us-west-1, eu-west-1, etc.

4 – App Demo en Node.js

Crearemos una carpeta donde instalaremos los packages necesarios y el script para node que enviará las notificaciones SNS. Nota: en este caso usamos YARN como package manager, pero los pasos son equivalente con NPM

$ mkdir node-sns-app
$ cd node-sns-app
$ yarn init

Ahora instalaremos algunos de los packages que usaremos

yarn add aws-sdk 

y crearemos el script para Node.js

touch index.js

Como contenido inicial pondremos:

import AWS from 'aws-sdk';

const credentials = new AWS.SharedIniFileCredentials({ profile: 'sns_profile' });
const sns = new AWS.SNS({ credentials: credentials, region: 'us-west-2' });

Aquí estamos importando AWS desde el SDK de Amazon y cargando el objeto de credenciales que creamos anteriormente. Es importante notar que cuando se crea el objeto “sns” se define la región en donde hemos creado el Topic en el inicio del articulo.

5 – Suscribirse a un Topic

Para suscribirse a un topic creado previamente se puede usar una función como la siguiente:

const subscribe = (topicarn, email) => {
    let params = {
        Protocol: 'EMAIL',
        TopicArn: topicarn,
        Endpoint: email
    };

    sns.subscribe(params, (err, data) => {
        if (err) {
            console.log(err);
        } else {
            console.log(data);
        }
    });
}

y para ejecutarla, dentro del mismo archivo, se puede escribir algo como:

const TopicArn = '<EL ARN DEL TOPIC AQUI>';
subscribe(TopicArn, '<UN EMAIL A SUSCRIBIR>');

Si todo se hizo de forma correcta, por el terminal se podrá ver un mensaje indicando que esta pendiente la confirmación de suscripción, esto quiere decir que se envió un correo desde AWS al destino y se espera un OK del usuario.

{
  ResponseMetadata: { RequestId: '629b0f63-cf00-5202-8e48-55bd68d4513s' },
  SubscriptionArn: 'pending confirmation'
}

6 – Publicar un mensaje vía SNS

Con todos los pasos anteriores ya tenemos un Topic SNS creado y un correo suscrito a dicho tópico, ahora lo que resta es gatillar un mensaje hacia SNS para que este se encargue de enviar dicho mensaje a todos los suscriptores que hayan y por los protocolos que se hayan definido, para hacerlo es muy simple:

const publish = (message, subject, topicarn) => {
    let params = {
        Message: message,
        Subject: subject,
        TopicArn: topicarn
    };

    sns.publish(params, function (err, data) {
        if (err) console.log(err, err.stack);
        else console.log(data);
    });
}

y se puede ejecutar con un par de lineas estilo:

const TopicArn = '<EL ARN DEL TOPIC AQUI>';
publish('Test message', 'Test subject', TopicArn);

Si todo fue OK verán un mensaje como el siguiente en consola:

{
  ResponseMetadata: { RequestId: '5908b0Ce-d063-537e-9f6e-ea3079103b0X' },
  MessageId: '8b3c6dd6-3daa-5bcC-83a1-370894d9b3bX'
}

Y en la bandeja de entrada del mail suscrito aparecerá el correo con el asunto “Test subject” y como mensaje “Test message”

el código completo lo puedes ver a continuación:


import AWS from 'aws-sdk';

const credentials = new AWS.SharedIniFileCredentials({ profile: '<PROFILE NAME>' });
const sns = new AWS.SNS({ credentials: credentials, region: '<REGION>' });

const subscribe = (topicarn, email) => {
    let params = {
        Protocol: 'EMAIL',
        TopicArn: topicarn,
        Endpoint: email
    };

    sns.subscribe(params, (err, data) => {
        if (err) {
            console.log(err);
        } else {
            console.log(data);
        }
    });
}

const publish = (message, subject, topicarn) => {
    let params = {
        Message: message,
        Subject: subject,
        TopicArn: topicarn
    };

    sns.publish(params, function (err, data) {
        if (err) console.log(err, err.stack);
        else console.log(data);
    });
}

// solo para ejecutar y probar el codigo: 
const TopicArn = '<TOPIC ARN>';
subscribe(TopicArn, '<MAIL ADDRESS>');
publish('Test message', 'Test subject', TopicArn);

7 – Próximos pasos

Se puede seguir expandiendo la idea trabajando por ejemplo en el formateo del mensaje, de modo que se envíe en HTML y claro esta, enviando información que sea relevante para el propósito que se busque.

Eventualmente, solo cambiando el protocolo de la suscripción se pueden enviar mensajes SNS no solo a emails suscritos, sino que por ejemplo se pueden gatillar llamadas HTTP, funciones lambda, colas SQS, entre otros, generando así una gama de opciones y posibilidades. ¿recuperaciones automáticas de servicio frente a algún tipo de alerta? ¿avisos tempranos frente a problemas…? Etc…

Leave a Reply