MongoDB: Privileges on objects created by me only

mongodbpermissions

Is it possible to define a custom role, or otherwise assign privileges to allow a user read/write access only on objects that they have created?

Imagine 3 applications, each having its own login. For example: The recipe_app uses recipe_user to access the MongoDB store, and the lizard_app uses lizard_user to do the same. Part of the way the applications work is that they create and drop their own databases as necessary.

At any given time there may be only a northern_recipe database, a southern_recipe database, and a western_lizard database, or only an eastern_recipe database and a northern_lizard database (or any other permutation), and what will exist when is not foreknown.

Is it possible to set up recipe_user's privileges to only be able to read/write the recipe_* databases? Let's assume that the naming conventions stay as consistent as those in the example.

I thought about adding a tag with the creating user's name to each collection on import, and then a "redaction" filter to limit its access, but I don't like

  1. that what I want to filter on is properly metadata, and shouldn't be mixed in with the data, and
  2. that it's not really addressing the issue at the database level.

UPDATE: Inspired by this question about dropping collections based on a regex, I'm thinking running an admin script like this on a regular basis would achieve what I want, but with some delay between a database's creation and effecting the grant. (Please note this is tested but makes no presumption of being optimized.)

db.runCommand({listDatabases:1})['databases'].forEach(
  function(d) {
    if (d.name.match(/lizard$/)) {     
      db.grantRolesToUser(
        "lizard_user",
        [ {role: "readWrite", db: d.name} ]
      )
    }
  }
)

MongoDB 3.4.0

Best Answer

A database does not need to exist at the time you grant a user permissions on it.

So the solution to this is simply to pre-grant a superset of all permissions you expect might be needed in the future. Then they will just sit there unless and until needed.

In my case the list of permissions needed changes fairly frequently, but the prefix-style patterns are predictable. (Namely, the user's name matches the first part of its databases' names.) So I use a config file like this, to which I add entries before they are needed. The script runs regularly, and grants new permissions, which just sit there until they are actually used.

[ { 'replica_set' : 'cluster0',
    'members' : [ 'server0', 'server1', ... 'serverN' ],
    'permissions' : [ 'user' : 'lizard_user', 'db_patterns' : [ 'lizard_' ] },
    ...
  },
  { 'replica_set' : 'cluster1',
  ...
  }
]

I'm posting this workaround primarily to note the misconception I had about granting permissions on not-yet-existent objects, in case others share it. It would still be cool if there were a privilege like 'readWriteAllMyDatabases'.