🔐Ciberseguridad

Infisical: cómo gestionar secretos sin depender de archivos .env

Felipe••24 min de lectura
Gestiona secretos con Infisical, Node.js y TypeScript: CLI, SDK, identidades de máquina y GitLab OIDC, con permisos mínimos y sin filtrarlos en logs.

Una persona del equipo cambia la contraseña de la base de datos. Otra sigue utilizando una copia antigua del .env. El pipeline tiene un tercer valor y nadie recuerda quién conserva la credencial de producción. La aplicación puede estar bien programada y, aun así, depender de una distribución de secretos difícil de controlar.

Infisical permite centralizar esos valores y decidir qué identidades pueden obtenerlos. La aplicación puede seguir leyendo variables de entorno; lo que cambia es cómo se almacenan, entregan y administran las credenciales antes de llegar al proceso.

Vamos a construir un ejemplo pequeño con Node.js, TypeScript y pnpm. Primero utilizaremos el CLI y después el SDK oficial. También veremos cómo trasladar la idea a GitLab CI/CD sin guardar una contraseña permanente de Infisical en el pipeline.

Configuración y secretos: no todo valor tiene la misma sensibilidad

El puerto HTTP, una bandera de funcionalidad o el nombre del entorno son configuración. Una contraseña de base de datos, una API key privada o una clave de firma son secretos: conocerlos permite realizar operaciones que deberían estar restringidas.

Algunos valores mezclan ambas cosas. DATABASE_URL puede contener host, puerto, usuario y contraseña; aunque el host no sea confidencial, la cadena completa merece tratamiento de secreto. La sensibilidad depende de su contenido y uso, no de que su nombre termine en _SECRET.

Hardcodear una credencial en TypeScript la vincula al código y a su distribución. Puede terminar en el historial Git, artefactos compilados, una imagen de contenedor o un respaldo del repositorio. Borrar la línea del último commit no invalida las copias anteriores: una credencial expuesta debe revocarse o rotarse en el sistema que la acepta.

Un archivo .env es útil para desarrollo, pero no resuelve por sí solo quién puede leer un valor, quién lo cambió, qué copia está vigente ni cómo retirarlo de veinte equipos. Si se comparte por chat, cada descarga crea otra copia fuera de control. Tampoco basta con .gitignore: no elimina archivos ya versionados ni impide filtraciones en logs, contextos de construcción o artefactos de CI.

Una variable de entorno es un mecanismo de entrega al proceso. Puede formar parte de una arquitectura segura si el origen, los permisos y la ejecución están protegidos. No es, por sí sola, un gestor de secretos. Esta distinción también aparece en los controles esenciales para una API REST.

La recomendación de centralizar, limitar acceso y administrar el ciclo de vida está desarrollada en OWASP Secrets Management Cheat Sheet. Es una guía de buenas prácticas, no una obligación legal universal.

Qué aporta Infisical y qué sigue siendo responsabilidad del equipo

Infisical es una plataforma que incluye gestión de secretos. Para este artículo nos interesa su organización por proyectos, entornos y carpetas, y la entrega mediante CLI o SDK. Por ejemplo, el proyecto api-laboratorio puede tener un entorno dev y una carpeta /api, separada de otras aplicaciones. La documentación de Secrets Management describe también integraciones con infraestructura y sincronización hacia otros almacenes.

No confundas organizar con autorizar: tener carpetas llamadas dev y prod no demuestra que una identidad de desarrollo tenga prohibido leer producción. Esa frontera debe existir en los permisos efectivos.

flowchart TB
  H[Desarrollador] -->|Sesión personal| I[Infisical]
  M[Aplicación o pipeline] -->|Identidad de máquina| I
  I --> P{Permisos sobre proyecto y entorno}
  P -->|Permitido| S[Secretos de la carpeta autorizada]
  S --> E[CLI: entorno del proceso]
  S --> K[SDK: valores en memoria]
  E --> A[Aplicación Node.js]
  K --> A

El gestor reduce la dispersión, pero no impide que un proceso autorizado filtre los valores que recibe. El código de la aplicación, las dependencias, los runners y los operadores con acceso al sistema siguen formando parte de la frontera de confianza.

Cloud, self-hosted y límites del plan

Infisical Cloud evita que operes el servicio. En self-hosted administras disponibilidad, actualizaciones, almacenamiento, TLS y recuperación. El núcleo abierto y las funciones comerciales no son equivalentes: alojarlo tú mismo no desbloquea automáticamente todas las capacidades. Consulta los modelos de despliegue.

Al consultar la tabla oficial de planes el 1 de noviembre de 2026, la oferta de Secrets Management distinguía:

PlanAspectos relevantes para este tutorial
FreeCinco identidades, proyectos ilimitados y tres entornos; no incluye todas las capacidades de gobierno
ProControles de acceso, versionado, recuperación y auditoría con 30 días de retención; la tabla limita su rotación a bases de datos públicas
AdvancedRoles personalizados, secretos dinámicos y auditoría con 90 días de retención, entre otras capacidades
EnterpriseFlujos de aprobación, retención personalizada e integración de auditoría con SIEM, entre otras opciones

Una identidad puede ser humana o de máquina. Revisa el plan vigente antes de diseñar permisos o estimar costos; una prueba temporal de pago tampoco equivale al plan gratuito. No abras una base de datos a Internet para ajustarte a una limitación comercial de rotación.

El versionado conserva cambios y permite recuperar estados anteriores. La auditoría registra operaciones y actores, con disponibilidad y retención según plan. La rotación automática requiere una integración compatible con el proveedor de la credencial; guardar un valor no significa que Infisical pueda renovarlo automáticamente.

Preparar un proyecto Cloud con datos ficticios

Usaremos Node.js 22 o superior, pnpm 11.14.0, CLI 0.44.11 y SDK 5.0.2. Las versiones del CLI y SDK se fijan porque sus comandos y APIs pueden cambiar. Los comandos de terminal están pensados para Bash; no necesitas una base de datos real.

  1. Crea una cuenta en Infisical Cloud, elige la región adecuada y habilita MFA para tu usuario.
  2. Crea un proyecto de Secrets Management llamado api-laboratorio.
  3. Selecciona Development, cuyo identificador será dev en este ejemplo. Comprueba ese slug, no solo su nombre visible.
  4. Crea la carpeta /api dentro de ese entorno.
  5. Añade estos tres secretos compartidos desde el panel:
NombreValor ficticio para el laboratorio
DATABASE_URLpostgresql://demo:solo-laboratorio@127.0.0.1:5432/demo
API_KEYapi-ficticia-no-utilizable
JWT_SECRETjwt-ficticio-no-utilizable

Son datos públicos de demostración. No los uses para proteger servicios, firmar tokens ni conectarte a producción. El programa solo comprobará que recibe la configuración; no implementa autenticación ni abre conexiones con esa base de datos.

Obtén el Project ID desde la configuración del proyecto. Es un identificador, no una credencial. La guía para añadir los primeros secretos explica el recorrido del panel.

Si tu plan no permite delimitar los permisos necesarios, mantén el ejercicio en un proyecto desechable que contenga únicamente estos valores. No lo mezcles con secretos reales ni presentes esa limitación como una configuración apropiada para producción.

Crear la aplicación TypeScript

En una carpeta nueva:

mkdir infisical-lab
cd infisical-lab
pnpm init
mkdir src

En package.json, conserva el nombre y añade "type": "module" y estos scripts:

{
  "build": "tsc",
  "start": "node dist/cli.js",
  "start:sdk": "node dist/sdk.js"
}

El objeto anterior es el contenido de la propiedad scripts, no el archivo completo. Instala las dependencias de TypeScript:

pnpm add -D -E typescript@7.0.2 @types/node@22.20.5

Crea tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "types": ["node"],
    "rootDir": "src",
    "outDir": "dist",
    "skipLibCheck": true
  },
  "include": ["src/**/*.ts"]
}

Añade a .gitignore y .dockerignore, según corresponda:

node_modules/
dist/
.env
.env.*
!.env.example

Un .env.example con nombres y valores vacíos puede documentar el contrato de configuración. Este ejemplo no necesita un .env real.

Validar antes de iniciar

Crea src/config.ts:

export function requireValue(
  source: Record<string, unknown>,
  name: string,
): string {
  const value = source[name];

  if (typeof value !== 'string' || value.trim().length === 0) {
    throw new Error(`Configuración requerida ausente: ${name}`);
  }

  return value;
}

export function loadConfig(source: Record<string, unknown>) {
  const databaseUrl = requireValue(source, 'DATABASE_URL');
  const apiKey = requireValue(source, 'API_KEY');
  const jwtSecret = requireValue(source, 'JWT_SECRET');

  let database: URL;

  try {
    database = new URL(databaseUrl);
  } catch {
    throw new Error('DATABASE_URL no tiene un formato válido');
  }

  if (!['postgres:', 'postgresql:'].includes(database.protocol) || !database.hostname) {
    throw new Error('DATABASE_URL debe usar PostgreSQL en este ejemplo');
  }

  return Object.freeze({ databaseUrl, apiKey, jwtSecret });
}

La función rechaza campos ausentes o vacíos y una URL que no corresponda al formato básico del ejemplo. No recorta ni transforma el valor del secreto: los espacios podrían formar parte de una credencial. Tampoco comprueba que la base de datos exista o que la API key sea válida ante su proveedor.

Esto es validación en runtime, no una garantía proporcionada por TypeScript. Para contratos más grandes puedes usar un esquema; aquí unas comprobaciones explícitas mantienen el ejemplo acotado. Object.freeze evita reasignaciones accidentales del objeto, no protege su contenido frente a lectura.

Crea src/cli.ts:

import { loadConfig } from './config.js';

try {
  const config = loadConfig(process.env);

  // Aquí se entregarían los valores al pool y a los clientes necesarios.
  // Este laboratorio no se conecta a servicios externos ni firma JWT.
  void config;

  console.info('Configuración válida. No se imprimieron secretos.');
} catch {
  console.error('Inicio cancelado: revisa la configuración requerida.');
  process.exitCode = 1;
}

Cancelamos el inicio ante una configuración incompleta, sin inventar una contraseña por defecto. En una aplicación real, ese mismo punto precedería a crear el pool de conexiones o empezar a aceptar solicitudes.

El mensaje público es deliberadamente limitado. Para diagnosticar en producción, registra códigos controlados y contexto no sensible; no serialices process.env, el objeto de configuración ni errores completos del SDK. Las recomendaciones de OWASP sobre datos que deben excluirse de logs incluyen credenciales, tokens y claves.

Enfoque A: inyectar secretos con el CLI

La instalación oficial ofrece paquetes para distintos sistemas y el paquete @infisical/cli. Aquí utilizamos una dependencia local para fijar la versión junto al laboratorio.

Ese paquete descarga su ejecutable mediante un script de instalación. Con pnpm 11, crea primero pnpm-workspace.yaml para permitir solo ese paquete, después de revisar su procedencia:

allowBuilds:
  '@infisical/cli': true
pnpm add -D -E @infisical/cli@0.44.11
pnpm exec infisical --version

No habilites indiscriminadamente los scripts de todas las dependencias. Conserva el lockfile. Si utilizas otra versión de pnpm, consulta su configuración de scripts de instalación.

Autenticar al desarrollador y asociar la carpeta

Para Cloud US:

pnpm exec infisical login --domain=https://app.infisical.com
pnpm exec infisical init --domain=https://app.infisical.com

Completa el acceso interactivo y selecciona el proyecto. Para Cloud EU usa https://eu.infisical.com de forma consistente. El dominio del servicio es configuración de confianza; no debe proceder de entradas HTTP controladas por un usuario.

En esta versión, init crea .infisical.yaml con la asociación del proyecto. El formato anterior .infisical.json sigue documentado. El archivo de proyecto generado no contiene los secretos ni sustituye la sesión personal: puedes versionarlo tras revisarlo, pero no copies los archivos de sesión del CLI al repositorio ni a una imagen de contenedor. Consulta la configuración de proyecto.

Compila y ejecuta:

pnpm run build

pnpm exec infisical sm run \
  --domain=https://app.infisical.com \
  --env=dev \
  --path=/api \
  --expand=false \
  --include-imports=false \
  --secret-overriding=false \
  -- node dist/cli.js

El CLI obtiene los valores y los entrega como variables de entorno al proceso hijo. -- separa sus opciones del comando de Node. Desactivamos expansiones, importaciones y overrides personales para usar los valores compartidos de esa carpeta sin transformaciones implícitas. La sintaxis sm run y esas opciones se comprobaron con --help en la versión indicada; algunos tutoriales antiguos muestran infisical run.

La salida esperada, una vez configurado Cloud, es:

Configuración válida. No se imprimieron secretos.

El proceso solo recibe una instantánea. Modificar el valor en el panel no actualiza mágicamente el entorno de un Node que ya está corriendo. Define cuándo reiniciar o recargar. Tampoco ejecutes un build del frontend bajo secretos de backend: un bundler puede incorporarlos a archivos que terminarán descargando los visitantes.

Enfoque B: recuperar valores con el SDK oficial

El CLI deja el código independiente del proveedor. El SDK permite escoger qué nombres recuperar y entregar sus valores directamente a un componente, sin convertirlos todos en variables de entorno. A cambio, introduces llamadas de red y dependencia de Infisical dentro de tu aplicación.

Instala el SDK oficial para Node.js:

pnpm add -E @infisical/sdk@5.0.2

Una identidad para la aplicación

La cuenta personal responde a «qué persona está trabajando». Una machine identity, o identidad de máquina, representa una aplicación, servicio o automatización. No despliegues una sesión personal para que producción funcione mientras esa persona conserve su cuenta.

Para este laboratorio, crea una identidad, configura Universal Auth, genera su Client Secret y agrégala al proyecto. Concede solo lectura de dev y /api mediante los controles disponibles en tu plan. Comprueba que otra carpeta o entorno quede denegado; no basta con seleccionar dev en el código. La guía de Universal Auth distingue las credenciales iniciales del access token que se obtiene al autenticarse.

El Client ID identifica a la máquina. El Client Secret sí es un secreto y permite solicitar tokens: debe tener caducidad y un mecanismo protegido de entrega. Este es el problema del secreto inicial: un gestor no elimina la necesidad de autenticar a su cliente. En producción, prefiere una identidad del entorno o federación cuando esté disponible; Universal Auth es una alternativa cuando puedes proteger esa credencial inicial.

Crea src/sdk.ts:

import { InfisicalSDK } from '@infisical/sdk';
import { loadConfig, requireValue } from './config.js';

async function main() {
  // URL fija de Cloud US; usa https://eu.infisical.com para Cloud EU.
  // No aceptes esta URL desde una petición de usuario.
  const client = new InfisicalSDK({ siteUrl: 'https://app.infisical.com' });
  const projectId = requireValue(process.env, 'INFISICAL_PROJECT_ID');
  const clientId = requireValue(process.env, 'INFISICAL_CLIENT_ID');
  const clientSecret = requireValue(process.env, 'INFISICAL_CLIENT_SECRET');

  // Reduce la herencia accidental en futuros procesos hijos.
  // Esto no borra las copias que ya existen en memoria.
  delete process.env.INFISICAL_CLIENT_SECRET;

  await client.auth().universalAuth.login({ clientId, clientSecret });

  const values: Record<string, unknown> = {};

  for (const secretName of ['DATABASE_URL', 'API_KEY', 'JWT_SECRET']) {
    const secret = await client.secrets().getSecret({
      projectId,
      environment: 'dev',
      secretPath: '/api',
      secretName,
    });

    values[secretName] = secret.secretValue;
  }

  const config = loadConfig(values);
  void config;

  console.info('Configuración válida obtenida mediante el SDK.');
}

main().catch(() => {
  // No serializar errores del SDK, respuestas HTTP ni credenciales.
  console.error('Inicio cancelado: no se pudo cargar la configuración.');
  process.exitCode = 1;
});

Los valores se recuperan antes de iniciar trabajo y no se imprimen. La región, el entorno y la carpeta son decisiones de despliegue, no parámetros tomados de la petición de un visitante. En un servicio duradero, también necesitas definir renovación de autenticación, actualización de secretos y reacción a revocaciones; este programa termina después de validar la carga inicial.

Para ejecutar manualmente el laboratorio, abre una sesión Bash y solicita las credenciales sin incluir el secreto literal en el historial:

pnpm run build

read -r -p 'Project ID: ' INFISICAL_PROJECT_ID
read -r -p 'Client ID: ' INFISICAL_CLIENT_ID
read -r -s -p 'Client Secret: ' INFISICAL_CLIENT_SECRET
printf '\n'

export INFISICAL_PROJECT_ID INFISICAL_CLIENT_ID INFISICAL_CLIENT_SECRET

pnpm run start:sdk

unset INFISICAL_CLIENT_SECRET INFISICAL_CLIENT_ID INFISICAL_PROJECT_ID

Haz la compilación antes de introducir credenciales en una automatización. Aquí la lectura oculta evita mostrarlas en pantalla; no vuelve invulnerables el terminal o el proceso. No uses set -x ni compartas volcados de memoria. El ejemplo tampoco garantiza borrado seguro de strings en JavaScript.

La salida esperada es Configuración válida obtenida mediante el SDK.. Si falla la autenticación, falta un secreto o la respuesta no cumple el contrato, el programa termina con código de error sin imprimir la respuesta recibida.

Elegir entre CLI y SDK

EnfoqueCuándo encajaResponsabilidad que incorpora
CLIAplicaciones que ya leen configuración del entorno; desarrollo y procesos de duración acotadaInstalar el ejecutable, proteger su autenticación y decidir cuándo reiniciar
SDKRecuperación selectiva y configuración que se entrega directamente a componentesGestionar errores de red, renovación, caché y actualización dentro de la aplicación

Usar el SDK no significa que los secretos dejen de existir en memoria. Usar el CLI tampoco significa que hayan quedado guardados en un .env. Son formas distintas de entrega con límites diferentes.

GitLab CI/CD: autenticar el job mediante OIDC

Una variable protegida con el Client Secret funciona como credencial inicial, pero sigue siendo un valor persistente que debes custodiar y rotar. OIDC permite que GitLab emita un token de identidad para el job y que Infisical lo intercambie por un access token. La integración está documentada en Infisical OIDC con GitLab.

No estamos usando el flujo interactivo de una SPA: aquí la plataforma de CI identifica una carga de trabajo. Si necesitas repasar el vocabulario, consulta OAuth 2.0 y OpenID Connect.

sequenceDiagram
  participant G as GitLab
  participant R as Runner del job
  participant I as Infisical
  G->>R: ID token para la audiencia configurada
  R->>I: Intercambio del token por OIDC Auth
  I->>I: Verificar firma, emisor, audiencia y claims
  I-->>R: Access token con duración limitada
  R->>I: Solicitar secretos de dev y /api
  I->>I: Comprobar permisos de la identidad
  I-->>R: Solo los secretos autorizados
  R->>R: Ejecutar Node con la configuración

Configurar la confianza antes del YAML

Crea una identidad exclusiva para el pipeline y habilita OIDC Auth. Para GitLab.com, configura Discovery URL e issuer como https://gitlab.com; define una audiencia que coincida exactamente con la que solicitará el job. En el ejemplo será https://app.infisical.com.

Restringe el subject al proyecto y rama autorizados. Un subject habitual tiene esta forma: project_path:grupo/api-laboratorio:ref_type:branch:ref:main. Verifica el formato real: GitLab permite personalizarlo. Añade restricciones de claims, por ejemplo el ID del proyecto, ref_type: branch, ref: main y ref_protected: "true", según los valores emitidos por tu instancia. Evita comodines amplios. Configura un TTL del access token acorde con la duración del job; no asumas que el valor por defecto es el adecuado.

La identidad debe pertenecer al proyecto de Infisical y tener permiso de lectura únicamente sobre el entorno y carpeta previstos. Verificar el token y autorizar el acceso son comprobaciones distintas, igual que en RBAC y ABAC. Para producción, utiliza otra identidad y otros permisos.

Un job adaptable al laboratorio

El siguiente YAML requiere una imagen de CI confiable que ya tenga Node.js y pnpm 11.14.0. Define NODE_PNPM_IMAGE con su referencia fijada, preferiblemente por digest; no es el nombre de una imagen pública que debas copiar literalmente. Define también INFISICAL_IDENTITY_ID e INFISICAL_PROJECT_ID en GitLab. Son identificadores, no Client Secrets. Versiona el código del laboratorio, su lockfile y la autorización acotada del script de instalación del CLI.

stages:
  - verify

verify-configuration:
  image: $NODE_PNPM_IMAGE
  stage: verify
  timeout: 5m

  id_tokens:
    INFISICAL_ID_TOKEN:
      aud: https://app.infisical.com

  rules:
    - if: '$CI_COMMIT_BRANCH == "main" && $CI_COMMIT_REF_PROTECTED == "true"'

  script:
    - pnpm install --frozen-lockfile
    - pnpm run build
    - |
      set -eu
      set +x

      INFISICAL_TOKEN="$(pnpm exec infisical login \
        --domain=https://app.infisical.com \
        --method=oidc-auth \
        --machine-identity-id="$INFISICAL_IDENTITY_ID" \
        --jwt="$INFISICAL_ID_TOKEN" \
        --plain --silent)"

      test -n "$INFISICAL_TOKEN"
      export INFISICAL_TOKEN
      unset INFISICAL_ID_TOKEN

      pnpm exec infisical sm run \
        --domain=https://app.infisical.com \
        --projectId="$INFISICAL_PROJECT_ID" \
        --env=dev \
        --path=/api \
        --expand=false \
        --include-imports=false \
        --secret-overriding=false \
        -- node dist/cli.js

      unset INFISICAL_TOKEN

Aquí usamos el flag --jwt comprobado en CLI 0.44.11. Los ID tokens se declaran con id_tokens de GitLab; no necesitas guardar su valor manualmente. La opción --projectId es explícita porque la autenticación de máquina no debe depender de la asociación interactiva del desarrollador.

Este YAML muestra la integración; debes adaptarlo y probarlo en tu proyecto. Las rules reducen ejecuciones, pero no reemplazan las restricciones de confianza en Infisical. Protege main, revisa cambios del pipeline y usa runners aislados. El ID token ya existe en el entorno del job antes de ejecutar el script: dependencias y scripts de instalación también forman parte de su confianza. Para un pipeline más exigente, separa la construcción sin acceso a secretos del job que consume el artefacto.

El token pasado por argumento puede ser visible para procesos con permisos suficientes en el runner. Desactiva también CI_DEBUG_TRACE, no imprimas el entorno y no guardes tokens ni secretos en cachés, artefactos o reportes dotenv. El enmascaramiento de GitLab no convierte cualquier valor recuperado dinámicamente en invisible, ni evita que código malicioso lo envíe fuera. Revisa las reglas de seguridad de variables CI/CD.

Si no puedes usar OIDC, almacena la credencial de máquina mediante variables protegidas, enmascaradas y ocultas cuando tu versión lo permita, con alcance por entorno. Mantén permisos y duración mínimos; nunca escribas el valor en .gitlab-ci.yml.

Operación: centralizar también introduce dependencias

Rotar no es editar un texto

Cambiar DATABASE_URL en Infisical no cambia por sí mismo la contraseña aceptada por PostgreSQL. Una rotación coordinada necesita crear o activar la nueva credencial en el proveedor, distribuirla, actualizar consumidores, comprobar que funcionan y retirar la anterior. Cuando la integración soporta automatizarlo, configura y prueba ese recorrido.

Distingue una transición planificada de un incidente. Ante compromiso puede ser necesario revocar inmediatamente aunque implique interrupciones; conservar la credencial filtrada durante una ventana cómoda no siempre es aceptable. El diseño de transición se desarrolla en rotación de claves en producción.

Retirar a una persona del proyecto o revocar un token impide nuevos accesos según la política aplicada, pero no borra secretos ya copiados. Verifica el alcance de la revocación sobre tokens emitidos y rota las credenciales de destino expuestas. Recuperar una versión antigua tampoco reactiva una contraseña que el proveedor ya dejó de aceptar.

Qué ocurre si el gestor no responde

Como criterio de diseño para estos ejemplos, la aplicación no debe iniciar con valores vacíos ni con una credencial de emergencia hardcodeada. Un fallo de recuperación cancela el arranque. Eso hace visible el problema, pero puede impedir nuevos despliegues durante una caída del gestor.

Un proceso que ya cargó una credencial puede seguir utilizándola mientras el servicio de destino la acepte; si necesita renovarla o volver a consultar, también puede fallar. Un rollout que sustituya simultáneamente todas las instancias agrava esa dependencia. Define tiempos máximos de arranque, reintentos acotados, backoff, alertas y una política de disponibilidad antes de producción.

La caché en memoria reduce llamadas, pero retrasa la aplicación de cambios y revocaciones. Define su vigencia según el riesgo, la caducidad y la tolerancia a caída. No conviertas un error de red en permiso para utilizar indefinidamente cualquier copia antigua. Una copia persistente agrega otro almacén sensible: requiere protección, acceso limitado, expiración y limpieza.

Prepara recuperación con responsables y un procedimiento de acceso de emergencia probado. En self-hosted, incluye respaldos y recuperación del material criptográfico necesario para leerlos; tener la base de datos sin las claves correspondientes puede no bastar. Estas decisiones deben ajustarse a tu modelo operativo, no a un intervalo universal.

Auditoría útil y límites de memoria

Revisa accesos inusuales, cambios de permisos y operaciones de rotación, con alertas y retención adecuadas al plan. Un evento de lectura del gestor permite investigar esa lectura; no muestra automáticamente todo uso posterior de la credencial en una base de datos. Correlaciona con registros del servicio de destino sin registrar el secreto.

Evita volcados, endpoints de diagnóstico y trazas que serialicen configuración. Un proceso comprometido puede leer los secretos que necesita para trabajar, estén en variables o en objetos del SDK. El gestor no sustituye autorización, validación y protección de errores en la API.

Migrar desde .env sin cambiar todo de golpe

Una migración razonable puede empezar por un servicio y un entorno:

  1. Inventaría los nombres, consumidores, permisos y responsables. Separa configuración pública de credenciales.
  2. Crea el proyecto y el entorno de desarrollo con valores distintos de producción.
  3. Integra el CLI conservando el contrato que ya lee la aplicación. Comprueba que falten valores y que el inicio falle correctamente.
  4. Sustituye credenciales compartidas por accesos individuales y una identidad por carga de trabajo cuando aporte aislamiento.
  5. Prueba renovación, revocación y caída del gestor antes de migrar producción.
  6. Retira las copias .env que ya no se necesitan. Si estuvieron expuestas, rota los valores; borrar archivos no elimina el riesgo histórico.

En desarrollo importa facilitar el acceso personal y evitar compartir contraseñas. En producción importan además disponibilidad, identidades no interactivas y permisos reproducibles. En CI/CD, limita qué jobs reciben secretos y en qué momento. Esa coordinación entre desarrollo, seguridad y operación es una aplicación concreta de DevSecOps.

Compararlo con otras opciones

La siguiente comparación es un criterio de selección, no un ranking. Considera la plataforma que ya opera tu equipo y el costo de introducir otra frontera de identidad.

OpciónIntegración y accesoOrganización y alojamientoCompromiso operativo
InfisicalCLI, SDK y machine identitiesProyectos, entornos y carpetas; Cloud o self-hostedEntrada cómoda para equipos que parten de .env; revisar planes y operación si se autoaloja
HashiCorp VaultAPIs, métodos de autenticación, políticas y motores de secretosRutas y políticas; despliegue propio u opciones administradas de HashiCorpFlexible para necesidades diversas; operar almacenamiento, disponibilidad y políticas requiere experiencia
Azure Key VaultSDK e identidad de Microsoft Entra, con controles de acceso de AzureBóvedas y recursos dentro de AzureEncaja si las cargas ya usan identidad y operación de Azure
AWS Secrets ManagerSDK, IAM e integraciones de AWSSecretos y versiones, separados mediante cuentas y políticas según el diseñoReduce infraestructura propia; revisar uso, llamadas y rotación compatible
Google Cloud Secret ManagerAPIs, SDK e IAMProyectos, secretos y versiones en Google CloudEncaja con la identidad y operación de GCP; diseñar acceso y ciclo de vida de versiones

Las capacidades base pueden consultarse en la documentación oficial de Vault, Azure Key Vault, AWS Secrets Manager y Google Cloud Secret Manager.

Para costos, compara el plan y sus límites, volumen de operaciones, infraestructura, soporte y tiempo de operación. Self-hosted no significa costo total cero. Tampoco todas las opciones representan los entornos con una entidad llamada environment: a veces se separan mediante proyectos, cuentas, bóvedas o políticas. El aislamiento efectivo importa más que el nombre.

Comprobar el laboratorio y retirarlo

Después de completar la configuración Cloud, verifica que ambos enfoques obtengan los valores sin imprimirlos. En el proyecto desechable, retira temporalmente API_KEY y confirma que el programa termine con error; restáurala después. Prueba también una identidad sin acceso y una petición fuera de su entorno autorizado. No amplíes los permisos simplemente para hacer desaparecer un error.

Durante la preparación de este artículo se verificaron la instalación y ayuda del CLI, la compilación TypeScript, los casos locales de validación y el comportamiento del SDK con respuestas HTTP simuladas. No se ejecutó una sesión autenticada contra Infisical Cloud ni un pipeline real de GitLab. Las salidas de esos recorridos se describen como esperadas, no como resultados observados.

Para limpiar, revoca las credenciales e identidades creadas para el ejercicio, elimina el proyecto de laboratorio cuando ya no sea necesario, cierra su sesión del CLI con pnpm exec infisical logout y borra la carpeta local. Si utilizas varias sesiones, comprueba que cierras la correspondiente al laboratorio. Retira también las variables e identidades de CI que hayas creado.

Elegir según el problema que necesitas resolver

En un proyecto personal con pocas credenciales, el mecanismo protegido de tu plataforma de despliegue puede ser suficiente. Agregar otro servicio sin un problema de colaboración, permisos o ciclo de vida puede aumentar mantenimiento y puntos de fallo.

En un equipo pequeño, la distribución centralizada empieza a aportar valor cuando aparecen copias divergentes y accesos compartidos. En una aplicación empresarial, la decisión exige verificar permisos, auditoría, identidad y recuperación, incluyendo las funciones que requieren otro plan. Para contenedores, separa secretos de la imagen; para pipelines, evita credenciales persistentes cuando la federación cubra el caso.

Si la organización ya utiliza correctamente un gestor administrado de Azure, AWS o Google Cloud, evalúa qué problema adicional resolvería Infisical antes de duplicar almacenes. El objetivo es poder explicar quién obtiene cada secreto, para qué, durante cuánto tiempo y cómo se revoca, con una operación que el equipo sea capaz de mantener.

Referencias

#Infisical#gestión de secretos#Node.js#TypeScript#variables de entorno#GitLab CI/CD#OIDC#DevSecOps

Artículos relacionados