Least-privilege users and roles

TeselaDB

TeselaDB

TeselaDB team

25 minIntermediate

Create a role that reads and writes one collection without deleting from it and give it to an application's user.

An application that only creates and updates orders does not need to delete them or to read other collections. With a custom role you give it only those actions on that collection, so if its password leaks, whoever uses it cannot do more than the application could.

What you will build

An ordersWriter role with the find, insert and update actions on the shop.orders collection, and a shop-orders user that only has that role.

Requirements

  • A TeselaDB cluster and mongosh.
  • A user allowed to create roles and users, such as root.

1. Create the role

Each privilege joins a resource, here a collection, with the actions allowed on it:

JavaScript
db.getSiblingDB("admin").createRole({
  role: "ordersWriter",
  privileges: [{ resource: { db: "shop", collection: "orders" }, actions: ["find", "insert", "update"] }],
  roles: [],
});

2. Create the user

The user has only the ordersWriter role. passwordPrompt() asks for the password without leaving it in the mongosh history:

JavaScript
db.getSiblingDB("admin").createUser({ user: "shop-orders", pwd: passwordPrompt(), roles: ["ordersWriter"] });

Try it

Connected as shop-orders, try an insert and a delete on shop.orders, knowing that the role carries the insert action but none that deletes documents, so only the first of the two writes below can work:

JavaScript
const shop = db.getSiblingDB("shop");
shop.orders.insertOne({ total: 30 });
shop.orders.deleteOne({});

The insert works and the delete fails with Unauthorized, the same error you get if you try to read another collection of shop.

Clean up

If it was a test, drop the user and the role while connected as root:

JavaScript
db.getSiblingDB("admin").dropUser("shop-orders");
db.getSiblingDB("admin").dropRole("ordersWriter");

Next steps