Skip to content
Snippets Groups Projects
Commit cc5ef01e authored by ale's avatar ale
Browse files

Support includes in passwords.yml

Distribute a default passwords.yml file for users to include. Mirrors
the setup used for services.yml.
parent 58aae5bb
Branches
No related tags found
No related merge requests found
- name: sso_session_auth_secret
description: sso-server cookie auth key
type: binary
length: 64
- name: sso_session_enc_secret
description: sso-server cookie encryption key
type: binary
length: 16
- name: sso_csrf_secret
description: sso-server cookie-based CSRF secret
type: binary
length: 64
- name: sso_device_manager_auth_secret
description: sso-server cookie-based device manager secret
type: binary
length: 64
- name: ssoproxy_session_auth_key
description: sso-proxy cookie authentication key
type: binary
length: 64
- name: ssoproxy_session_enc_key
description: sso-proxy cookie encryption key
type: binary
length: 32
- name: ldap_root_password
description: LDAP cn=manager password
- name: ldap_replica_password
description: LDAP cn=replica password
- name: ldap_authserver_password
description: LDAP cn=authserver password
- name: ldap_keystore_password
description: LDAP cn=keystore password
- name: ldap_accountserver_password
description: LDAP cn=accountserver password
- name: grafana_session_secret
description: session secret for Grafana
length: 32
- name: acme_tsig_key
type: tsig
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
# First of all, generate secrets from the passwords.yml file. # First of all, generate secrets from the passwords.yml file.
- name: Initialize secrets - name: Initialize secrets
local_action: command ../scripts/pwgen.py --vars "{{ credentials_dir }}/secrets.yml" "{{ passwords_file }}" local_action: command ../scripts/pwgen.py --vars "{{ credentials_dir }}/secrets.yml" "{{ passwords_file }}"
register: pwgen_result
changed_when: "pwgen_result.rc == 1"
failed_when: "pwgen_result.rc > 1"
- name: Link secrets.yml from the vars directory - name: Link secrets.yml from the vars directory
file: file:
src: "{{ credentials_dir }}/secrets.yml" src: "{{ credentials_dir }}/secrets.yml"
......
...@@ -6,18 +6,49 @@ ...@@ -6,18 +6,49 @@
from __future__ import print_function from __future__ import print_function
import argparse
import base64 import base64
import sys
import optparse
import os import os
import random import random
import shutil import shutil
import subprocess import subprocess
import string import string
import sys
import tempfile import tempfile
import yaml import yaml
# Possible exit codes for this program.
EXIT_NOTHING_TO_DO = 0
EXIT_CHANGED = 1
EXIT_ERROR = 2
# Returns the absolute path to a file. If the given path is relative,
# it will be evaluated based on the given path_reference.
def _abspath(path, relative_to='/'):
if path.startswith('/'):
return path
return os.path.abspath(os.path.join(os.path.dirname(relative_to), path))
# A version of yaml.safe_load that supports the special 'include'
# top-level attribute and recursively merges included files.
def _read_yaml(path):
with open(path) as fd:
data = yaml.safe_load(fd)
if not isinstance(data, list):
raise Exception('data in %s is not a list' % (path,))
# Find elements that include other files.
out = []
for entry in data:
if 'include' in entry:
out.extend(_read_yaml(_abspath(entry['include'], path)))
else:
out.append(entry)
return out
def decrypt(src): def decrypt(src):
return subprocess.check_output( return subprocess.check_output(
['ansible-vault', 'decrypt', '--output=-', src]) ['ansible-vault', 'decrypt', '--output=-', src])
...@@ -99,38 +130,48 @@ def generate_password(entry): ...@@ -99,38 +130,48 @@ def generate_password(entry):
def main(): def main():
parser = optparse.OptionParser(usage='%prog <password file>') parser = argparse.ArgumentParser(description='''
parser.add_option('--vars', metavar='FILE', dest='vars', Autogenerate secrets for use with Ansible.
default='vars/passwords',
Secrets are encrypted with Ansible Vault, so the
ANSIBLE_VAULT_PASSWORD_FILE environment variable must be defined.
''')
parser.add_argument(
'--vars', metavar='FILE', dest='vars_file',
help='Output vars file') help='Output vars file')
opts, args = parser.parse_args() parser.add_argument(
if len(args) != 1: 'password_file',
parser.error('Not enough arguments') help='Secrets metadata')
args = parser.parse_args()
if not os.getenv('ANSIBLE_VAULT_PASSWORD_FILE'): if not os.getenv('ANSIBLE_VAULT_PASSWORD_FILE'):
print("You need to set ANSIBLE_VAULT_PASSWORD_FILE", file=sys.stderr) raise Exception("You need to set ANSIBLE_VAULT_PASSWORD_FILE")
sys.exit(2)
password_file = args[0]
vars_file = opts.vars
passwords = {} passwords = {}
if os.path.exists(vars_file): if os.path.exists(args.vars_file):
passwords.update(yaml.load(decrypt(vars_file))) passwords.update(yaml.safe_load(decrypt(args.vars_file)))
changed = False changed = False
with open(password_file) as fd:
for entry in yaml.load(fd):
name = entry['name']
for entry in _read_yaml(args.password_file):
name = entry['name']
if name not in passwords: if name not in passwords:
print("Generating password for '%s'" % name, file=sys.stderr) print("Generating password for '%s'" % name, file=sys.stderr)
passwords[name] = generate_password(entry) passwords[name] = generate_password(entry)
changed = True changed = True
if changed: if changed:
encrypt(yaml.dump(passwords), vars_file) encrypt(yaml.dump(passwords), args.vars_file)
return EXIT_CHANGED
return EXIT_NOTHING_TO_DO
if __name__ == '__main__': if __name__ == '__main__':
main() try:
sys.exit(main())
except Exception as e:
print("Error: %s" % str(e), file=sys.stderr)
sys.exit(EXIT_ERROR)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment