AT
AgileTrust
Home Manual EN Manual ES API Reference Swagger Examples Live Best Practices
  • Introducción
  • Descripción general
  • Cómo funciona
  • Modos de codificación
  • Primeros pasos
  • Inicio rápido
  • Autenticación
  • Endpoints
  • GET /health
  • POST /tokenize
  • POST /detokenize
  • Ejemplos
  • RUT y numeración
  • Nombres y texto
  • Correo electrónico
  • Uso del tweak
  • Ejemplo Python
  • Despliegue
  • Modo Single-Tenant
  • Multi-Tenant y Consola
  • Proveedores de clave
  • Consola de Administración
  • Variables de entorno
  • SSO / Proveedores de identidad
  • Roles y permisos
  • Gestionar aplicaciones
  • Gestionar API keys
  • Gestionar usuarios
  • Registro de auditoría
  • Referencia
  • Límites y restricciones
  • Respuestas de error
  • Preguntas frecuentes
Introducción

Descripción general

AgileTrust Tokenization reemplaza datos sensibles con tokens que preservan el formato: valores que lucen idénticos al original (misma longitud, misma estructura, mismo conjunto de caracteres) pero son sustituciones criptográficamente seguras.

A diferencia del enmascaramiento tradicional o el hashing, la tokenización es completamente reversible. Con la misma clave, el valor original puede recuperarse en cualquier momento sin necesidad de almacenar una tabla de correspondencias.

ℹ

AgileTrust Tokenization está construido sobre FF3-1 (NIST SP 800-38G Revisión 1) con AES-128, AES-192 o AES-256 — el mismo estándar utilizado por los principales procesadores de pago y bóvedas de datos de salud.

Propiedades clave

  • Preserva el formato: un número de tarjeta de 16 dígitos tokeniza en otro de 16 dígitos; un RUT chileno como 13301430-6 tokeniza en 35240589-5.
  • Determinista: la misma entrada + misma clave + misma codificación + mismo tweak siempre produce el mismo token.
  • Reversible: /detokenize recupera el valor original con 100% de fidelidad.
  • Preserva símbolos: espacios, guiones, @, ., () y todos los caracteres no alfanuméricos permanecen en sus posiciones exactas.
  • Transparente al esquema: no requiere cambios en la base de datos, ni actualizar reglas de validación, ni reescribir expresiones regulares.

Cómo funciona

Cada solicitud de tokenización pasa por tres etapas:

  1. Normalizar — La entrada se normaliza a NFC (Forma de Normalización C de Unicode) para garantizar una representación de bytes consistente entre plataformas y locales.
  2. Dividir — La cadena se separa en dos listas: caracteres tokenizables (letras y dígitos del alfabeto de la codificación elegida) y caracteres de paso (todo lo demás: espacios, guiones, puntuación, símbolos). Las posiciones de paso se registran.
  3. Cifrar — Los caracteres tokenizables se cifran con FF3-1/AES. Para entradas más cortas que el mínimo de FF3 (6 para numérico, 3 para texto), se usa una sustitución con SHA-256 basada en la clave. Para entradas muy largas, los caracteres tokenizables se procesan en segmentos. Los caracteres de paso se reinsertan en sus posiciones originales.

La destokenización ejecuta exactamente el mismo proceso en sentido inverso — el cifrado opera de forma idéntica en ambas direcciones.

Modos de codificación

El parámetro encoding controla qué caracteres se consideran "tokenizables" y establece el alfabeto de cifrado.

Modo Alfabeto Longitud máxima Ideal para
numeric 0123456789 (base 10) 16 caracteres RUTs, teléfonos, tarjetas de crédito, IDs numéricos
latin1 ~127 letras y dígitos Latin-1 (U+0021–U+00FF) 256 caracteres Nombres en Europa occidental, direcciones
utf8 (por defecto) ~256 letras y dígitos Unicode (BMP) 256 caracteres Cualquier nombre Unicode, texto libre, email, datos multilingüe
⚠

Se debe usar la misma codificación en /tokenize y en /detokenize. Usar una codificación diferente al destokenizar devolverá texto plano incorrecto sin ningún error — esta es una propiedad de seguridad de los algoritmos FPE.

Cómo elegir el modo correcto

  • Use numeric para cualquier valor compuesto principalmente de dígitos, incluso si contiene separadores como guiones o paréntesis (estos se preservan, no se cifran).
  • Use utf8 (por defecto) para nombres, texto libre, correos electrónicos y cualquier cadena con caracteres no latinos.
  • Use latin1 para nombres en Europa occidental cuando necesite tokens que permanezcan dentro de la página de códigos Latin-1 (sistemas legados que no soportan caracteres por encima de U+00FF).
Primeros pasos

Inicio rápido

1. Ejecutar el contenedor

bash
export TOKENIZATION_KEY="$(python3 -c 'import os,base64; print(base64.b64encode(os.urandom(32)).decode())')"
export API_KEY="$(openssl rand -hex 24)"

docker run -d \
  --name tokenizer \
  -p 8000:8000 \
  -e TOKENIZATION_KEY="$TOKENIZATION_KEY" \
  -e API_KEY="$API_KEY" \
  agiletrust/tokenization:0.3

El contenedor inicia un servidor FastAPI en el puerto 8000. TOKENIZATION_KEY debe ser una clave AES en base64 — 16, 24 o 32 bytes (AES-128/192/256). API_KEY es el secreto compartido requerido en el header X-API-Key.

2. Tokenizar un valor

bash — cURL
curl -s -X POST http://localhost:8000/tokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"plaintext": "13301430-6", "encoding": "numeric"}' | jq .
json — respuesta
{
  "token": "35240589-5",
  "algorithm": "FF3-1/AES",
  "encoding": "numeric"
}

3. Destokenizar para recuperar el original

bash — cURL
curl -s -X POST http://localhost:8000/detokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"token": "35240589-5", "encoding": "numeric"}' | jq .
json — respuesta
{
  "plaintext": "13301430-6"
}
✓

El guion de 13301430-6 se preserva en la posición 8, tanto en el texto original como en el token. Solo los dígitos son cifrados.

Autenticación

Todas las solicitudes a /tokenize y /detokenize requieren el encabezado X-API-Key con la clave API compartida. El endpoint /health es abierto (requerido para sondas de liveness).

bash — solicitud autenticada
curl -s -X POST http://localhost:8000/tokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"plaintext": "13301430-6", "encoding": "numeric"}' | jq .
CondiciónEstado HTTPCuerpo de respuesta
Encabezado ausente401 Unauthorized{"error": "Missing API key."}
Encabezado presente pero valor incorrecto403 Forbidden{"error": "Invalid API key."}
Clave correcta200 OKToken / texto en claro

En modo single-tenant, la clave API se configura mediante la variable de entorno API_KEY y es compartida por todos los llamantes. La clave AES se configura mediante TOKENIZATION_KEY. Ninguna de las dos aparece en registros ni en respuestas — los clientes nunca envían material de clave en los cuerpos de solicitud.

En modo multi-tenant (MULTI_TENANT=true), las API keys se generan por aplicación desde la consola de administración. Cada clave se almacena como hash SHA-256 y resuelve su propia clave AES desde la base de datos en cada solicitud. Consulte la sección Multi-Tenant y Consola para los detalles de configuración.

⚠

Restrinja el acceso de red al contenedor de tokenización. Nunca debe estar expuesto a internet. Despliegue dentro de una VPC privada o detrás de un API gateway con mTLS.

Endpoints

GET /health

Devuelve el estado del servicio y la versión actual. Utilice este endpoint para sondas de liveness y monitoreo de disponibilidad.

Respuesta — 200 OK

json
{
  "status": "ok",
  "version": "0.3"
}

POST /tokenize

Convierte una cadena de texto en claro en un token que preserva el formato.

Cuerpo de la solicitud

CampoTipoDescripción
plaintext requerido string El valor a tokenizar. Puede ser vacío (devuelve token vacío).
encoding opcional string enum utf8 (por defecto), latin1 o numeric.
tweak opcional string 14 caracteres hex (7 bytes). Contexto a nivel de campo. Por defecto: 00000000000000.

Respuesta — 200 OK

CampoTipoDescripción
tokenstringToken que preserva el formato. Misma longitud que la entrada normalizada NFC.
algorithmstringSiempre "FF3-1/AES".
encodingstringEl modo de codificación usado (devuelto en la respuesta).

Respuesta — 422 Unprocessable Entity

Se devuelve cuando hay errores de validación. El campo error describe el problema:

CausaMensaje de error
Falta plaintextplaintext: Field required
Codificación desconocidaencoding: Value error, 'encoding' must be one of ['latin1', 'utf8', 'numeric']; got 'ascii'.
Entrada numérica > 16 caracteresplaintext: Value error, 'plaintext' exceeds maximum length of 16 characters.
Texto > 256 caracteresplaintext: Value error, 'plaintext' exceeds maximum length of 256 characters.
Formato de tweak inválidotweak: Value error, 'tweak' must be exactly 14 hex characters (7 bytes).

POST /detokenize

Invierte un token producido por /tokenize, recuperando el texto original.

⚠

Una clave o codificación incorrecta devuelve HTTP 200 con texto incorrecto. No hay indicador de error. Esta es una propiedad de seguridad fundamental de los algoritmos FPE — un atacante no puede saber si la destokenización tuvo éxito o falló.

Cuerpo de la solicitud

CampoTipoDescripción
token requerido string Token devuelto por /tokenize.
encoding opcional string enum Debe coincidir con la codificación usada en la tokenización. Por defecto: utf8.
tweak opcional string Debe coincidir con el tweak usado en la tokenización. Por defecto: 00000000000000.

Respuesta — 200 OK

CampoTipoDescripción
plaintextstringEl valor original recuperado del token.
Ejemplos

RUT y valores numéricos

Use "encoding": "numeric" para cualquier identificador con dígitos. Los separadores se preservan automáticamente.

bash
curl -s -X POST http://localhost:8000/tokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"plaintext": "13301430-6", "encoding": "numeric"}' | jq .
json — respuesta
{
  "token": "35240589-5",
  "algorithm": "FF3-1/AES",
  "encoding": "numeric"
}

El guion en la posición 8 se preserva. Solo los 9 dígitos son cifrados. El token sigue siendo un RUT válido en formato.

bash
curl -s -X POST http://localhost:8000/detokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"token": "35240589-5", "encoding": "numeric"}' | jq .
json — respuesta
{
  "plaintext": "13301430-6"
}

Recuperación perfecta del RUT original.

bash
# Teléfono chileno
curl -s -X POST http://localhost:8000/tokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"plaintext": "+56 9 8765 4321", "encoding": "numeric"}' | jq .
json
{
  "token": "+56 9 2341 8907",
  "algorithm": "FF3-1/AES",
  "encoding": "numeric"
}

El prefijo +56, los espacios y la estructura del número se preservan. Solo los dígitos variables se cifran.

Nombres y texto libre

bash
curl -s -X POST http://localhost:8000/tokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"plaintext": "Juan Pérez-García"}' | jq .
json
{
  "token": "Ñkrp Çmevq-Ĥapcw",
  "algorithm": "FF3-1/AES",
  "encoding": "utf8"
}

El espacio y el guion permanecen en sus posiciones. Todas las letras son cifradas con el alfabeto Unicode.

bash
curl -s -X POST http://localhost:8000/tokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"plaintext": "Juan Pérez-García", "encoding": "latin1"}' | jq .
json
{
  "token": "YrfãröxÍ-Ý",
  "algorithm": "FF3-1/AES",
  "encoding": "latin1"
}

El token permanece dentro del rango Latin-1 (U+0000–U+00FF). Ideal para sistemas legados.

Correo electrónico

El símbolo @ y el punto . siempre se preservan, haciendo que los correos tokenizados sean sintácticamente válidos en la mayoría de los validadores.

bash
curl -s -X POST http://localhost:8000/tokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"plaintext": "juan.perez@empresa.cl"}' | jq .
json
{
  "token": "ĭğĬħ.ŋĕĮĕž@ĩźĝŋĪĮĩ.ĕĝ",
  "algorithm": "FF3-1/AES",
  "encoding": "utf8"
}

Uso del Tweak

Un tweak es una cadena hexadecimal de 14 caracteres (7 bytes) que aporta contexto a nivel de campo. El mismo texto en claro tokenizado con tweaks diferentes produce tokens completamente distintos, impidiendo que un atacante correlacione tokens entre campos.

bash — mismo nombre, tweaks diferentes
# Tokenizar como campo "nombre"
curl -s -X POST http://localhost:8000/tokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"plaintext": "Maria Lopez", "tweak": "6e6f6d62726500"}' | jq .token

# Tokenizar como campo "alias"
curl -s -X POST http://localhost:8000/tokenize \
  -H "Content-Type: application/json" \
  -H "X-API-Key: su-clave-api-aqui" \
  -d '{"plaintext": "Maria Lopez", "tweak": "616c6961730000"}' | jq .token

Valores de tweak comunes

CampoTweak (hex)Origen
nombre / name6e616d65000000ASCII "name" + relleno cero
rut72757400000000ASCII "rut" + relleno cero
email656d61696c0000ASCII "email" + relleno cero
telefono / phone70686f6e650000ASCII "phone" + relleno cero
dirección / addr61646472000000ASCII "addr" + relleno cero

Ejemplo completo en Python

python
import requests

BASE_URL = "http://localhost:8000"

ENCABEZADOS = {"X-API-Key": "su-clave-api-aqui"}

def tokenizar(texto, codificacion="utf8", tweak=None):
    """Convierte un texto en un token que preserva el formato."""
    payload = {"plaintext": texto, "encoding": codificacion}
    if tweak:
        payload["tweak"] = tweak
    respuesta = requests.post(f"{BASE_URL}/tokenize", json=payload, headers=ENCABEZADOS)
    respuesta.raise_for_status()
    return respuesta.json()["token"]

def destokenizar(token, codificacion="utf8", tweak=None):
    """Recupera el texto original a partir de un token."""
    payload = {"token": token, "encoding": codificacion}
    if tweak:
        payload["tweak"] = tweak
    respuesta = requests.post(f"{BASE_URL}/detokenize", json=payload, headers=ENCABEZADOS)
    respuesta.raise_for_status()
    return respuesta.json()["plaintext"]

# ── Ejemplos de uso ───────────────────────────────────────

# RUT chileno
token_rut = tokenizar("13301430-6", codificacion="numeric")
print(f"RUT token: {token_rut}")           # 35240589-5
print(f"RUT original: {destokenizar(token_rut, 'numeric')}")  # 13301430-6

# Nombre completo
token_nombre = tokenizar("María González López")
print(f"Nombre token: {token_nombre}")
print(f"Nombre original: {destokenizar(token_nombre)}")

# Email
token_email = tokenizar("maria@empresa.cl")
print(f"Email token: {token_email}")

# Con tweak por campo
tweak_rut   = "72757400000000"
tweak_email = "656d61696c0000"

t1 = tokenizar("maria@empresa.cl", tweak=tweak_email)
t2 = tokenizar("maria@empresa.cl", tweak=tweak_rut)
print(f"Con tweak email: {t1}")
print(f"Con tweak rut:   {t2}")
print(f"Son distintos: {t1 != t2}")   # True
Referencia

Límites y restricciones

CodificaciónLongitud máxima totalNota
numeric16 caracteresIncluye separadores (guiones, paréntesis, etc.)
latin1256 caracteresLongitud normalizada NFC
utf8256 caracteresLongitud normalizada NFC
  • Las cadenas vacías son aceptadas y devuelven un token vacío.
  • La entrada se normaliza a NFC antes de verificar la longitud. Pre-normalice si los límites exactos son críticos.
  • El tweak debe tener exactamente 14 caracteres hexadecimales (sin distinción entre mayúsculas y minúsculas). Por defecto: 00000000000000.

Respuestas de error

Todos los errores devuelven JSON con un único campo error:

json
{ "error": "plaintext: Value error, 'plaintext' exceeds maximum length of 16 characters." }
Estado HTTPSignificado
200Éxito. También se devuelve con clave/codificación incorrecta en destokenización (fallo silencioso por diseño).
422Error de validación — campo requerido faltante, codificación desconocida, entrada muy larga o formato de tweak inválido.
500Error interno del servidor. Consulte los registros del servidor.

Preguntas frecuentes

¿Dos textos distintos pueden producir el mismo token?

No. FF3-1 es una permutación pseudoaleatoria (PRP), por lo que la tokenización es una biyección: cada texto en claro corresponde a un token único y viceversa, para una misma clave + tweak + codificación.

¿La longitud del token siempre iguala la del texto original?

Sí. La longitud del token iguala la longitud de la entrada normalizada NFC. Si la entrada ya está en NFC, las longitudes son idénticas.

¿Qué ocurre si tokenizo el mismo valor dos veces?

Obtendrá el mismo token. La tokenización es determinista. Si necesita tokens distintos para el mismo valor en contextos diferentes, use tweaks distintos.

¿Puedo usar el modo numérico para números de tarjeta de crédito?

Sí. Un PAN de 16 dígitos como 4532015112830366 tokenizará en otro número de 16 dígitos. El número tokenizado no pasará la verificación Luhn — esto es esperado e intencional.

¿Cómo sé si la destokenización fue exitosa?

No hay indicador criptográfico. Si necesita verificar la corrección, almacene un hash del texto original y compárelo después de destokenizar.

¿El servicio guarda estado?

La lógica de tokenización es sin estado — no se almacena ninguna tabla de búsqueda y el valor original se deriva matemáticamente del token + clave + tweak + codificación. En modo multi-tenant, el servicio se conecta a PostgreSQL para resolver API keys y configuraciones de aplicaciones, pero cada solicitud sigue siendo independiente sin estado de sesión.

¿Es compatible con la normativa PCI DSS o HIPAA?

AgileTrust Tokenization implementa FPE estándar NIST, que es un componente técnico reconocido en esquemas de tokenización PCI DSS y HIPAA. Consulte a su equipo de cumplimiento para determinar si satisface los requisitos específicos de su organización.

Despliegue

Modo Single-Tenant

El modo de operación por defecto. Una única clave AES se carga al inicio y se comparte entre todas las solicitudes. Adecuado para una sola aplicación o cuando la aislación se gestiona a nivel de infraestructura.

Variables de entorno requeridas

VariableRequeridaDescripción
TOKENIZATION_KEYSíClave AES en base64 (16, 24 o 32 bytes)
API_KEYSíSecreto compartido para el header X-API-Key
KEY_PROVIDERNoFuente de la clave: env (por defecto), aws_secretsmanager, aws_kms, azure_keyvault, gcp_secretmanager, oci_vault, ciphertrust
DEFAULT_TWEAKNo14 caracteres hexadecimales (7 bytes). Sobreescribe el tweak por defecto (ceros).
bash
export TOKENIZATION_KEY="$(python3 -c 'import os,base64; print(base64.b64encode(os.urandom(32)).decode())')"
export API_KEY="$(openssl rand -hex 24)"

docker run -d -p 8000:8000 \
  -e TOKENIZATION_KEY="$TOKENIZATION_KEY" \
  -e API_KEY="$API_KEY" \
  tokenizer:0.3

Modo Multi-Tenant y Consola de Administración

Con MULTI_TENANT=true, el tokenizer resuelve las claves desde PostgreSQL en cada solicitud. Cada aplicación tiene su propia clave AES, configurada a través de la Consola AgileTrust — una interfaz de administración Next.js con autenticación SSO.

Arquitectura

  • Consola (Next.js, puerto 3000): crear tenants, aplicaciones y API keys. Acceso con Google, Microsoft u Okta.
  • Tokenizer (FastAPI, puerto 8000): resuelve la API key desde la base de datos, descifra el provider_config de la aplicación y cachea la clave por KEY_CACHE_TTL segundos.
  • PostgreSQL: base de datos compartida. La consola tiene acceso lectura-escritura; el tokenizer usa una conexión de solo lectura.
⚠

MASTER_ENCRYPTION_KEY debe ser idéntica en la consola y el tokenizer. Es la clave AES-256 usada para cifrar el provider_config de cada aplicación en la base de datos. Nunca la almacene en la propia base de datos.

Variables de entorno multi-tenant (tokenizer)

VariableRequeridaDescripción
MULTI_TENANTSí"true" para activar
DATABASE_URLSíConnection string de PostgreSQL (se recomienda solo lectura)
MASTER_ENCRYPTION_KEYSíClave AES-256 de 32 bytes, en base64. Igual que en la consola.
KEY_CACHE_TTLNoSegundos de caché por aplicación. Por defecto: 300.

Inicio rápido (Docker Compose)

bash
export POSTGRES_PASSWORD="$(openssl rand -hex 16)"
export NEXTAUTH_SECRET="$(openssl rand -base64 32)"
export MASTER_ENCRYPTION_KEY="$(python3 -c 'import os,base64; print(base64.b64encode(os.urandom(32)).decode())')"
export GOOGLE_CLIENT_ID="your-client-id"
export GOOGLE_CLIENT_SECRET="your-client-secret"

# Ejecutar migración Prisma (solo la primera vez)
cd console && npm install && npx prisma migrate deploy && cd ..

# Levantar los 3 servicios
docker compose -f docker-compose.full.yml up -d

Flujo del primer inicio de sesión

  1. Abrir http://localhost:3000 e iniciar sesión con su proveedor OAuth.
  2. El primer usuario del dominio de email se convierte en owner de un nuevo tenant. Los usuarios siguientes del mismo dominio se añaden como viewers.
  3. Ir a Applications → New Application. Elegir un proveedor de clave (System Vault es el predeterminado — no necesita vault externo).
  4. Abrir la aplicación y hacer clic en New Key. Copiar la API key — se muestra una única vez.
  5. Usar la API key en el header X-API-Key al llamar al tokenizer.

Rotación de API key vs. rotación de clave de cifrado

  • Rotación de API key: genera una nueva clave tok_… para la misma aplicación. La clave de cifrado y todos los tokens permanecen válidos.
  • Rotación de clave de cifrado (solo System Vault): genera una nueva clave AES. Todos los tokens existentes se vuelven irrecuperables — FPE con una clave incorrecta devuelve un valor plausible pero erróneo, sin ninguna señal de error.

Proveedores de clave

En modo single-tenant, seleccione el proveedor con la variable KEY_PROVIDER en el tokenizer. En modo multi-tenant, cada aplicación selecciona su propio proveedor en la consola — no se necesitan variables de entorno adicionales en el tokenizer.

ProveedorDescripciónParámetros de config
envClave AES desde la variable TOKENIZATION_KEY—
system_vaultClave AES almacenada cifrada en PostgreSQL (predeterminado multi-tenant)generada automáticamente por la consola
aws_secretsmanagerAWS Secrets Managersecret_id, region
aws_kmsAWS KMS (blob cifrado con KMS)key_ref (base64), region
azure_keyvaultAzure Key Vaultvault_url, secret_name
gcp_secretmanagerGCP Secret Managersecret_resource
oci_vaultOCI Vaultsecret_id
ciphertrustThales CipherTrust ManagerGuía de configuración próximamente
ℹ

Los SDKs de proveedores cloud no se instalan por defecto. Construya la imagen con el argumento de build correspondiente:
docker build --build-arg KEY_PROVIDER_DEPS=aws .
Valores válidos: aws, azure, gcp, oci, ciphertrust.

env — Variable de entorno (por defecto)

La clave AES se suministra directamente como variable de entorno en base64. Adecuado para despliegues single-tenant o desarrollo local.

ModoVariable / campoValor
Single-tenantKEY_PROVIDER=env
TOKENIZATION_KEY
Clave AES en base64 (16, 24 o 32 bytes)
Multi-tenantCampo de config: keyClave AES en base64

system_vault — Clave almacenada en base de datos (predeterminado multi-tenant)

La consola genera una clave AES-256 aleatoria al crear la aplicación, la cifra con MASTER_ENCRYPTION_KEY usando AES-256-GCM, y almacena el texto cifrado en la columna applications.provider_config. No se requieren credenciales de vault externo ni cloud.

Es el punto de partida recomendado para la mayoría de los despliegues. La clave nunca sale de la base de datos sin cifrar.

⚠

Rotación de clave (Applications → [app] → Rotate Key) genera una nueva clave AES. Todos los tokens emitidos con la clave anterior se vuelven irrecuperables — FPE con la clave incorrecta devuelve un valor plausible pero erróneo, sin señal de error.

aws_secretsmanager — AWS Secrets Manager

El tokenizer llama a GetSecretValue al inicio (single-tenant) o en fallo de caché (multi-tenant) para obtener la clave AES en base64 almacenada como secreto de texto plano.

ModoVariable / campoValor
Single-tenantKEY_PROVIDER=aws_secretsmanager
AWS_SECRET_ID
AWS_REGION
ARN o nombre del secreto
p.ej. us-east-1
Multi-tenantsecret_id
region
ARN o nombre del secreto
Región de AWS
ℹ

Permiso IAM requerido: secretsmanager:GetSecretValue sobre el ARN del secreto. Use un task role (ECS), instance profile (EC2) o las variables AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY.

bash — crear el secreto
KEY=$(python3 -c 'import os,base64; print(base64.b64encode(os.urandom(32)).decode())')
aws secretsmanager create-secret \
  --name agiletrust/tokenization-key \
  --secret-string "$KEY" \
  --region us-east-1

aws_kms — AWS KMS

La clave AES se cifra con una Customer Managed Key (CMK) de AWS KMS y se almacena como blob en base64. El tokenizer llama a kms:Decrypt para recuperar la clave en texto plano en tiempo de ejecución.

ModoVariable / campoValor
Single-tenantKEY_PROVIDER=aws_kms
AWS_KMS_KEY_REF
AWS_REGION
Texto cifrado en base64 de aws kms encrypt
Región de AWS
Multi-tenantkey_ref
region
Texto cifrado en base64
Región de AWS
ℹ

Permiso IAM requerido: kms:Decrypt sobre la CMK.

bash — cifrar la clave AES con KMS
KEY=$(python3 -c 'import os,base64; print(base64.b64encode(os.urandom(32)).decode())')
CIPHERTEXT=$(aws kms encrypt \
  --key-id alias/my-cmk \
  --plaintext "$KEY" \
  --query CiphertextBlob \
  --output text \
  --region us-east-1)
# Almacenar CIPHERTEXT como AWS_KMS_KEY_REF

azure_keyvault — Azure Key Vault

La clave AES se almacena como secreto en Azure Key Vault. La autenticación usa DefaultAzureCredential de azure-identity, que soporta managed identity, service principal y credenciales de desarrollador automáticamente.

ModoVariable / campoValor
Single-tenantKEY_PROVIDER=azure_keyvault
AZURE_VAULT_URL
AZURE_SECRET_NAME
https://my-vault.vault.azure.net
Nombre del secreto en Key Vault
Multi-tenantvault_url
secret_name
URL HTTPS del Key Vault
Nombre del secreto
ℹ

RBAC: Otorgue a la identidad del tokenizer el rol Key Vault Secrets User sobre el vault. Para autenticación con service principal, establezca AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID.

gcp_secretmanager — GCP Secret Manager

La clave AES se almacena como versión de secreto en GCP Secret Manager. La autenticación usa Application Default Credentials (ADC) — se otorga acceso a la cuenta de servicio que ejecuta el contenedor.

ModoVariable / campoValor
Single-tenantKEY_PROVIDER=gcp_secretmanager
GCP_SECRET_RESOURCE
Nombre completo del recurso, p.ej.
projects/my-project/secrets/tok-key/versions/latest
Multi-tenantsecret_resourceNombre completo del recurso
ℹ

IAM: Otorgue a la cuenta de servicio el rol Secret Manager Secret Accessor (roles/secretmanager.secretAccessor) sobre el secreto.

oci_vault — OCI Vault

La clave AES se almacena como secreto en Oracle Cloud Infrastructure Vault. La autenticación usa el archivo de configuración OCI o instance principal al ejecutarse en OCI Compute.

ModoVariable / campoValor
Single-tenantKEY_PROVIDER=oci_vault
OCI_SECRET_ID
OCID del secreto, p.ej.
ocid1.vaultsecret.oc1.phx.xxx
Multi-tenantsecret_idOCID del secreto
ℹ

IAM: Otorgue al instance principal o al dynamic group el permiso manage secret-family en el compartimento del vault.

Consola de Administración

Variables de entorno de la consola

La consola de administración es una aplicación Next.js configurada completamente mediante variables de entorno. Establézcalas en un archivo .env en la raíz de console/, o páselas directamente a Docker.

VariableRequeridaDescripción
DATABASE_URLSíConnection string de PostgreSQL. Ejemplo: postgresql://user:pass@host:5432/agiletrust
NEXTAUTH_URLSíURL base pública de la consola. Ejemplo: https://console.ejemplo.com. Se usa para construir las URLs de callback OAuth.
NEXTAUTH_SECRETSíSecreto aleatorio para firmar tokens de sesión. Generar con openssl rand -base64 32.
MASTER_ENCRYPTION_KEYSíClave AES-256 de 32 bytes en base64. Cifra el provider_config de aplicaciones en la base de datos. Debe ser idéntica en la consola y el tokenizer.
GOOGLE_CLIENT_IDOpcional*Client ID de OAuth 2.0 de Google.
GOOGLE_CLIENT_SECRETOpcional*Client Secret de OAuth 2.0 de Google.
AZURE_AD_CLIENT_IDOpcional*ID de aplicación (client) de Microsoft Entra ID.
AZURE_AD_CLIENT_SECRETOpcional*Secreto de cliente de Microsoft Entra ID.
AZURE_AD_TENANT_IDOpcional*ID de tenant (directorio) de Microsoft Entra ID.
OKTA_CLIENT_IDOpcional*Client ID de la aplicación OIDC de Okta.
OKTA_CLIENT_SECRETOpcional*Client Secret de la aplicación OIDC de Okta.
OKTA_ISSUEROpcional*URL del servidor de autorización de Okta. Ejemplo: https://su-org.okta.com/oauth2/default
KEYCLOAK_CLIENT_IDOpcional*Client ID del cliente Keycloak.
KEYCLOAK_CLIENT_SECRETOpcional*Client Secret del cliente Keycloak.
KEYCLOAK_ISSUEROpcional*URL del realm de Keycloak. Ejemplo: https://keycloak.ejemplo.com/realms/myrealm
POSTGRES_PASSWORDNoUsado solo en docker-compose.full.yml para establecer la contraseña del superusuario PostgreSQL.

* Debe configurarse al menos un proveedor OAuth.

ℹ

Las cuatro variables principales (DATABASE_URL, NEXTAUTH_URL, NEXTAUTH_SECRET, MASTER_ENCRYPTION_KEY) son siempre obligatorias. Las variables de proveedor OAuth son obligatorias solo para los proveedores que desee activar — puede activar varios simultáneamente.

SSO / Proveedores de identidad

La consola autentica usuarios mediante OAuth 2.0 / OIDC a través de NextAuth.js v5. Configure al menos uno de los cuatro proveedores soportados. Todos los proveedores activados aparecen simultáneamente en la página de inicio de sesión.

Google

  1. Abra Google Cloud Console → APIs y servicios → Credenciales.
  2. Haga clic en Crear credenciales → ID de cliente OAuth 2.0.
  3. Establezca el tipo de aplicación como Aplicación web.
  4. En URIs de redireccionamiento autorizados, agregue:
    {NEXTAUTH_URL}/api/auth/callback/google
  5. Copie el Client ID y el Client Secret en sus variables de entorno.
VariableDónde encontrarla
GOOGLE_CLIENT_IDCredenciales → OAuth 2.0 → Client ID
GOOGLE_CLIENT_SECRETCredenciales → OAuth 2.0 → Client Secret

Microsoft Entra ID (Azure AD)

  1. Abra el portal de Azure → Microsoft Entra ID → Registros de aplicaciones.
  2. Haga clic en Nuevo registro. Asigne un nombre; en Tipos de cuenta admitidos elija el ámbito deseado.
  3. En URI de redireccionamiento, seleccione Web e ingrese:
    {NEXTAUTH_URL}/api/auth/callback/azure-ad
  4. Tras la creación, anote el ID de aplicación (client) y el ID de directorio (tenant).
  5. Vaya a Certificados y secretos → Nuevo secreto de cliente. Copie el valor del secreto (no el ID).
VariableDónde encontrarla
AZURE_AD_CLIENT_IDRegistro de aplicación → Información general → ID de aplicación (client)
AZURE_AD_CLIENT_SECRETCertificados y secretos → Valor
AZURE_AD_TENANT_IDRegistro de aplicación → Información general → ID de directorio (tenant)

Okta

  1. Abra la Consola de administración de Okta → Applications → Create App Integration.
  2. Seleccione OIDC – OpenID Connect como método de inicio de sesión y Web Application como tipo de aplicación.
  3. En Sign-in redirect URIs, agregue:
    {NEXTAUTH_URL}/api/auth/callback/okta
  4. Copie el Client ID y el Client Secret de la configuración de la aplicación.
  5. La URL del Issuer se encuentra en Security → API → Authorization Servers. Por defecto: https://su-org.okta.com/oauth2/default.
VariableDónde encontrarla
OKTA_CLIENT_IDConfiguración de la aplicación → Client ID
OKTA_CLIENT_SECRETConfiguración de la aplicación → Client Secret
OKTA_ISSUERSecurity → API → Authorization Servers → Issuer URI

Keycloak

  1. Abra la Consola de administración de Keycloak → seleccione su realm → Clients → Create client.
  2. Establezca el Client type como OpenID Connect e ingrese un Client ID.
  3. Active Client authentication (tipo de acceso confidencial).
  4. En Valid redirect URIs, agregue:
    {NEXTAUTH_URL}/api/auth/callback/keycloak
  5. Guarde. Vaya a la pestaña Credentials y copie el Client Secret.
  6. La URL del issuer es la URL de su realm: https://<host>/realms/<nombre-realm>.
VariableDónde encontrarla
KEYCLOAK_CLIENT_IDClients → su cliente → Settings → Client ID
KEYCLOAK_CLIENT_SECRETClients → su cliente → Credentials → Client Secret
KEYCLOAK_ISSUERhttps://<host>/realms/<nombre-realm>
ℹ

Si Keycloak se ejecuta detrás de un proxy inverso, asegúrese de que KEYCLOAK_ISSUER coincida con la URL pública. El endpoint de descubrimiento OIDC debe ser accesible desde la consola en {KEYCLOAK_ISSUER}/.well-known/openid-configuration.

ℹ

Aprovisionamiento de tenant: El primer usuario que inicie sesión con un dominio de correo electrónico determinado se convierte automáticamente en owner de un nuevo tenant (con el nombre del dominio). Todos los usuarios siguientes del mismo dominio se añaden como viewer. El owner puede posteriormente promover a cualquier usuario a admin.

Roles y permisos

La consola aplica una jerarquía de tres niveles de roles. Un usuario con un rol de rango superior hereda todos los permisos de los roles de rango inferior.

RolRangoCapacidades
owner3 Control total: gestionar configuración del tenant, crear/editar/eliminar aplicaciones, gestionar API keys, gestionar usuarios (cambiar roles, eliminar), ver registro de auditoría.
admin2 Crear/editar/eliminar aplicaciones, gestionar API keys (crear, revocar, rotar). Ver usuarios y registro de auditoría. No puede gestionar roles de usuarios.
viewer1 Acceso de solo lectura a todos los recursos. No puede crear ni modificar nada.
  • El primer usuario en iniciar sesión para un dominio de correo determinado se convierte en owner.
  • Los usuarios siguientes del mismo dominio se unen como viewer.
  • Un owner puede promover un viewer a admin, un admin a owner, o degradar a cualquier usuario.
  • Un owner no puede eliminarse ni degradarse a sí mismo si es el último owner del tenant.

Gestionar aplicaciones

Una aplicación representa un servicio lógico que llamará a la API del tokenizer. Cada aplicación tiene su propia clave AES de cifrado y genera sus propias API keys. Requiere el rol admin u owner.

Crear una aplicación

  1. Navegue a Applications en la barra lateral.
  2. Haga clic en New Application.
  3. Ingrese un Nombre (obligatorio) y una Descripción opcional.
  4. Seleccione un Proveedor de clave. system_vault es el predeterminado — la consola genera y almacena la clave AES automáticamente; no se necesitan credenciales de vault externo.
  5. Para proveedores cloud, complete los campos de configuración requeridos (p.ej., secret_id y region para AWS Secrets Manager).
  6. Haga clic en Create. La aplicación se crea y su clave se aprovisiona inmediatamente.

Campos de configuración por proveedor

ProveedorCampos mostrados en el formulario de la consola
system_vaultNinguno — la clave se genera automáticamente
envkey (clave AES en base64, campo de contraseña)
aws_secretsmanagersecret_id, region
aws_kmskey_ref (texto cifrado en base64, campo de contraseña), region
azure_keyvaultvault_url, secret_name
gcp_secretmanagersecret_resource
oci_vaultsecret_id

Editar o eliminar una aplicación

Abra la página de detalle de la aplicación y use los botones Edit o Delete. Eliminar una aplicación revoca inmediatamente todas sus API keys — cualquier solicitud en curso que use esas claves recibirá 403 Forbidden.

Gestionar API keys

Las API keys autentican las llamadas al tokenizer. Cada clave está asociada a una sola aplicación y resuelve la clave AES de esa aplicación. Requiere el rol admin u owner.

Crear una clave

  1. Abra la página de detalle de una aplicación.
  2. Haga clic en New Key.
  3. Opcionalmente ingrese una Etiqueta (p.ej., producción, staging) y una fecha de expiración.
  4. Haga clic en Generate. La clave completa se muestra exactamente una vez — cópiela inmediatamente.
⚠

El texto en claro de la API key nunca se almacena. Solo su hash SHA-256 se guarda en la base de datos. Si pierde la clave, revóquela y cree una nueva.

Formato de la clave: tok_{tenant_slug}_{32 caracteres aleatorios}
Ejemplo: tok_acmecorp_K7mP2xQnRvW9jLdF8bTsZeYhAcGiNuXo

Revocar una clave

Haga clic en Revoke junto a la clave. La clave deja de funcionar inmediatamente — el tokenizer la rechaza con 403 Forbidden en la siguiente solicitud.

Rotar una clave

Haga clic en Rotate. Esto genera atómicamente una nueva clave y revoca la anterior. El nuevo texto en claro se muestra una vez. Use la rotación para reemplazar una clave que pueda haber sido expuesta sin interrumpir el servicio entre la generación y el despliegue.

Gestionar usuarios

Los usuarios se unen automáticamente — cualquier persona que inicie sesión con una dirección de correo electrónico perteneciente al dominio del tenant se añade como viewer. No se requiere ningún paso de invitación.

Ver usuarios

Navegue a Users en la barra lateral para ver todos los usuarios, sus roles, la fecha del último inicio de sesión y el proveedor OAuth.

Cambiar el rol de un usuario

Haga clic en el badge de rol junto a un usuario para abrir el selector de rol. Requiere el rol owner. Transiciones disponibles:

  • viewer → admin o owner
  • admin → viewer o owner
  • owner → admin o viewer (solo si existe al menos otro owner)

Eliminar un usuario

Haga clic en Remove junto al usuario. Requiere el rol owner. La sesión del usuario se invalida y no puede volver a iniciar sesión a menos que se reautentique (en cuyo caso se uniría nuevamente como viewer).

ℹ

Un tenant debe tener siempre al menos un owner. El último owner no puede degradarse ni eliminarse a sí mismo.

Registro de auditoría

Cada acción de mutación realizada a través de la consola se registra en el log de auditoría. Navegue a Audit Log en la barra lateral para ver y paginar las entradas.

Cada entrada registra: fecha/hora, actor (nombre y correo del usuario), dirección IP, tipo de acción, recurso objetivo y un blob JSON de detalles opcional.

AcciónObjetivoDescripción
tenant.updateTenantNombre o configuración del tenant modificada
application.createAplicaciónNueva aplicación creada
application.updateAplicaciónNombre, descripción o config del proveedor modificados
application.deleteAplicaciónAplicación y todas sus API keys eliminadas
application.rotate_keyAplicaciónClave de cifrado (system_vault) rotada — los tokens existentes se vuelven irrecuperables
api_key.createAPI KeyNueva API key generada para una aplicación
api_key.revokeAPI KeyAPI key revocada
api_key.rotateAPI KeyAPI key rotada (nueva clave generada, anterior revocada)
user.inviteUsuarioUsuario invitado (reservado para flujo de invitación futuro)
user.role_changeUsuarioRol de usuario modificado
user.removeUsuarioUsuario eliminado del tenant
ℹ

Las entradas del registro de auditoría son de solo escritura y no pueden eliminarse a través de la consola. Requiere rol admin o superior para visualizarlas.

AgileTrust Tokenization v0.3 — FF3-1/AES — NIST SP 800-38G Rev 1

Home  •  Manual in English  •  API Reference  •  Best Practices