diff --git a/action_plugins/sshfp.py b/action_plugins/sshfp.py new file mode 100755 index 0000000000000000000000000000000000000000..c5034527d5c79c499a4f97085a6394f379725c01 --- /dev/null +++ b/action_plugins/sshfp.py @@ -0,0 +1,75 @@ +import base64 +import hashlib + +from ansible.errors import AnsibleError +from ansible.plugins.action import ActionBase +from ansible.utils.display import Display +from ansible.module_utils._text import to_native + +display = Display() + + +class ActionModule(ActionBase): + + TRANSFERS_FILES = False + + def _sshfp(self, key): + return(b'SHA256:'+base64.b64encode( + hashlib.sha256(base64.b64decode(key) + ).digest()).replace(b'=',b'')).decode('utf-8') + + def run(self, tmp=None, task_vars=None): + """ + The run method is the main Action Plugin driver. All work is done from within this method. + + tmp: Temporary directory. Sometimes an action plugin sets up + a temporary directory and then calls another module. This parameter + allows us to reuse the same directory for both. + + task_vars: The variables (host vars, group vars, config vars, etc) associated with this task. + Note that while this will contain Ansible facts from the host, they should be used + with caution as a user running Ansible can disable their collection. If you want + make sure that your Action Plugin always has access to the ones it needs, you may + want to consider running the setup module directly in the run the method and getting + the Ansible facts that way. + The strategy plugin which manages running tasks on instances uses an ansible.vars.manager + VariableManager instance to retrieve this context specific dict of variables. + """ + if task_vars is None: + task_vars = dict() + + result = super(ActionModule, self).run(tmp, task_vars) + + self._supports_check_mode = True + self._supports_async = False + + setup_module_args=dict( + gather_subset='all', + gather_timeout=10 + ) + + setup_result = self._execute_module( + module_name='setup', + module_args=setup_module_args, + persist_files=False, + task_vars=task_vars, + tmp=tmp, + ) + + hostname = task_vars.get('inventory_hostname') + + for algo in ['rsa', 'ecdsa', 'ed25519']: + key = f'ansible_ssh_host_key_{algo}_public' + keyblob = setup_result['ansible_facts'].get(key) + if not keyblob: + display.vvv(f"host {hostname} doesn't offer {algo} ssh host key. Skipping...") + result[f'ssh_host_key_{algo}_fp'] = None + continue + try: + display.vvv("Trying to get fingerprint for {algo} ssh host key.") + fp = self._sshfp(keyblob) + result[f'ssh_host_key_{algo}_fp'] = fp + except Exception as e: + err_msg = to_native(e) + raise AnsibleError(err_msg) + return result diff --git a/ansible.cfg b/ansible.cfg index 4dd2dddf430eb6aa239ab2c96cee19a5e243bc78..32a6f327da84e4c287712c915da421f2b3b1a6eb 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -4,6 +4,7 @@ # Explicitely redefined some defaults to make play execution work roles_path = ./roles +action_plugins = ./action_plugins vars_plugins = ./vars_plugins lookup_plugins = ./lookup_plugins diff --git a/roles/moinmoin-gendoc/tasks/main.yml b/roles/moinmoin-gendoc/tasks/main.yml index 9499c165c07d247163ed210e18ee508f355c403b..bcc819b5d1e403cdfcbc5ef56f7de166300d215d 100644 --- a/roles/moinmoin-gendoc/tasks/main.yml +++ b/roles/moinmoin-gendoc/tasks/main.yml @@ -10,6 +10,10 @@ - name: get dmidecode facts dmidecode: {} +- name: get ssh fingerprints + sshfp: {} + register: sshfp + - name: "Create wiki page documenting {{ ansible_hostname }} (physical)" when: ansible_system_vendor != 'QEMU' moinmoin_page: diff --git a/roles/moinmoin-gendoc/templates/server.j2 b/roles/moinmoin-gendoc/templates/server.j2 index baf14dad7a34e561dd1f38973ae95208e7350ae1..e287e258f246eef8d6943296fcb24346694d0f9b 100644 --- a/roles/moinmoin-gendoc/templates/server.j2 +++ b/roles/moinmoin-gendoc/templates/server.j2 @@ -83,15 +83,15 @@ et {{ (ansible_memory_mb.swap.total/1024)|round(1) }} GiB de SWAP. '''RSA''' : {{ '{{{' }} -{{ ansible_ssh_host_key_rsa_public | wordwrap }} +{{ sshfp.ssh_host_key_rsa_fp }} {{ '}}}' }} '''ECDSA''' : {{ '{{{' }} -{{ ansible_ssh_host_key_ecdsa_public | wordwrap }} +{{ sshfp.ssh_host_key_ecdsa_fp }} {{ '}}}' }} '''ED25519''' : {{ '{{{' }} -{{ ansible_ssh_host_key_ed25519_public | wordwrap }} +{{ sshfp.ssh_host_key_ed25519_fp }} {{ '}}}' }}