¿Qué son las variables de ambiente y cómo se usan en aplicaciones?
Las variables de ambiente son herramientas esenciales en la configuración de aplicaciones modernas. Estas permiten manejar configuraciones de manera flexible, dependiendo del entorno en el que se está ejecutando la aplicación, ya sea desarrollo, producción o staging. Al definir estas variables, garantizamos que nuestra aplicación se comporta correctamente en cada contexto específico.
¿Cómo integramos variables de ambiente en nuestro proyecto?
La integración de variables de ambiente en un proyecto requiere unos pasos específicos. Primero, decidimos qué variables son necesarias para cada entorno. En el caso de las credenciales de API, como visto en el ejemplo, se utilizan para autenticar solicitudes de forma segura.
Definición de variables: En el proyecto, por ejemplo, se definen variables como APK y se asignan valores dependiendo del entorno. Para desarrollo, podemos asignar ABC.23, y para staging, ZXC.123.
Lectura en el código: Usamos inyecciones de dependencia para acceder a las configuraciones desde el sistema. Se importan herramientas de configuración para gestionar estas variables de manera modular.
Validación de variables: Las aplicaciones deben ser robustas frente a errores de validación. En nuestro código, cambiamos la validación de APK a un string que acepta combinaciones de letras y números, garantizando compatibilidad con las claves API reales.
Una vez definida e implementada la gestión de variables de ambiente, es crucial probarla. Para ello, cambiamos entre diferentes entornos y observamos el comportamiento de la aplicación:
Entorno de desarrollo: Al ejecutar el entorno de desarrollo, aseguramos que las variables como ABC.123 son válidas para los endpoints protegidos.
Entorno de staging: Cambiamos a este entorno para verificar que las variables como ZXC.123 funcionen correctamente, y cualquier otro valor resulte en una respuesta de error.
# Ejecutar en entorno de desarrolloNODE_ENV=development node app.js
# Ejecutar en entorno de stagingNODE_ENV=staging node app.js
¿Qué pasa si hay un error de validación?
Si una variable de ambiente no pasa la validación, se debe revisar el esquema. En el caso mencionado, si la APK aceptara solo números pero necesita letras, simplemente ajustamos esa validación en el módulo principal de la aplicación para aceptar strings más flexibles:
{APK:Joi.string().required(),}
¿Por qué es importante esta configuración?
Incorporar variables de ambiente no solo mejora la seguridad al evitar la exposición de credenciales en el código fuente, sino que también facilita la gestión de configuraciones al permitir cambios sin necesidad de alterar el código base. Este enfoque modular es crucial para aplicaciones escalables y mantenibles en distintos entornos.
Los modulos inyectables son algo fascinante.
el dinamismo que da NESTJS es muy interesante!
Es un stack back super interesante!
Hola Nico!
¿Qué diferencia puede haber entre utilizar un middleware implementando NestMiddleware en lugar de los Guards?
Se podría implementar un middleware personalizado que valide la request del usuario antes de que esta llegue al controlador.
Gracias!
Si lo puedes hacer, pero recuerda que NestJs nos da todos estos artefactos con una responsabilidad en específico entonces si lo que quieres es proteger una ruta es la responsabilidad de un Guard, pero si técnicamente lo podrías hacer con un middleware.
Guard con variables de ambiente
Ahora, lo que vamos a hacer es que la clave de autenticación la vamos a guardar en una variable de ambiente, con esto no tenemos esta clave harcodeada en nuestro guardián, y podemos hacer que esta sea dinámica. Veamos como:
**src/auth/guards/api-key.guard.ts**:
import{// ...Injectable,}from'@nestjs/common';import{IS_PUBLIC_KEY}from'../decorators/public.decorator';// traemos al configurador y a los tipos del configuradorimportconfigfrom'src/config';import{ConfigType}from'@nestjs/config';@Injectable()exportclassApiKeyGuardimplementsCanActivate{constructor(// ... // inyectamos la el servicio de config en nuestro guardian @Inject(config.KEY)private configService:ConfigType<typeof config>,){}canActivate( context:ExecutionContext,):boolean|Promise<boolean>|Observable<boolean>{const isPublic =this.reflector.get(IS_PUBLIC_KEY, context.getHandler());// ...// la clave de autenticación va a ser igual a la apiKey de nuestras variables de entornoreturn authHeader ===this.configService.apiKey;}}
Y listo, así de fácil hemos logrado tener un guardián que por medio de una clave dinámica nos permita o no acceder a Endpoints protegidos.
Ty for notes!
En los headers hay distinción entre number y string?
se me ocurre que esa cadena que viene en el header no este en una variable de entorno, si no en una tabla donde guardemos una url de un tercero y un token o cadena autogenerada, para ir creando una lista blanca de sitios que pueden usar nuestra api, es viable?