0

I'm using ansible to deploy mongodb-cluster

I connected to primary_node and created admin user in the admin database:

then updated /etc/mongo.conf to looks like this:

net:
  port: 27017
  bindIpAll: true

systemLog:
  destination: file
  logAppend: true
  path: /log/mongod.log

storage:
  dbPath: /data
  journal:
    enabled: true

security:
  authorization: enabled
  keyFile: /mongo_auth/mongodb.key

processManagement:
  fork: true  # fork and run in background
  pidFilePath: /var/run/mongodb/mongod.pid
  timeZoneInfo: /usr/share/zoneinfo

replication:
  replSetName: s0

After this mongod process restarted.

Now I can login using admin/login credentials and I can run command to start replicaSet

rs.initiate({ _id: "s0", version: 1, members: [{ _id: 0, host: "stage-mongoprimary0.server.loc:27017", priority: 2 }, { _id: 1, host: "stage-mongosecondary1.server.loc:27017", priority: 1 }, { _id: 2, host: "stage-mongosecondary2.server.loc:27017", priority: 1 }] })

and everything works just fine. But I can't acomplish the same with ansible module for some reason. Here is my task

- name: Initialize MongoDB replica set
  community.mongodb.mongodb_replicaset:
    login_user: admin
    login_password: "{{ admin_password }}"
    replica_set: s0
    members:
      - _id: 0
        host: stage-mongoprimary0.server.loc
        priority: 2
      - _id: 1
        host: stage-mongosecondary1.server.loc
        priority: 1
      - _id: 2
        host: stage-mongosecondary2.server.loc
        priority: 1
  when: inventory_hostname == mongo_primary

by default module uses admin db and default port which exactly what I already setup.

but when I run this task I get an error:

"msg": "Unable to create replica_set: Some problem not authorized on admin to execute command

But I can do the same if I login directly into mogo shell using the same creds. Please help.

admin role is root with highet privileges.

I'm using mongodb 3.6.23 pymongo 4.3.3 and Python3.8, ansible 2.9.23

this is what I see in logs:

2023-04-14T00:58:06.143+0000 I NETWORK [conn19] received client metadata from xx.xx.xx.xx:52300 conn19: { driver: { name: "PyMongo", version: "4.3.3" }, os: { type: "Linux", name: "Linux", architecture: "x86_64", version: "4.14.311-233.529.amzn2.x86_64" }, platform: "CPython 3.8.16.final.0" } 2023-04-14T00:58:06.144+0000 I ACCESS [conn19] Unauthorized: not authorized on admin to execute command { replSetInitiate: { _id: "s0", protocolVersion: 1, members: [ { _id: 0, host: "stage-mongoprimary0.server.loc:27017", priority: 2 }, { _id: 1, host: "stage-mongosecondary1.server.loc:27017", priority: 1 }, { _id: 2, host: "stage-mongosecondary2.server.loc:27017", priority: 1 } ], settings: { chainingAllowed: true, electionTimeoutMillis: 10000 } }, $db: "admin", $readPreference: { mode: "primaryPreferred" } }

already tried to assign following roles:

 - { db: "admin", role: "userAdminAnyDatabase" }
  - { db: "admin", role: "dbAdminAnyDatabase" }
  - { db: "admin", role: "clusterAdmin" }
  - { db: "admin", role: "readWriteAnyDatabase" }

even tried with

 - { db: "admin", role: "__system" }
  - { db: "admin", role: "root" }

still the same.

I can start ReplicaSet and add members only if I disable security which is not what I'm looking for.

1 Answer 1

0

You don't have to modify the config file. You can start mongod directly with security.authorization: enabled. If an admin user does not exist, then you can connect with the localhost exception. As soon as the first admin user is created, authorization becomes effective.

According to Deploy Replica Set With Keyfile Authentication you first need to initiate the replica set, then you can create the admin user.

I am not using the community.mongodb.mongodb_replicaset plug-in, I do it manually like this:

- name: Check if authentication is enabled
  shell: 
    cmd: "/usr/bin/mongosh --norc --quiet 'mongodb://admin:{{ password | urlencode() }}@localhost/admin?&authSource=admin&readPreference=primaryPreferred' --eval 'db.getMongo()'"
    executable: /bin/bash
  register: authenticate
  failed_when: false
  changed_when: false
  check_mode: no


- name: Initialize ReplicaSet and create admin user
  shell: 
    cmd: "/usr/bin/mongosh --norc --quiet 'mongodb://localhost/admin?readPreference=primaryPreferred' --eval '{{ js }}'"
    executable: /bin/bash
  vars: 
    js: |
      rs.initiate({ _id: "{{ replica_set }}", members: [{ _id: 0, host: "{{ item.memberFQN | first }}" }]})
      while (! db.hello().isWritablePrimary) sleep(1000)
      db.getSiblingDB("admin").createUser({ user: "admin", pwd: "{{ password }}", roles: ["root"] })
      db.getSiblingDB("admin").auth("admin", "{{ password }}")
      {% for m in item.memberFQN[1:] %}
      rs.add({_id: {{loop.index}}, host: "{{ m }}" })
      {% endfor %}
  loop: "{{ members }}"
  when: authenticate.rc != 0

A more advanced version would be this one:

- hosts: all
  vars: 
    uriAuth: "mongodb://admin:{{ password | urlencode() }}@{{ inventory_hostname_short }}:27017/admin?authSource=admin"
    uriNoAuth: "mongodb://localhost:27017/admin"
  remote_user: mongod
  tasks:

  - name: Check if authentication is enabled
    shell: 
      cmd: "/usr/bin/mongosh --norc --quiet '{{ uriAuth }}' --eval 'db.getMongo()'"
      executable: /bin/bash
    register: authenticate
    failed_when: false
    changed_when: false
    check_mode: no

  - name: Check if Replicaset is initialized
    shell: 
      cmd: "/usr/bin/mongosh --norc --quiet '{{ (authenticate.rc == 0) | ternary(uriAuth, uriNoAuth) }}' --eval 'print(e.codeName)'"
      executable: /bin/bash
    register: initialized
    changed_when: false
    check_mode: no

  - name: Init Replicaset
    shell: 
      cmd: "/usr/bin/mongosh '{{ uriNoAuth }}&readPreference=primaryPreferred' --eval '{{ js }}'"
      executable: /bin/bash
    vars:
      js: |
        var ret = rs.initiate({{ rs_initiate | to_json }})
        if (ret.ok != 1) {
          print(EJSON.stringify(ret))
          quit(1)
        }
        while ( !db.hello().isWritablePrimary ) sleep(1000)
        print(rs.status().members.map(x => {return {name: x.name, stateStr: x.stateStr}}))
    register: ret_initconfig
    when: initialized.stdout == 'NotYetInitialized'

  - debug:
      msg: "{{ ret_initconfig.stdout_lines }}"
    when: (ret_initconfig.stdout | default('')) != ''

  - name: Create users and roles
    shell: 
      cmd: "/usr/bin/mongosh --norc --quiet '{{ (authenticate.rc == 0) | ternary(uriAuth, uriNoAuth) }}' --eval '{{ js }}'"
      executable: /bin/bash
    vars: 
      js: |
        const admin = db.getSiblingDB("admin")
        {% if authenticate.rc != 0 %}
        var ret = admin.createUser({ user: "admin", pwd: "{{ password }}", roles: ["root"] })
        if (ret.ok != 1) { print(EJSON.stringify(ret)); quit(1) }
        print(EJSON.stringify({user: "admin", ok: ret.ok}))
        let auth = admin.auth("admin", "{{ password }}")
        if (auth.ok != 1) { print(EJSON.stringify(auth)); quit(1) }
        {% endif %} 
        ... create other users and/or roles
    register: ret_createUser
    changed_when: ret_createUser.stdout != ''
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.