From b53d61adfc9c554c6979708948d16031175b445d Mon Sep 17 00:00:00 2001 From: Chad Heuschober Date: Tue, 1 Jul 2014 15:18:54 -0400 Subject: [PATCH] Adds meta state and also deals with the default password security issue. --- README.rst | 20 +++++++++++- mysql/database.sls | 12 ++++--- mysql/init.sls | 29 +++++++++++++++++ mysql/python.sls | 2 +- mysql/server.sls | 80 +++++++++++++++++++++++++++------------------- mysql/user.sls | 11 ++++--- 6 files changed, 111 insertions(+), 43 deletions(-) create mode 100644 mysql/init.sls diff --git a/README.rst b/README.rst index 6c92764..9a6c0de 100644 --- a/README.rst +++ b/README.rst @@ -15,6 +15,10 @@ Available states .. contents:: :local: +``mysql`` + +Meta-state that includes all server packages in the correct order. + ``mysql.client`` ---------------- @@ -25,13 +29,27 @@ Install the MySQL client package. Install the MySQL server package and start the service. -Debian OS family supports setting MySQL root password during install via debconf. +Debian OS family supports setting MySQL root password during install via +debconf. + +.. note:: + + If no root password is provided in the pillar, a random one will + be created. As-of Hydrogen, this password uses the Python ``random`` + module via ``test.rand_str``. As ``random`` is considered + cryptographically insecure, future formula versions should use the + newly available ``random.get_str`` method. ``mysql.database`` ------------------ Create and manage MySQL databases. +``mysql.python`` +------------------ + +Install mysql python bindings. + ``mysql.user`` ---------------- diff --git a/mysql/database.sls b/mysql/database.sls index 41a2661..dc021ac 100644 --- a/mysql/database.sls +++ b/mysql/database.sls @@ -1,16 +1,20 @@ {% from "mysql/map.jinja" import mysql with context %} +{% set mysql_root_pass = salt['pillar.get']('mysql:server:root_password', salt['test.rand_str'](64)) %} +{% set db_states = [] %} + include: - mysql.python {% for database in salt['pillar.get']('mysql:database', []) %} -mysql_db_{{ database }}: +{% set state_id = 'mysql_db_' ~ loop.index0 %} +{{ state_id }}: mysql_database.present: - name: {{ database }} - host: localhost - connection_user: root - - connection_pass: '{{ salt['pillar.get']('mysql:server:root_password', 'somepass') }}' + - connection_pass: '{{ mysql_root_pass }}' - connection_charset: utf8 + +{% do db_states.append(state_id) %} {% endfor %} - - diff --git a/mysql/init.sls b/mysql/init.sls new file mode 100644 index 0000000..22439b0 --- /dev/null +++ b/mysql/init.sls @@ -0,0 +1,29 @@ +{% from 'mysql/database.sls' import db_states with context %} +{% from 'mysql/user.sls' import user_states with context %} + +{% macro requisites(type, states) %} + {%- for state in states %} + - {{ type }}: {{ state }} + {%- endfor -%} +{% endmacro %} + +include: + - mysql.server + - mysql.database + - mysql.user + +{% if (db_states|length() + user_states()) > 0 %} +extend: + mysqld: + service: + - require_in: + {{ requisites(db_states) }} + {{ requisites(user_states) }} + {% for state in user_states %} + {{ state }}: + mysql_user: + - require: + sls: mysql.database + {% endfor %} +{% endif %} + diff --git a/mysql/python.sls b/mysql/python.sls index 598110c..ce50064 100644 --- a/mysql/python.sls +++ b/mysql/python.sls @@ -1,6 +1,6 @@ {% from "mysql/map.jinja" import mysql with context %} -mysql-python: +mysql_python: pkg: - installed - name: {{ mysql.python }} diff --git a/mysql/server.sls b/mysql/server.sls index f7cbcd0..8d6481e 100644 --- a/mysql/server.sls +++ b/mysql/server.sls @@ -1,26 +1,50 @@ {% from "mysql/map.jinja" import mysql with context %} -{% set mysql_root_password = salt['pillar.get']('mysql:server:root_password', 'somepass') %} +{% set os = salt['grains.get']('os', None) %} +{% set os_family = salt['grains.get']('os_family', None) %} -{% if grains['os'] in ['Ubuntu', 'Debian'] %} -mysql-debconf: +{% if 'mysql:server:root_password' in pillar %} + {% set mysql_root_password = pillar['mysql:server:root_password'] %} +{% else %} +mysql_missing_root_password: + test.configurable_test_state: + - name: mysql_missing_root_password + - changes: False + - result: False + - comment: 'MySQL pillar is missing root password data. A random password will be used.' + + {% set mysql_root_password = salt['test.rand_str](64) %} +{% endif %} + +{% endif %} + +{% if os in ['Ubuntu', 'Debian'] %} +mysql_debconf: debconf.set: - name: mysql-server - data: 'mysql-server/root_password': {'type': 'password', 'value': '{{ mysql_root_password }}'} 'mysql-server/root_password_again': {'type': 'password', 'value': '{{ mysql_root_password }}'} 'mysql-server/start_on_boot': {'type': 'boolean', 'value': 'true'} -{% elif grains['os'] in ['CentOS'] %} -mysql-root-password: - cmd: - - run + - require_in: + - pkg: mysqld + {% if 'mysql:server:root_password' not in pillar %} + - require: + - test: mysql_missing_root_password + {% endif %} +{% elif os == 'CentOS' %} +mysql_root_password: + cmd.run: - name: mysqladmin --user root password '{{ mysql_root_password|replace("'", "'\"'\"'") }}' - unless: mysql --user root --password='{{ mysql_root_password|replace("'", "'\"'\"'") }}' --execute="SELECT 1;" - require: - service: mysqld + {% if 'mysql:server:root_password' not in pillar %} + - test: mysql_missing_root_password + {% endif %} -{% for host in ['localhost', grains['fqdn']] %} -mysql-delete-anonymous-user-{{ host }}: +{% for host in ['localhost', salt['grains.get']('fqdn')] %} +mysql_delete_anonymous_user_{{ host }}: mysql_user: - absent - host: {{ host }} @@ -28,47 +52,37 @@ mysql-delete-anonymous-user-{{ host }}: - connection_pass: {{ mysql_root_password }} - require: - service: mysqld - - pkg: mysql-python + - pkg: mysql_python {%- if mysql_root_password %} - - cmd: mysql-root-password + - cmd: mysql_root_password {%- endif %} {% endfor %} {% endif %} mysqld: - pkg: - - installed + pkg.installed: - name: {{ mysql.server }} -{% if grains['os'] in ['Ubuntu', 'Debian'] %} +{% if os in ['Ubuntu', 'Debian'] %} - require: - - debconf: mysql-debconf + - debconf: mysql_debconf {% endif %} - service: - - running + service.running: - name: {{ mysql.service }} - enable: True - watch: - pkg: mysqld -{% if grains['os'] in ['Ubuntu', 'Debian', 'Gentoo', 'CentOS'] %} -my.cnf: +mysql_config: file.managed: - name: {{ mysql.config }} - - source: salt://mysql/files/{{ grains['os'] }}-my.cnf + - template: jinja + - watch_in: + - service: mysqld + {% if os in ['Ubuntu', 'Debian', 'Gentoo', 'CentOS'] %} + - source: salt://mysql/files/{{ os }}-my.cnf - user: root - group: root - mode: 644 - - template: jinja - - watch_in: - - service: mysqld -{% endif %} - -{% if grains['os'] in 'FreeBSD' %} -my.cnf: - file.managed: - - name: {{ mysql.config }} + {% elif os == 'FreeBSD' %} - source: salt://mysql/files/my-{{ mysql.mysql_size }}.cnf - - template: jinja - - watch_in: - - service: mysqld -{% endif %} + {% endif %} diff --git a/mysql/user.sls b/mysql/user.sls index 54f6f7d..c07e9ee 100644 --- a/mysql/user.sls +++ b/mysql/user.sls @@ -1,10 +1,13 @@ {% from "mysql/map.jinja" import mysql with context %} +{% set user_states = [] %} + include: - mysql.python {% for user in salt['pillar.get']('mysql:user', []) %} -mysql_user_{{ user['name'] }}: +{% set state_id = 'mysql_user_' ~ loop.index0 %} +{{ state_id }}: mysql_user.present: - name: {{ user['name'] }} - host: {{ user['host'] }} @@ -19,10 +22,9 @@ mysql_user_{{ user['name'] }}: - connection_charset: utf8 {% for db in user['databases'] %} -{% set name = user['name'] ~ '_' ~ db['database'] %} -mysql_user_{{ name }}: +{{ state_id ~ '_' ~ loop.index0 }}: mysql_grants.present: - - name: {{ name }} + - name: {{ user['name'] ~ '_' ~ db['database'] }} - grant: {{db['grants']|join(",")}} - database: {{ db['database'] }}.* - user: {{ user['name'] }} @@ -35,6 +37,7 @@ mysql_user_{{ name }}: - mysql_user: {{ user['name'] }} {% endfor %} +{% do user_states.append(state_id) %} {% endfor %}