From 596c03fe225f726f82a0f0273666da9b135b3eaa Mon Sep 17 00:00:00 2001 From: Felix Stupp Date: Fri, 19 Apr 2019 13:21:46 +0200 Subject: [PATCH] Added role bootstrap --- README.md | 1 + roles/bootstrap/README.md | 21 ++++++++++++++ roles/bootstrap/defaults/main.yml | 4 +++ roles/bootstrap/tasks/deprivilege.yml | 9 ++++++ roles/bootstrap/tasks/main.yml | 19 ++++++++++++ roles/bootstrap/tasks/privilege.yml | 37 ++++++++++++++++++++++++ roles/bootstrap/tasks/shift_back.yml | 8 +++++ roles/bootstrap/tasks/try_else_shift.yml | 12 ++++++++ 8 files changed, 111 insertions(+) create mode 100644 roles/bootstrap/README.md create mode 100644 roles/bootstrap/defaults/main.yml create mode 100644 roles/bootstrap/tasks/deprivilege.yml create mode 100644 roles/bootstrap/tasks/main.yml create mode 100644 roles/bootstrap/tasks/privilege.yml create mode 100644 roles/bootstrap/tasks/shift_back.yml create mode 100644 roles/bootstrap/tasks/try_else_shift.yml diff --git a/README.md b/README.md index 474cbed..0093e35 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,5 @@ Following roles have been defined to make creating a server configuration easy: - **acme** defines roles for handling the automatic handling of certificates with *acme.sh* - **application** installs main application - **certificate** issues a given certificate +- **bootstrap** defines a way to connect to a server which has not been configured yet - **common** defines the installation of common packages and common configurations like firewall diff --git a/roles/bootstrap/README.md b/roles/bootstrap/README.md new file mode 100644 index 0000000..aae5518 --- /dev/null +++ b/roles/bootstrap/README.md @@ -0,0 +1,21 @@ +# Ansible Bootstrap Role + +This role will manage to use another user to connect to the server, +if your server hoster configures another root / sudo user as you want to use. +This allows you to build one simple playbook and execute it +no matter if your server is already configured or not. + +## Example + +My server hoster allows me to define a password for root while configuring the server, +then I can connect via SSH using this password to this new server, +however I prefer to use another account with sudo privileges. + +Now you can use this role to etablish this workflow to Ansible. +Configure Ansible's `remote_user` to be the user you want to give sudo privileges to. +Define this role to be the first executed and set the variable `bootstrap_sudo_user` +to the user your hoster configures for you. +Ansible will try to log in as `remote_user` at first, +if this fails, then it will try to log in as `bootstrap_sudo_user`. +As long as one of both connection attempts succeeds, +the execution of the playbook will continue using the privileges of the first succeeded login. \ No newline at end of file diff --git a/roles/bootstrap/defaults/main.yml b/roles/bootstrap/defaults/main.yml new file mode 100644 index 0000000..08a266a --- /dev/null +++ b/roles/bootstrap/defaults/main.yml @@ -0,0 +1,4 @@ +bootstrap_used: false + +bootstrap_user: root +bootstrap_become_pass: "" diff --git a/roles/bootstrap/tasks/deprivilege.yml b/roles/bootstrap/tasks/deprivilege.yml new file mode 100644 index 0000000..0998cab --- /dev/null +++ b/roles/bootstrap/tasks/deprivilege.yml @@ -0,0 +1,9 @@ +--- + +- user: + name: "{{ bootstrap_user }}" + state: absent + become: yes + when: + - bootstrap_user != "root" + - bootstrap_user != bootstrap_expected_user diff --git a/roles/bootstrap/tasks/main.yml b/roles/bootstrap/tasks/main.yml new file mode 100644 index 0000000..f42c867 --- /dev/null +++ b/roles/bootstrap/tasks/main.yml @@ -0,0 +1,19 @@ +--- + +- name: Store facts given by configuration + set_fact: + bootstrap_expected_user: "{{ ansible_user }}" + bootstrap_expected_become_pass: "{{ ansible_become_pass }}" + +- name: Bootstrap shift if required + include_tasks: try_else_shift.yml + +- name: Privilege expected user + include_tasks: privilege.yml + +- name: Bootstrap shift back if was shifted + include_tasks: shift_back.yml + when: bootstrap_used + +- name: Deprivilege bootstrap user + include_tasks: deprivilege.yml diff --git a/roles/bootstrap/tasks/privilege.yml b/roles/bootstrap/tasks/privilege.yml new file mode 100644 index 0000000..b587c03 --- /dev/null +++ b/roles/bootstrap/tasks/privilege.yml @@ -0,0 +1,37 @@ +--- + +- name: Create new user {{ bootstrap_expected_user }} + user: + state: present + name: "{{ bootstrap_expected_user }}" + groups: + - sudo + append: yes + password: "{{ bootstrap_expected_become_pass | password_hash('sha512', LOCAL_SALT) }}" + update_password: on_create + register: bootstrap_expected_user_data + +- name: Copy SSH Keys if bootstraped now + when: bootstrap_used + block: + - name: Retrieve data from user {{ bootstrap_user }} + user: + name: "{{ bootstrap_user }}" + state: present + register: bootstrap_user_data + - name: Create .ssh directory for user {{ bootstrap_expected_user }} + file: + path: "{{ bootstrap_expected_user_data.home }}/.ssh" + state: directory + owner: "{{ bootstrap_expected_user }}" + group: "{{ bootstrap_expected_user }}" + become: yes + - name: Transfer SSH keys to new user + copy: + remote_src: yes + src: "{{ bootstrap_user_data.home }}/.ssh/authorized_keys" + dest: "{{ bootstrap_expected_user_data.home }}/.ssh/authorized_keys" + owner: "{{ bootstrap_expected_user }}" + group: "{{ bootstrap_expected_user }}" + mode: u=rw,g=r + become: yes diff --git a/roles/bootstrap/tasks/shift_back.yml b/roles/bootstrap/tasks/shift_back.yml new file mode 100644 index 0000000..ec5310d --- /dev/null +++ b/roles/bootstrap/tasks/shift_back.yml @@ -0,0 +1,8 @@ +--- + +- set_fact: + bootstrap_used: no + ansible_user: '{{ bootstrap_expected_user }}' + ansible_become_pass: '{{ bootstrap_expected_become_pass }}' + +- meta: reset_connection \ No newline at end of file diff --git a/roles/bootstrap/tasks/try_else_shift.yml b/roles/bootstrap/tasks/try_else_shift.yml new file mode 100644 index 0000000..2d7c8d3 --- /dev/null +++ b/roles/bootstrap/tasks/try_else_shift.yml @@ -0,0 +1,12 @@ +--- + +- action: ping + ignore_unreachable: true + ignore_errors: yes + register: pingtest +- meta: clear_host_errors +- set_fact: + bootstrap_used: yes + ansible_user: '{{ bootstrap_user }}' + ansible_become_pass: '{{ bootstrap_become_pass }}' + when: pingtest.failed | d(pingtest.unreachable) | d(false)