0

I am am using ansible to add admin user in mongodb.. I used below playbook but i am getting error. Can someone suggest the solution.. i have also installed pymongo prior to adding user in order to use module. authentication is disabled in mongod.conf and bindIp is set to 0.0.0.0

- hosts: devqa_mongod_single:dwprod_mongod_single
  become: yes
  vars_files:
    - ../../vars/vars_secrets.yaml

  vars: 
    password: "mongoadmin"
    mongoAuth: "/usr/bin/mongosh 'mongodb://admin:{{ password | urlencode() }}@localhost:27017/admin?authSource=admin' --norc --quiet"
    mongoNoAuth: "/usr/bin/mongosh 'mongodb://localhost:27017/admin' --norc --quiet"
  
  tasks:
    # volume config for mongodb
    - name: Create a new xfs primary partition
      community.general.parted:
        device: /dev/nvme1n1
        number: 1
        state: present
        fs_type: xfs
        label: gpt

    - name: Create an xfs filesystem on /dev/nvme1n1
      community.general.filesystem:
        fstype: xfs
        state: present
        dev: /dev/nvme1n1p1

    - name: Create Directory /data/db
      ansible.builtin.file:
        path: /data/db
        state: directory
        owner: root
        group: root
        mode: 0751

    - name: Fetch the UUID of /dev/nvme1n1p1 
      command: blkid -s UUID -o value /dev/nvme1n1p1 
      changed_when: false
      register: blkid_out
           
    - name: Mount /dev/nvme1n1 by UUID 
      ansible.posix.mount:
        path: /data/db
        src: UUID={{ blkid_out.stdout }}
        fstype: xfs
        opts: "defaults,nofail"
        passno: 2
        state: mounted
 
  # Installation of mongodb
    - name: Install aptitude using apt
      apt: 
        name: aptitude 
        state: latest 
        update_cache: yes 
    
    - name: Import public key
      apt_key:
        url: 'https://www.mongodb.org/static/pgp/server-6.0.asc'
        state: present
    
    - name: Add repository
      apt_repository:
        filename: '/etc/apt/sources.list.d/mongodb-org-6.0.list'
        repo: 'deb https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/6.0 multiverse'
        state: present
        update_cache: yes
    
    - name: Install mongoDB
      apt: 
        name: mongodb-org
        state: present
        update_cache: yes 
      notify:
        - restart mongodb  
    
    - name: Recursively change ownership of a /data/db
      ansible.builtin.file:
        path: /data/db
        state: directory
        recurse: yes
        owner: mongodb
        group: mongodb
      notify:
        - restart mongodb
    
    - name: Create Directory /var/run/mongodb
      ansible.builtin.file:
        path: /var/run/mongodb
        state: directory
        owner: mongodb
        group: mongodb
        mode: 0751
      notify:
        - restart mongodb

    - name: Ensure mongodb is running and and enabled to start automatically on reboots
      service: 
        name: mongod 
        enabled: yes
        state: started

  # Installing pymongo to use community.mongodb.mongodb_user module      
    - name: "Install PyMongo"
      apt:
        update_cache: yes
        name: "python3-pymongo"
        state: "latest"    
  
  # copy temorary config file
    - name: user_init | set temporary conf
      become: yes
      timeout: 300
      ansible.builtin.copy:
        src: ../templates/mongodb/mongod_init.conf.j2
        dest: /etc/mongod.conf
        owner: root
        group: root
        mode: '0644'
      notify:
        - restart mongodb   

  # Adding root user
    - name: Check if authentication is enabled
      shell: 
        cmd: "{{ mongoAuth }} --eval 'db.getMongo()'"
        executable: /bin/bash
      register: authenticate 
      failed_when: false 
      changed_when: false
      check_mode: no 

    - name: Create users
      shell: 
        cmd: "{{ (authenticate.rc == 0) | ternary(mongoAuth, mongoNoAuth) }} --eval '{{ js }}'"
        executable: /bin/bash
      vars: 
        js: |
          admin = db.getSiblingDB("admin")
          {% if authenticate.rc != 0 %}
          admin.createUser({ user: "admin", pwd: "{{ password }}", roles: ["root"] })
          admin.auth("admin", "{{ password }}")
          {% endif %} 
      notify:
        - restart mongodb

  # Copy mongod.conf file having auth enabled   
    - name: copy mongod.conf | set
      become: yes
      timeout: 300
      ansible.builtin.copy:
        src: ../templates/mongodb/mongod.conf.j2
        dest: /etc/mongod.conf
        owner: root
        group: root
        mode: '0644'
      register: mongo_conf_set
      notify:
        - restart mongodb 

    - name: Copy mongodb file for log rotation
      become: yes
      timeout: 300
      ansible.builtin.copy:
        src: ../templates/mongodb/mongodb
        dest: /etc/logrotate.d/mongodb
        owner: root
        group: root
        mode: 0644    

    - name: Daemon Reload
      shell: systemctl daemon-reload

    - name: Starting MongoDB service
      service:
        name: mongod
        state: started
  
  handlers:
    - name: restart mongodb
      service: name=mongod state=restarted

my mongod.conf file on instance

systemLog:
  destination: file
  logAppend: true
  logRotate: reopen
  path: /var/log/mongodb/mongod.log

storage:
  dbPath: /data/db
  journal:
    enabled: true
  engine: wiredTiger

processManagement:
  fork: true
  pidFilePath: /var/run/mongodb/mongod.pid

net:
  port: 27017
  bindIp: 0.0.0.0

security:
  authorization: enabled

  • I have added my entire script.. still no luck.. – brijesh kalavadia Dec 02 '22 at 00:48
  • You must create and set ownership of folder `/data/db` **before** you start `mongod` the first time. Folder `/var/run/mongodb` is created in `mongod.service` file, thus you may skip this task. – Wernfried Domscheit Dec 02 '22 at 07:26
  • How do you try connect with mongosh? Please show us the `/etc/mongod.conf` file (on the remote machine). Your source file is `mongod.conf.j2`, file extension `j2` is typically used for jinja templates, but you do a plain `copy` (instead of `template`). Show us also the service file `mongod.service` – Wernfried Domscheit Dec 07 '22 at 06:29
  • @WernfriedDomscheit Ok so i have made changes in script and now everything works fine.. changed builtin copy and added template to copy conf file.. now when i reboot my instance mongod service couldnt start and i found that `/var/run/mongodb` folder is missing.. – brijesh kalavadia Dec 07 '22 at 20:07
  • Folder `/var/run/mongodb` should be created in `mongod.service` (see `systemctl status mongod`), have a look at it. Perhaps the file is different depending on Linux distribution. Just a note, on my Linux the user is `mongod`, not `mongodb`. Check carefully! – Wernfried Domscheit Dec 07 '22 at 20:28
  • Please edit your question for such information. And please provide the `mongod.service` file – Wernfried Domscheit Dec 07 '22 at 20:43
  • @WernfriedDomscheit I dont see `mongod.service` in any location `/usr/lib/systemd` or `/etc/systemd/system`.. where can i find that file or how can i keep `/var/run/mongdb` and not being deleted ? – brijesh kalavadia Dec 07 '22 at 22:44
  • Do you use systemctl (`systemd`) or System V Init (`service`)? If you use systemd then `systemctl status mongod` should show the location. For System V Init I don't know. – Wernfried Domscheit Dec 08 '22 at 07:57
  • yes i did and it was there before restart and as soon as i restart instance .. it also disappeared – brijesh kalavadia Dec 08 '22 at 16:48
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/250273/discussion-between-brijesh-kalavadia-and-wernfried-domscheit). – brijesh kalavadia Dec 08 '22 at 17:48
  • Why do you set owner of `/data/db` to `root:root`? Set `mongodb:mongodb`, then you can skip "Recursively change ownership of a /data/db" – Wernfried Domscheit Dec 08 '22 at 20:53
  • user `mongodb` only available once we do installation.. `/data/db` we are mounting with ebs volume we added. so i am doing that first and then once installation done.. i am changing ownership to `mongodb:mongodb` I dont think that is the reason for `var/run/mongodb` folder gets deleted after reboot – brijesh kalavadia Dec 08 '22 at 23:17
  • It seems to be the default: https://serverfault.com/questions/74796/directory-in-var-run-gets-deleted-after-hard-reboot or https://unix.stackexchange.com/questions/648000/how-to-avoid-deletion-of-folders-under-run-or-var-run - One more reason to skip this task. Why do you restart mongod after each change? In the entire playbook one single `start mongod` is sufficient. – Wernfried Domscheit Dec 09 '22 at 08:13
  • Thanks @WernfriedDomscheit for all your help here.. i was able to resolve my issue by following both the link you provided above.. made changes in mongod.service file to `RuntimeDirectoryPreserve=yes` and `RuntimeDirectory=mongodb` and it works – brijesh kalavadia Dec 09 '22 at 19:33

2 Answers2

0

I create the users manually:

- hosts: all
  vars: 
    mongoAuth: "/usr/bin/mongosh 'mongodb://admin:{{ password | urlencode() }}@localhost:27017/admin?authSource=admin' --norc --quiet"
    mongoNoAuth: "/usr/bin/mongosh 'mongodb://localhost:27017/admin' --norc --quiet"

  tasks: 
  - name: Check if authentication is enabled and if user already exists
    shell: 
      cmd: "{{ mongoAuth }} --eval 'db.getMongo()'"
      executable: /bin/bash
    register: authenticate 
    failed_when: false 
    changed_when: false
    check_mode: no 


  - name: Create users
    shell: 
      cmd: "{{ (authenticate.rc == 0) | ternary(mongoAuth, mongoNoAuth) }} --eval '{{ js }}'"
      executable: /bin/bash
    vars: 
      js: |
        admin = db.getSiblingDB("admin")
        {% if authenticate.rc != 0 %}
        admin.createUser({ user: "admin", pwd: "{{ password }}", roles: ["root"] })
        admin.auth("admin", "{{ password }}")
        {% endif %} 
        // create more users if needed
        admin.createUser(...)
Wernfried Domscheit
  • 54,457
  • 9
  • 76
  • 110
  • The preferable method is to use the Ansible methods. The shell tasks are not idempotent as well. – Kevin C Dec 01 '22 at 08:37
  • The ansible methods have a few limitations - at least when I developed the playbooks for my shared cluster. You can write the scripts idempotent as well. – Wernfried Domscheit Dec 01 '22 at 09:00
  • It feels like you're trying to re-invent the wheel, while you could simplify and reduce tasks by simply using Ansible modules. – Kevin C Dec 01 '22 at 09:57
  • @KevinC because when I developed my Sharded cluster, the Ansible mongodb plugin was not available yet in my environment. It also have several limitations. For a simple "create user" the ansible would be fine. For a complex sharded cluster deployment you run into limitations. – Wernfried Domscheit Dec 01 '22 at 11:20
  • @WernfriedDomscheit.. do i need to set auth prior to add those tasks ? – brijesh kalavadia Dec 02 '22 at 01:06
  • Up to you. When authentication is enabled, then you can create the **first** admin user, see [Localhost Exception](https://www.mongodb.com/docs/manual/core/localhost-exception/). From the moment on when the first user has been created, authentication takes effect. Thus the script runs `auth("admin", "{{ password }}")` immediately after `createUser` . Without authentication you can create as many users as you like - or change anybodies password - at any time (and anybody else could do it, because the database is completely open) – Wernfried Domscheit Dec 02 '22 at 07:14
  • @WernfriedDomscheit I tried your solution and seems script ran successfully but when i tried to login with user it says below error.. also when i tried to do show user with disabling auth.. it show nothing.. it should have admin user when i use admin db `test> use admin` `switched to db admin` `admin> db.auth("mongoadmin","pwd")` `MongoServerError: Authentication failed.` `admin>` – brijesh kalavadia Dec 02 '22 at 22:02
  • Check with `db.getUsers()` in which database the user has been created. You can also use `db.getSiblingDB("admin").createUser(...)` When I deploy my MongoDB then I **never** start mongod process without authentication. Have also a look at https://stackoverflow.com/questions/63754742/authentication-failure-while-trying-to-save-to-mongodb/63755470#63755470 – Wernfried Domscheit Dec 02 '22 at 22:22
  • Maybe try `ret = db.createUser(...); print(ret)`, register the output and check stdout/stderr – Wernfried Domscheit Dec 02 '22 at 22:29
  • When you restart the database, ensure the configuration file always use the same folder for `dbPath` – Wernfried Domscheit Dec 02 '22 at 22:47
0

I assume you have a wrong configuration setting on the host.

Unable to connect to database: Unknown option directconnection

This doesn't look like an Ansible error to me.

To help you further out, you should disable mongo authentication, and restart mongo. Then, create 3 users, admin, root and userAdminAnyDatabase. Then restart mongo. Here is an Ansible role I've written for MongoDB, so you can take a look there to see how it works.

Kevin C
  • 4,851
  • 8
  • 30
  • 64
  • Stop the mongobd, restart without authentication and restart again with authentication enabled, is what I would consider as an overkill. It's fine for a deployment from scratch, however if you like to update and existing MongoDB then you may run into trouble regarding security and availability. – Wernfried Domscheit Dec 01 '22 at 11:28
  • Mongo wouldn't work/properly start without these users in the first place... – Kevin C Dec 01 '22 at 12:44
  • That's wrong. Mongo starts without any users when authentication is enabled. Everybody can connect to this database without any credentials - called [Localhost Exception](https://www.mongodb.com/docs/manual/core/localhost-exception/) - as soon as the first admin user is created the authentication is effective and users need credentials. You can always connect to an MongoDB without any credentials, however without valid credentials you cannot execute any command apart from harmless commands like `help(), db.getMongo(), db.listCommands(), etc.` – Wernfried Domscheit Dec 01 '22 at 13:19
  • I tried disabling auth and adding user, enable auth but still getting same user. – brijesh kalavadia Dec 02 '22 at 00:46
  • @WernfriedDomscheit, so here is thing.. when i try my script first time.. it runs successfully but when i try to authenticate through mongosh .. it says user not found in logs .. but when i re-run same script.. it add user then.. can you suggest what should be wrong here ? I have updated my script above.. – brijesh kalavadia Dec 06 '22 at 23:42