Referència d'envilder validate
Com saps que un fitxer de mapatge funcionarà abans d'un pull, un desplegament o envilder exec? envilder validate comprova que el fitxer de mapatge és vàlid i que cada secret declarat existeix a AWS SSM o Azure Key Vault, i pot comparar-hi un fitxer .env local. No mostra mai cap valor de secret i surt amb 1 quan alguna cosa falla, així que encaixa com a pas de CI.
Requisits previs
- La CLI d'envilder. --offline està disponible des de la versió 0.18 i la comprovació d'existència dels secrets des de la 0.20. --envfile, --compare-values i --format json arriben amb la propera versió.
- Un fitxer de mapatge. Sense --offline, credencials del proveïdor i els permisos que es detallen a l'apartat Permisos.
Sinopsi
envilder validate [--offline] [--envfile <path> [--compare-values]] \
[--format <text|json>] [--map <path>] [--provider <name>] \
[--profile <name>] [--vault-url <url>]Per defecte, validate comprova el fitxer de mapatge i després pregunta al proveïdor si existeix cada secret declarat. Amb --envfile també compara les claus d'un fitxer env local amb el fitxer de mapatge, i amb --compare-values en compara els valors amb els remots. Amb --offline només es llegeixen fitxers locals: no es crida cap proveïdor i no calen credencials del núvol. No mostra mai cap valor de secret.
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=jsonOpcions
| Opció | Descripció |
|---|---|
--offline | Valida el fitxer de mapatge en local sense cridar el proveïdor |
--envfile | Compara les claus d'aquest fitxer env amb el fitxer de mapatge. No es llegeix si no s'indica |
--compare-values | Compara també cada valor declarat al fitxer env amb el seu valor remot. Requereix --envfile; no es pot combinar amb --offline |
--format | text (per defecte) per a una sortida llegible, o json per a un únic document JSON a stdout |
--map | Fitxer de mapatge a comprovar (per defecte: envilder.json) |
--provider | aws o azure. Substitueix $config.provider |
--profile | Perfil d'AWS CLI. Substitueix $config.profile |
--vault-url | URL d'Azure Key Vault. Substitueix $config.vaultUrl |
Les opcions tenen els mateixos noms, valors per defecte i precedència que pull i exec: les opcions guanyen a $config, i una opció buida s'ignora. Posa-les després de validate; les que s'escriuen abans es rebutgen. Com a push, un valor buit de --envfile és un error.
--compare-values sense --envfile o amb --offline, i un --format que no sigui text ni json, es rebutgen abans de llegir cap fitxer o cridar cap proveïdor.
Què es comprova
El fitxer de mapatge (sempre)
El fitxer de mapatge es comprova primer, amb els mateixos missatges que fan servir pull, push i exec. S'informa de cada problema, no només del primer, amb la clau que el causa ($config.profile, --vault-url, DB_URL...). Els missatges anomenen claus i tipus, mai valors mapats.
- El fitxer s'analitza com a JSON. Un error d'anàlisi indica la ruta i, quan l'analitzador la dona, la línia i la columna, però mai cita el text del voltant, perquè pot ser un secret enganxat al fitxer.
- El document compleix l'esquema publicat del fitxer de mapatge (map-file.v1.json): camps de $config coneguts, noms de variable vàlids i mapatges de tipus string.
- La configuració del proveïdor és coherent un cop aplicades les opcions: aws o azure, profile només amb aws, vaultUrl només amb azure, i azure té un vaultUrl.
Quan el fitxer de mapatge no és vàlid, validate s'atura aquí: no es crida cap proveïdor, amb --offline o sense.
Les claus remotes (sense --offline)
Cada ruta de secret declarada al fitxer de mapatge es comprova al proveïdor. Envilder no fa servir ni mostra mai cap valor: a AWS, els paràmetres String poden arribar a la resposta, i es descarten. Una ruta a la qual apunten diverses variables es comprova una sola vegada. Cada variable rep un estat:
| Estat | Significat |
|---|---|
exists | El secret existeix i la identitat el pot veure |
missing | El proveïdor ha respost que aquest secret no existeix |
access denied | La identitat no té permís per comprovar el secret, així que no se sap si existeix. Mai s'informa com a missing |
authentication failed | El proveïdor ha rebutjat les credencials, o no se n'ha trobat cap |
provider error | Qualsevol altra cosa, per exemple un proveïdor inaccessible o un nom de secret no vàlid |
Les credencials d'AWS i les sessions SSO caducades s'informen amb el mateix missatge que pull i exec. En un terminal interactiu, una sessió SSO caducada ofereix executar aws sso login i després torna a provar.
Les claus del fitxer env (amb --envfile)
Disponible a partir de la propera versió. El fitxer env es llegeix amb el mateix analitzador que fan servir pull i push, així que els comentaris, export, les cometes i els valors multilínia es comporten igual. Les seves claus es comparen amb les variables que declara el fitxer de mapatge, pel nom exacte, distingint majúscules i minúscules:
| Troballa | Efecte |
|---|---|
missing from .env | Una variable declarada no és al fitxer env. Falla |
duplicated in .env | Una clau s'assigna més d'una vegada. Falla |
not declared in map file | Una clau només és al fitxer env. Un avís que no canvia el codi de sortida |
KEY= amb un valor buit compta com a present, i un fitxer env inexistent falla amb Env file not found. Aquesta comprovació només llegeix fitxers locals, així que s'executa abans de cap crida al proveïdor i també amb --offline. Els valors no es comparen ni es mostren.
Els valors del fitxer env (amb --compare-values)
Per a cada variable declarada que és al fitxer env i existeix al proveïdor, el valor remot es llegeix com ho fa pull i es compara amb el local. Quan una clau es repeteix, es compara l'última assignació, tal com la carrega dotenv:
| Estat | Significat |
|---|---|
matches | Els dos valors són idèntics |
differs | Els dos valors no són idèntics. Falla |
unreadable | El secret existeix però el seu valor no s'ha pogut llegir, amb el motiu del proveïdor. Falla |
Cap dels dos valors es mostra mai, i cada valor remot es descarta just després de la comparació. Les variables que ja s'han informat com a absents no es llegeixen. Sense --compare-values no es llegeix cap valor.
Permisos
La comprovació d'existència fa servir una crida al proveïdor que pull no fa, així que la identitat necessita un permís més que per a un pull. --offline no necessita cap credencial.
AWS SSM
Les rutes es comproven amb GetParameters, deu per crida, amb WithDecryption: false: els paràmetres SecureString no es desxifren mai. És una acció d'IAM diferent de la ssm:GetParameter que fa servir pull, així que afegeix-la a la política, limitada a les mateixes rutes:
{
"Effect": "Allow",
"Action": ["ssm:GetParameter", "ssm:GetParameters"],
"Resource": "arn:aws:ssm:*:*:parameter/myapp/*"
}La comprovació d'existència no necessita el permís kms:Decrypt. --compare-values llegeix els valors com pull, així que necessita el mateix accés a KMS que pull: kms:Decrypt sobre la clau de cada paràmetre SecureString xifrat amb una clau gestionada pel client. Amb kms:Decrypt, ssm:GetParameters també pot llegir valors desxifrats, així que limita'l a les mateixes rutes que ssm:GetParameter. Quan es denega una crida, cada ruta s'hi comprova per separat, així que access denied només s'informa per a les rutes que la identitat no pot llegir.
Azure Key Vault
Els noms dels secrets del vault es llisten una vegada (només metadades) i cada nom declarat, després de la conversió habitual de / a -, es compara amb aquesta llista sense distingir majúscules. Un secret desactivat s'informa com a missing, perquè pull no el pot llegir. Llistar requereix:
- Azure RBAC: Microsoft.KeyVault/vaults/secrets/readMetadata/action sobre el vault, inclòs als rols integrats Key Vault Secrets User i Key Vault Reader.
- Polítiques d'accés: el permís de secret List, a mé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 llista cobreix tot el vault, així que una identitat sense aquest permís rep access denied per a cada clau, amb el motiu que retorna Key Vault.
--compare-values també llegeix valors, així que necessita els mateixos permisos que un pull a més d'aquests.
Sortida
Tots els secrets existeixen (codi de sortida 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 existAlguns secrets falten o no es poden comprovar (codi de sortida 1; el resum 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 deniedAmb --offline:
✓ Map file valid: envilder.json
Remote validation skipped (--offline): no provider was called, so the secrets were not checked.Amb --envfile=.env --compare-values (codi de sortida 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 differsQuan totes les variables declarades són al fitxer env, el seu bloc acaba amb ✓ All 3 declared variables are in .env, i quan tots els valors comparats coincideixen, el bloc de valors acaba amb ✓ All 2 values match.
Un fitxer de mapatge no vàlid, a 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).Sortida JSON (--format json)
Disponible a partir de la propera versió. Amb --format=json, validate escriu exactament un document JSON a stdout i res més, sigui quin sigui el resultat. Els logs, el bàner d'identitat d'AWS, els avisos, els errors i la sol·licitud d'inici de sessió SSO van a stderr, així que stdout es pot passar a jq o desar com a artefacte de CI. Els codis de sortida són els mateixos que amb la sortida de text. Els errors d'opcions com --format=yaml s'informen a stderr abans d'executar res, sense document.
{
"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"]
}
}| Camp | Descripció |
|---|---|
valid | true exactament quan el codi de sortida és 0 |
offline | true amb --offline |
mapFile | path, valid i errors (un { key, message } per problema, amb els mateixos missatges que la sortida de text). S'omet quan el fitxer de mapatge no s'ha pogut llegir |
keys | Una entrada per variable declarada, en l'ordre del fitxer de mapatge: name, provider, path, status i, quan el proveïdor en dona un, reason. status és exists, missing, access_denied, authentication_failed o provider_error. S'omet quan no s'han comprovat els secrets |
envFile | S'omet sense --envfile. Si no, path, valid, keys (cada variable declarada amb status present o missing, i value matches, differs o unreadable amb --compare-values), duplicates ({ name, count }) i undeclared |
error | { message }, només quan l'execució s'ha aturat abans d'acabar totes les comprovacions (credencials caducades, un fitxer env inexistent, un inici de sessió SSO rebutjat). Les seccions completades abans continuen plenes |
El document no conté mai cap valor de secret, ni local ni remot, i cap camp és mai null: una secció que no aplica s'omet. Una secció pot guanyar camps en versions futures; els camps existents mantenen el seu significat.
Codis de sortida
| Codi | Significat |
|---|---|
0 | El fitxer de mapatge és vàlid; sense --offline, cada secret declarat existeix; amb --envfile, cada variable declarada és al fitxer env exactament una vegada; amb --compare-values, cada valor comparat coincideix. Les claus que només són al fitxer env no el canvien |
1 | Qualsevol altra cosa: fitxer de mapatge absent o no vàlid, opcions no vàlides, un secret que falta o no es pot comprovar, credencials absents o caducades, o un fitxer env que no existeix, no té una variable declarada, repeteix una clau o té un valor que difereix o no es pot comparar |
A CI
Executa la comprovació offline a cada pull request, també des de forks, perquè no necessita credencials del núvol. Executa la comprovació d'existència on el job tingui les mateixes credencials que un pull, més els permisos d'aquesta 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 propera versió, per comprovar sense credencials que un .env.example versionat declara cada variable, afegeix --offline --envfile=.env.example al primer pas.
A partir de la propera versió, per conservar el resultat per a passos posteriors o altres eines, fes servir la sortida JSON. El pas continua fallant quan la validació falla:
- name: Check that every secret exists
run: npx envilder validate --map=envilder.json --format=json > validate.jsonvalidate surt amb 1 davant de qualsevol error, així que pot bloquejar un pas de desplegament abans que s'executi pull o envilder exec.
Des dels SDK
Els SDK de .NET, Python i Node.js (versió 1.1 o posterior) executen la mateixa comprovació del fitxer de mapatge i d'existència de claus des del codi de l'aplicació, amb els mateixos estats, sense la comparació del fitxer env:
| SDK | Comprovació que retorna un resultat | Fer fallar la càrrega si no passa |
|---|---|---|
| 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ó del contracte és diferent de la validació de secrets: comprova el fitxer de mapatge i que cada secret existeix abans de carregar, mentre que la validació de secrets comprova que els valors ja resolts no siguin buits.
Què no fa validate
- No mostra mai valors de secrets, i només els llegeix amb --compare-values.
- Amb --offline no comprova que els secrets existeixin ni que les credencials els puguin llegir.
- No corregeix el fitxer env: informa del que cal canviar.
- No comprova la forma dels valors (tipus, URL, longitud).