Referencia de envilder validate
¿Cómo sabes que un archivo de mapeo funcionará antes de un pull, un despliegue o envilder exec? envilder validate comprueba que el archivo de mapeo es válido y que cada secreto declarado existe en AWS SSM o Azure Key Vault, y puede compararlo con un archivo .env local. Nunca muestra ningún valor de secreto y sale con 1 cuando algo falla, así que encaja como paso de CI.
Requisitos previos
- La CLI de envilder. --offline está disponible desde la versión 0.18 y la comprobación de existencia de los secretos desde la 0.20. --envfile, --compare-values y --format json llegan con la próxima versión.
- Un archivo de mapeo. Sin --offline, credenciales del proveedor y los permisos que se detallan en el apartado Permisos.
Sinopsis
envilder validate [--offline] [--envfile <path> [--compare-values]] \
[--format <text|json>] [--map <path>] [--provider <name>] \
[--profile <name>] [--vault-url <url>]Por defecto, validate comprueba el archivo de mapeo y después pregunta al proveedor si existe cada secreto declarado. Con --envfile también compara las claves de un archivo env local con el archivo de mapeo, y con --compare-values compara sus valores con los remotos. Con --offline solo se leen archivos locales: no se llama a ningún proveedor y no hacen falta credenciales de la nube. Nunca muestra ningún valor de secreto.
envilder validate
envilder validate --map=config/envilder.json --profile=dev
envilder validate --provider=azure --vault-url=https://my-vault.vault.azure.net
envilder validate --offline
envilder validate --envfile=.env --compare-values
envilder validate --format=jsonOpciones
| Opción | Descripción |
|---|---|
--offline | Valida el archivo de mapeo en local sin llamar al proveedor |
--envfile | Compara las claves de este archivo env con el archivo de mapeo. No se lee si no se indica |
--compare-values | Compara también cada valor declarado en el archivo env con su valor remoto. Requiere --envfile; no se puede combinar con --offline |
--format | text (por defecto) para una salida legible, o json para un único documento JSON en stdout |
--map | Archivo de mapeo a comprobar (por defecto: envilder.json) |
--provider | aws o azure. Sustituye $config.provider |
--profile | Perfil de AWS CLI. Sustituye $config.profile |
--vault-url | URL de Azure Key Vault. Sustituye $config.vaultUrl |
Las opciones tienen los mismos nombres, valores por defecto y precedencia que pull y exec: las opciones ganan a $config, y una opción vacía se ignora. Ponlas después de validate; las que se escriben antes se rechazan. Como en push, un valor vacío de --envfile es un error.
--compare-values sin --envfile o con --offline, y un --format que no sea text ni json, se rechazan antes de leer ningún archivo o llamar a ningún proveedor.
Qué se comprueba
El archivo de mapeo (siempre)
El archivo de mapeo se comprueba primero, con los mismos mensajes que usan pull, push y exec. Se informa de cada problema, no solo del primero, con la clave que lo causa ($config.profile, --vault-url, DB_URL...). Los mensajes nombran claves y tipos, nunca valores mapeados.
- El archivo se analiza como JSON. Un error de análisis indica la ruta y, cuando el analizador la da, la línea y la columna, pero nunca cita el texto de alrededor, porque puede ser un secreto pegado en el archivo.
- El documento cumple el esquema publicado del archivo de mapeo (map-file.v1.json): campos de $config conocidos, nombres de variable válidos y mapeos de tipo string.
- La configuración del proveedor es coherente una vez aplicadas las opciones: aws o azure, profile solo con aws, vaultUrl solo con azure, y azure tiene un vaultUrl.
Cuando el archivo de mapeo no es válido, validate se detiene ahí: no se llama a ningún proveedor, con --offline o sin él.
Las claves remotas (sin --offline)
Cada ruta de secreto declarada en el archivo de mapeo se comprueba en el proveedor. Envilder nunca usa ni muestra ningún valor: en AWS, los parámetros String pueden llegar en la respuesta, y se descartan. Una ruta a la que apuntan varias variables se comprueba una sola vez. Cada variable recibe un estado:
| Estado | Significado |
|---|---|
exists | El secreto existe y la identidad puede verlo |
missing | El proveedor ha respondido que ese secreto no existe |
access denied | La identidad no tiene permiso para comprobar el secreto, así que no se sabe si existe. Nunca se informa como missing |
authentication failed | El proveedor ha rechazado las credenciales, o no se ha encontrado ninguna |
provider error | Cualquier otra cosa, por ejemplo un proveedor inaccesible o un nombre de secreto no válido |
Las credenciales de AWS y las sesiones SSO caducadas se informan con el mismo mensaje que pull y exec. En un terminal interactivo, una sesión SSO caducada ofrece ejecutar aws sso login y después vuelve a intentarlo.
Las claves del archivo env (con --envfile)
Disponible a partir de la próxima versión. El archivo env se lee con el mismo analizador que usan pull y push, así que los comentarios, export, las comillas y los valores multilínea se comportan igual. Sus claves se comparan con las variables que declara el archivo de mapeo, por el nombre exacto, distinguiendo mayúsculas y minúsculas:
| Hallazgo | Efecto |
|---|---|
missing from .env | Una variable declarada no está en el archivo env. Falla |
duplicated in .env | Una clave se asigna más de una vez. Falla |
not declared in map file | Una clave solo está en el archivo env. Un aviso que no cambia el código de salida |
KEY= con un valor vacío cuenta como presente, y un archivo env inexistente falla con Env file not found. Esta comprobación solo lee archivos locales, así que se ejecuta antes de cualquier llamada al proveedor y también con --offline. Los valores no se comparan ni se muestran.
Los valores del archivo env (con --compare-values)
Para cada variable declarada que está en el archivo env y existe en el proveedor, el valor remoto se lee como lo hace pull y se compara con el local. Cuando una clave se repite, se compara la última asignación, tal como la carga dotenv:
| Estado | Significado |
|---|---|
matches | Los dos valores son idénticos |
differs | Los dos valores no son idénticos. Falla |
unreadable | El secreto existe pero su valor no se ha podido leer, con el motivo del proveedor. Falla |
Ninguno de los dos valores se muestra nunca, y cada valor remoto se descarta justo después de la comparación. Las variables ya informadas como ausentes no se leen. Sin --compare-values no se lee ningún valor.
Permisos
La comprobación de existencia usa una llamada al proveedor que pull no hace, así que la identidad necesita un permiso más que para un pull. --offline no necesita ninguna credencial.
AWS SSM
Las rutas se comprueban con GetParameters, diez por llamada, con WithDecryption: false: los parámetros SecureString nunca se descifran. Es una acción de IAM distinta de la ssm:GetParameter que usa pull, así que añádela a la política, limitada a las mismas rutas:
{
"Effect": "Allow",
"Action": ["ssm:GetParameter", "ssm:GetParameters"],
"Resource": "arn:aws:ssm:*:*:parameter/myapp/*"
}La comprobación de existencia no necesita el permiso kms:Decrypt. --compare-values lee los valores como pull, así que necesita el mismo acceso a KMS que pull: kms:Decrypt sobre la clave de cada parámetro SecureString cifrado con una clave administrada por el cliente. Con kms:Decrypt, ssm:GetParameters también puede leer valores descifrados, así que limítalo a las mismas rutas que ssm:GetParameter. Cuando se deniega una llamada, cada ruta se comprueba por separado, así que access denied solo se informa para las rutas que la identidad no puede leer.
Azure Key Vault
Los nombres de los secretos del vault se listan una vez (solo metadatos) y cada nombre declarado, tras la conversión habitual de / a -, se compara con esa lista sin distinguir mayúsculas. Un secreto deshabilitado se informa como missing, porque pull no puede leerlo. Listar requiere:
- Azure RBAC: Microsoft.KeyVault/vaults/secrets/readMetadata/action sobre el vault, incluido en los roles integrados Key Vault Secrets User y Key Vault Reader.
- Directivas de acceso: el permiso de secreto List, además de Get.
az role assignment create \
--role "Key Vault Secrets User" \
--assignee {YOUR_OBJECT_ID} \
--scope /subscriptions/{SUB}/resourceGroups/{RG}/providers/Microsoft.KeyVault/vaults/{VAULT}az keyvault set-policy \
--name {VAULT_NAME} \
--object-id {YOUR_OBJECT_ID} \
--secret-permissions get listLa lista cubre todo el vault, así que una identidad sin este permiso recibe access denied para cada clave, con el motivo que devuelve Key Vault.
--compare-values también lee valores, así que necesita los mismos permisos que un pull además de estos.
Salida
Todos los secretos existen (código de salida 0):
✓ Map file valid: envilder.json
☁ AWS identity · account=123456789012 · region=eu-west-1 · profile=dev
Checking 3 secrets in aws, profile=dev
✓ DB_URL /myapp/db-url exists
✓ DATABASE_URL /myapp/db-url exists
✓ API_KEY /myapp/api-key exists
✓ All 3 secrets existAlgunos secretos faltan o no se pueden comprobar (código de salida 1; el resumen va a stderr):
✓ Map file valid: envilder.json
Checking 3 secrets in aws, profile=dev
✓ DB_URL /myapp/db-url exists
✗ API_KEY /myapp/api-key missing
✗ TOKEN /myapp/token access denied (User: arn:aws:sts::123456789012:assumed-role/dev/ci is not authorized to perform: ssm:GetParameters ...)
✗ Validation failed: 1 missing, 1 access deniedCon --offline:
✓ Map file valid: envilder.json
Remote validation skipped (--offline): no provider was called, so the secrets were not checked.Con --envfile=.env --compare-values (código de salida 1):
✓ Map file valid: envilder.json
Checking env file .env
✗ TOKEN missing from .env
⚠ DEBUG not declared in map file
Checking 3 secrets in aws, profile=dev
✓ DB_URL /myapp/db-url exists
✓ API_KEY /myapp/api-key exists
✓ TOKEN /myapp/token exists
Comparing 2 values with aws, profile=dev
✓ DB_URL matches
✗ API_KEY differs
✗ Validation failed: 1 missing from .env, 1 differsCuando todas las variables declaradas están en el archivo env, su bloque termina con ✓ All 3 declared variables are in .env, y cuando todos los valores comparados coinciden, el bloque de valores termina con ✓ All 2 values match.
Un archivo de mapeo no válido, en stderr:
✗ Map file invalid: envilder.json (3 problems)
• $config.region is not a known field. Allowed fields: provider, profile, vaultUrl, projectId, namespace, path, name, description, owner, environment.
• DB_PORT must map to a string secret path, not a number.
• $config.profile is only supported with the aws provider (current provider: azure).Salida JSON (--format json)
Disponible a partir de la próxima versión. Con --format=json, validate escribe exactamente un documento JSON en stdout y nada más, sea cual sea el resultado. Los logs, el banner de identidad de AWS, los avisos, los errores y la solicitud de inicio de sesión SSO van a stderr, así que stdout se puede pasar a jq o guardar como artefacto de CI. Los códigos de salida son los mismos que con la salida de texto. Los errores de opciones como --format=yaml se informan en stderr antes de ejecutar nada, sin documento.
{
"valid": false,
"offline": false,
"mapFile": { "path": "envilder.json", "valid": true, "errors": [] },
"keys": [
{ "name": "DB_URL", "provider": "aws", "path": "/myapp/db-url", "status": "exists" },
{ "name": "API_KEY", "provider": "aws", "path": "/myapp/api-key", "status": "exists" },
{
"name": "TOKEN",
"provider": "aws",
"path": "/myapp/token",
"status": "access_denied",
"reason": "User: arn:aws:sts::123456789012:assumed-role/dev/ci is not authorized to perform: ssm:GetParameters ..."
}
],
"envFile": {
"path": ".env",
"valid": false,
"keys": [
{ "name": "DB_URL", "status": "present", "value": "matches" },
{ "name": "API_KEY", "status": "present", "value": "differs" },
{ "name": "TOKEN", "status": "missing" }
],
"duplicates": [],
"undeclared": ["DEBUG"]
}
}| Campo | Descripción |
|---|---|
valid | true exactamente cuando el código de salida es 0 |
offline | true con --offline |
mapFile | path, valid y errors (un { key, message } por problema, con los mismos mensajes que la salida de texto). Se omite cuando el archivo de mapeo no se ha podido leer |
keys | Una entrada por variable declarada, en el orden del archivo de mapeo: name, provider, path, status y, cuando el proveedor da uno, reason. status es exists, missing, access_denied, authentication_failed o provider_error. Se omite cuando no se han comprobado los secretos |
envFile | Se omite sin --envfile. Si no, path, valid, keys (cada variable declarada con status present o missing, y value matches, differs o unreadable con --compare-values), duplicates ({ name, count }) y undeclared |
error | { message }, solo cuando la ejecución se ha detenido antes de terminar todas las comprobaciones (credenciales caducadas, un archivo env inexistente, un inicio de sesión SSO rechazado). Las secciones completadas antes siguen llenas |
El documento nunca contiene ningún valor de secreto, ni local ni remoto, y ningún campo es nunca null: una sección que no aplica se omite. Una sección puede ganar campos en versiones futuras; los campos existentes mantienen su significado.
Códigos de salida
| Código | Significado |
|---|---|
0 | El archivo de mapeo es válido; sin --offline, cada secreto declarado existe; con --envfile, cada variable declarada está en el archivo env exactamente una vez; con --compare-values, cada valor comparado coincide. Las claves que solo están en el archivo env no lo cambian |
1 | Cualquier otra cosa: archivo de mapeo ausente o no válido, opciones no válidas, un secreto que falta o no se puede comprobar, credenciales ausentes o caducadas, o un archivo env que no existe, no tiene una variable declarada, repite una clave o tiene un valor que difiere o no se puede comparar |
En CI
Ejecuta la comprobación offline en cada pull request, también desde forks, porque no necesita credenciales de la nube. Ejecuta la comprobación de existencia donde el job tenga las mismas credenciales que un pull, más los permisos de esta página:
- name: Check the map file
run: npx envilder validate --offline --map=envilder.json
- name: Check that every secret exists
run: npx envilder validate --map=envilder.jsonA partir de la próxima versión, para comprobar sin credenciales que un .env.example versionado declara cada variable, añade --offline --envfile=.env.example al primer paso.
A partir de la próxima versión, para conservar el resultado para pasos posteriores u otras herramientas, usa la salida JSON. El paso sigue fallando cuando la validación falla:
- name: Check that every secret exists
run: npx envilder validate --map=envilder.json --format=json > validate.jsonvalidate sale con 1 ante cualquier error, así que puede bloquear un paso de despliegue antes de que se ejecute pull o envilder exec.
Desde los SDK
Los SDK de .NET, Python y Node.js (versión 1.1 o posterior) ejecutan la misma comprobación del archivo de mapeo y de existencia de claves desde el código de la aplicación, con los mismos estados, sin la comparación del archivo env:
| SDK | Comprobación que devuelve un resultado | Hacer fallar la carga si no pasa |
|---|---|---|
| Node.js | await Envilder.fromMapFile(path).validateContract() | .withContractValidation() |
| Python | Envilder.from_map_file(path).validate_contract() | .with_contract_validation() |
| .NET | await Env.FromMapFile(path).ValidateContractAsync(ct) | .WithContractValidation() |
La validación del contrato es distinta de la validación de secretos: comprueba el archivo de mapeo y que cada secreto existe antes de cargar, mientras que la validación de secretos comprueba que los valores ya resueltos no estén vacíos.
Qué no hace validate
- Nunca muestra valores de secretos, y solo los lee con --compare-values.
- Con --offline no comprueba que los secretos existan ni que las credenciales puedan leerlos.
- No corrige el archivo env: informa de lo que hay que cambiar.
- No comprueba la forma de los valores (tipos, URL, longitud).