Control de acceso
Introducción
Section titled “Introducción”El control de acceso, también conocido como autorización, es una técnica de seguridad que consiste en determinar quién puede acceder a qué recursos.
Autenticación
Section titled “Autenticación”En muchos sistemas de gestión de bases de datos, un usuario se identifica sólo con un nombre de usuario.
En cambio, en MongoDB un usuario no sólo se identifica por su nombre de usuario, sino también por la base de datos en la que se crea (que es como base de datos de autenticación de ese usuario).
Esto significa que en MongoDB es posible tener varios usuarios con el mismo nombre de usuario siempre que se creen en bases de datos de autenticación distintas. Para autenticarte como usuario, debes proporcionar no sólo un nombre de usuario y una contraseña, sino también el nombre de la base de datos de autenticación asociada a ese usuario.
Se podría suponer que los usuarios creados en una base de datos de autenticación determinada tendrían privilegios de acceso disponibles sólo para esa base de datos en particular, pero éste no es el caso. Cada usuario, independientemente de la base de datos de autenticación en la que se creó, puede tener privilegios asignados a diferentes bases de datos.
Autorización
Section titled “Autorización”En un control de acceso basado en roles, los usuarios no tienen permiso para realizar acciones directamente sobre los recursos, como insertar un documento nuevo en la base de datos o consultar una colección concreta, sino que las reglas que permiten acciones sobre recursos concretos se asignan a roles.
Los roles se definen con un conjunto de uno o varios privilegios. Cada privilegio consiste en una acción (como crear nuevos documentos, recuperar datos de un documento o crear y suprimir usuarios) y el recurso sobre el que se puede realizar esta acción (como una base de datos llamada reports
o una colección llamada orders
).
Los roles se identifican con la combinación del nombre del rol y la base de datos, ya que cada rol, excepto los creados en la base de datos admin
, sólo puede incluir privilegios que se aplican a su propia base de datos. Al conceder a un usuario roles definidos en una base de datos distinta a su base de datos de autenticación, se puede dar permiso a un usuario para actuar en más de una base de datos. Los roles se pueden conceder cuando creas un usuario o en cualquier momento después. La revocación de la pertenencia al rol también puede realizarse a voluntad, por lo que es sencillo desvincular la gestión de usuarios de la gestión de los derechos de acceso.
MongoDB proporciona un conjunto de roles integrados que describen privilegios que se utilizan habitualmente en sistemas de bases de datos, tales como read
para conceder acceso de sólo lectura, readWrite
para otorgar tanto permisos de lectura como de escritura o dbOwner
para conceder privilegios administrativos completos sobre una base de datos determinada. Para escenarios más específicos, también pueden crearse roles definidos por el usuario con conjuntos personalizados de privilegios.
El control de acceso basado en roles permite asignar a los usuarios sólo el nivel mínimo y preciso de permisos de acceso que necesitan para trabajar en sus respectivas tareas. Ésta es una práctica de seguridad importante conocida como principio de privilegios mínimos.
Entorno de trabajo
Section titled “Entorno de trabajo”El control de acceso de MongoDB no está habilitado por defecto
Arranca la base de datos y crea una sesión:
> start-process -NoNewWindow mongodb> mongosh
Crea el usuario administrador root
:
> use adminswitched to db adminadmin> db.createUser( { user: "root", pwd: passwordPrompt(), roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ] })Enter password********{ ok: 1 }
Para el servidor y sal del shell:
> db.adminCommand({ shutdown: 1 })> exit
Vuelve a ejecutar mongod
, pero esta vez con el flag --auth
:
> start-process -NoNewWindow mongod --auth
Crea una nueva sesión con el usuario root
:
> mongosh.exe -u rootEnter password: ********...test>
Puedes ver que ahora ya no te avisa de que RBAC está deshabilitado.
Roles predefinidos
Section titled “Roles predefinidos”Para explicar cómo funciona el control de acceso basado en roles (RBAC, para abreviar) en la práctica utilizaremos de ejemplo una empresa de ventas que utiliza dos bases de datos.
-
La primera base de datos (llamada
sales
) almacenará datos sobre los pedidos de los clientes en la tienda de la empresa con dos colecciones separadas:customers
para los datos personales de sus clientes yorders
para los detalles del pedido. -
La segunda base de datos (llamada
reports
) almacenará informes agregados de ventas mensuales. Esta base de datos contendrá una única colección llamadareports
.
La empresa sólo tiene dos empleados, Laura y Roser.
Y estos son los permisos que crearás a continuación:
Usuari | sales | reports | admin |
---|---|---|---|
root | readWriteAnyDatabase , admin:userAdminAnyDatabase | ||
laura | readWrite | ||
roser | read | readWrite |
Cambia a la base de datos sales
:
> use salesswitched to db sales
Inserta un cliente en la colección customers
:
sales> db.customers.insertOne({name: "David"}){ acknowledged: true, insertedId: ObjectId('67882f9242d68a24b1cb0ce3')}
Inserta una orden en la colección orders
:
sales> db.orders.insert({total: 100}){ acknowledged: true, insertedIds: { '0': ObjectId('67882fd442d68a24b1cb0ce4') }}
A continuación crea el usuario “Laura” que trabaja en el departamento de ventas y necesita acceso completo a las dos colecciones de la base de datos sales
, pero no necesita trabajar con la base de datos reports
.
sales> db.createUser( { user: "laura", pwd: passwordPrompt(), roles: [ {role : "readWrite", db: "sales" }]})Enter password********{ ok: 1 }
Puedes confirmar que se ha añadido la “Laura” a la lista de usuarios de la base de datos sales
:
sales> show users[ { _id: 'sales.laura', userId: UUID('f97f35ec-b6c9-4175-adef-7ddd1b3f47da'), user: 'laura', db: 'sales', roles: [ { role: 'readWrite', db: 'sales' } ], mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ] }]
Cambia a la base de datos reports
:
sales> use reportsswitched to db reports
Inserta un documento en la colección reports
:
> db.reports.insertOne({orders: 1}){ acknowledged: true, insertedId: ObjectId('678833800c36be4e5fcb0ce2')}
Cierra la sesión y crea una nueva sesión con el usuario laura
:
> mongosh -u laura sales...
Ejecuta el orden show dbs
para listar las bases de datos disponibles:
sales> show dbssales 80.00 KiB
A diferencia de su cuenta de administrador, sólo aparecerá una base de datos para la laura
, ya que sólo le has concedido acceso a la base de datos sales
.
Ahora compruebe si laura
puede recuperar objetos de ambas colecciones en la base de datos sales
:
sales> db.customers.find()[ { _id: ObjectId('67882f9242d68a24b1cb0ce3'), name: 'David' } ]sales> db.orders.find()[ { _id: ObjectId('67882fd442d68a24b1cb0ce4'), total: 100 } ]
Para asegurarte de que los derechos de acceso a la base de datos sales
se han configurado correctamente, puedes comprobar si laura
también puede insertar nuevos documentos:
sales> db.customers.insertOne({name: "Maria"}){ acknowledged: true, insertedId: ObjectId('6789044acdca8d8d69cb0ce2')}
Como has concedido a la laura
el rol readWrite
, está autorizado a escribir nuevos documentos en esta base de datos.
Finalmente, verifica que laura
no puede leer ni escribir ningún dato en la base de datos reports
, ya que no le concediste acceso a través de los roles asignados.
sales> use reportsswitched to db reportsreports> db.reports.find()MongoServerError[Unauthorized]: not authorized on reports to execute command { find: "reports", filter: {}, lsid: { id: UUID("461bf330-c3d1-4344-a350-d89e646843eb") }, $db: "reports" }
El mensaje de error Unauthorized
indica que laura
no tiene suficientes derechos de acceso para interactuar con los datos de la base de datos reports
.
Ahora debes crear la cuenta para roser
, la analista de ventas de la empresa.
La roser
necesita acceso de escritura a la base de datos reports
para crear informes, así como sólo acceso de lectura a la base de datos sales
para recuperar los datos.
Cambia a la base de datos admin
y auténticate como root
:
sales> use adminswitched to db adminadmin> db.auth("root")Enter password********{ ok: 1 }
Crea el usuario roser
en la base de datos reports
:
admin> use reportsswitched to db reportsreports> db.createUser({... user: "roser",... pwd: passwordPrompt(),... roles: [ { role: "readWrite", db: "reports"}, {role: "read", db: "sales"} ]... })Enter password********{ ok: 1 }
Autentícate como el usuario roser
:
reports> db.auth("roser")Enter password********{ ok: 1 }
Ejecuta la orden show dbs
para listar las bases de datos disponibles para roser
:
reports> show dbsreports 40.00 KiBsales 112.00 KiB
Puesto que la roser
puede utilizar las bases de datos sales
y reports
, estas dos bases de datos se mostrarán en la salida.
Comprueba si la roser
puede recuperar objetos de la base de datos sales
:
reports> use salesswitched to db salessales> db.orders.find()[ { _id: ObjectId('67882fd442d68a24b1cb0ce4'), total: 100 } ]
A continuación, puedes intentar insertar un documento nuevo en la colección orders
:
sales> db.orders.insertOne({total: 50})MongoServerError[Unauthorized]: not authorized on sales to execute command { insert: "orders", documents: [ { total: 50, _id: ObjectId('67890a7d86d96a7e1dcb0ce2') } ], ordered: true, lsid: { id: UUID("f2005137-cf06-411a-8cae-5bd2e3d878c1") }, $db: "sales" }
Al asignar a roser
sólo el rol read
para esta base de datos, la orden insertOne
fallará con un mensaje de error.
A continuación, confirma si la roser
puede leer y escribir datos en la base de datos reports
:
sales> use reportsswitched to db reportsreports> db.reports.find()[ { _id: ObjectId('678833800c36be4e5fcb0ce2'), orders: 1 } ]reports> db.reports.insertOne({orders:2}){ acknowledged: true, insertedId: ObjectId('67890b2086d96a7e1dcb0ce3')}
Concesión y revocación de roles para usuarios existentes
Section titled “Concesión y revocación de roles para usuarios existentes”En la práctica, los administradores de bases de datos a menudo necesitan revocar o conceder nuevos privilegios a los usuarios que ya se han creado en su sistema.
A continuación, auténticate como el usuario root
,
reports> use adminswitched to db adminadmin> db.auth("root")Enter password********{ ok: 1 }
Concede permiso de sólo lectura a la laura
en la base de datos reports
:
admin> use salesswitched to db salessales> db.grantRolesToUser("laura", [{role: "read", db: "reports"}]){ ok: 1 }
Verifica los roles de la laura
:
sales> show users[ { _id: 'sales.laura', userId: UUID('f97f35ec-b6c9-4175-adef-7ddd1b3f47da'), user: 'laura', db: 'sales', roles: [ { role: 'readWrite', db: 'sales' }, { role: 'read', db: 'reports' } ], mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ] }]
Autentícate con el usuario laura
y verifica que puede acceder a la base de datos reports
después del cambio:
sales> db.auth("laura")Enter password********{ ok: 1 }sales> use reportsswitched to db reportsreports> db.reports.find()[ { _id: ObjectId('678833800c36be4e5fcb0ce2'), orders: 1 }, { _id: ObjectId('67890b2086d96a7e1dcb0ce3'), orders: 2 }]
Si al cabo de un tiempo quieres revocar la capacidad del usuario laura
para acceder a los informes, con el usuario root
elimina el permiso correspondiente:
...sales> db.revokeRolesFromUser("laura",[ {role:"read", db:"reports"} ]){ ok: 1 }
Verifica que la laura
ya no puede leer documentos de la base de datos reports
:
...reports> db.reports.find()MongoServerError[Unauthorized]: not authorized on reports to execute command { find: "reports", filter: {}, lsid: { id: UUID("55abd9f8-d8b1-479c-a7b2-cae6a4163505") }, $db: "reports" }
Roles definidos por el usuario
Section titled “Roles definidos por el usuario”Mediante el método createRole
, puedes crear un rol según tus necesidades.
Añade algunos productos a la base de datos sales
:
sales> db.products.insertMany( [{"name":"orange"}, {"name": "apple"}, {"name":"banana"}] )...
Cambia al usuario root
y crea un rol customer
en la base de datos sales
que pueda buscar y leer de la colección products
:
sales> db.createRole({... role: "customer",... privileges: [{... resource: { db: "sales", collection: "products"},... actions: [ "find"]... }],... roles: []... }){ ok: 1 }
Cuando añades un rol, creas el rol en una base de datos específica: MongoDB utiliza la combinación de la base de datos y el nombre del rol para definir de forma única un rol.
Más información en: User-Defined Roles on Self-Managed Deployments
En este enlace tienes la lista de acciones: Privilege Actions
Si miras la información de los roles de la base de datos sales
puedes ver que la propiedad isBuiltin
indica que el rol customer
está definido por el usuario.
sales> db.getRoles(){ roles: [ { _id: 'sales.customer', role: 'customer', db: 'sales', roles: [], isBuiltin: false, inheritedRoles: [] } ], ok: 1}
Este rol lo utilizarás para añadir clientes que puedan consultar la lista de productos de nuestra empresa:
sales> db.customers.find()[ { _id: ObjectId('67882f9242d68a24b1cb0ce3'), name: 'David' }, { _id: ObjectId('6789044acdca8d8d69cb0ce2'), name: 'Maria' }]
Por ejemplo, añade a maria
como usuario de la base de datos sales
:
sales> db.createUser( {... user: "maria",... pwd: passwordPrompt(),... roles: [ {role: "customer", db: "sales"} ]... })Enter password********{ ok: 1 }sales>
A continuación modifica el documento de Maria para registrar que tiene un usuario en la base de datos:
sales> db.customers.updateOne( {name: "Maria"}, { $set: {username: "maria"}} )...
Ahora Maria puedes consultar la lista de nuestros productos, pero ¿cómo puede crear una orden de compra?
Crea un rol maria
con el que pueda realizar acciones find
y insert
en la colección orders_maria
:
> db.createRole({... role: "maria",... privileges: [{... resource: {db: "sales", collection: "orders_maria"},... actions: [ "find", "insert" ]... }],... roles: ["customer"]... }){ ok: 1 }
Añade el rol maria
al usuario maria
:
sales> db.grantRolesToUser("maria", [{role: "maria", db: "sales"}]){ ok: 1 }
Como el rol maria
hereda los privilegios de customer
, puedes revocar el rol customer
al usuario maria
:
sales> db.revokeRolesFromUser("maria", [{ role:"customer", db: "sales"}]){ ok: 1 }
Autentícate como el usuario maria
:
sales> db.auth("maria")Enter password********{ ok: 1 }
Verifica que el usuario maria
puede buscar productos e insertar órdenes en la colección orders_maria
:
sales> db.products.find()[ { _id: ObjectId('67893a9520c44545d1cb0ce2'), name: 'orange' }, { _id: ObjectId('67893a9520c44545d1cb0ce3'), name: 'apple' }, { _id: ObjectId('67893a9520c44545d1cb0ce4'), name: 'banana' }]sales> db.orders_maria.insertOne({product: "orange", quantity: 5, price: 1.23 }){ acknowledged: true, insertedId: ObjectId('678946b720c44545d1cb0ce5')}
Verifica que el usuario maria
no puede insertar documentos en la colección orders
:
sales> db.orders.insertOne({product: "orange", quantity: 5, price: 1.23 })MongoServerError[Unauthorized]: not authorized on sales to execute command { insert: "orders", documents: [ { product: "orange", quantity: 5, price: 1.23, _id: ObjectId('6789477120c44545d1cb0ce6') } ], ordered: true, lsid: { id: UUID("51dc4213-8d64-4c2f-b5a2-8dd5a9d838a4") }, $db: "sales" }
Inmutabilidad
Section titled “Inmutabilidad”Si te fijas, los permisos de un usuario customer no permiten las acciones update
o remove
en su colección de órdenes.
Esto es importante porque ¿cómo podemos seguir todas las órdenes de todos los clientes?
Debemos permitir que los usuarios con el rol de customer insertan órdenes en la colección ordres
, pero nada más.
TODO
El contingut d'aquest lloc web té llicència CC BY-NC-ND 4.0.
©2022-2025 xtec.dev