Forks enmascarados
Dé a un agente (o a un humano) la forma de producción y nada de su PII — políticas de enmascaramiento, la biblioteca de funciones integradas y cómo las ramas y los sandboxes enmascarados permanecen sellados hasta que el enmascaramiento se confirma.
MASK es el track de Agent-Safe Change Control para datos sensibles: entrega a un agente un fork con la forma de producción y nada de su PII. Funciona de dos maneras — ramas enmascaradas (para humanos: dev, CI, contratistas) y sandboxes enmascarados (para agentes). Ambas se cubren a continuación.
El enmascaramiento de datos anonimiza las columnas sensibles en el momento en que se crea una rama. Se adjunta una política de enmascaramiento a la llamada de creación de rama, y las columnas coincidentes de la nueva rama se reescriben de forma irreversible — con hash, anuladas, truncadas o reemplazadas — antes de que la rama sea siquiera accesible. La rama padre nunca se modifica.
Recurriría a ello para entregar datos con forma de producción a desarrollo, CI o un contratista sin entregar la PII que contienen: formas de tabla reales, recuentos de filas reales, correos electrónicos falsos.
Cómo funciona
Una política de enmascaramiento es un conjunto de reglas con nombre y alcance de proyecto. Cada regla hace coincidir columnas por patrón y nombra una función de enmascaramiento integrada:
| Campo | Significado |
|---|---|
schema_pattern | Patrón de nombre de esquema (% o * = cualquiera, _ = un carácter). El valor por defecto es *. |
table_pattern | Patrón de nombre de tabla. |
column_pattern | Patrón de nombre de columna. |
masking_fn | Una de las funciones integradas de abajo. |
fn_args | Argumentos de la función (solo mask_constant toma uno: value). |
En el momento de la creación de la rama, cuando se proporciona un
masking_policy_id:
- La rama se bifurca de su padre como de costumbre (copy-on-write — instantáneo).
- La rama entra en el estado
masking. No se aprovisiona ningún endpoint y el proxy rechaza las conexiones a ella: no hay ninguna ventana en la que se puedan leer los datos previos al enmascaramiento. - Un worker de enmascaramiento se conecta a la compute de la rama como un rol de mínimo privilegio, descubre el esquema, hace coincidir sus reglas con él y ejecuta cada reescritura en una sola transacción.
- La rama aterriza en
readyy sus endpoints se levantan — ahora sirviendo solo datos enmascarados. Ante cualquier fallo, la rama aterriza enfailedy permanece sellada; elimínela y reinténtela.
Las entradas de las reglas se tratan como datos, nunca como SQL: los identificadores se entrecomillan y los valores de los argumentos se vinculan como parámetros en la ejecución, de modo que un nombre de columna o una constante hostil no puede escapar de la reescritura.
Funciones integradas
| Función | Efecto |
|---|---|
mask_email | md5(value)@masked.invalid |
mask_name | Name_ + un prefijo de hash de 8 caracteres |
mask_null | NULL (la columna debe admitir nulos) |
mask_constant | Un valor fijo que usted proporciona (fn_args.value) |
mask_ssn_partial | ***-**-1234 — conserva los últimos 4 dígitos |
mask_credit_card | ****-****-****-1234 — conserva los últimos 4 dígitos |
mask_ip | 0.0.0.0 |
mask_date_year | Conserva el año, trunca al 1 de enero |
mask_hash | md5(value) |
mask_shuffle | Mezcla basada en hash (la mezcla completa de caracteres está planificada) |
mask_phone | Un número sintético +1-555-XXXX |
mask_uuid | Un UUID aleatorio nuevo |
El catálogo también lo sirve la API:
curl -s https://api.kisenon.com/v1/masking-functions \
-H "Authorization: Bearer $KISENON_API_KEY"Gestión de políticas
En la consola, abra Project settings → Data masking para crear una política: póngale nombre, añada reglas (columnas de patrón + un desplegable de función) y guarde. La misma superficie existe en la API:
curl -s -X POST \
https://api.kisenon.com/v1/projects/$PROJECT_ID/masking-policies \
-H "Authorization: Bearer $KISENON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "dev-safe",
"rules": [
{"table_pattern": "users", "column_pattern": "email", "masking_fn": "mask_email"},
{"table_pattern": "users", "column_pattern": "phone", "masking_fn": "mask_null"},
{"table_pattern": "%", "column_pattern": "%ssn%", "masking_fn": "mask_ssn_partial"}
]
}'Luego cree una rama enmascarada añadiendo la política a una llamada normal de creación de rama:
curl -s -X POST \
https://api.kisenon.com/v1/projects/$PROJECT_ID/branches \
-H "Authorization: Bearer $KISENON_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "masked-dev", "masking_policy_id": "'$POLICY_ID'"}'La rama informa state: "masking" mientras se ejecuta la reescritura;
obsérvela cambiar a ready en la consola (en vivo, a través del flujo de
eventos del proyecto) o sondeando GET /v1/branches/{id}.
Sandboxes enmascarados (para agentes)
Las mismas políticas enmascaran el fork del sandbox de un agente, de modo que un agente trabaja contra la forma de producción y nunca ve su PII. Adjunte una política en la creación:
keon sandbox create --project <id> --masking-policy <policy-id>El enmascaramiento se ejecuta antes de que el sandbox se active. El sandbox
informa masked: true y su masking_policy_id, y mientras sigue en creating
un objeto de progreso masking (state, phase, rules_total,
rules_completed, rows_affected_so_far, error) muestra la reescritura
avanzando.
Establezca un mínimo por proyecto para que cada sandbox quede enmascarado por defecto:
keon projects update <id> --sandbox-masking-policy <policy-id> # or: noneUn --masking-policy por solicitud anula el valor por defecto del proyecto,
pero nunca puede excluirse de un mandato — una defensa contra un agente que
se libra del enmascaramiento con labia. Establecer el mandato es solo para
propietario/administrador; las claves con capacidad de agente se rechazan
(403).
Fallo cerrado por construcción. Los endpoints de un fork enmascarado nacen
en un estado de enmascaramiento — el proxy rechaza las conexiones (SQLSTATE
57P05) hasta que la reescritura se confirma. Si el paso de enmascaramiento
falla o no está conectado, la creación falla cerrada: nunca se emite una URL
para un fork sin enmascarar. El worker de enmascaramiento se conecta como el rol
de mínimo privilegio kisenon_masker (nunca un superusuario), no posee ningún
RBAC de clúster, y su contraseña por ejecución nunca se persiste ni se registra.
Dos salvedades que conviene conocer:
- El DML contra valores enmascarados no coincidirá en el padre durante la
reproducción. Una sentencia como
UPDATE … WHERE email = 'a1b2@masked.invalid'apunta a un valor enmascarado que no existe enmain. El trabajo de carril de esquema es independiente del valor y se promociona limpiamente; el DML dependiente del valor no es tarea para un fork enmascarado. - Las claves foráneas siguen aplicándose. El enmascaramiento deshabilita los
triggers de usuario (
ALTER TABLE … DISABLE TRIGGER USER), no los triggers de integridad referencial. Enmascarar una columna dentro de una relación de clave foránea puede, por tanto, provocar un error de RI y hacer fallar el fork cerrado en lugar de romper la referencia en silencio. - v1 enmascara solo la base de datos
main.
Conviene saber
- El enmascaramiento es de una sola vez, en la creación. Editar una política nunca toca las ramas que ya se crearon con ella — conservan la forma de datos con la que nacieron. Vuelva a crear la rama para aplicar las nuevas reglas.
- Una política en uso no se puede eliminar. Eliminar una política con la que
se creó una rama activa devuelve
409 policy_in_use; elimine primero esas ramas. - Las reglas sin coincidencia se omiten, no son fatales. Si su esquema se desvió y un patrón no coincide con nada, la rama igualmente se completa — revise los patrones de las reglas si una columna que esperaba enmascarada todavía tiene una forma de datos real.
- Las discrepancias de tipo hacen fallar la rama. Una regla que coincide con
una columna que su función no puede reescribir (digamos
mask_emailsobre uninteger) aborta todo el enmascaramiento — la rama aterriza enfailedy nunca se expone enmascarada a medias.