Como proteger o acesso aos dados do MongoDB com o Views
Avalie esse Artigo
Às vezes, as collection do MongoDB contêm informações confidenciais que exigem controle de acesso. Usando o RBAC ( Controle de Acesso Baseado em Funçãofornecido pelo MongoDB, é fácil restringir o acesso a essa collection. Mas e se você quiser compartilhar sua collection com um público mais amplo sem expor dados confidenciais?
Por exemplo, pode ser interessante compartilhar suas collection com a equipe de marketing para fins de análise sem compartilhar informações de identificação pessoal (PII) ou dados que você prefere manter privados, como os salários dos funcionários.
É possível alcançar esse resultado com visualizações MongoDB combinadas com o MongoDB RBAC, e é isso que vamos explorar nesta publicação do blog.
Você precisará de:
- Um cluster MongoDB com autenticação ativada (que é recomendado em produção!).
- Um cluster do MongoDB Atlas.
Presumirei que você já tem um usuário administrador em seu cluster com autorizações completas ou pelo menos um usuário que pode criar visualizações e funções personalizadas. e usuários. Se você estiver no Atlas, você pode criar este usuário na aba
Database Access
ou utilizaro MongoDB Shell, como este:1 mongosh "mongodb://localhost/admin" --quiet --eval "db.createUser({'user': 'root', 'pwd': 'root', 'roles': ['root']});"
Então você pode se conectar com a linha de comando fornecida no Atlas ou assim, se você não estiver no Atlas:
1 mongosh "mongodb://localhost" --quiet -u root -p root
Neste exemplo, simularei ter uma collection
employees
com dados confidenciais:1 db.employees.insertMany( 2 [ 3 { 4 _id: 1, 5 firstname: 'Scott', 6 lastname: 'Snyder', 7 age: 21, 8 ssn: '351-40-7153', 9 salary: 100000 10 }, 11 { 12 _id: 2, 13 firstname: 'Patricia', 14 lastname: 'Hanna', 15 age: 57, 16 ssn: '426-57-8180', 17 salary: 95000 18 }, 19 { 20 _id: 3, 21 firstname: 'Michelle', 22 lastname: 'Blair', 23 age: 61, 24 ssn: '399-04-0314', 25 salary: 71000 26 }, 27 { 28 _id: 4, 29 firstname: 'Benjamin', 30 lastname: 'Roberts', 31 age: 46, 32 ssn: '712-13-9307', 33 salary: 60000 34 }, 35 { 36 _id: 5, 37 firstname: 'Nicholas', 38 lastname: 'Parker', 39 age: 69, 40 ssn: '320-25-5610', 41 salary: 81000 42 } 43 ] 44 )
Agora quero compartilhar essa coleção com um público mais amplo, mas não quero compartilhar os números do seguro social e os salários.
Para resolver esse problema, posso criar uma visualização com um
$project
estágio que permite apenas um conjunto de campos selecionados.1 db.createView('employees_view', 'employees', [{$project: {firstname: 1, lastname: 1, age: 1}}])
Observe que não estou fazendo
{$project: {ssn: 0, salary: 0}}
porque todos os campos, exceto esses dois, apareceriam na visualização. Funciona hoje, mas talvez amanhã adicione um campocredit_card
em alguns documentos. Em seguida, ele apareceria instantaneamente na visualização.Vamos confirmar se a visualização funciona:
1 db.employees_view.find()
Resultado:
1 [ 2 { _id: 1, firstname: 'Scott', lastname: 'Snyder', age: 21 }, 3 { _id: 2, firstname: 'Patricia', lastname: 'Hanna', age: 57 }, 4 { _id: 3, firstname: 'Michelle', lastname: 'Blair', age: 61 }, 5 { _id: 4, firstname: 'Benjamin', lastname: 'Roberts', age: 46 }, 6 { _id: 5, firstname: 'Nicholas', lastname: 'Parker', age: 69 } 7 ]
Dependendo do design do esquema e de como você deseja filtrar os campos, pode ser mais fácil usar $unset em vez de $project. Você pode saber mais no Practical MongoDB Aggregations Book. Mas, novamente,
$unset
apenas removerá os campos especificados sem filtrar novos campos que podem ser adicionados no futuro.Agora que temos nossa visualização, podemos compartilhá-la com direitos de acesso restritos. No MongoDB, precisamos criar uma função personalizada para conseguir isso.
Aqui estão as linhas de comando se você não estiver no Atlas.
1 use admin 2 db.createRole( 3 { 4 role: "view_access", 5 privileges: [ 6 {resource: {db: "test", collection: "employees_view"}, actions: ["find"]} 7 ], 8 roles: [] 9 } 10 )
Então podemos criar o usuário:
1 use admin 2 db.createUser({user: 'view_user', pwd: '123', roles: ["view_access"]})
Se você estiver no Atlas, o acesso ao banco de dados será gerenciado diretamente no site do Atlas, na guia
Database Access
. Você também pode usar o Atlas CLI se desejar.Então você precisa criar uma função personalizada.
Observação: Na etapa 2, selecionei apenas a opção Ações decollection > Ações de consulta e gravação > localizar.
Agora que sua função foi criada, volte para a guia
Database Users
e crie um usuário com essa função personalizada.Agora que nosso usuário foi criado, podemos confirmar que esse novo usuário restrito não tem acesso à coleção subjacente, mas tem acesso à visualização.
1 $ mongosh "mongodb+srv://hidingfields.as3qc0s.mongodb.net/test" --apiVersion 1 --username view_user --quiet 2 Enter password: *** 3 Atlas atlas-odym8f-shard-0 [primary] test> db.employees.find() 4 MongoServerError: user is not allowed to do action [find] on [test.employees] 5 Atlas atlas-odym8f-shard-0 [primary] test> db.employees_view.find() 6 [ 7 { _id: 1, firstname: 'Scott', lastname: 'Snyder', age: 21 }, 8 { _id: 2, firstname: 'Patricia', lastname: 'Hanna', age: 57 }, 9 { _id: 3, firstname: 'Michelle', lastname: 'Blair', age: 61 }, 10 { _id: 4, firstname: 'Benjamin', lastname: 'Roberts', age: 46 }, 11 { _id: 5, firstname: 'Nicholas', lastname: 'Parker', age: 69 } 12 ]
Nesta publicação do blog, você aprendera a compartilhar suas coleções do MongoDB com um público mais amplo, mesmo os mais críticos, sem expor dados confidenciais.
Observe que as visualizações podem usar os índices da collection de origem para que seu usuário restrito possa aproveitá-los para consultas mais avançadas.
Você também pode optar por adicionar um estágio
$match
extra antes do estágio $project para filtrar documentos inteiros para que não apareçam na visualização. Você pode ver um exemplo no Practical MongoDB Aggregations Book. E não se lembre de apoiar o $match
com um índice!