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

Add vault_users for easier password management #614

Merged
merged 2 commits into from
Aug 3, 2016
Merged
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### HEAD
* [BREAKING] Add `vault_users` for easier password management ([#614](https://github.com/roots/trellis/pull/614))
* Fix #581 - Use WP-CLI to run WP cron ([#583](https://github.com/roots/trellis/pull/583))
* Require explicit redirects and drop www_redirect ([#622](https://github.com/roots/trellis/pull/622))
* [BREAKING] Require explicit redirects and drop `www_redirect` ([#622](https://github.com/roots/trellis/pull/622))
* Fix #612 - Bump nginx_fastcgi_buffer_size to `8k` ([#620](https://github.com/roots/trellis/pull/620))
* Setup permalink structure for multisite installs too ([#617](https://github.com/roots/trellis/pull/617))
* Fix `wp_home` option in Multisite after install in development ([#616](https://github.com/roots/trellis/pull/616))
Expand Down
2 changes: 1 addition & 1 deletion group_vars/all/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ ferm_input_list:

# Documentation: https://roots.io/trellis/docs/security/
# If sshd_permit_root_login: false, admin_user must be in 'users' (`group_vars/all/users.yml`) with sudo group
# and in 'vault_sudoer_passwords' (`group_vars/staging/vault.yml`, `group_vars/production/vault.yml`)
# and in 'vault_users' (`group_vars/staging/vault.yml`, `group_vars/production/vault.yml`)
sshd_permit_root_login: true
sshd_password_authentication: false
2 changes: 1 addition & 1 deletion group_vars/all/users.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Documentation: https://roots.io/trellis/docs/ssh-keys/
admin_user: admin

# Also define 'vault_sudoer_passwords' (`group_vars/staging/vault.yml`, `group_vars/production/vault.yml`)
# Also define 'vault_users' (`group_vars/staging/vault.yml`, `group_vars/production/vault.yml`)
users:
- name: "{{ web_user }}"
groups:
Expand Down
1 change: 0 additions & 1 deletion group_vars/production/main.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
mysql_root_password: "{{ vault_mysql_root_password }}" # Define this variable in group_vars/production/vault.yml
sudoer_passwords: "{{ vault_sudoer_passwords }}" # Define this variable in group_vars/production/vault.yml
6 changes: 4 additions & 2 deletions group_vars/production/vault.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
vault_mysql_root_password: productionpw

# Documentation: https://roots.io/trellis/docs/security/
vault_sudoer_passwords:
admin: $6$rounds=100000$JUkj1d3hCa6uFp6R$3rZ8jImyCpTP40e4I5APx7SbBvDCM8fB6GP/IGOrsk/GEUTUhl1i/Q2JNOpj9ashLpkgaCxqMqbFKdZdmAh26/
vault_users:
- name: "{{ admin_user }}"
password: example_password
salt: "generateme"

# Variables to accompany `group_vars/production/wordpress_sites.yml`
# Note: the site name (`example.com`) must match up with the site name in the above file.
Expand Down
1 change: 0 additions & 1 deletion group_vars/staging/main.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
mysql_root_password: "{{ vault_mysql_root_password }}" # Define this variable in group_vars/staging/vault.yml
sudoer_passwords: "{{ vault_sudoer_passwords }}" # Define this variable in group_vars/staging/vault.yml
6 changes: 4 additions & 2 deletions group_vars/staging/vault.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
vault_mysql_root_password: stagingpw

# Documentation: https://roots.io/trellis/docs/security/
vault_sudoer_passwords:
admin: $6$rounds=100000$JUkj1d3hCa6uFp6R$3rZ8jImyCpTP40e4I5APx7SbBvDCM8fB6GP/IGOrsk/GEUTUhl1i/Q2JNOpj9ashLpkgaCxqMqbFKdZdmAh26/
vault_users:
- name: "{{ admin_user }}"
password: example_password
salt: "generateme"

# Variables to accompany `group_vars/staging/wordpress_sites.yml`
# Note: the site name (`example.com`) must match up with the site name in the above file.
Expand Down
8 changes: 8 additions & 0 deletions lib/trellis/plugins/vars/vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
__metaclass__ = type

import re
import sys

from ansible import __version__
from ansible.errors import AnsibleError
Expand All @@ -16,6 +17,12 @@
from ansible.parsing.yaml.objects import AnsibleMapping, AnsibleSequence, AnsibleUnicode
from ansible.template import Templar

try:
import passlib.hash
except:
if sys.platform.startswith('darwin'):
raise AnsibleError('Ansible on OS X requires the python passlib module to create user password hashes.\nsudo easy_install pip\npip install passlib')


class VarsModule(object):
''' Creates and modifies host variables '''
Expand Down Expand Up @@ -79,4 +86,5 @@ def get_host_vars(self, host, vault_password=None):
self.raw_vars(host, host.get_group_vars())
host.vars['cli_options'] = self.cli_options()
host.vars['cli_ask_pass'] = getattr(self._options, 'ask_pass', False)
host.vars['cli_ask_become_pass'] = getattr(self._options, 'become_ask_pass', False)
return {}
4 changes: 2 additions & 2 deletions lib/trellis/utils/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ def system(vagrant_version=None):

# Retrieve most recent changelog entry
else:
change = re.search(r'.*\n\*\s*([^\(\n\[]+)', str)
change = re.search(r'^\*\s?(\[BREAKING\])?([^\(\n\[]+)', str, re.M|re.I)
if change is not None:
changelog_msg = '\n Trellis at "{0}"'.format(change.group(1).strip())
changelog_msg = '\n Trellis at "{0}"'.format(change.group(2).strip())

# Vagrant info, if available
vagrant = ' Vagrant {0};'.format(vagrant_version) if vagrant_version else ''
Expand Down
6 changes: 6 additions & 0 deletions roles/remote-user/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@
- name: Announce which user was selected
debug:
msg: "Note: Ansible will attempt connections as user = {{ ansible_user }}"

- name: Load become password
set_fact:
ansible_become_pass: "{% for user in vault_users | default([]) if user.name == ansible_user and user.password is defined %}{% if loop.first %}{{ user.password }}{% endif %}{% endfor %}"
when: ansible_user != 'root' and not cli_ask_become_pass | default(false) and ansible_become_pass is not defined
no_log: true
15 changes: 10 additions & 5 deletions roles/users/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@
- name: Fail if root login will be disabled but admin_user will not be a sudoer
assert:
that:
- "{{ admin_user in (users | map(attribute='name') | list) }}"
- "{% for item in users if item.name == admin_user %}{{ 'sudo' in item.groups }}{% endfor %}"
- "{{ admin_user in sudoer_passwords.keys() }}"
msg: "When `sshd_permit_root_login: false`, you must add `sudo` to the `groups` for admin_user (in `users` hash), and set a password for admin_user in `sudoer_passwords`. Otherwise Ansible could lose the ability to run the necessary sudo commands."
- "{% for user in users if user.name == admin_user %}{% if loop.first %}{{ 'sudo' in user.groups }}{% endif %}{% else %}{{ false }}{% endfor %}"
- "{% for user in vault_users | default([]) if user.name == admin_user %}{% if loop.first %}{{ user.password is defined }}{% endif %}{% else %}{{ false }}{% endfor %}"
msg: |
When `sshd_permit_root_login: false`, you must add `sudo` to the `groups` for admin_user (in `users` hash), and set a password for admin_user in `vault_users` (in `group_vars/{{ env }}/vault.yml`). Otherwise Ansible could lose the ability to run the necessary sudo commands. {% if sudoer_passwords is defined or vault_sudoer_passwords is defined %}


Please note that `sudoer_passwords` and `vault_sudoer_passwords have been replaced with `vault_users`. {% endif %}
More info:
> https://roots.io/trellis/docs/security/#admin-user-sudoer-password
when: not sshd_permit_root_login
tags: sshd

Expand All @@ -27,7 +32,7 @@
name: "{{ item.name }}"
group: "{{ item.groups[0] }}"
groups: "{{ item.groups | join(',') }}"
password: "{{ sudoer_passwords[item.name] | default(None) }}"
password: "{% for user in vault_users | default([]) if user.name == item.name and user.password is defined %}{% if loop.first %}{{ user.password | password_hash('sha512', user.salt | default(None)) }}{% endif %}{% else %}{{ None }}{% endfor %}"
state: present
shell: /bin/bash
update_password: always
Expand Down