El hardening de seguridad en BaaS es un conjunto de controles en capas — CLPs, ACLs y disciplina de claves — que cierra las brechas con que nace un backend. Los backends nacen permisivos a propósito: las clases abiertas y los esquemas escribibles por el cliente hacen volar los prototipos. El hardening es la pasada deliberada que invierte esos defaults antes del lanzamiento — y es un checklist corto y conocido, no un proyecto de investigación.
Puntos clave
| Pregunta | Respuesta |
|---|---|
| Qué es | La pasada previa al lanzamiento que bloquea permisos de clase, ACLs, claves y esquema |
| Las capas | Las CLPs custodian la clase → las ACLs custodian la fila → los campos protegidos custodian la columna |
| La regla absoluta | La master key lo salta todo — jamás sale del servidor |
| El camino privilegiado | Las funciones de Cloud Code son la puerta auditada para escrituras sensibles |
| Lo que las claves no son | Los app IDs y las client keys son identificadores, no secretos — planifica en consecuencia |
El default endurecido, en código
La mitad por objeto de la historia — una ACL acotada al dueño, en capa bajo una clase bloqueada:
// JavaScript / Node.js — Back4app JS SDK
// Per-object ACL: the owner reads and writes, a moderator role reads,
// the public gets nothing — layered under the class-level permissions
const note = new Parse.Object('Note');
note.set('body', 'quarterly numbers');
const acl = new Parse.ACL(Parse.User.current()); // owner: read + write
acl.setPublicReadAccess(false);
acl.setPublicWriteAccess(false);
acl.setRoleReadAccess('moderator', true); // role: read only
note.setACL(acl);
await note.save();
// The class gate above it is schema config, set in the dashboard:
// find/get: requiresAuthentication · create: authenticated · addField: nobody // Flutter / Dart — Back4app Flutter SDK
// Per-object ACL: owner read/write, moderator role read, public nothing
final note = ParseObject('Note')..set('body', 'quarterly numbers');
final acl = ParseACL(owner: await ParseUser.currentUser()); // owner: r+w
acl.setPublicReadAccess(allowed: false);
acl.setPublicWriteAccess(allowed: false);
acl.setReadAccess(userId: 'role:moderator', allowed: true); // role: read
note.setACL(acl);
await note.save();
// The class gate above it is schema config, set in the dashboard:
// find/get requiresAuthentication, create authenticated, addField off // iOS / Swift — Back4app Swift SDK
// Per-object ACL: owner read/write, moderator role read, public nothing
var note = Note()
note.body = "quarterly numbers"
var acl = ParseACL()
acl.publicRead = false
acl.publicWrite = false
if let user = User.current {
acl.setReadAccess(user: user, value: true) // owner: read
acl.setWriteAccess(user: user, value: true) // owner: write
}
acl.setReadAccess(roleName: "moderator", value: true) // role: read only
note.ACL = acl
note.save { result in
if case .failure(let error) = result { print(error) }
} // Android / Kotlin — Back4app Android SDK
// Per-object ACL: owner read/write, moderator role read, public nothing
val note = ParseObject("Note").apply { put("body", "quarterly numbers") }
val acl = ParseACL(ParseUser.getCurrentUser()) // owner: read + write
acl.publicReadAccess = false
acl.publicWriteAccess = false
acl.setRoleReadAccess("moderator", true) // role: read only
note.acl = acl
note.saveInBackground { e ->
if (e != null) Log.w("ACL", "save failed: ${e.code}")
}
// The class gate above it is schema config, set in the dashboard:
// find/get requiresAuthentication, create authenticated, addField off CLP vs. ACL vs. master key: qué controla cada uno
| Control | Alcance | Se configura en | Cómo falla |
|---|---|---|---|
| Permiso a nivel de clase | La clase entera, por operación | El esquema (dashboard) | Dejado en defaults permisivos |
| ACL | Un objeto | En cada fila, al guardar | Olvidada en objetos nuevos |
| Campos protegidos | Una columna | El esquema | Columnas sensibles legibles por pares |
| Master key | Salta todo lo anterior | Solo el entorno del servidor | Embarcada en un binario de cliente |
Los tres primeros se componen en una escalera de permisos que toda solicitud sube. El cuarto es la salida de emergencia de la escalera — indispensable del lado del servidor, catastrófica en cualquier otro lugar. Y los identificadores que las apps sí llevan a bordo — el app ID y las claves de API de cliente — pertenecen a una categoría mental completamente distinta: son extraíbles de cualquier binario, así que identifican la app en lugar de protegerla. Asume que son públicos y deja que la capa de datos haga el enforcement.
Dónde muere una solicitud hostil
El diagrama es también el guion de auditoría: en cada gate, pregunta qué pasa cuando un atacante con tus claves públicas llega como usuario anónimo, como usuario con sesión iniciada y como usuario de otro tenant. Cada “permitido” que te sorprenda es el hallazgo.
Cómo endurecer un backend BaaS
| Paso | Acción | Qué cierra |
|---|---|---|
| 1 | Configura las CLPs de cada clase: requiresAuthentication como mínimo, escrituras acotadas por rol | El clásico dump anónimo de la tabla entera |
| 2 | Apaga addField en todas las clases y la creación de clases desde el cliente | La deriva de esquema y la inyección de clases basura |
| 3 | ACL por defecto en los objetos del usuario: el dueño lee/escribe, el público nada | Lecturas y escrituras entre usuarios |
| 4 | Protege las columnas sensibles (email, tokens, scores) con reglas por campo | Usuarios pares leyendo atributos privados |
| 5 | Confina la master key a entornos de servidor; rótala por calendario y ante cualquier filtración | La exposición total por bypass |
| 6 | Dirige las escrituras sensibles por funciones de Cloud Code con clases bloqueadas detrás | Violaciones de reglas de negocio y manipulación |
| 7 | Aplica rate limits a los endpoints de auth y las consultas caras | Credential stuffing y scraping masivo |
| 8 | Vuelve a probar desde un cliente real solo con claves públicas; loguea y revisa el uso de la master key | La deriva de configuración pasando inadvertida |
Los pasos 1–4 son enforcement en la capa de datos — declarativo, verificado en cada camino. Los pasos 5–8 son disciplina operativa. Ambas mitades son necesarias; ninguna es suficiente.
Disciplina de master key y el camino privilegiado
La master key existe porque alguien legítimo — migraciones, herramientas de admin, jobs programados — debe poder ignorar los gates. La disciplina consiste en tratarla como la credencial de root que es: inyectada en los entornos de servidor como configuración, nunca commiteada, nunca logueada, jamás embebida en nada que un usuario descargue, y usada por operación en lugar de mantenida como default de sesión. La rotación es la mitad subestimada — las claves se fugan en silencio a los logs de CI y las laptops viejas, así que rotarlas por calendario (y al instante ante cualquier sospecha) acota el radio de daño de una fuga que nunca detectaste.
Cloud Code es el patrón que hace vivibles las reglas estrictas de la capa de datos. Bloquea una clase por completo — cero escrituras de cliente — y expone una función serverless como única puerta. La función valida la entrada, aplica las reglas de negocio que el esquema no puede expresar (“solo antes de que el pedido se envíe”), escribe con privilegios elevados y deja rastro de auditoría. El gate de la clase garantiza que el chokepoint no puede rodearse; el chokepoint mantiene la lógica revisable en un solo lugar.
Casos de uso comunes
- El lockdown previo al lanzamiento. El checklist completo de arriba, ejecutado una vez antes de que lleguen usuarios reales — la hora de seguridad de mayor apalancamiento que un equipo pequeño invierte.
- Aislamiento de datos multi-tenant. ACLs acotadas al dueño más CLPs de solo autenticados, para que el tenant A jamás pueda consultar al tenant B — con enforcement por debajo del código de la aplicación.
- Pagos e inventario. Clases bloqueadas a cero escrituras de cliente, con funciones de Cloud Code como el camino auditado para todo lo que toque dinero o stock.
- Respuesta a incidentes. Una clave filtrada o una sorpresa en los logs dispara la rotación, una auditoría de accesos y una nueva ronda del test de permisos de afuera hacia adentro.
- Evidencia de compliance. Una matriz de permisos versionada y logs de uso de la master key convierten “nos tomamos la seguridad en serio” en un artefacto que un auditor puede leer.
¿Deberías endurecer en la capa de datos o en el código de la aplicación? Matriz de decisión
| Aplícalo en la capa de datos (CLPs + ACLs) cuando… | Aplícalo en el código de la aplicación (Cloud Code) cuando… |
|---|---|
| La regla trata de identidad y propiedad | La regla necesita lógica de negocio o estado entre objetos |
| Debe valer en todo camino, incluidos clientes futuros | El requisito es un único chokepoint auditado |
| Un toggle del dashboard es toda la especificación | La validación, el enriquecimiento o los efectos secundarios van a bordo |
| Quieres seguridad que sobreviva a reescrituras de la app | La regla cambia más rápido de lo que el esquema debería |
| El modo de falla del olvido es catastrófico | El modo de falla es un bug de negocio, no una brecha |
En la práctica la respuesta es en capas, no una u otra: reglas en la capa de datos como el piso que siempre sostiene, funciones en la capa de aplicación para todo lo condicional — la misma solicitud atraviesa ambas.
Limitaciones y trade-offs
- El hardening es configuración, y la configuración deriva. Las clases nuevas llegan con defaults permisivos; sin el hábito de reauditar, el lockdown del año pasado se erosiona en silencio.
- Las reglas declarativas no pueden expresar lógica. “Solo los dueños” es un toggle; “solo reembolsable dentro de 30 días” es código — depender demasiado de la capa de datos empuja a los equipos a contorsionar esquemas en vez de escribir una función.
- La rigidez tiene un costo de experiencia de desarrollo. Las clases bloqueadas y los esquemas congelados frenan el prototipado, y por eso la disciplina se escalona: abierto en desarrollo, bloqueado en el lanzamiento.
- Los rate limits y las auditorías necesitan ajuste. Los límites demasiado apretados estrangulan picos legítimos; los logs que nadie lee son decoración. Ambos necesitan un dueño, no solo un commit de setup.
- Las capas protegen los datos, no todo. Las vulnerabilidades en dependencias, las contraseñas de usuario filtradas y la ingeniería social viven fuera de este modelo — endurecer la capa de datos es necesario, no suficiente, como deja claro el catálogo del OWASP API Security Top 10.
Hardening de seguridad en BaaS en Back4app
Back4app es una plataforma open-source de Backend as a Service (BaaS) que combina base de datos gestionada, APIs REST y GraphQL generadas automáticamente, autenticación, almacenamiento de archivos y funciones serverless con Cloud Code. El checklist de este artículo se mapea a su dashboard casi uno a uno: los permisos a nivel de clase y los campos protegidos son checkboxes por clase, las ACLs se aplican del lado del servidor en cada solicitud — por SDKs, REST y GraphQL — y la master key se queda en la configuración del servidor, donde Cloud Code — el camino privilegiado — puede usarla por operación. Las guías de seguridad recorren la misma pasada paso a paso, así que endurecer un backend es una tarde de toggles y un test honesto de afuera hacia adentro.
Preguntas frecuentes
¿Qué es el hardening de seguridad en BaaS?
La pasada previa al lanzamiento que convierte un backend de desarrollo permisivo en uno de producción bloqueado: permisos a nivel de clase restringidos por operación, ACLs por objeto en los datos de usuario, la master key confinada al código del servidor, el esquema congelado, rate limits configurados y la configuración auditada desde un cliente real. Cada control cubre una capa distinta, y las capas se verifican en secuencia en cada solicitud.
¿El application ID es un secreto?
No — trátalo como público. Las client keys y los app IDs viajan dentro de cada binario móvil y cada página de JavaScript, donde cualquiera puede extraerlos. Identifican la app; no autentican a quien llama. La protección real viene de lo que el backend aplica después de la identificación: permisos a nivel de clase, ACLs y autenticación — las capas que resisten incluso cuando todas las claves del lado del cliente son conocidas.
¿Por qué la master key nunca debe viajar en una app cliente?
Porque salta todos los gates: los permisos a nivel de clase, las ACLs, los campos protegidos y las verificaciones de autenticación son nulos para las solicitudes con master key. Una clave embebida en un binario puede ser extraída por cualquiera que descargue la app, y eso vuelve tu base de datos entera pública en lectura y escritura. La master key pertenece solo al código del servidor — usada por operación, jamás guardada donde un cliente pueda alcanzarla.
¿Cuál es la diferencia entre CLPs y ACLs?
El alcance. Un permiso a nivel de clase es una regla en el esquema que responde "quién puede ejecutar esta operación en esta clase"; una ACL es un dato en cada objeto que responde "quién puede tocar esta fila". Las solicitudes pasan primero por el gate de la clase, después por el del objeto, y cualquiera puede denegar. El hardening usa ambos: trazo grueso en el esquema, grano fino en las filas.
¿Cómo se rota una master key filtrada?
Genera de inmediato una clave nueva en el dashboard de la plataforma, actualiza todos los consumidores del lado del servidor — Cloud Code, jobs, scripts de admin, CI — y revoca la clave vieja. Después audita lo que la clave filtrada pudo haber tocado mientras era válida. La rotación también debe ser rutina, no solo respuesta a incidentes: las claves envejecen en logs, backups y laptops viejas, así que agenda la rotación como si fuera renovación de certificados.
¿Cuándo deben pasar las escrituras por Cloud Code en vez del SDK?
Siempre que la regla necesite lógica, no solo identidad: invariantes entre varios objetos, precios, inventario, cualquier cosa que involucre dinero o cuotas. El patrón endurecido bloquea la clase para que los clientes no puedan escribirla directamente y expone una función de Cloud Code como única puerta — la validación, el enriquecimiento y el log de auditoría van a bordo, y el gate de la clase garantiza que nadie rodee el chokepoint.
¿Los rate limits pertenecen a una configuración de seguridad en BaaS?
Sí — los permisos deciden quién puede llamar un endpoint; los rate limits deciden con qué frecuencia. Sin ellos, unas credenciales válidas se vuelven herramienta de scraping o fuerza bruta: los endpoints de login sufren credential stuffing y las consultas abiertas se cosechan a velocidad de línea. Aprieta los límites en las rutas de autenticación y las consultas caras, y combínalos con alertas para que un pico anómalo sea un aviso, no una factura sorpresa.
¿Cómo se audita la configuración de seguridad de un BaaS?
Prueba desde afuera, como lo haría un atacante: solo con las claves públicas del cliente, intenta leer y escribir cada clase como usuario anónimo, como usuario autenticado y como usuario de otro tenant. Todo lo que funcione y no debería es un hallazgo. Repite tras cada cambio de esquema, mantén la matriz de permisos en documentación versionada y revisa los logs en busca de usos de la master key que no deberían existir.