Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Junte-se a nós no Amazon Web Services re:Invent 2024! Saiba como usar o MongoDB para casos de uso de AI .
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
Atlaschevron-right

MongoDB Atlas com Terraform: usuários do banco de dados e Vault

SM
Samuel Molling8 min read • Published Apr 15, 2024 • Updated Apr 15, 2024
TerraformAtlas
APLICATIVO COMPLETO
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Neste tutorial, mostrarei como criar um usuário para o MongoDB database no MongoDB Atlas usando o Terraform e como armazenar essa credencial com segurança no HashiCorp Vault. Vimos no artigo anterior, MongoDB Atlas With Terraform - Cluster and Backup Políticas, como criar um cluster com políticas de backup configuradas. Agora, Go e criaremos nosso primeiro usuário. Se você não leu os artigos anteriores, sugerimos que você procure para entender como começar.
Este artigo é para qualquer pessoa que pretende usar ou já usa infraestrutura como código (IaC) na plataforma MongoDB Atlas ou deseja saber mais sobre ela.
Tudo o que fazemos aqui está contido na documentação do provedor/recurso:
Observação: não usaremos um arquivo de backend. No entanto, para implementações produtivos, é extremamente importante e seguro armazenar o arquivo de estado em um local remoto, como S3, GCS, Azurermetc.

Criando um usuário

Neste ponto, criaremos nosso primeiro usuário usando Terraform no MongoDB Atlas e armazenaremos o URI para se conectar ao meu cluster no HashiCorp Vault. Para quem não conhece, o HashiCorp Vault é uma ferramenta de gerenciamento de segredos que permite armazenar, acessar e gerenciar com segurança credenciais confidenciais, como senhas, chaves de API, certificados e muito mais. Ele foi projetado para ajudar as organizações a proteger seus dados e infraestrutura em ambientes de Tl complexos e distribuídos. Nela, armazenaremos o URI de conexão do usuário que será criado com o cluster que criamos no último artigo.
Antes de começarmos, certifique-se de que todos os pré-requisitos mencionados no artigo anterior estejam configurados corretamente: Instalar o Terraform, criar uma chave de API no MongoDB Atlas e configurar um projeto e um cluster no Atlas. Estas etapas são essenciais para garantir o sucesso da criação do seu usuário do banco de dados.

Configurando o HashiCorp Vault para ser executado no Docker

O primeiro passo é executar o HashiCorp Vault para que possamos testar nosso módulo. É possível executar o Vault no Docker Local. Se você não tiver o Docker instalado, poderá baixá-lo. Depois de baixar o Docker, baixaremos a imagem que queremos executar — neste caso, do Vault. Para fazer isso, executaremos um comando no terminal docker pull vault:1.13.3 ou fará o download usando o Docker Desktop.
Procurando a imagem no docker
Agora, criaremos um container a partir desta imagem. Clique na imagem e clique em Executar. Depois disso, uma caixa será aberta onde só precisamos mapear a porta do nosso computador para o container. Nesse caso, usarei a porta 8200 , que é a porta padrão do Vault. Clique em Executar.
Tela para configurar a porta do docker
O contêiner começará a ser executado. Se formos ao nosso navegador e inserirmos a URL localhost:8200/, a tela de login do Vault aparecerá.
Tela de login do Vault
Para acessar o Vault, usaremos o Token Raiz que é gerado quando criarmos o container.
Tela de registro contendo token
Agora, vamos fazer login. Após a abertura, criaremos um novo motor do tipo KV apenas para ilustrá-lo um pouco melhor. Clique em Secrets Engines -> Enable new Engine -> Generic KV e clique em Next.
Tela de seleção do mecanismo de segredos
Em Path coloque kv/my_app e clique em Enable Engine. Agora temos nosso Vault configurado e funcionando.

Configuração do provedor de Terraform para MongoDB Atlas e HashiCorp Vault

A próxima etapa é configurar o provedor Terraform. Isso permitirá que o Terraform se comunique com a API MongoDB Atlas and Vault para gerenciar recursos. Adicione o seguinte bloco de código ao seu arquivo providers.tf:
1provider "mongodbatlas" {}
2provider "vault" {
3 address = "http://localhost:8200"
4 token = "hvs.brmNeZd31NwEmyky1uYI2wvY"
5 skip_child_token = true
6}
No artigo anterior, configuramos o provedor Terraform colocando nossas chaves públicas e privadas em variáveis de ambiente. Continuaremos desta forma. Adicionaremos um novo provedor, o Vault. Nele, configuraremos o endereço do Vault, o token de autenticação e o parâmetro skip_child_token para que possamos nos autenticar no Vault.
Observação: não é aconselhável especificar o token de autenticação em um ambiente de produção. Use um dos métodos de autenticação recomendados pela HashiCorp, como app_role. Você pode avaliar as opções nos Docs do Terraform

Criando o arquivo de versão do Terraform

O arquivo de versão continua tendo a mesma finalidade, conforme mencionado em outros artigos, mas adicionaremos a versão do provedor do Vault como algo novo.
1terraform {
2 required_version = ">= 0.12"
3 required_providers {
4 mongodbatlas = {
5 source = "mongodb/mongodbatlas"
6 version = "1.14.0"
7 }
8 vault = {
9 source = "hashicorp/vault"
10 version = "4.0.0"
11 }
12 }
13}

Definindo o usuário do banco de dados e o recurso do cofre

Depois de configurar o arquivo de versão e estabelecer as versões do Terraform e do provedor, a próxima etapa é definir o recurso do usuário no MongoDB Atlas. Isso é feito criando um arquivo .tf arquivo — por exemplo, main.tf — onde criaremos nosso módulo. Como criaremos um módulo que será reutilizável, usaremos variáveis e valores padrão para que outras chamadas possam criar usuários com permissões diferentes, sem precisar escrever um novo módulo.
1# ------------------------------------------------------------------------------
2# RANDOM PASSWORD
3# ------------------------------------------------------------------------------
4resource "random_password" "default" {
5 length = var.password_length
6 special = false
7}
8
9# ------------------------------------------------------------------------------
10# DATABASE USER
11# ------------------------------------------------------------------------------
12resource "mongodbatlas_database_user" "default" {
13 project_id = data.mongodbatlas_project.default.id
14 username = var.username
15 password = random_password.default.result
16 auth_database_name = var.auth_database_name
17
18 dynamic "roles" {
19 for_each = var.roles
20 content {
21 role_name = try(roles.value["role_name"], null)
22 database_name = try(roles.value["database_name"], null)
23 collection_name = try(roles.value["collection_name"], null)
24 }
25 }
26
27 dynamic "scopes" {
28 for_each = var.scope
29 content {
30 name = scopes.value["name"]
31 type = scopes.value["type"]
32 }
33 }
34
35
36 dynamic "labels" {
37 for_each = local.tags
38 content {
39 key = labels.key
40 value = labels.value
41 }
42 }
43}
44
45resource "vault_kv_secret_v2" "default" {
46 mount = var.vault_mount
47 name = var.secret_name
48 data_json = jsonencode(local.secret)
49}
No início do arquivo, temos o recurso random_password que é usado para gerar uma senha aleatória para o nosso usuário. No recurso mongodbatlas_database_user, especificaremos nossos detalhes de usuário. Estamos colocando alguns valores como variáveis, como feito em outros artigos, como nome e auth_database_name com um valor padrão de admin. Abaixo, criamos três blocos dinâmicos: funções, escopos e rótulos. Para roles, é uma lista de mapas que podem conter o nome da role (read, readWrite ou algum outro), o database_name e o collection_name. Esses valores podem ser opcionais se você criar um usuário com permissão atlasAdmin, como neste caso, não. É necessário especificar um banco de dados ou uma collection ou, se você quiser, especificar apenas o banco de dados e não uma collection específica. Faremos um exemplo. Para o bloco de escopos, o tipo é DATA_LAKE ou CLUSTER. No nosso caso, especificaremos um cluster, que é o nome do nosso cluster criado, o cluster de demonstração. E os rótulos servem como tags para o nosso usuário.
Finalmente, definimos o recurso vault_kv_secret_v2 que criará um segredo em nosso Vault. Ele recebe o monte onde será criado e o nome do segredo. O data_json é o valor do segredo; estamos criando-o no arquivo locals.tf que avaliaremos abaixo. É um valor JSON — é por isso que o estamos codificando.
No arquivo variable.tf, criamos variáveis com valores padrão:
1variable "project_name" {
2 description = "The name of the Atlas project"
3 type = string
4}
5
6variable "cluster_name" {
7 description = "The name of the Atlas cluster"
8 type = string
9}
10
11variable "password_length" {
12 description = "The length of the password"
13 type = number
14 default = 20
15}
16
17variable "username" {
18 description = "The username of the database user"
19 type = string
20}
21
22variable "auth_database_name" {
23 description = "The name of the database in which the user is created"
24 type = string
25 default = "admin"
26}
27
28variable "roles" {
29 description = <<HEREDOC
30 Required - One or more user roles blocks.
31 HEREDOC
32 type = list(map(string))
33}
34
35variable "scope" {
36 description = "The scopes to assign to the user"
37 type = list(object({
38 name = string
39 type = string
40 }))
41 default = []
42}
43
44variable "labels" {
45 type = map(any)
46 default = null
47 description = "A JSON containing additional labels"
48}
49
50variable "uri_options" {
51 type = string
52 default = "retryWrites=true&w=majority&readPreference=secondaryPreferred"
53 description = "A string containing additional URI configs"
54}
55
56variable "vault_mount" {
57 description = "The mount point for the Vault secret"
58 type = string
59}
60
61variable "secret_name" {
62 description = "The name of the Vault secret"
63 type = string
64}
65
66variable "application" {
67 description = <<HEREDOC
68 Optional - Key-value pairs that tag and categorize the cluster for billing and organizational purposes.
69 HEREDOC
70 type = string
71}
72
73variable "environment" {
74 description = <<HEREDOC
75 Optional - Key-value pairs that tag and categorize the cluster for billing and organizational purposes.
76 HEREDOC
77 type = string
78}
Configuramos um arquivo chamado locals.tf com os valores do nosso Vault e as marcações que foram criadas, como o último artigo. O interessante aqui é que estamos definindo como a connection string do nosso usuário será montada e salva no Vault. Também não foi possível salvar o nome de usuário e a senha, mas eu pessoalmente preferi salvar o URI. Dessa forma, posso especificar algumas boas práticas, como definir tags de conexão, como readPreference, sem depender do desenvolvedor para colocá-las no aplicativo. No código abaixo, existem alguns tratados de texto para que o URI esteja correto. No final, crio uma variável chamada segredo que possui uma chave de URI e recebe o valor do URI criado.
1locals {
2 private_connection_srv = data.mongodbatlas_advanced_cluster.default.connection_strings.0.standard_srv
3 cluster_uri = trimprefix(local.private_connection_srv, "mongodb+srv://")
4 private_connection_string = "mongodb+srv://${mongodbatlas_database_user.default.username}:${random_password.default.result}@${local.cluster_uri}/${var.auth_database_name}?${var.uri_options}"
5
6 secret = { "URI" = local.private_connection_string }
7
8 tags = {
9 name = var.application
10 environment = var.environment
11 }
12}
Neste artigo, adotamos o uso de fontes de dados no Terraform para estabelecer uma conexão dinâmica com os recursos existentes, como nosso projeto MongoDB Atlas e nosso cluster. Especificamente, no arquivo data.tf, definimos uma fonte de dados, mongodbotlas_project e mongodcatlas_advanced_cluster, para acessar informações sobre um projeto e cluster existentes com base em seu nome:
1data "mongodbatlas_project" "default" {
2 name = var.project_name
3}
4
5
6data "mongodbatlas_advanced_cluster" "default" {
7 project_id = data.mongodbatlas_project.default.id
8 name = var.cluster_name
9}
Finalmente, definimos nosso arquivo de variáveis, terraform.tfvars:
1project_name = "project-test"
2username = "usr_myapp"
3application = "teste-cluster"
4environment = "dev"
5cluster_name = "cluster-demo"
6
7roles = [{
8 "role_name" = "readWrite",
9 "database_name" = "db1",
10 "collection_name" = "collection1"
11 }, {
12 "role_name" : "read",
13 "database_name" : "db2"
14}]
15
16scope = [{
17 name = "cluster-demo",
18 type = "CLUSTER"
19}]
20
21secret_name = "MY_MONGODB_SECRET"
22vault_mount = "kv/my_app"
Estes valores definidos em terraform.tfvars são utilizados pelo Terraform para preencher variáveis correspondentes em sua configuração. Nele, estamos especificando o escopo do usuário, os valores do Vault e as funções do usuário. O usuário terá permissão de leitura e gravação no banco de dados1 na collection1 e permissão de leitura no banco de dados2 em todas as collections do cluster de demonstração.
A estrutura do arquivo é a seguinte:
  • main.tf: Neste arquivo, definiremos o recurso principal, o mongodbatlas_database_user e o vault_kv_secret_v2, junto com uma geração aleatória de senhas. Aqui, você configurou o cluster e as rotinas de backup.
  • provider.tf: É neste arquivo que definimos o provedor que estamos usando, no nosso caso, mongodbotlas e Vault.
  • terraform.tfvars: Este arquivo contém as variáveis que serão usadas em nosso módulo — por exemplo, o nome do usuário e as informações do Vault, entre outras.
  • variable.tf: Aqui, definimos as variáveis mencionadas no arquivo terraform.tfvars, especificando o tipo e, opcionalmente, um valor padrão.
  • version.tf: Este arquivo é usado para especificar a versão do Terraform e os fornecedores que estamos usando.
  • data.tf: Aqui, especificamos uma fonte de dados que nos trará informações sobre nosso projeto e o cluster criado. Faremos a pesquisa do Atlas por seu nome e para nosso módulo, ele nos fornecerá o ID do projeto e as informações do cluster, como sua connection string.
  • locals.tf: Especificamos tags de exemplo a serem usadas em nosso usuário e tratamento para criar o URI no Vault.
Agora é a hora de se inscrever. =D
Executamos um Terraform init no terminal na pasta onde os arquivos estão localizados para que ele baixe os provedores, módulos, etc...
Observação: lembre-se de exportar as variáveis de ambiente com a chave pública e privada.
1export MONGODB_ATLAS_PUBLIC_KEY="your_public_key"
2export MONGODB_ATLAS_PRIVATE_KEY=your_private_key"
Agora, executamos init e depois planejamos, como nos artigos anteriores.
Avaliamos que nosso plano é exatamente o que esperamos e executamos a aplicação para criá-lo.
Ao executar o comandoterraform apply, você será solicitado para aprovação com yes ou no. Digite yes.
Agora, vejamos no Atlas se o usuário foi criado com sucesso...
Usuário exibido no acesso ao banco de dados
Permissões de acesso exibidas
Vamos também dar uma olhada no Vault para ver se nosso segredo foi criado.
URI secreto do MongoDB
Foi criado com sucesso! Agora, vamos testar se o URI está funcionando perfeitamente.
Este é o formato do URI que é gerado: mongosh "mongodb+srv://usr_myapp:<password>@<clusterEndpoint>/admin?retryWrites=true&majority&readPreference=secondaryPreferred"
Login do Mongosh
Conectamos e faremos uma inserção para avaliar se as permissões são adequadas — inicialmente, em db1 em collection1.
Comando a ser inserido no banco de dados e confirmado
Sucesso! Agora, no db3, verifique se ele não terá permissão em outro banco de dados.
Acesso negado a collection não autorizada Excelent — permissão negada, como esperado.
Chegamos ao final desta série de artigos sobre MongoDB. espero que tenham sido úteis para você e para você!
Para saber mais sobre o MongoDB e várias ferramentas, Convido você a visitar o Centro do Desenvolvedor para ler os outros artigos.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Exemplo de código

Blogue


Sep 11, 2024 | 1 min read
Tutorial

Primeiro passos na segurança do Atlas Stream Processing


May 17, 2024 | 9 min read
Tutorial

Como distribuir um aplicativo no Kubernetes com o MongoDB Atlas Operator


Aug 30, 2024 | 9 min read
Artigo

Como trabalhar com os dados da Johns Hopkins University sobre COVID-19 no MongoDB Atlas


Sep 09, 2024 | 8 min read
Sumário