¿Qué vamos a hacer?
Hoy, para firmar ante el SAT, le envías a SatGo tu certificado .cer y tu llave privada .key. La llave privada es lo más sensible que tienes: quien la posee puede firmar en tu nombre.
Con esta guía vas a guardar esa llave en un Azure Key Vault tuyo. A partir de ese momento SatGo no recibe la llave: cuando necesita firmar algo, le pide a tu vault que firme y solo recibe de vuelta la firma. La llave nunca sale de tu suscripción, cada uso queda en tu bitácora de Azure, y puedes revocar el acceso cuando quieras sin pedirnos permiso.
¿No quieres montar un Key Vault? Existe una alternativa más ligera: puedes cifrar tu llave privada y contraseña en tu propio equipo (estándar JWE RSA-OAEP-256 + A256GCM) antes de enviarlas. Así viajan siempre cifradas y SatGo solo las descifra en memoria, sin que tengas que configurar nada en Azure. Ver la guía para cifrar tu e.firma (navegador o línea de comandos), la documentación de la API y Seguridad.
Antes
- Envías
.cer+.keyen cada petición - SatGo firma con tu llave en memoria
- La llave viaja por internet cada vez
Después
- Envías solo el
.cer - Tu vault firma; SatGo solo recibe la firma
- La llave nunca sale de tu suscripción
Antes de empezar necesitas:
- Una cuenta en SatGo con tu RFC ya registrado.
- Tu token JWT de SatGo (lo obtienes con
POST /api/auth/token; ver Autenticación en la documentación). - Los archivos
.cery.keyde tu FIEL, y su contraseña. - Una tarjeta de crédito o débito (Azure la pide para verificar identidad, aunque el costo del vault sea de centavos).
¿No quieres administrar Azure?
.cer y el .key una sola vez a POST /api/v1/secretprovider/signing-key/store y nosotros los guardamos en nuestro vault. No necesitas cuenta de Azure ni esta guía. Es más cómodo, pero la llave queda bajo nuestra custodia en vez de la tuya.Crear tu cuenta y suscripción de Azure
Una suscripción de Azure es simplemente tu cuenta de facturación: el contenedor donde vivirán los recursos que crees. Si tu empresa ya tiene una, pídele acceso a tu área de sistemas y salta al paso 2.
- Entra a azure.microsoft.com/free y haz clic en Comenzar gratis.
- Inicia sesión con una cuenta Microsoft. Si vas a usarlo para la empresa, crea una cuenta con el correo corporativo en lugar de usar una personal.
- Llena tus datos y verifica con teléfono y tarjeta. Azure hace un cargo temporal de verificación (se reembolsa); no se te cobra nada por usar la cuenta gratuita.
- Al terminar llegarás al portal en portal.azure.com. Ya tienes suscripción.
Sobre el idioma del portal
¿Cuánto cuesta esto?
Crear el Key Vault
El Key Vault es la caja fuerte donde guardarás tu llave. Azure la administra por ti; tú solo decides quién entra.
- En el portal, escribe Key vaults en la barra de búsqueda superior y entra a la sección que aparece bajo Services (servicios).
Microsoft.KeyVault/vaults), el resaltado en rojo. El otro, Managed HSMs, es un servicio distinto y mucho más caro que no necesitas. La ilustración es aproximada: el portal cambia de aspecto con el tiempo.- Ya dentro de Key vaults, haz clic en + Create.
- Llena la pestaña Basics (datos básicos) con estos valores:
| Campo | Qué poner |
|---|---|
| Subscription | La que acabas de crearSuscripción. |
| Resource group | rg-satgoGrupo de recursos. Haz clic en 'Create new'; es solo una carpeta para agrupar recursos. |
| Key vault name | kv-miempresa-fielDebe ser único en todo Azure. Solo letras, números y guiones. Anótalo: lo usarás en el paso 8. |
| Region | Mexico CentralCualquiera funciona; elige la más cercana. |
| Pricing tier | StandardPlan de tarifa. |
| Days to retain deleted vaults | 90 (default)Protección contra borrado accidental. Déjalo como viene. Soft-delete aparece como 'Enabled' y no se puede desactivar. |
- Ve a la pestaña Access configuration y en Permission model elige Azure role-based access control (RBAC). Este paso importa: el paso 6 asume RBAC.
- Haz clic en Review + create y luego en Create. Espera a que termine el despliegue (menos de un minuto).
- Abre el vault recién creado y copia su Vault URI desde la pantalla de Overview (la verás completa en el paso 3). Se ve así:
URI del vault — lo necesitarás en el paso 8
https://kv-miempresa-fiel.vault.azure.net/
Obtener tu Tenant ID (y el Vault URI)
Tu tenant (o directorio) es la organización dueña de la cuenta. Su ID es un identificador largo que le dice a SatGo a qué directorio pedirle permiso.
No hace falta ir a buscarlo a otra pantalla: los dos datos que necesitas están en el Overview de tu propio Key Vault, en el panel Essentials.
- Abre tu Key Vault y quédate en Overview (es la pantalla que abre por omisión).
- En la columna derecha del panel Essentials copia Vault URI (el del paso 2) y Directory ID.
keyOptions en el paso 8. Directory Name te confirma que es el directorio correcto.Tenant ID (Directory ID) — guárdalo, lo usarás en los pasos 5 y 8
3f2a91c4-7b8d-4e15-9a06-2c5d8e7f1b3a
¿Prefieres otro camino?
az login y luego az account show --query tenantId -o tsv.Pedirle a SatGo su identidad
Para que tu vault pueda darle permiso a SatGo, primero necesitas saber quién es SatGo dentro de Azure. Ese dato lo entrega el endpoint GET /api/v1/secretprovider/identity, que además te devuelve la guía completa en formato JSON.
Petición
curl -X GET "https://api.sat-go.com/api/v1/secretprovider/identity" \ -H "Authorization: Bearer <TU_TOKEN_JWT>"
Respuesta (recortada a lo que nos importa ahora)
{
"crossTenant": {
"consent": {
"appClientId": "8c1d5e90-4f3b-42a7-b6e8-0d9c7a1f2e34",
"adminConsentUrl": "https://login.microsoftonline.com/YOUR_TENANT_ID/adminconsent?client_id=8c1d5e90-4f3b-42a7-b6e8-0d9c7a1f2e34",
"steps": [ "..." ]
},
"signingKey_fiel": {
"endpoint": "POST /api/v1/secretprovider/signing-key/register",
"requiredKvRole": "Key Vault Crypto User",
"example": {
"rfc": "XAXX010101ABC",
"providerType": "AzureKeyVault",
"providerUri": "https://mi-vault.vault.azure.net/",
"keyName": "fiel-xaxx010101abc",
"keyOptions": { "tenantId": "<tu-tenant-id>" }
}
}
},
"satGoManaged": { "...": "la alternativa sin Azure" }
}Guarda dos datos de aquí:
appClientId (la identidad de SatGo en Azure) y el adminConsentUrl, que usarás tal cual en el siguiente paso.Autorizar a SatGo en tu directorio
Este paso crea una Aplicación empresarial de SatGo dentro de tu tenant. Piénsalo como darle de alta un gafete de visitante: existe en tu edificio, pero todavía no abre ninguna puerta. Los permisos reales se los das en el paso 6.
- Toma el
adminConsentUrldel paso 4 y reemplazaYOUR_TENANT_IDpor tu Tenant ID del paso 3:
URL final (con tu tenant ya sustituido)
https://login.microsoftonline.com/3f2a91c4-7b8d-4e15-9a06-2c5d8e7f1b3a/adminconsent?client_id=8c1d5e90-4f3b-42a7-b6e8-0d9c7a1f2e34
- Ábrela en el navegador e inicia sesión con una cuenta administrador global de tu tenant.
- Lee la pantalla de consentimiento y acepta. Azure te redirigirá a una página que puede mostrar un error de navegación: es normal e inofensivo, el consentimiento ya quedó registrado.
- Verifícalo en Microsoft Entra ID → Enterprise applications: debe aparecer una app cuyo Application ID coincide con el
appClientId.
Si el botón de aceptar aparece deshabilitado
Darle a SatGo permiso de firma sobre tu vault
Ahora sí, la parte que define qué puede hacer SatGo. Le asignarás el rol Key Vault Crypto User, que permite usar la llave para firmar pero no exportarla ni leerla. Es exactamente el permiso mínimo que necesita.
- Abre tu Key Vault en el portal.
- En el menú izquierdo entra a Access control (IAM) y haz clic en + Add → Add role assignment.
- En la pestaña Role, busca y selecciona Key Vault Crypto User. Next.
- En Members, deja User, group, or service principal y haz clic en + Select members. Busca
satgo-kv-byos-reader: es el nombre de la aplicación de SatGo que creó el consentimiento del paso 5. También puedes buscarla pegando elappClientIddel paso 4. - Review + assign. El permiso puede tardar hasta 5 minutos en propagarse.
satgo-kv-byos-reader y tipo App. Si no la encuentras, es que falta el consentimiento del paso 5 — sin él la aplicación no existe todavía en tu tenant.El Object ID de la tabla no es el appClientId
appClientId que te dio /identity. Es normal y no significa que te hayas equivocado de aplicación: son dos identificadores diferentes del mismo objeto (el Application ID identifica la app; el Object ID identifica su representación dentro de tu tenant). Lo que debe coincidir es el nombre.Alternativa por línea de comandos (Azure CLI)
az role assignment create \ --role "Key Vault Crypto User" \ --assignee 8c1d5e90-4f3b-42a7-b6e8-0d9c7a1f2e34 \ --scope "/subscriptions/<TU_SUBSCRIPTION_ID>/resourceGroups/rg-satgo/providers/Microsoft.KeyVault/vaults/kv-miempresa-fiel"
¿Y si también quiero guardar la CIEC aquí?
POST /api/v1/secretprovider/secret/register. Los roles son independientes: uno permite firmar, el otro leer secretos.Subir tu FIEL al vault
El SAT te entrega la FIEL en dos archivos separados (.cer y .key), pero Azure los quiere juntos en un solo archivo PKCS#12 (.pfx). Vamos a convertirlos con OpenSSL y luego importarlos.
7.1 — Convertir los archivos del SAT a .pfx
Tienes dos caminos. El primero es una herramienta que hicimos justo para esto; el segundo es OpenSSL, por si prefieres no descargar nada.
Opción A — Convertidor de SatGo (recomendado)
Descarga convertidorpkcs12.zip (81 KB) y descomprímelo. Hace la conversión en un solo comando, sin archivos intermedios con tu llave expuesta. Requiere tener instalado el runtime de .NET 10.
Uso
SatScraper.Pkcs12Tool <certificado.cer> <llave.key> <password> [directorioSalida] [nombre.pfx]
| Campo | Qué poner |
|---|---|
| certificado.cer | fiel.cerTu certificado del SAT, tal cual (DER o PEM). Obligatorio. |
| llave.key | fiel.keyTu llave privada del SAT, tal cual (PKCS8 DER). Obligatorio. |
| password | la contraseña de tu FIELObligatorio. Sirve para dos cosas: descifra tu .key y protege el .pfx que se genera. Es decir, el .pfx queda con esta misma contraseña. |
| directorioSalida | ./salidaOpcional. Si no lo pones, usa la carpeta actual. La crea si no existe. |
| nombre.pfx | XAXX010101ABC.pfxOpcional. Si no lo pones, usa el nombre del .cer con extensión .pfx. |
Ejemplo
SatScraper.Pkcs12Tool fiel.cer fiel.key "MiContraseñaFIEL" ./salida XAXX010101ABC.pfx # → PKCS12 generado exitosamente en: ./salida\XAXX010101ABC.pfx
La contraseña del .pfx es la misma de tu FIEL
Opción B — OpenSSL
Los archivos del SAT vienen en formato DER, por eso los pasos intermedios. Necesitas OpenSSL instalado (en Windows viene incluido con Git Bash).
Convertir .cer + .key → .pfx
# 1. El .key del SAT (DER cifrado) → PEM. Te pedirá la contraseña de tu FIEL. openssl pkcs8 -inform DER -in fiel.key -out fiel_privada.pem # 2. El .cer del SAT (DER) → PEM openssl x509 -inform DER -in fiel.cer -out fiel_cert.pem # 3. Unir ambos en un PKCS#12. Define aquí una contraseña para el .pfx. openssl pkcs12 -export \ -inkey fiel_privada.pem \ -in fiel_cert.pem \ -out fiel.pfx
Cuida los archivos intermedios
fiel_privada.pem contiene tu llave privada sin cifrar. Bórralo en cuanto generes el .pfx y no lo subas nunca a un repositorio. La Opción A no crea este archivo.7.2 — Importar el .pfx como llave en el Key Vault
Fíjate bien en esto: la FIEL se importa en la sección Keys, no en Certificates. SatGo firma usando una llave (/keys/<nombre>) y el rol que le diste en el paso 6, Key Vault Crypto User, es justamente de llaves.
- En el menú izquierdo de tu vault abre Objects → Keys y haz clic en + Generate/Import.
- En Options elige Import.
- En File Upload selecciona el
.pfxque generaste en el paso 7.1. - Al seleccionarlo aparece un campo Password. Escribe ahí la contraseña de tu FIEL: es la misma que le pasaste al convertidor en el paso 7.1, porque el
.pfxquedó protegido con ella. - En Name escribe el nombre de la llave. Este es el valor exacto que irá en
keyNameen el paso 8, así que anótalo. - Deja Key type en RSA y Enabled en Yes. Los demás campos (fechas de activación y expiración, opciones confidenciales) déjalos como vienen.
- Create.
keyName del paso 8.Sobre el nombre de la llave
fiel-xaxx010101abc funciona bien y te dice a simple vista de qué RFC es.Registrar la llave en SatGo
Este es el paso final de configuración: le dices a SatGo dónde está tu llave. Fíjate que no envías la llave, solo la dirección donde vive.
POST /api/v1/secretprovider/signing-key/register
curl -X POST "https://api.sat-go.com/api/v1/secretprovider/signing-key/register" \
-H "Authorization: Bearer <TU_TOKEN_JWT>" \
-H "Content-Type: application/json" \
-d '{
"rfc": "XAXX010101ABC",
"providerType": "AzureKeyVault",
"providerUri": "https://kv-miempresa-fiel.vault.azure.net/",
"keyName": "fiel-xaxx010101abc",
"keyOptions": "{\"tenantId\": \"3f2a91c4-7b8d-4e15-9a06-2c5d8e7f1b3a\"}"
}'| Campo | Qué poner |
|---|---|
| rfc | XAXX010101ABCDebe estar ya registrado en tu cuenta de SatGo. |
| providerType | AzureKeyVaultLiteral, así se escribe. |
| providerUri | https://<tu-vault>.vault.azure.net/El URI que copiaste en el paso 2. |
| keyName | fiel-xaxx010101abcEl nombre que le diste a la llave en el paso 7.2 (campo Name). |
| keyOptions | "{\"tenantId\": \"...\"}"Ojo: es un string con JSON adentro, no un objeto. Lleva tu Tenant ID del paso 3 y es obligatorio. |
Respuesta 200 OK
{
"rfc": "XAXX010101ABC",
"providerType": "AzureKeyVault",
"providerUri": "https://kv-miempresa-fiel.vault.azure.net/",
"keyName": "fiel-xaxx010101abc",
"message": "Proveedor de firma registrado. Envía solo el .cer en las peticiones para usar firma remota."
}El registro se valida en el momento
Probar que todo funciona
Primero confirma el estado del registro:
GET /api/v1/secretprovider/signing-key/{rfc}/status
curl -X GET "https://api.sat-go.com/api/v1/secretprovider/signing-key/XAXX010101ABC/status" \ -H "Authorization: Bearer <TU_TOKEN_JWT>"
{
"rfc": "XAXX010101ABC",
"isRegistered": true,
"providerType": "AzureKeyVault",
"providerUri": "https://kv-miempresa-fiel.vault.azure.net/",
"keyName": "fiel-xaxx010101abc",
"updatedAt": "2026-07-16T10:32:00Z"
}Y ahora la prueba de fuego: descarga tu Constancia de Situación Fiscal mandando solo el .cer. Sin llavePrivada, sin Contrasena.
POST /api/v2/consultar/csffiel — firma remota en acción
curl -X POST "https://api.sat-go.com/api/v2/consultar/csffiel" \ -H "Authorization: Bearer <TU_TOKEN_JWT>" \ -F "Rfc=XAXX010101ABC" \ -F "Certificado=@fiel.cer" \ --output constancia.pdf
¡Listo!
Si algo falla
400 · No se pudo validar la llave de firma: Acceso denegado…
El rol no está asignado o todavía no se propaga. Revisa que la asignación del paso 6 sea Key Vault Crypto User (no Reader, no Secrets User) y que apunte a la app de SatGo. Espera 5 minutos y reintenta.
400 · La llave 'x' no fue encontrada en el vault…
El keyName no coincide. Corre az keyvault key list --vault-name <tu-vault> --query "[].name" y usa el nombre exacto que aparezca.
400 · El campo 'tenantId' es requerido en SigningKeyOptions…
Falta keyOptions o va mal formado. Recuerda que es un string que contiene JSON: "{\"tenantId\": \"...\"}", no un objeto JSON directo.
400 · Para AzureKeyVault el URI debe tener el formato…
El providerUri debe ser exactamente https://<nombre>.vault.azure.net/ — sin rutas adicionales ni el nombre del certificado al final.
404 · El RFC no está registrado para este usuario
Da de alta el RFC en tu cuenta desde web.sat-go.com antes de registrar la llave.
La pantalla de consentimiento no me deja aceptar
Necesitas rol de administrador global en el tenant. Pásale la URL del paso 5 a quien administre Azure en tu organización.
¿Sigues atorado? Escríbenos a soporte@sat-go.com con el mensaje de error completo y el RFC. También puedes revisar la referencia técnica del endpoint o cómo protegemos tus credenciales.