Criando controle de acesso baseado em função no MongoDB
O MongoDB fornece acesso ao usuário por meio de controles baseados em função, incluindo muitas funções internas que podem ser atribuídas aos usuários. Os dois controles mais conhecidos são os papéis de leitura e leitura/gravação. No entanto, às vezes, eles não são tão granulares quanto gostaríamos que fossem.
Recentemente, tive a chance de explorar as funções definidas pelo usuário introduzidas no MongoDB versão 2.6. Neste artigo, veremos as funções definidas pelo usuário do MongoDB e definiremos algumas funções personalizadas que podem ser úteis.
-
Criar funções no MongoDB
Criar uma função definida pelo usuário no MongoDB é bastante simples. Você pode usar o comando createRole para criar uma nova função e a sintaxe genérica de criação de função é a seguinte:
{ createRole: "<role name>", privileges: [{ resource: { <resource> }, actions: [ "<action>",] }, ], roles: [ { role: "<role>", db: "<database>" } | "<role>",], writeConcern: <write concern document> }
Antes de executar o comando createRole, certifique-se de alternar para o banco de dados no qual deseja criar a função, pois eles só serão definidos no banco de dados em quais foram criados. Se você quiser criar uma função que conceda acesso a mais de um banco de dados, ela precisará ser criada no banco de dados do administrador.
Vamos examinar os principais componentes da sintaxe de criação de função.
-
Privilégios de função
Crie permissões para uma função definida pelo usuário adicionando um privilégio e definindo suas ações e recursos:
Ações de privilégio
As ações são um conjunto de operações agrupadas, como a ação de inserção que pode executar inserir e criar. As ações são tão granulares quanto o controle de acesso baseado em função do MongoDB. O parâmetro de privilégios pode ser usado para adicionar funções às ações do mongo, e um privilégio constitui as ações junto com o recurso ao qual se aplica. Use o seguinte para adicionar as ações localizar, inserir e atualizar no banco de dados “mydb”.
privileges: [ {resource: {db: "mydb", collection: "" }, actions: [ “find”,”insert”,”update” ] } ]
Recursos de privilégio
O documento do recurso especifica o escopo ao qual suas ações de privilégio serão aplicadas e pode ser definido em várias granularidades da seguinte forma:
a. Coleção
O recurso pode ser definido como resource:
{db: "<db-name>", collection: "<collection name>" }
para conceder as ações especificadas apenas a essa coleção específica.
b. Banco de dados
O recurso pode ser definido para um banco de dados específico deixando o parâmetro de coleção vazio. Recurso de string de recurso:
{db: "<db-name>", collection: "<collection name>" }
define o escopo para todo o banco de dados.
c. Coleção única em bancos de dados
O recurso pode ser definido para uma coleção específica usando resource:
{db: ", collection: "<collection name>" }
para conceder permissões à coleção em todos os bancos de dados. Esta permissão só pode ser adicionada a uma função criada no banco de dados do administrador.
d. Várias coleções em bancos de dados
O recurso pode ser definido para todas as coleções (exceto as coleções do sistema) em todos os bancos de dados, deixando os parâmetros db e collection vazio. recurso:
{db: "", collection: "" }
. Este recurso, como o acima, só pode ser concedido em uma função criada no banco de dados do administrador.
e. Recurso de todo o cluster
Um recurso de todo o cluster pode ser especificado usando resource:
{ cluster : true }
. Esse recurso em todo o cluster é usado para especificar o estado do sistema, como desligamento replSetReconfig em vez de conceder permissões em qualquer documento específico.
f. Todos os recursos
Não é recomendado usar este escopo para nada além de circunstâncias extraordinárias.
{anyResource: true }
pode ser usado para definir o escopo definido para todos os recursos.
-
Funções
As funções incorporadas também podem ser adicionadas a uma função personalizada. Quando uma função incorporada é adicionada usando o parâmetro roles:[], ele adiciona as permissões da função incorporada à função personalizada.
Aqui está um exemplo do parâmetro roles:
roles: [{ role: "read", db: "&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;db name&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;"}]
Neste exemplo, a função personalizada herdaria todas as permissões da função “ler” sobre o banco de dados definido. Se uma função for herdada em um banco de dados db1, a função personalizada poderá ser criada no banco de dados db1 ou no banco de dados admin.
Escreva uma preocupação
A preocupação de gravação define o nível de confirmação solicitada do MongoDB e pode ser usada para controlar as confirmações de gravação do banco de dados. Observe que uma preocupação de gravação não é necessária ao criar uma função. A preocupação de gravação pode incluir os campos w, j e wtimeout:
W - Escrever preocupação
O campo W pode ser usado para indicar o número de instâncias para as quais a gravação foi propagada.
J - Escrever preocupação
O campo J pode ser definido para determinar se a gravação é gravada no diário.
Wtimeout - Write Concern
Isso é usado para definir o tempo em que a gravação deve atingir a preocupação de gravação. A preocupação de gravação ainda pode ser alcançada após o erro ser lançado. Se um Wtimeout não tiver sido definido e o problema de gravação não puder ser alcançado, a gravação será bloqueada indefinidamente.
-
Atribuindo funções
As funções personalizadas são específicas do banco de dados e só podem ser atribuídas a um usuário no mesmo banco de dados.
Digamos que criamos uma função “myrole” no banco de dados “db1”. Podemos criar um usuário no banco de dados usando os seguintes comandos:
Use db1 db.createUser({"user" : "&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;user&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;",pwd: "&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;password&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;","roles" : [{"role" : "myrole", "db" : "db1"}]})
Para mais informações sobre gerenciamento de usuários, consulte esta postagem de Dharshan sobre gerenciamento de usuários no MongoDB.
-
Funções de usuário personalizadas
Vamos analisar algumas funções personalizadas que podem ser úteis.
Banco único – Permissões de leitura, inserção e atualização
As funções incorporadas read e readWrite às vezes podem parecer permissões demais ou de menos. Vamos ver como podemos criar uma função personalizada concedendo apenas permissões de leitura, inserção e gravação.
Já sabemos que precisamos de todas as permissões de leitura para que possamos adicionar a função incorporada “read” à nossa função personalizada. Também precisamos de permissões para criar e atualizar documentos, e isso pode ser incluído adicionando ações de privilégio inserir e atualizar. Se quisermos dar ao usuário a capacidade de criar índice e criar coleção, podemos adicionar a ação de privilégio createIndex e createCollection.
Para o escopo, vamos supor que eu tenha um banco de dados chamado “db1” no qual defini as permissões acima. O comando create ficaria assim:
Use db1. db.createRole( { createRole: "&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;role-name&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;", privileges: [ { resource: { db: "db1", collection: "" }, actions: [ "insert","update","createIndex", "createCollection" ] } ], roles: [{ role: "read", db: "db1"}] })
O comando acima criaria uma função com
<role-name>
no banco de dados db1. Um usuário que recebeu permissão da função acima não terá a ação de privilégio "remover". Além disso, observe que os métodos db.collection.findAndModify(), db.collection.mapReduce() e db.collection.aggregate() não podem ser executados integralmente, pois exigem o privilégio de remoção.
Todos os bancos de dados – permissões de leitura, inserção e atualização
Podemos criar uma função no banco de dados admin semelhante à acima, para conceder privilégios de leitura, criação e atualização em todos os bancos de dados. Essa função deve ser criada no banco de dados admin e o usuário subsequente também deve ser criado no banco de dados admin.
Para essa função, em vez de usar a função de leitura padrão, podemos herdar permissões da função readAnyDatabase. A criação da função seria algo assim:
Use admin. db.createRole( { createRole: "&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;role-name&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;", privileges: [ { resource: { db: "", collection: "" }, actions: [ "insert","update","createIndex", "createCollection" ] } ], roles: [{ role: "readAnyDatabase", db: "admin"}] })
Funções de escritor com preocupação de gravação
Se você tiver um cenário em que a preocupação com a gravação precise ser aplicada, veja como ela pode ser adicionada a uma função. Adicionar preocupação de gravação a uma função a imporia a todos os usuários concedidos sob essa função no banco de dados. Vamos definir um papel com uma preocupação de gravação que impõe gravações majoritárias:
Use admin. db.createRole( { createRole: "&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;role-name&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;", privileges: [ ], roles: [{ role: "readWriteAnyDatabase", db: "admin"}], writeConcern: { w: “majority”, j: false, wtimeout: 300 } })