diff options
-rw-r--r-- | chaos-at-home/ch-testvm-prometheus.yml | 6 | ||||
-rw-r--r-- | filter_plugins/crypto.py | 14 | ||||
-rw-r--r-- | inventory/host_vars/ch-testvm-prometheus.yml | 50 | ||||
-rw-r--r-- | roles/mosquitto/defaults/main.yml | 31 | ||||
-rw-r--r-- | roles/mosquitto/handlers/main.yml | 10 | ||||
-rw-r--r-- | roles/mosquitto/tasks/main.yml | 71 | ||||
-rw-r--r-- | roles/mosquitto/templates/config.j2 | 29 |
7 files changed, 211 insertions, 0 deletions
diff --git a/chaos-at-home/ch-testvm-prometheus.yml b/chaos-at-home/ch-testvm-prometheus.yml index 9a1191ad..bd71a3a4 100644 --- a/chaos-at-home/ch-testvm-prometheus.yml +++ b/chaos-at-home/ch-testvm-prometheus.yml @@ -7,3 +7,9 @@ - role: core/sshd/base - role: core/zsh - role: core/ntp + +- name: Payload Setup + hosts: ch-testvm-prometheus + roles: + - role: x509/selfsigned/base + - role: mosquitto diff --git a/filter_plugins/crypto.py b/filter_plugins/crypto.py index 54547a34..995776d3 100644 --- a/filter_plugins/crypto.py +++ b/filter_plugins/crypto.py @@ -2,6 +2,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type import hashlib +import passlib from binascii import hexlify from passlib.utils.binary import Base64Engine, HASH64_CHARS, BCRYPT_CHARS from ansible.module_utils._text import to_bytes, to_text @@ -53,6 +54,18 @@ def wifi_80211r_key(seed): raise errors.AnsibleFilterError("wifi_80211r_key(): %s" % str(e)) +def mosquitto_passwd_hash(password, seed): + ''' generate password hash for use by mosquitto mqtt server ''' + try: + h = hashlib.new('sha512') + h.update(to_bytes(seed, errors='surrogate_or_strict')) + salt = h.digest()[0:12] + digest = passlib.hash.pbkdf2_sha512.using(salt=salt).hash(password).replace('pbkdf2-sha512', '7').replace('.', '+') + return digest + '==' + except Exception as e: + raise errors.AnsibleFilterError("mosquitto_passwd_hash(): %s" % str(e)) + + class FilterModule(object): ''' crypto helpers ''' @@ -62,6 +75,7 @@ class FilterModule(object): 'sha512_salt': sha2_crypt_salt, 'bcrypt_salt': bcrypt_salt, 'wifi_80211r_key': wifi_80211r_key, + 'mosquitto_passwd_hash': mosquitto_passwd_hash, } def filters(self): diff --git a/inventory/host_vars/ch-testvm-prometheus.yml b/inventory/host_vars/ch-testvm-prometheus.yml index 415e6774..50e625fa 100644 --- a/inventory/host_vars/ch-testvm-prometheus.yml +++ b/inventory/host_vars/ch-testvm-prometheus.yml @@ -35,3 +35,53 @@ network: - *_network_primary_ ntp_variant: systemd-timesyncd + + +### +mosquitto_global_config_options: + per_listener_settings: "true" + +mosquitto_listeners: + example: + bind: 1884 192.168.32.42 + hostnames: + - mqtt.example.com + tls: + certificate_provider: selfsigned + certificate_config: + cert: + organization_name: "spreadspace" + organizational_unit_name: "ansible" + san_extra: + - "IP:192.168.32.42" + create_subject_key_identifier: yes + not_after: +100w + options: + allow_anonymous: "true" + require_certificate: "true" + acl_file: /etc/mosquitto/foo.acl + foo: + bind: 1883 + options: + allow_anonymous: "false" + acl_file: /etc/mosquitto/example.acl + password_file: /etc/mosquitto/example.passwd + +mosquitto_prometheus_listener: true + +mosquitto_acl_files: + example: | + user admin + topic read test/+ + user equinox + topic write test/+ + foo: | + user consumer + topic read foo/+ + user producer + topic write foo/+ + +mosquitto_password_files: + example: | + admin:{{ 'admin' | mosquitto_passwd_hash('admin@mqtt.example.com') }} + equinox:{{ 'secret' | mosquitto_passwd_hash('equinox@mqtt.example.com') }} diff --git a/roles/mosquitto/defaults/main.yml b/roles/mosquitto/defaults/main.yml new file mode 100644 index 00000000..32199a50 --- /dev/null +++ b/roles/mosquitto/defaults/main.yml @@ -0,0 +1,31 @@ +--- +# mosquitto_global_config_options: +# per_listener_settings: "true" + +mosquitto_listeners: {} +# example: +# bind: 1883 192.0.2.1 +# hostnames: +# - mqtt.example.com +# tls: +# certificate_provider: ... +# options: +# require_certificate: "true" +# use_identity_as_username: "true" +# foo: +# bind: 1884 +# options: +# allow_anonymous: "false" +# acl_file: /etc/mosquitto/example.acl +# password_file: /etc/mosquitto/example.passwd + +mosquitto_prometheus_listener: false + +mosquitto_acl_files: {} +# example: | +# user somebody +# topic read example/+/foo + +mosquitto_password_files: {} +# example: | +# somebody:{{ 'secret' | mosquitto_passwd_hash('somebody@mqtt.example.com') }} diff --git a/roles/mosquitto/handlers/main.yml b/roles/mosquitto/handlers/main.yml new file mode 100644 index 00000000..c188764d --- /dev/null +++ b/roles/mosquitto/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: restart mosquitto + service: + name: mosquitto + state: restarted + +- name: reload mosquitto + service: + name: mosquitto + state: reloaded diff --git a/roles/mosquitto/tasks/main.yml b/roles/mosquitto/tasks/main.yml new file mode 100644 index 00000000..ed872789 --- /dev/null +++ b/roles/mosquitto/tasks/main.yml @@ -0,0 +1,71 @@ +--- +- name: install mosquitto + apt: + name: + - mosquitto + - mosquitto-clients + state: present + +- name: install mosquitto acl files + loop: "{{ mosquitto_acl_files | dict2items }}" + loop_control: + label: "{{ item.key }}" + copy: + content: | + # Ansible managed + {{ item.value }} + dest: "/etc/mosquitto/{{ item.key }}.acl" + notify: reload mosquitto + +- name: install mosquitto password files + loop: "{{ mosquitto_password_files | dict2items }}" + loop_control: + label: "{{ item.key }}" + copy: + content: | + {{ item.value }} + dest: "/etc/mosquitto/{{ item.key }}.passwd" + owner: root + group: mosquitto + mode: "0640" + notify: reload mosquitto + +- name: generate Diffie-Hellman parameters + when: (mosquitto_listeners | dict2items | selectattr('value.tls', 'defined') | length) > 0 + openssl_dhparam: + path: /etc/mosquitto/certs/dhparams.pem + size: 2048 + notify: reload mosquitto + +- name: generate/install/fetch TLS certificate + loop: "{{ mosquitto_listeners | dict2items | selectattr('value.tls', 'defined') }}" + loop_control: + label: "{{ item.key }}" + vars: + x509_certificate_name: "mosquitto-{{ item.key }}" + x509_certificate_hostnames: "{{ item.value.hostnames }}" + x509_certificate_config: "{{ item.value.tls.certificate_config | default({}) }}" + x509_certificate_renewal: + install: + - dest: "/etc/mosquitto/certs/{{ item.key }}-crt.pem" + src: + - fullchain + owner: root + group: mosquitto + mode: "0644" + - dest: "/etc/mosquitto/certs/{{ item.key }}-key.pem" + src: + - key + owner: root + group: mosquitto + mode: "0640" + x509_certificate_reload_services: + - mosquitto + include_role: + name: "x509/{{ item.value.tls.certificate_provider }}/cert" + +- name: install mosquitto config + template: + src: config.j2 + dest: /etc/mosquitto/conf.d/main.conf + notify: restart mosquitto diff --git a/roles/mosquitto/templates/config.j2 b/roles/mosquitto/templates/config.j2 new file mode 100644 index 00000000..e6fa4b52 --- /dev/null +++ b/roles/mosquitto/templates/config.j2 @@ -0,0 +1,29 @@ +# {{ ansible_managed }} + +## Global +{% if mosquitto_global_config_options is defined %} +{% for option, value in mosquitto_global_config_options.items() %} +{{ option }} {{ value }} +{% endfor %} +{% endif %} +{% for name, listener in mosquitto_listeners.items() %} + +## Listener: {{ name }} +listener {{ listener.bind }} +{% if 'tls' in listener %} +certfile /etc/mosquitto/certs/{{ name }}-crt.pem +keyfile /etc/mosquitto/certs/{{ name }}-key.pem +dhparamfile /etc/mosquitto/certs/dhparams.pem +{% endif %} +{% if 'options' in listener %} +{% for option, value in listener.options.items() %} +{{ option }} {{ value }} +{% endfor %} +{% endif %} +{% endfor %} +{% if mosquitto_prometheus_listener %} + +## Prometheus monitoring +listener 0 /var/run/mosquitto/prometheus.sock +allow_anonymous true +{% endif %} |