forked from StackStorm/ansible-st2
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ability to enable mongo auth and add users
Adds auth to mongo when the mongodb_auth_enable flag is true. Any additional users should be passed in via mongodb_users. There are several other default variables as well (like mongodb_host, mongodb_port) that can be overridden in the play or inventory that uses this role. This does not attempt to generate any passwords. It only adds users if explicitly requested, but allows external tasks/roles to import the mongodb_auth.yml tasks to add users as required after mongo is installed. This uses lineinfile to edit mongod.conf with regexs to catch as many edge cases in yaml formatting (spaces, quotes) as possible. Also, this uses a bit of python to validate that the yaml file was modified in such a way that it is still valid yaml, and the entries intrduced in the file are present as expected. This uses the mongo shell to see if authorization is required before adding the admin user. This should handle cases such as the localhost exception in a new install or upgrades where auth is not enabled or upgrades where auth is enabled. This installs pip using system packages if `pip` is not present. `pip` is needed to install pymongo which is used to manage mongo users through the mongodb_user ansible module. As explained in comments, we only update mongo user passwords on_create because that is the only way to maintain idempotency. This should be idempotent. Part of StackStorm#75.
- Loading branch information
1 parent
1cd1c54
commit a9e34cc
Showing
5 changed files
with
233 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
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). | ||
|
||
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
--- | ||
- name: Check for pip (used to install pymongo) | ||
command: "{{ pip | default('pip') }} --version" | ||
register: pip_check | ||
changed_when: no | ||
failed_when: no | ||
|
||
# It shouldn't matter if it's an old version of pip for installing pymongo, so use the system package instead of get-pip.py | ||
- name: Install pip with system package (used to install pymongo) | ||
when: pip_check.rc != 0 | ||
become: yes | ||
package: | ||
name: 'python{% ansible_os_family == "RedHat" and ansible_distribution_major_version == "7" %}2{% endif %}-pip' | ||
state: present | ||
|
||
- name: Ensure pymongo is installed for the mongodb_user ansible module | ||
become: yes | ||
pip: | ||
name: pymongo | ||
|
||
- name: See if mongodb authorization is enabled and users are configured | ||
command: 'mongo --eval "db.getUsers()" {{ mongodb_admin_db }}' | ||
# 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 | ||
|
||
- name: Show mongodb auth check output | ||
debug: | ||
var: _mongo_authorization | ||
verbosity: 2 | ||
|
||
- 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!" | ||
|
||
- 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: "{{ mongodb_admin_db }}" | ||
roles: userAdminAnyDatabase | ||
|
||
login_host: "{{ mongodb_host }}" | ||
login_port: "{{ mongodb_port }}" | ||
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, mongodb_admin_db) }}" | ||
|
||
- name: Enable security section in mongod.conf | ||
become: yes | ||
lineinfile: | ||
path: /etc/mongod.conf | ||
regexp: |- | ||
^[#'"\s]*security['"]?\s*: | ||
line: 'security:' | ||
validate: | | ||
{{ ansible_python_interpreter|default("/usr/bin/python") }} -c ' | ||
import yaml, io | ||
if "security" not in yaml.safe_load(io.open("%s")): | ||
exit(1) | ||
' | ||
- 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: | | ||
{{ ansible_python_interpreter|default("/usr/bin/python") }} -c ' | ||
import yaml, io | ||
if yaml.safe_load(io.open("%s"))["security"]["authorization"] != "enabled": | ||
exit(1) | ||
' | ||
register: _enable_mongo_auth | ||
#notify: restart mongodb | ||
|
||
- name: Restart mongodb to enable auth before adding additional users | ||
# This allows us to safely assume auth is already enabled when adding more users | ||
when: | ||
- mongodb_users | ||
- _enable_mongo_auth is changed | ||
become: yes | ||
service: | ||
name: mongod | ||
state: restarted | ||
# TODO: Use filtered flush_handlers once this is merged: https://github.com/ansible/ansible/pull/25573 | ||
# As is, mongo may restart twice, once here and whenever the upgrade handlers get flushed. | ||
# when: mongodb_users | ||
# meta: | ||
# name: flush_handlers | ||
# filter: restart mongodb | ||
|
||
- name: Add additional mongo users | ||
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: "{{ item.username }}" | ||
password: "{{ item.password }}" | ||
database: "{{ item.db }}" | ||
roles: "{{ item.roles|default('readWrite') }}" | ||
|
||
login_host: "{{ mongodb_host }}" | ||
login_port: "{{ mongodb_port }}" | ||
login_user: "{{ mongodb_admin_username }}" | ||
login_password: "{{ mongodb_admin_password }}" | ||
login_database: "{{ mongodb_admin_db }}" | ||
loop_control: | ||
label: "{{ item.username }} on {{ item.db }}" | ||
with_items: "{{ mongodb_users }}" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters