From 7f112f11e093eb1e82cab681a3ef8e88ec7afbe8 Mon Sep 17 00:00:00 2001 From: Santiago Lo Coco Date: Sun, 14 Apr 2024 00:16:42 +0200 Subject: [PATCH] Implement passwordless authentication --- .../playground/roles/local_accounts/README.md | 5 +- .../local_accounts/meta/argument_specs.yml | 5 ++ .../roles/local_accounts/tasks/main.yml | 65 ++++++++++++++++++- .../roles/local_accounts/tests/test.yml | 2 +- 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/slococo/playground/roles/local_accounts/README.md b/slococo/playground/roles/local_accounts/README.md index b74d738..a0e936b 100644 --- a/slococo/playground/roles/local_accounts/README.md +++ b/slococo/playground/roles/local_accounts/README.md @@ -6,7 +6,8 @@ An Ansible Role to create local user accounts. Requirements ------------ -None. +- Ansible 2.12.0 or later +- This role requires elevated privileges. Make sure to set `become: true` when using this role. Role Variables -------------- @@ -33,7 +34,7 @@ Example Playbook userid: 1001 roles: - - { role: slococo.playground.local_accounts } + - { role: slococo.playground.local_accounts, become: true } ``` License diff --git a/slococo/playground/roles/local_accounts/meta/argument_specs.yml b/slococo/playground/roles/local_accounts/meta/argument_specs.yml index a201ca2..6eb92ed 100644 --- a/slococo/playground/roles/local_accounts/meta/argument_specs.yml +++ b/slococo/playground/roles/local_accounts/meta/argument_specs.yml @@ -35,3 +35,8 @@ argument_specs: required: false default: "" description: The primary group for the local user. + passwordless: + type: bool + required: false + default: false + description: Boolean value indicating whether SSH key pairs should be generated for passwordless authentication. diff --git a/slococo/playground/roles/local_accounts/tasks/main.yml b/slococo/playground/roles/local_accounts/tasks/main.yml index bb89fed..714c159 100644 --- a/slococo/playground/roles/local_accounts/tasks/main.yml +++ b/slococo/playground/roles/local_accounts/tasks/main.yml @@ -7,5 +7,68 @@ expires: "{{ (((item.expiry_date + ' 00:00:00') | to_datetime).strftime('%s')) if item.expiry_date is defined else omit }}" home: "{{ item.home | default(omit) }}" groups: "{{ item.groups | default(omit) }}" - generate_ssh_key: yes + # generate_ssh_key: "{{ item.passwordless | default(omit) }}" loop: "{{ accounts }}" + +- name: Add home + ansible.builtin.set_fact: + accounts_with_home: "{{ accounts_with_home | default([]) + [item | combine({'home': item.home | default('/home/' + item.name)})] }}" + loop: "{{ accounts }}" + +# - name: Read public keys from id_rsa.pub files +# ansible.builtin.slurp: +# src: "{{ item.home }}/.ssh/id_rsa.pub" +# loop: "{{ accounts_with_home }}" +# register: public_keys_result +# when: not ansible_check_mode and item.passwordless | default(false) | bool + +# - name: Add public keys to authorized_keys for passwordless authentication +# ansible.builtin.copy: +# content: "{{ item.content | b64decode }}" +# dest: "{{ item.item.home }}/.ssh/authorized_keys" +# owner: "{{ item.item.name }}" +# group: "{{ item.item.name }}" +# mode: '0600' +# loop: "{{ public_keys_result.results }}" +# when: not ansible_check_mode and item.item.passwordless | default(false) | bool + +# - name: Fetch private key from remote host to Ansible control node +# ansible.builtin.fetch: +# src: "{{ item.home }}/.ssh/id_rsa" +# dest: "{{ private_key_path }}/{{ item.name }}_id_rsa" +# flat: yes +# loop: "{{ accounts_with_home }}" +# when: not ansible_check_mode and item.passwordless | default(false) | bool + +# - name: Set permissions for fetched private key file +# ansible.builtin.file: +# path: "{{ private_key_path }}/{{ item.name }}_id_rsa" +# mode: '0600' +# loop: "{{ accounts_with_home }}" +# when: not ansible_check_mode and item.passwordless | default(false) | bool +# delegate_to: localhost +# run_once: true +# become: false + +- name: Determine key path + set_fact: + key_path: "{{ (private_key_path | default('/tmp')) + '/id_rsa' }}" + +- name: Generate SSH key pairs for local users + community.crypto.openssh_keypair: + path: "{{ key_path }}_{{ item.name }}" + loop: "{{ accounts_with_home }}" + when: not ansible_check_mode and item.passwordless | default(false) | bool + delegate_to: localhost + run_once: true + become: false + +- name: Copy public keys to authorized_keys for passwordless authentication + ansible.builtin.copy: + content: "{{ lookup('file', key_path + '_' + item.name + '.pub') }}" + dest: "{{ item.home }}/.ssh/authorized_keys" + owner: "{{ item.name }}" + group: "{{ item.name }}" + mode: '0600' + loop: "{{ accounts_with_home }}" + when: not ansible_check_mode and item.passwordless | default(false) | bool diff --git a/slococo/playground/roles/local_accounts/tests/test.yml b/slococo/playground/roles/local_accounts/tests/test.yml index 75344fb..d91ff12 100644 --- a/slococo/playground/roles/local_accounts/tests/test.yml +++ b/slococo/playground/roles/local_accounts/tests/test.yml @@ -14,7 +14,7 @@ shell: /bin/zsh userid: 1002 expiry_date: '2024-12-31' - home: /home/test_user3 + home: /home/test_user2_another groups: docker roles: