Gestionar secretos y claves

En esta página

Usa este inventario para decidir qué valores pertenecen al entorno de ejecución, cuáles se generan en la base de datos y cuáles son almacenados por plugins. Cada sección indica cómo la rotación afecta a un sitio en ejecución.

En Node.js, coloca los secretos de ejecución en el gestor de secretos de la plataforma de hosting para que entren en process.env cuando el proceso inicie. Para un Worker, usa wrangler secret put. No pongas valores secretos en astro.config.mjs, wrangler.jsonc o import.meta.env; Vite puede embeber valores de tiempo de build en el bundle del servidor.

Resumen

SecretoFuenteAlmacenado enImpacto por pérdida de clave
EMDASH_ENCRYPTION_KEYOperador (emdash secrets generate)Solo entorno / Worker secretSin impacto en datos actuales; EmDash solo verifica su formato
Preview secretAuto-generado (override de env)Tabla options (emdash:preview_secret)Los enlaces de preview pendientes dejan de funcionar; los nuevos están bien
IP saltAuto-generado (override de env)Tabla options (emdash:ip_salt)La continuidad del rate-limit de comentarios se reinicia
Session y API tokensGenerados por sesión/tokenSession store / base de datos (solo hashes)Nada — el texto plano nunca se almacena
Credenciales de proveedor OAuthTú (consola de Google/GitHub)EntornoEl inicio de sesión con ese proveedor se detiene hasta reemplazarlo
Secreto de TurnstileTú (dashboard de Cloudflare)EntornoLa verificación CAPTCHA de comentarios falla
Credenciales S3Tú (proveedor de almacenamiento)Entorno de ejecuciónLa carga/descarga de medios falla hasta reemplazarlas
Secretos de pluginsTú (UI de configuración del admin)Base de datos (configuración/almacenamiento del plugin)Reintroducir en el admin
Credenciales CLIemdash login / emdash plugin publish device flows~/.config/emdash/auth.json (modo 0600)Ejecutar el device flow de nuevo
Credenciales CLI del registryemdash-plugin atproto OAuth~/.emdash/oauth/, ~/.emdash/credentials.json (modo 0600)Iniciar sesión de nuevo; la identidad vive en tu PDS

La clave de cifrado

EMDASH_ENCRYPTION_KEY actualmente no cifra secretos de plugins ni ningún otro dato almacenado. Si la variable está configurada, EmDash verifica su formato durante el inicio. Un valor malformado produce un mensaje de log para el operador, pero el sitio continúa manejando solicitudes.

El siguiente comando genera un valor correctamente formateado. Almacénalo en el entorno de ejecución o como Worker secret si tu despliegue usa esta variable.

npx emdash secrets generate
# emdash_enc_v1_<43 caracteres base64url>

# Cloudflare:
wrangler secret put EMDASH_ENCRYPTION_KEY

El formato es emdash_enc_v1_ seguido de 32 bytes aleatorios como base64url sin relleno. El valor es proporcionado por el operador y no se almacena en la base de datos. Perderlo no tiene impacto en la recuperación de datos porque ningún dato almacenado depende de él.

Secretos del sitio generados

Dos secretos se generan automáticamente en el primer uso y se persisten en la tabla options, de modo que son estables entre solicitudes, despliegues y aislados. La generación es atómica — los arranques en frío concurrentes convergen en un valor.

Preview secret

Firma las URLs de preview (HMAC). Almacenado como emdash:preview_secret; 32 bytes aleatorios, base64url.

  • Override: configura EMDASH_PREVIEW_SECRET (alias legacy: PREVIEW_SECRET) si necesitas el mismo secreto entre múltiples procesos o quieres fijarlo por razones de auditoría. El entorno siempre tiene prioridad sobre el valor almacenado.
  • Rotación: elimina la fila emdash:preview_secret (o cambia la variable de entorno) y redespliega. Impacto: los enlaces de preview emitidos previamente dejan de validarse. Nada más se rompe — un secreto nuevo se genera (o se lee del entorno) en la siguiente solicitud de preview.
  • Si se pierde: nada es irrecuperable. Los enlaces de preview son de corta duración por diseño.

Consulta la guía de preview para cómo se construyen y verifican las URLs de preview.

IP salt

Agrega sal al hash SHA-256 de las direcciones IP de los comentaristas (ip_hash en comentarios) usado para el rate limiting de comentarios. Almacenado como emdash:ip_salt. Específico del sitio, por lo que los hashes no son correlacionables entre instalaciones de EmDash.

  • Override: configura EMDASH_IP_SALT. Por compatibilidad retroactiva, también se consultan EMDASH_AUTH_SECRET / AUTH_SECRET — las instalaciones que históricamente derivaron el salt de ellos mantienen hashes estables.
  • Rotación: cambia la variable de entorno o elimina la fila emdash:ip_salt. Impacto: los nuevos envíos de comentarios producen hashes diferentes, por lo que el conteo de rate-limit se reinicia para todos. Los comentarios existentes y sus hashes almacenados no se modifican.
  • Si se pierde: sin pérdida de datos. Solo se reinicia la continuidad del rate-limiting.

Session y API tokens

  • Sessions usan el session store de Astro (Workers KV en Cloudflare, sistema de archivos en Node). La cookie lleva un ID de sesión opaco; no hay secreto de firma que gestionar. Cierra sesión para terminar una sesión, o limpia el session store (ej. el namespace KV) para forzar a todos a iniciar sesión de nuevo.
  • API tokens (prefijos ec_pat_, ec_oat_, ec_ort_) son valores opacos aleatorios de 256 bits; solo su hash SHA-256 se almacena. El texto plano se muestra una vez al crearlo. Rota revocando y recreando en el admin.
  • Tokens de invitación, magic-link y recuperación son de uso único, almacenados como hashes SHA-256 en auth_tokens, y limitados en tiempo (invitaciones 7 días, magic links 15 minutos).

No hay nada que respaldar o rotar proactivamente: una filtración de base de datos expone solo hashes, y cada token puede ser revocado o reemitido desde el admin.

Credenciales de servicio proporcionadas por el usuario

Las credenciales para servicios externos se leen del entorno y nunca se escriben en la base de datos. Rótalas en el proveedor, actualiza la variable, redespliega.

ServicioVariables
Inicio de sesión GoogleEMDASH_OAUTH_GOOGLE_CLIENT_ID, EMDASH_OAUTH_GOOGLE_CLIENT_SECRET (o alias sin prefijo)
Inicio de sesión GitHubEMDASH_OAUTH_GITHUB_CLIENT_ID, EMDASH_OAUTH_GITHUB_CLIENT_SECRET (o alias sin prefijo)
Publishing de marketplace (CI)EMDASH_MARKETPLACE_TOKEN
Turnstile (comentarios)EMDASH_TURNSTILE_SECRET_KEY (o TURNSTILE_SECRET_KEY)
Almacenamiento S3S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_ENDPOINT, S3_BUCKET, S3_REGION

En Cloudflare, configúralas con wrangler secret put; para desarrollo local, ponlas en .env. Wrangler lee .dev.vars o .env, no ambos, y .dev.vars tiene prioridad cuando está presente. R2 a través de un binding no necesita variables de access-key porque el binding otorga acceso en tiempo de ejecución. Consulta almacenamiento de medios.

Secretos de plugins

Las configuraciones que un plugin declara con type: "secret" (claves API para proveedores de email, CAPTCHAs de formularios, etc.) se ingresan en la UI del admin y se almacenan en la base de datos — en la tabla options bajo plugin:<id>:settings:<key>, o en el almacenamiento clave-valor del plugin. Si un secreto almacenado se devuelve a la UI del admin depende del plugin; los plugins bien implementados devuelven solo una bandera “el valor está configurado” en lugar del secreto mismo (el plugin de formularios incluido hace esto).

  • Rotación: rota la clave en el proveedor y pega el nuevo valor en la página de configuración del plugin. Surte efecto inmediatamente.
  • Si se pierde: reintroduce el valor en el admin. Nada más depende de él.

Credenciales CLI

La CLI emdash mantiene dos tipos de credenciales, ambas en ~/.config/emdash/auth.json (respetando XDG_CONFIG_HOME), creadas con permisos solo del propietario (0600):

  • Site tokensemdash login se autentica contra tu instancia EmDash vía un flujo de dispositivo OAuth y almacena el token resultante indexado por URL de instancia. emdash logout lo elimina; por invocación, --token o EMDASH_TOKEN sobrescribe el token almacenado.
  • Marketplace tokensemdash plugin publish se autentica en el EmDash Marketplace vía un flujo de dispositivo GitHub y almacena el JWT resultante indexado por marketplace:<origin>. Para publishing CI, configura EMDASH_MARKETPLACE_TOKEN en su lugar — tiene prioridad sobre la credencial almacenada.

Perder el archivo es inofensivo: ejecuta emdash login (o emdash plugin publish, que re-ejecuta el flujo de dispositivo) de nuevo.

Credenciales CLI del plugin registry

La CLI separada emdash-plugin (paquete @emdash-cms/plugin-cli) apunta al registro experimental de AT Protocol. Publicar ahí está vinculado a tu identidad de AT Protocol (tu DID de publisher) — el sitio mismo no mantiene credenciales de publicación, y las instalaciones verifican artefactos contra checksums de registros de release atribuidos a ese DID.

  • Se autentica vía atproto OAuth. Los blobs de sesión/estado OAuth viven en ~/.emdash/oauth/, y la identidad del publisher (DID, handle, PDS) se almacena en caché en ~/.emdash/credentials.json; ambos se escriben con permisos solo del propietario.
  • En CI, proporciona la identidad vía EMDASH_PUBLISHER_DID, EMDASH_PUBLISHER_HANDLE y EMDASH_PUBLISHER_PDS; EMDASH_REGISTRY_URL sobrescribe el host del registro. El publish automatizado desde CI aún necesita los archivos de sesión OAuth en ~/.emdash/oauth/ en el runner — las variables de entorno solas no portan la sesión OAuth.
  • Rotar o revocar el acceso de publicación sucede en tu cuenta de AT Protocol (ej. contraseñas de app), no en EmDash. Consulta Autenticación de Atmosphere.

Referencia rápida de rotación

Quiero…Hacer esto
Invalidar todos los enlaces de previewEliminar la fila de opción emdash:preview_secret (o cambiar el override de env)
Reiniciar el hashing de rate-limit de comentariosCambiar EMDASH_IP_SALT (o eliminar la fila de opción emdash:ip_salt)
Revocar un API token filtradoAdmin → Usuarios → API tokens → revocar, luego crear un reemplazo
Terminar todas las sesionesLimpiar el session store (namespace Workers KV / directorio de sesiones)
Reemplazar una credencial de proveedorRotar en el proveedor, actualizar la variable de env, redesplegar
Reemplazar una clave API de pluginRotar en el proveedor, reintroducir en la configuración admin del plugin