Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configure/Set username/password for Mongo #256

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,18 @@ platforms:

suites:
- name: default
- name: secure_mongo
provisioner:
extra_vars:
st2_config:
database:
username: st2mongo
password: Sw33tPassw0rd
db_name: st2
mongodb_enable_auth: yes
mongodb_default_admin_password: AdminP@ssw0rd
mongodb_users:
- db: st2
username: st2mongo
password: Sw33tPassw0rd
roles: readWrite,dbAdmin
64 changes: 64 additions & 0 deletions roles/StackStorm.mongodb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
Ansible Role: stackstorm.mongodb
================================

Installs MongoDB. If the `mongodb_auth_enable` boolean is enabled, then this also enables authentication, adds an admin
user, and adds any other users defined in `mongodb_users`.

Requirements
------------

Enabling mongo auth requires the pymongo python module (requirement of the mongo_users ansible module).
Enabling mongo auth also requires PyYAML to validate changes to mongod.conf.

Role Variables
--------------

These default variables can be set in the inventory's group or host vars, or pass them in as vars in the playbook that
uses this role. An example of passing in some of these vars is shown in an example playbook below.

* `mongodb_version`: The major.minor version to install (only 3.4 or 3.2 are supported).
* `mongodb_enable_auth`: Whether or not to enable auth in mongodb (default: no)
* `mongodb_host`: Login to this host to add users (default '127.0.0.1')
* `mongodb_port`: Login on this port to add users (default '27017')
* `mongodb_admin_username`: The admin's username (default 'admin')
* `mongodb_admin_password`: The admin's password (default: generate a random password and store it in a file)
* `mongodb_users`: A list of users to add (see example playbook below; default: [])
* `mongodb_creds_dir`: The directory that should hold any generated credentials like admin (default: '.')

Dependencies
------------

On RedHat family distributions, this depends on the stackstorm.epel role.

Example Playbook
----------------

This playbook installs mongo without enabling auth or adding any users:

- hosts: localhost
roles:
- role: StackStorm.stackstorm/roles/mongodb


This playbook installs mongo, enables auth, and adds a stackstorm user, and force update the password if it already exists:

- hosts: localhost
roles:
- role: StackStorm.stackstorm/roles/mongodb
vars:
mongodb_enable_auth: yes
mongodb_users:
- db: st2
username: st2mongo
password: "{{ lookup('password', '{{ mongodb_creds_dir }}/mongodb-' + inventory_hostname + '-' + st2mongo_username + ' length=42' ) }}"
roles: readWrite
mongodb_force_password_update: yes

Note that the `readWrite` mongo role is used by default, so `roles` can be ommitted for the above playbook.
You can use the roles attribute to add any other mongo roles to your user.

License
-------

Apache 2.0

24 changes: 24 additions & 0 deletions roles/StackStorm.mongodb/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,27 @@
# MongoDB version to install
# Should be '3.2' or '3.4'
mongodb_version: "3.4"
punkrokk marked this conversation as resolved.
Show resolved Hide resolved

# do not enable mongo auth by default. Make sure to add required users in mongodb_users if auth is enabled.
mongodb_enable_auth: no

# when adding auth, the login credentials to use
mongodb_host: 127.0.0.1
mongodb_port: 27017
mongodb_admin_username: admin
# For production use - please change the admin password!
mongodb_admin_password: "{{ mongodb_default_admin_password }}"
# The default is separate so the st2 role can provide a default without overriding a user provided password.
mongodb_default_admin_password: "Ch@ngeMe"

# Additional users to add.
mongodb_users: []
# - db: st2
# username: st2mongo
# password: "Ch@ngeMe"
# roles: readWrite

# whether or not to force a password update for any users in mongodb_users
# Setting this to yes will result in 'changed' on every run, even if the password is the same.
# See the comment in tasks/mongodb_auth.yml for more details.
mongodb_force_update_password: no
5 changes: 5 additions & 0 deletions roles/StackStorm.mongodb/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@
state: started
enabled: yes
tags: [databases, mongodb]

- name: Enable mongodb authentication
when: mongodb_enable_auth
include_tasks: mongodb_auth.yml
tags: [databases, mongodb]
109 changes: 107 additions & 2 deletions roles/StackStorm.mongodb/tasks/mongodb_auth.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
- name: Install pip (for the installation of pymongo)
- name: Install role dependencies for mongodb config and validation
become: yes
package:
name: python-pip
name:
- python-pip # for the installation of pymongo
- "{% if ansible_facts.os_family == 'RedHat' %}PyYAML{% else %}python-yaml{% endif %}"
state: present
tags: [databases, mongodb]

Expand All @@ -13,3 +15,106 @@
pip:
name: "pymongo>=3.10.1,<4.0.0"
tags: [databases, mongodb]

- name: See if mongodb authorization is enabled and users are configured
command: 'mongo --eval "db.getUsers()" admin'
# this will fail (rc 252) if auth is enabled and users are configured
# With the localhost exception, this will succeed (rc 0) when users are not configured even if auth is enabled.
# see:
# - https://docs.mongodb.com/manual/core/security-users/#localhost-exception
# - https://stackoverflow.com/q/31949586/1134951
# - https://github.com/ansible/ansible/issues/33832#issuecomment-358031733
register: _mongo_authorization
changed_when: no # this does not change anything, it only checks
failed_when: no # The rc determines whether or not auth is required to create/update the admin user
tags: [databases, mongodb]

- name: Show mongodb auth check output
# the purpose of this task is to make sure task output is visible in travis if there are problems
debug:
var: _mongo_authorization
verbosity: 2
tags: [databases, mongodb]

- name: Warn about default credentials
when: "mongodb_admin_password == 'Ch@ngeMe'"
debug:
msg: "[WARNING] Using default admin credentials for mongodb admin account! Please change them!"
tags: [databases, mongodb]

- name: Add mongo admin
mongodb_user:
state: present

# NOTE: on_create is idempotent - see comment below
update_password: on_create

name: "{{ mongodb_admin_username }}"
password: "{{ mongodb_admin_password }}"
database: admin
roles: userAdminAnyDatabase

# This does NOT include the mongo_auth_user.yml because of the
# special omit handling of login_* when mongo auth is not enabled/configured
login_host: "{{ mongodb_host }}"
login_port: "{{ mongodb_port | string }}" # silence implicit int->str conversion warning
login_user: "{{ (_mongo_authorization.rc == 0) | ternary(omit, mongodb_admin_username) }}"
login_password: "{{ (_mongo_authorization.rc == 0) | ternary(omit, mongodb_admin_password) }}"
login_database: "{{ (_mongo_authorization.rc == 0) | ternary(omit, 'admin') }}"
tags: [databases, mongodb]

- name: Enable security section in mongod.conf
become: yes
lineinfile:
path: /etc/mongod.conf
regexp: |-
^[#'"\s]*security['"]?\s*:
line: 'security:'
validate: |
{{ mongodb_python }} -c '
import yaml, io
if "security" not in yaml.safe_load(io.open("%s")):
exit(1)
'
tags: [databases, mongodb]

- name: Enable authentication in mongod.conf
become: yes
lineinfile:
path: /etc/mongod.conf
insertafter: '^security:'
# two space indentation (the default) assumed
line: ' authorization: enabled'
regexp: |-
^[#'"\s]+authorization['"]?\s*:
validate: |
{{ mongodb_python }} -c '
import yaml, io
if yaml.safe_load(io.open("%s"))["security"]["authorization"] != "enabled":
exit(1)
'
register: _enable_mongo_auth
#notify: restart mongodb
tags: [databases, mongodb]

- name: Restart mongodb to enable auth before adding additional users
# This is not a handler because restarting mongo now simplifies adding users.
# Restarting allows us to safely assume auth is already enabled.
when:
- mongodb_users | bool
- _enable_mongo_auth is changed
become: yes
service:
name: mongod
state: restarted
tags: [databases, mongodb]

- name: Add additional mongo users
include_tasks: mongodb_auth_user.yml
loop_control:
loop_var: _mongodb_user
loop: "{{ mongodb_users }}"
# using loop_control: label does not obscure the password in output for verbosity > 1
# So, loop over an include where the task name will include the username + db, but the loop var won't print out.
no_log: yes
tags: [databases, mongodb]
26 changes: 26 additions & 0 deletions roles/StackStorm.mongodb/tasks/mongodb_auth_user.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
- name: "Add mongo auth user - {{ _mongodb_user.username }} on {{ _mongodb_user.db }}"
mongodb_user:
state: present

# NOTE: on_create is idempotent, always is not.
# With `update_password: on_create`, mongodb_user checks to see if the user
# (a) exists on the db, and (b) has the same roles,
# and then it only adds the user if it's not there or the roles have changed.
# With `update_password: always`, mongodb_user cannot tell if the password
# needs to be changed without attempting a login with those credentials.
# But mongodb_user does not currently implement such a check.
# A comment in mongodb_user points to https://jira.mongodb.org/browse/SERVER-22848
update_password: "{{ mongodb_force_update_password|ternary('always', 'on_create') }}"

name: "{{ _mongodb_user.username }}"
password: "{{ _mongodb_user.password }}"
database: "{{ _mongodb_user.db }}"
roles: "{{ _mongodb_user.roles|default('readWrite') }}"

login_host: "{{ mongodb_host }}"
login_port: "{{ mongodb_port }}"
login_user: "{{ mongodb_admin_username }}"
login_password: "{{ mongodb_admin_password }}"
login_database: admin
tags: [databases, mongodb]
2 changes: 2 additions & 0 deletions roles/StackStorm.mongodb/vars/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ mongodb_major_minor_version: "{{ (mongodb_version|string)[:3] }}"
mongodb_apt_keys:
"3.2": "42F3E95A2C4F08279C4960ADD68FA50FEA312927"
"3.4": "0C49F3730359A14518585931BC711F9BA15703C6"

mongodb_python: "{{ ansible_python_interpreter | default( (ansible_python|default({})).get('executable', 'python') ) }}"