Skip to main content

Crea e implementa una API de análisis de seguridad de Node.js en Platformatic Cloud

Escrito por
Headshot of Matteo Collina

Matteo Collina

feature platformic security

5 de enero de 2024

0 minutos de lectura

En esta guía, exploraremos la potente combinación de Platformatic y Fastify para agilizar el desarrollo de backend, con énfasis en la solidez y la seguridad.

Tanto si tienes mucha experiencia como desarrollador de Node.js como si apenas estás empezando, este artículo es un buen punto de partida para familiarizarte con los entornos PaaS de Node.js, como Platformatic. Exploraremos cómo integrar Snyk sin complicaciones en tu flujo de trabajo para garantizar que tu código esté libre de vulnerabilidades y filtraciones de secretos, y cómo usar la API de Snyk para crear aplicaciones de seguridad.

¿Qué es Platformatic?

Platformatic es una plataforma de alojamiento en la nube diseñada para agilizar la creación y administración de API y backends en Node.js. Con Platformatic, los desarrolladores pueden crear fácilmente API escalables y eficientes gracias a una variedad de herramientas y funciones que simplifican tareas como el enrutamiento, las interacciones con bases de datos y la autenticación. Su integración con Fastify mejora aún más el rendimiento y la experiencia de desarrollo.

¿Qué es Fastify?

Fastify es un framework web moderno y de código abierto para Node.js, conocido por su alto rendimiento y su bajo consumo de recursos. Si tienes experiencia con Express, apreciarás la experiencia de desarrollo que ofrece Fastify y lo ligero y potente que es. Fastify se enfoca en la velocidad y la eficiencia, y ofrece una API sencilla e intuitiva, una gestión fácil de solicitudes y respuestas, y compatibilidad integrada con la validación y serialización basadas en esquemas.

Al ofrecer un conjunto integral de herramientas en un paquete unificado, Platformatic permite a los desarrolladores de Node.js enfocarse más en crear la funcionalidad principal de sus aplicaciones y menos en las complejidades de la infraestructura de backend.

Crear el esqueleto de una aplicación de Node.js con el servicio de Platformatic

Primero, crea un directorio nuevo para alojar nuestra aplicación de Node.js:

mkdir pkg-probe

Luego, ejecutamos el siguiente comando de npm para instalar el generador de proyectos de Platformatic:

npm create platformatic@latest

Este comando te pedirá que confirmes la descarga de la versión más reciente del paquete npm platformatic:

Need to install the following packages:
create-platformatic@1.11.0
Ok to proceed? (y) y

A continuación, respondemos las indicaciones como se muestra para crear el esqueleto de un nuevo servicio de API de Node.js:

 Hello Liran Tal, welcome to Platformatic 1.11.0!
 Let's start by creating a new project.
? Which kind of project do you want to create? Service
? Where would you like to create your project? platformatic-service
? Do you want to run npm install? yes
? Do you want to use TypeScript? no
? What port do you want to use? 3042
? Do you want to create the github action to deploy this application to Platformatic Cloud? yes
? Do you want to enable PR Previews in your application? yes
? Do you want to init the git repository? no

Esto completa un proyecto de servicio de Platformatic dentro del directorio platformatic-service, que usa JavaScript simple y tiene integración con GitHub Actions, además de revisiones de PR conectadas a Platformatic que proporcionan una captura inmutable del servicio en cada PR.

La estructura de directorios y archivos debería verse más o menos así:

.
└── platformatic-service
    ├── README.md
    ├── global.d.ts
    ├── node_modules
    ├── package-lock.json
    ├── package.json
    ├── platformatic.service.json
    ├── plugins
    ├── routes
    └── test

5 directories, 5 files

Inicia el servicio de Node.js de Platformatic

El servicio de Platformatic generado ya está listo para ejecutarse. Iniciemos la aplicación, pero primero tenemos que cambiar de directorio:

cd platformatic-service

Y luego:

npm run start

lirantal  …/repos/pkg-probe/platformatic-service   v20.8.0 
♥ npm run start

> start
> platformatic start

[12:56:12.555] INFO (main/75676): Server listening at http://127.0.0.1:3042

La aplicación de Node.js generada ya está lista y atiende solicitudes HTTP en el puerto 3042. La aplicación muestra la siguiente guía introductoria en su endpoint predeterminado GET /:

Página de bienvenida de Platformatic Service que muestra enlaces a la documentación, la documentación de OpenAPI y GraphiQL.

Es importante tener en cuenta que esta página de índice la sirve específicamente la CLI de Platformatic y está pensada para el desarrollo local. No forma parte del código del navegador del lado del cliente que se implementa junto con el servicio de la aplicación de Node.js.

Explorar el servicio de Platformatic 

Para comprender mejor cómo funciona esta aplicación de Node.js, debemos profundizar en la configuración y la estructura de directorios de Platformatic.

El archivo platformatic.service.json define la configuración general del servicio implementado en Platformatic, como el puerto en el que debe escuchar las solicitudes HTTP y los plugins o las rutas (que también se definen como plugins) que se deben cargar. Este es el archivo de configuración del servicio que se generó:

{
  "$schema": "https://platformatic.dev/schemas/v1.11.0/service",
  "service": {
    "openapi": true
  },
  "watch": true,
  "plugins": {
    "paths": [
      {
        "path": "./plugins",
        "encapsulate": false
      },
      "./routes"
    ]
  },
  "server": {
    "hostname": "{PLT_SERVER_HOSTNAME}",
    "port": "{PORT}",
    "logger": {
      "level": "{PLT_SERVER_LOGGER_LEVEL}"
    }
  }
}

Según la configuración anterior, los plugins incluyen una entrada ./routes, que define el directorio desde el que se cargarán las rutas de la API.

Las rutas HTTP están disponibles en el archivo routes/root.js, y el ejemplo incluido de forma predeterminada proporciona el siguiente endpoint GET en el parámetro de ruta /example:

/// <reference path="../global.d.ts" />
'use strict'

/** @param {import('fastify').FastifyInstance} fastify */
module.exports = async function (fastify, opts) {
  fastify.get('/example', async (request, reply) => {
    return { hello: fastify.example }
  })
}

Confirmemos que funciona enviando la siguiente solicitud HTTP a GET /example:

 curl http://localhost:3042/example -vvv  
*   Trying 127.0.0.1:3042...
* Connected to localhost (127.0.0.1) port 3042 (#0)
> GET /example HTTP/1.1
> Host: localhost:3042
> User-Agent: curl/8.1.2
> Accept: */*
> 

< HTTP/1.1 200 OK
< content-type: application/json; charset=utf-8
< content-length: 18
< Date: Thu, 16 Nov 2023 11:24:41 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< 
* Connection #0 to host localhost left intact
{"hello":"foobar"}%   

Agrega una ruta nueva para probar si los paquetes npm tienen vulnerabilidades de seguridad

Ahora, agreguemos una nueva capacidad a nuestra API de Node.js que le permita recibir nombres y versiones de paquetes como entrada del usuario, y comprobar si tienen vulnerabilidades de seguridad conocidas.

A continuación, se detallan las tareas que debemos completar en esta sección del tutorial:

  • Instalar y configurar la CLI de Snyk

  • Obtener el token de API de Snyk

  • Enviar solicitudes HTTP a la API de Snyk con el token de API

  • Definir un nuevo endpoint de API POST /test/vulnerabilities en el servicio de Node.js de Platformatic

Instala y configura la CLI de Snyk para obtener un token de API

Comenzar a usar la CLI de Snyk es tan fácil como instalar un paquete npm:

npm install -g snyk

Instalar la dependencia de Snyk en el ámbito global de paquetes npm es útil porque podemos usarla para probar varios aspectos del código y la seguridad de los proyectos de JavaScript en los que trabajamos. De hecho, Snyk también puede analizar el código y las dependencias de Python, Java, Ruby, PHP y otros lenguajes de programación.

A continuación, debemos crear una cuenta gratuita de Snyk para poder consultar en la API las vulnerabilidades de los paquetes. Ejecuta:

snyk auth

Sigue las instrucciones de la CLI y, una vez que termines, puedes extraer tu token de API con el comando snyk config, que devuelve una clave de configuración de API:

snyk config

api: <YOUR_API_TOKEN_HERE>

Guarda el token de API en un lugar práctico, porque pronto lo usaremos (pero ten cuidado de no filtrarlo accidentalmente en Internet).

Ya puedes analizar tu código y tus dependencias para detectar vulnerabilidades de seguridad. ¿Por qué no aprovechas esta oportunidad para analizar nuestra aplicación de servicio de Node.js de Platformatic?

lirantal  …/pkg-probe/platformatic-service   main !   v20.8.0 
♥  snyk test   

Testing ~/repos/pkg-probe/platformatic-service...

Organization:      snyk-demo-567
Package manager:   npm
Target file:       package-lock.json
Project name:      package.json
Open source:       no
Project path:      ~/repos/pkg-probe/platformatic-service
Licenses:          enabled

✔ Tested 500 dependencies for known issues, no vulnerable paths found.

Next steps:
- Run `snyk monitor` to be notified about new related vulnerabilities.
- Run `snyk test` as part of your CI/test.

¡Felicitaciones al equipo de Platformatic por lanzar herramientas de proyecto con 0 vulnerabilidades!

Para obtener más información sobre cómo usar la CLI de Snyk, consulta Snyk User Docs y nuestra práctica hoja de referencia de la CLI de Snyk.

Define el endpoint de API POST /test/vulnerabilities de Node.js

Abre el archivo routes/root.js y agrega una nueva declaración de ruta de API de Fastify justo después del código fastify.get() existente:

  fastify.post("/test/vulnerabilities", async (request, reply) => {
    const packageName = request.query.packageName;
    const packageVersion = request.query.packageVersion;

    const snykApiToken = "12345”
    const url = `https://snyk.io/api/v1/test/npm/${packageName}/${packageVersion}`;

    const response = await fetch(url, {
      headers: {
        Authorization: `token ${snykApiToken}`,
      },
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    return { vulnerabilities: data.issues?.vulnerabilities };
  });

Este código configura un endpoint de API para comprobar si los paquetes npm tienen vulnerabilidades usando el endpoint de la API v1 de Snyk. Veamos cada parte en detalle:

Primero, la creación de rutas de Fastify:

fastify.post("/test/vulnerabilities", async (request, reply) => {...});

Esta línea crea un nuevo endpoint POST en /test/vulnerabilities. Aquí se usa Fastify, un framework web rápido y de bajo consumo para Node.js. La palabra clave async indica que esta función puede realizar operaciones asíncronas.

A continuación, extraemos los parámetros de consulta de la solicitud HTTP:

const packageName = request.query.packageName;
const packageVersion = request.query.packageVersion;

Estos parámetros especifican el paquete npm y la versión que el usuario quiere analizar para detectar vulnerabilidades.

La integración con la API de Snyk comienza en la siguiente parte:

const snykApiToken = "12345";
const url = `https://snyk.io/api/v1/test/npm/${packageName}/${packageVersion}`;
const response = await fetch(url, { headers: { Authorization: `token ${snykApiToken}` } });

La URL del endpoint de la API de Snyk se construye con el nombre del paquete y un número de versión explícito (no una etiqueta, por lo que “latest” no es compatible). Luego, hacemos una llamada fetch asíncrona a la API de Snyk y pasamos el token de autorización en los encabezados de la solicitud. Este es el token de API que obtuviste con el comando snyk config.

Por último, el endpoint responde con las vulnerabilidades encontradas en el paquete npm especificado. Usa el encadenamiento opcional (?.) para manejar los casos en los que la respuesta no incluya problemas.

return { vulnerabilities: data.issues?.vulnerabilities };

Por último, podrías mejorar la definición de la ruta de Fastify para el endpoint POST /test/vulnerabilities mediante la definición de un esquema de solicitud y respuesta. Esto permite agregar validación de entradas y que la ruta se incluya automáticamente en la documentación de la API de OpenAPI. Te recomiendo seguir el tutorial de Platformatic sobre una aplicación de películas y la publicación de blog de Simon Plenderleith sobre la creación de API REST con Platformatic DB.

¡Ten cuidado de no filtrar información confidencial, como las claves de API!


¿Notaste que acabamos de incluir el token de API directamente en el código? ¡Eso no se hace!

No se me pasó por alto, porque tengo instalada la extensión de Snyk en mi IDE de VS Code, que incluye automáticamente la detección de secretos y marca cualquier problema de código inseguro que pueda introducir una vulnerabilidad de seguridad en mi propio código:

Editor de código que muestra una ruta de Node.js con un token de API de Snyk codificado directamente y resaltado.

Instala la extensión de Snyk directamente desde el IDE de VS Code o consulta las extensiones de Snyk en VS Code Marketplace para obtener más información.

Ahora, corrijamos esa filtración de credenciales gracias a la alerta de detección de secretos. Primero, define una nueva variable de entorno en .env y reemplaza “1234” por tu propio token de API de Snyk:

PLT_SNYK_API_TOKEN=1234

A continuación, podemos agregarla al archivo de configuración platformatic.service.json, actualizando la clave de cadena ./routes existente en el arreglo para convertirla en un objeto que reciba una clave options:

{
  …
  "plugins": {
    "paths": [
      {
        "path": "./plugins",
        "encapsulate": false
      },
     {
        "path": "./routes",
        "options": {
           "snykApiToken": "{PLT_SNYK_API_TOKEN}"
       }
     }
    ]
  },
  …
}
module.exports = async function (fastify, opts) {

    const snykApiToken = opts.snykApiToken;
    const url = `https://snyk.io/api/v1/test/npm/${packageName}/${packageVersion}`;

Ten en cuenta que, si usas npm run start para ejecutar el servicio de Node.js de Platformatic, no necesitas volver a ejecutar este comando, ya que admite la recarga automática y actualiza el código del servidor cada vez que guardas archivos de rutas o plugins.

Analiza un paquete npm para detectar vulnerabilidades de seguridad con nuestro nuevo servicio de API de Node.js 

Ahora que conectamos Snyk y el servicio de API de Node.js de Platformatic, confirmemos que todo funcione en conjunto.

Comprobemos si es seguro usar la versión más reciente del paquete npm vm2, que algunos desarrolladores podrían usar como sandbox de seguridad para ejecutar código no confiable.

La siguiente solicitud HTTP especifica el nombre del paquete, la versión más reciente en el registro npmjs y pasa el resultado a la herramienta jq para mostrar una respuesta JSON con formato:

curl -X POST "http://localhost:3042/test/vulnerabilities?packageName=vm2&packageVersion=3.9.19" | jq 

{
  "vulnerabilities": [
    {
      "id": "SNYK-JS-VM2-5772823",
      "url": "https://snyk.io/vuln/SNYK-JS-VM2-5772823",
      "title": "Remote Code Execution (RCE)",
      "type": "vuln",
      "description": "## Overview\n[vm2](https://github.com/patriksimek/vm2#readme) is a sandbox that can run untrusted code with whitelisted Node's built-in modules.\n\nAffected versions of this package are vulnerable to Remote Code Execution (RCE) due to insufficient checks which allow an attacker to escape the sandbox.\r\n\r\n**Note:**\r\n\r\nAccording to the maintainer, the security issue cannot be properly addressed and the library will be discontinued.\n## Remediation\nThere is no fixed version for `vm2`.\n## References\n- [GitHub Issue](https://github.com/patriksimek/vm2/issues/533)\n",
      "from": [
        "vm2@3.9.19"
      ],
      "package": "vm2",
      "version": "3.9.19",
      "severity": "critical",
      "exploitMaturity": "proof-of-concept",
      "language": "js",
      "packageManager": "npm",
      "semver": {
        "vulnerable": [
          "*"
        ]
      },
      "publicationTime": "2023-07-12T14:50:43.988574Z",
      "disclosureTime": "2023-07-12T14:10:56Z",
      "isUpgradable": false,
      "isPatchable": false,
      "isPinnable": false,
      "identifiers": {
        "CVE": [
          "CVE-2023-37903"
        ],

¡Funciona! ¡Felicitaciones por crear tu primera herramienta de seguridad con Snyk y Platformatic!

Sigamos creando un frontend para esta aplicación web y luego implementemos la API de Node.js en Platformatic Cloud.

Una aplicación frontend de Vue para analizar vulnerabilidades de seguridad

En esta parte, revisaremos los componentes básicos de la aplicación web frontend que se comunica con la API de backend de Node.js que creamos con el servicio de Platformatic.

Escáner de seguridad de paquetes npm que muestra la versión 3.9.19 de vm2 y dos informes de vulnerabilidades de ejecución remota de código

La aplicación web frontend se compone de lo siguiente:

  • Un frontend del lado del cliente con Vue.js 3 + Vite

  • Tailwind CSS

La parte frontend es un formulario sencillo con campos de texto para el nombre y la versión del paquete, que se envían a la API de Node.js de Platformatic.

A continuación, se muestra un formulario básico de Vue.js que se comunica con el servicio de Node.js que se ejecuta localmente en localhost:3042:

<script setup>
import { ref } from "vue";

const processing = ref(false);
const packageName = ref("vm2");
const packageVersion = ref("3.9.19");
const vulnerabilities = ref([]);

async function scanPackage() {
  processing.value = true;

  const BASE_URL = "http://localhost:3042";
  const httpResponseRaw = await fetch(
    `${BASE_URL}/test/vulnerabilities?packageName=${packageName.value}&packageVersion=${packageVersion.value}`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({}),
    }
  );

  const httpResponse = await httpResponseRaw.json();
  vulnerabilities.value = httpResponse.vulnerabilities;

  processing.value = false;
}
</script>

Puedes consultar el código completo de la aplicación web frontend en este repositorio de GitHub: https://github.com/lirantal/pkg-probe.

Implementa la API de backend de Node.js en Platformatic Cloud

Platformatic Cloud es una PaaS especializada (plataforma como servicio), ideal para alojar aplicaciones de Node.js. Además de las excelentes herramientas de Platformatic, ahora podemos usar su entorno en la nube para alojar nuestra aplicación web de análisis de seguridad y hacerla accesible en Internet.

Comienza iniciando sesión en la página de inicio con el botón Conectar con GitHub, autoriza la integración de la aplicación de GitHub y acepta los términos del servicio y la política de privacidad. Luego, ya puedes hacer clic en Crear una aplicación en el panel:

Pantalla de importación de Platformatic que muestra el paso de repositorio de GitHub, con menús desplegables para la organización y el repositorio, y un botón Siguiente

Este flujo de trabajo predeterminado crea una nueva aplicación de ejemplo de Platformatic. Sin embargo, ya tenemos una en funcionamiento, así que debes hacer clic en el enlace Hacerlo manualmente que aparece al final de la pantalla de instrucciones.

A continuación, asigna un nombre a la aplicación y al espacio de trabajo. Mantén desactivada la opción Espacio de trabajo dinámico, ya que por ahora no necesitamos revisiones de PR automatizadas para implementar la aplicación de Node.js desde la CLI.

Al final, verás una pantalla de resumen de Platformatic como esta:

Pantalla de configuración del espacio de trabajo que confirma que “pkg-probe” se creó correctamente, con los campos de ID del espacio de trabajo y clave de API ocultos.

Ahora que tenemos el ID del espacio de trabajo y la clave de API, podemos usarlos para implementar nuestra aplicación de backend de Node.js en el entorno de alojamiento de Platformatic Cloud.

Con el ID del espacio de trabajo y la clave de API listos, cambia al directorio platformatic-service de nuestros proyectos para ejecutar un comando del ciclo de vida de npm en el código fuente de la API de Node.js. Ejecuta el siguiente comando npm run deploy e ingresa los datos del espacio de trabajo de Platformatic Cloud de esta manera:

$  npm run deploy

This application will be deployed to Platformatic Cloud. To change the target use the --deploy-service-host flag
? Select workspace type: static
? Enter workspace id: 09d9a354-b755-40da-b4ab-841a43d8c074
? Enter workspace key: ********************************
[13:41:52] INFO: Found Platformatic config file: platformatic.service.json
[13:41:54] INFO: Project has been successfully archived
[13:41:55] INFO: Uploading bundle (95.9 MB) to the cloud…
…
[13:42:52] INFO: Application has been successfully started

Cuando el comando termine, también indicará la URL en la que se implementó la API de Node.js y estará disponible, por ejemplo: https://something-something-funny.deploy.space

Si volvemos al panel de Platformatic Cloud en https://platformatic.cloud, veremos que se creó nuestra nueva aplicación de análisis de seguridad:

Panel de control de una aplicación en azul oscuro que muestra un recuadro «Crear una aplicación» y otro de una aplicación existente llamada «pkg-probe».

Al abrir nuestra aplicación, podemos ver su estado en tiempo real, como las métricas de rendimiento y la dirección URL pública para acceder a ella:

Panel del espacio de trabajo de Platformatic que muestra una implementación activa de pkg-probe, los detalles del paquete más reciente y métricas de solicitudes, latencia, clientes conectados y tasa de fallas.

Solo queda un último elemento de configuración que debes agregar a la API de Node.js con tecnología de Platformatic: habilitar CORS.

¿Qué es CORS?

El intercambio de recursos de origen cruzado (CORS) es una función de seguridad implementada en los navegadores web para gestionar cómo se comparten recursos entre distintos orígenes, que suelen corresponder a diferentes dominios, protocolos o puertos. En el contexto de una aplicación backend, CORS es fundamental porque controla si los datos de un servidor pueden compartirse con páginas web de otro origen y de qué manera. Sin CORS, las aplicaciones web modernas que dependen de API y otros recursos de origen cruzado tendrían limitaciones importantes.

¿Por qué es importante CORS?

Esta política impide que una página web haga solicitudes a un dominio distinto del que la sirve, lo que ayuda a proteger contra ciertos tipos de amenazas de ciberseguridad, como los ataques de cross-site scripting (XSS). Sin embargo, CORS permite un acceso seguro y controlado al especificar qué dominios pueden acceder a los recursos de tu servidor. Así, facilita el desarrollo de aplicaciones web interactivas y completas que pueden interactuar de forma segura con recursos de varios orígenes.

Agreguemos una configuración de CORS a la API de Node.js. Abre el archivo .env y agrega la siguiente configuración de CORS de Platformatic:

PLT_SERVER_CORS_ORIGIN=http://localhost:5173

Como puedes ver en este ejemplo de configuración, está establecido en el puerto del servidor de desarrollo local de Vue.js que se ejecuta en localhost. Si implementas tu frontend en otro lugar, como en un entorno de alojamiento en la nube de Netlify o Vercel, deberás configurarlo según corresponda.

A continuación, actualicemos la directiva de configuración de server en platformatic.service.json para incluir también lo siguiente:

  "server": {
    "hostname": "{PLT_SERVER_HOSTNAME}",
     // other configuration options…
     // add CORS too:
    "cors": {
      "origin": "{PLT_SERVER_CORS_ORIGIN}"
    }
 }

Éxito

¡Eso es todo!

Creaste correctamente una aplicación web con Node.js que busca vulnerabilidades de seguridad mediante la API de Snyk y la implementaste en el entorno de hosting de Platformatic Cloud para que esté disponible públicamente.

Empieza a proteger tus aplicaciones JavaScript

Encuentra y corrige vulnerabilidades de JavaScript gratis con Snyk. 

No necesitas tarjeta de crédito.

O regístrate con Azure AD Docker ID Bitbucket

Al usar Snyk, aceptas cumplir nuestras políticas, incluidos nuestros Términos del servicio y nuestra Política de privacidad.

Leer más

Blog

Los modelos de frontera encontraron las vulnerabilidades. Solo el atacante encontró las cadenas.

El análisis estático encontró las fallas, pero solo las pruebas de ataque en vivo demostraron cómo podían encadenarse para provocar brechas. Una comparación de Evo COS, Claude Security y Claude Code Security.

feature insights context
Blog

Los ataques autónomos ya están aquí. La defensa debe estar a su altura.

Los atacantes autónomos están reduciendo el tiempo disponible para defenderse. Descubre cómo el descubrimiento, la corrección, la validación y la prevención continuos pueden ayudar a los equipos de seguridad a seguirles el ritmo.

Blog

Por qué los agentes de programación con IA siguen generando fallas de control de acceso

Los agentes de programación con IA pueden generar lógica de autorización que compila y supera la revisión, pero expone los datos de un inquilino a otro. Descubre por qué es difícil detectar el control de acceso roto y cómo prevenirlo.