Actualmente las aplicaciones que nacen nativamente cloud, tienden a comunicarse con muchos servicios de terceros, esto debido a que parte de su naturaleza consiste en dejar el trabajo pesado a servicios especializados,  los cuales resuelven problemas puntuales, en ese contexto estos servicios necesitan credenciales para conectarse a ellos, por eso es importante gestionar las credenciales e inyectarlas como variables de entorno en el sistema, para ello serverless maneja algunos métodos que explicare a continuación

Variables de entorno

En los proyectos de desarrollo generalmente se gestionan las variables de entorno con librerías que leen la información de algún archivo .env y cargan estas variables a la memoria, lo cual se puede apreciar en la Figura 1 , cuando trabajamos con serverless como hablaba hace poco en un post de algunos dolores de cabeza y entre ellos mencionaba las variables de entorno, al final del día en arquitectura serverless y cualquier otra arquitectura la diferencia es muy poca, una lambda es un servicio efímero que se ejecuta en una maquina por un tiempo, la diferencia en este caso es el como hacerlo y para ello debemos soportarnos sobre el SDK de serverleess

Figura 1: Cargando variables de entorno obtenido de https://wizardzines.com/comics/environment-variables/

Variables de consola

Las variables de CLI son las variables que utilizamos dentro del SDK cuando ejecutamos algún comando, estos parámetros son los que dispone el serverless como banderas, en el siguiente código se puede ver un ejemplo

service: mycognito-cognito-auth
frameworkVersion: '2'
variablesResolutionMode: 20210326
provider:
  name: aws
  runtime: python3.8
  lambdaHashingVersion: 20201221
  environment:
    stage: ${opt:stage, 'dev'}
 


functions:
  hello:
    handler: handler.hello
    events:
      - httpApi:
          method: POST
          path: /upload
    

para ejecutar el despliegue ejecutamos el siguiente comando

serverless deploy --stage dev   --aws-profile personal-account

como se aprecia en el código del archivo serverless.yml en la sección enviroment, la estructura para manejar variables de entorno proporcionados por medio de banderas de consola es

${opt:stage, 'dev'}

el valor después de los puntos es el nombre de la bandera, y el valor entre comillas simples es el valor por defecto si la bandera no se pasa, ya que si no se pone un valor por defecto el valor a tomar es nulo

Variables de archivos

Esta opción es usada cuando se necesita referenciar variables de archivos, serverless no soporta .env pero si soporta las dos principales estructuras de archivos usados JSON y YAML la sintaxis para referenciar una variable especifica es ${file(./myFile.json):someProperty} veamos un ejemplo

service: mycognito-cognito-auth
frameworkVersion: '2'
variablesResolutionMode: 20210326
provider:
  name: aws
  runtime: python3.8
  lambdaHashingVersion: 20201221
  environment:
    stage: ${opt:stage, 'dev'}
  httpApi:
    authorizers:
      MyProjectAuthorizer:
        type: jwt
        identitySource: $request.header.Authorization
        issuerUrl:  ${file(./config.${opt:stage, 'dev'}.json):ISSUER_URL}
        audience:
          -  ${file(./config.${opt:stage, 'dev'}.json):AUDIENCE}


functions:
  hello:
    handler: handler.hello
    events:
      - httpApi:
          method: POST
          path: /upload
          authorizer:
            name: MyProjectAuthorizer

lo ejecutamos para desplegar con el siguiente comando

 serverless deploy --aws-profile personal-account

como se aprecia en el archivo yml en la sección httpApi tenemos  la siguiente linea

${file(./config.${opt:stage, 'dev'}.json):AUDIENCE}

aquí lo que se hace es abrir el archivo que se llame config.dev.json si el stage es dev, config.qa.json si el stage es qa y asi sucesivamente, es decir se pueden tener archivos de configuraron para diferentes ambientes usando la bandera stage,  el archivo json tiene la siguiente estructura

{
  "AUDIENCE": "https://test",
  "ISSUER_URL": "test"
}

con el :AUDIENCE lo que sucede es que selecciona el atributo audience y asigna este valor, esta opción es bastante utilizada para gestionar nuestras variables de entorno por ambiente

Variables de AWS

Esta opción nos permite referenciar básicamente dos valores pertenecientes a identificadores de AWS, estos valores son el accountid y la region, estas variables son muy importantes sobre todo a la hora de construir identificadores de recursos, usando el ARN,  veamos el siguiente ejemplo

service: mycognito-cognito-auth
frameworkVersion: '2'
variablesResolutionMode: 20210326
provider:
  name: aws
  runtime: python3.8
  lambdaHashingVersion: 20201221
  environment:
    stage: ${opt:stage, 'dev'}
  httpApi:
    authorizers:
      MyProjectAuthorizer:
        type: jwt
        identitySource: $request.header.Authorization
        issuerUrl:  ${file(./config.${opt:stage, 'dev'}.json):ISSUER_URL}
        audience:
          -  ${file(./config.${opt:stage, 'dev'}.json):AUDIENCE}


functions:
  update:
    handler: handler.update
    events:
      - stream:
          type: kinesis
          arn: arn:aws:kinesis:${aws:region}:${aws:accountId}:stream/mystream
          batchSize: 100
          startingPosition: LATEST
          maximumRetryAttempts: 10
          enabled: true


ejecutamos el despliegue

 serverless deploy --stage dev --region us-east-1  --aws-profile personal-account

observen que yo le digo la región por medio del CLI, así que por defecto tomara la región que le pase, ahora cree una función update de tipo stream con kinesis, algo importante es que este recurso requiere identificarlo por medio del arn, si especifico directamente el arn que genera el recurso, cuando haga un despliegue en otra cuenta al harcodear el ARN ocurrirá un error, en este caso lo que hago es referenciar un ARN "dinamico", de tal forma que si cambio de región o cuenta solo debo ponerle el mismo nombre (o podría cargar el nombre de una variable de archivo) con esto mantengo un despliegue dinámico

arn: arn:aws:kinesis:${aws:region}:${aws:accountId}:stream/mystream

Variables de parameter store

Este es un servicio de AWS que permite gestionar datos secretos de una forma fácil y sencilla, esto servicio bastante amplio e interesante pero yo solo me centrare en la conexión que presta al SDK, serverless tiene una integración con SSM, lo que permite acceder a este servicio de forma sencilla, aquí se guardaran variables o credenciales que contienen información sensible, debido que este servicio se conecta con KMS, para resumir, usaremos este servicio cuando se requieran guardar datos que no pueden ser visibles en el código ni en ningún archivo, creare una variable en KMS y luego la guardare en parameter store

Figura 2: Creando un key en KMS

Luego la relaciono con parameter store para poder accederla

Figura 3: Creando un parametro en parameter store

ahora ya la puedo acceder desde serverless, como mencione es nativa por lo tanto sera bastante sencillo

service: mycognito-cognito-auth
frameworkVersion: '2'
variablesResolutionMode: 20210326
provider:
  name: aws
  runtime: python3.8
  lambdaHashingVersion: 20201221
  environment:
    stage: ${opt:stage, 'dev'}
    environment:
      SECRET_VALUE: ${ssm:/secret/url}
  httpApi:
    authorizers:
      MyProjectAuthorizer:
        type: jwt
        identitySource: $request.header.Authorization
        issuerUrl:  ${file(./config.${opt:stage, 'dev'}.json):ISSUER_URL}
        audience:
          -  ${file(./config.${opt:stage, 'dev'}.json):AUDIENCE}


functions:
  update:
    handler: handler.update
    events:
      - stream:
          type: kinesis
          arn: arn:aws:kinesis:${aws:region}:${aws:accountId}:stream/mystream
          batchSize: 10
          startingPosition: LATEST
          maximumRetryAttempts: 10
          enabled: true


Como se puede apreciar en el código cree una variable en enviroment llamada SECRET_VALUE  con el siguiente valor

${ssm:/secret/url}

aquí lo que hago es acceder al servicio de parameter store y obtener el valor en plano de esa variable, el nombre  debe ser único por región, si quisiera hacerlo un poco mas dinamice y cambiarlo de región podría hacer lo siguiente

${ssm(us-west-2):/secret/url-${opt:stage, 'dev'}}

en este caso cambie la obtención del parámetro a otra región pero adicional obtiene las que el nombre lleven -stage, de esta forma puedo tener variables de producción, desarrollo, qa etc

Conclusiones

La gran cantidad de opciones para variables de entorno en serverless, no es exactamente para decidir por alguna en especifico, esto debido a que la mayor ventaja esta en mesclar su uso, por lo tanto si yo puedo utilizar varias  formas de cargar variables, obtendré un mayor beneficio haciendo mi proyecto lo mas dinámico posible, logrando facilitar el despliegue de mi producto

Te gusto el post y quisieras poder aplicar lo aprendido?

Únete al equipo de Simetrik AQUI