add remote_unlock role
This commit is contained in:
parent
afbb8cadc6
commit
94aa41bb86
58
roles/remote_unlock/README.md
Normal file
58
roles/remote_unlock/README.md
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
# remote_unlock Role
|
||||||
|
Login to initial ram filesystem via SSH and unlock encrypted disks.
|
||||||
|
Proceed boot after unlock.
|
||||||
|
|
||||||
|
With alternative entry point 'prepare' that system gets setup for this task.
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
<!-- BEGIN Argument Specs -->
|
||||||
|
|Name |Type |Requiered |Default |Description |
|
||||||
|
|------|------|-----------|--------|-------------|
|
||||||
|
|unlock_port |int | no | 222 | TCP/IP port of the initial ram filesystem SSH daemon |
|
||||||
|
|luks_passphrase |str | yes | | Passphrase to unlock encrypted LUKS disks |
|
||||||
|
|
||||||
|
### Alternative Entry Point 'prepare'
|
||||||
|
|
||||||
|
Install all dependencies and build a initial ram filesystem that runs a SSH daemon.
|
||||||
|
SSH will that be available to unlock LUKS encrypted disks from remote.
|
||||||
|
|
||||||
|
|Name |Type |Requiered |Default |Description |
|
||||||
|
|------|------|-----------|--------|-------------|
|
||||||
|
|unlock_port |int | no | 222 | TCP/IP port of the initial ram filesystem SSH daemon |
|
||||||
|
|ssh_keys |list[str] | yes | | List of ssh public keys that will be added to .ssh/authorized_keys |
|
||||||
|
<!-- END Argument Specs -->
|
||||||
|
|
||||||
|
## Example
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
- name: Remote Unlock Test
|
||||||
|
hosts: all
|
||||||
|
vars:
|
||||||
|
unlock_port: 2224
|
||||||
|
luks_passphrase: '123456'
|
||||||
|
ssh_keys:
|
||||||
|
- "ssh-rsa 8J+OtU5ldmVyIGdvbm5hIGdpdmUgeW91IHVw8J+Otg== UmljayDwn5W6@IPCfp7sg"
|
||||||
|
- "ssh-ed25519 TmV2ZXIgZ29ubmEgbGV0IHlvdSBkb3du8J+Otg== UmljayDwn5W6@IPCfp7sg"
|
||||||
|
tasks:
|
||||||
|
- name: Prepare Unlock
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: copyrights.on_premises.remote_unlock
|
||||||
|
tasks_from: prepare.yml
|
||||||
|
vars:
|
||||||
|
ansible_become: true
|
||||||
|
|
||||||
|
- name: Flush handlers
|
||||||
|
ansible.builtin.meta: flush_handlers
|
||||||
|
|
||||||
|
- name: Restart
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: shutdown -r +1
|
||||||
|
become: true
|
||||||
|
changed_when: result['rc'] == 0
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Unlock after reboot
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: copyrights.on_premises.remote_unlock
|
||||||
|
|
||||||
|
```
|
||||||
2
roles/remote_unlock/defaults/main.yml
Normal file
2
roles/remote_unlock/defaults/main.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
unlock_port: 222
|
||||||
29
roles/remote_unlock/handlers/main.yml
Normal file
29
roles/remote_unlock/handlers/main.yml
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
---
|
||||||
|
- name: Regenerate initramfs
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: dracut --force
|
||||||
|
changed_when: result['rc'] == 0
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Configure dracut-crypt-ssh build
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: ./configure
|
||||||
|
chdir: /opt/src/dracut-crypt-ssh
|
||||||
|
changed_when: result['rc'] == 0
|
||||||
|
register: result
|
||||||
|
listen: Build dracut-crypt-ssh
|
||||||
|
|
||||||
|
- name: Build dracut-crypt-ssh
|
||||||
|
community.general.make:
|
||||||
|
chdir: /opt/src/dracut-crypt-ssh
|
||||||
|
listen: Build dracut-crypt-ssh
|
||||||
|
|
||||||
|
- name: Install dracut-crypt-ssh
|
||||||
|
community.general.make:
|
||||||
|
chdir: /opt/src/dracut-crypt-ssh
|
||||||
|
target: install
|
||||||
|
listen: Build dracut-crypt-ssh
|
||||||
|
|
||||||
|
- name: Regenerate GRUB
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: grub2-mkconfig --output /etc/grub2.cfg
|
||||||
31
roles/remote_unlock/meta/argument_specs.yml
Normal file
31
roles/remote_unlock/meta/argument_specs.yml
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
---
|
||||||
|
argument_specs:
|
||||||
|
main:
|
||||||
|
short_description: Unlock LUKS encrypted disks from within initial ram filesystem
|
||||||
|
description: |
|
||||||
|
Login to initial ram filesystem via SSH and unlock encrypted disks.
|
||||||
|
Proceed boot after unlock.
|
||||||
|
options:
|
||||||
|
unlock_port:
|
||||||
|
default: 222
|
||||||
|
description: TCP/IP port of the initial ram filesystem SSH daemon
|
||||||
|
type: "int"
|
||||||
|
luks_passphrase:
|
||||||
|
description: Passphrase to unlock encrypted LUKS disks
|
||||||
|
type: "str"
|
||||||
|
required: true
|
||||||
|
prepare:
|
||||||
|
short_description: Setup initial ram filesystem to run a SSH daemon
|
||||||
|
description: |
|
||||||
|
Install all dependencies and build a initial ram filesystem that runs a SSH daemon.
|
||||||
|
SSH will that be available to unlock LUKS encrypted disks from remote.
|
||||||
|
options:
|
||||||
|
unlock_port:
|
||||||
|
default: 222
|
||||||
|
description: TCP/IP port of the initial ram filesystem SSH daemon
|
||||||
|
type: "int"
|
||||||
|
ssh_keys:
|
||||||
|
description: "List of ssh public keys that will be added to .ssh/authorized_keys"
|
||||||
|
type: 'list'
|
||||||
|
elements: 'str'
|
||||||
|
required: true
|
||||||
45
roles/remote_unlock/meta/main.yml
Normal file
45
roles/remote_unlock/meta/main.yml
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
author: Frank Adaemmer <frank@adaemmer.com>
|
||||||
|
description: Unlock LUKS encrypted disks from within initial ram filesystem
|
||||||
|
|
||||||
|
# If the issue tracker for your role is not on github, uncomment the
|
||||||
|
# next line and provide a value
|
||||||
|
# issue_tracker_url: http://example.com/issue/tracker
|
||||||
|
|
||||||
|
# Choose a valid license ID from https://spdx.org - some suggested licenses:
|
||||||
|
# - BSD-3-Clause (default)
|
||||||
|
# - MIT
|
||||||
|
# - GPL-2.0-or-later
|
||||||
|
# - GPL-3.0-only
|
||||||
|
# - Apache-2.0
|
||||||
|
# - CC-BY-4.0
|
||||||
|
license: GPL-3.0-or-later
|
||||||
|
|
||||||
|
min_ansible_version: '2.9'
|
||||||
|
|
||||||
|
# If this a Container Enabled role, provide the minimum Ansible Container version.
|
||||||
|
# min_ansible_container_version:
|
||||||
|
|
||||||
|
#
|
||||||
|
# Provide a list of supported platforms, and for each platform a list of versions.
|
||||||
|
# If you don't wish to enumerate all versions for a particular platform, use 'all'.
|
||||||
|
# To view available platforms and versions (or releases), visit:
|
||||||
|
# https://galaxy.ansible.com/api/v1/platforms/
|
||||||
|
#
|
||||||
|
platforms:
|
||||||
|
- name: EL
|
||||||
|
version:
|
||||||
|
- '9'
|
||||||
|
|
||||||
|
galaxy_tags: []
|
||||||
|
# List tags for your role here, one per line. A tag is a keyword that describes
|
||||||
|
# and categorizes the role. Users find roles by searching for tags. Be sure to
|
||||||
|
# remove the '[]' above, if you add tags to this list.
|
||||||
|
#
|
||||||
|
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
|
||||||
|
# Maximum 20 tags per role.
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
|
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
|
||||||
|
# if you add dependencies to this list.
|
||||||
12
roles/remote_unlock/tasks/main.yml
Normal file
12
roles/remote_unlock/tasks/main.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
- name: Wait unlock port
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
host: "{{ ansible_host }}"
|
||||||
|
port: "{{ unlock_port }}"
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
- name: Unlock
|
||||||
|
ansible.builtin.include_tasks: unlock.yml
|
||||||
|
|
||||||
|
- name: Wait for {{ inventory_hostname }}
|
||||||
|
ansible.builtin.wait_for_connection:
|
||||||
116
roles/remote_unlock/tasks/prepare.yml
Normal file
116
roles/remote_unlock/tasks/prepare.yml
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
---
|
||||||
|
- name: Install EPEL
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name:
|
||||||
|
- oracle-epel-release-el9
|
||||||
|
state: present
|
||||||
|
- name: Install Dependencies
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name:
|
||||||
|
- make
|
||||||
|
- libblkid-devel
|
||||||
|
- gcc
|
||||||
|
- git
|
||||||
|
- dropbear
|
||||||
|
state: present
|
||||||
|
- name: Clone dracut-crypt-ssh
|
||||||
|
ansible.builtin.git:
|
||||||
|
repo: https://github.com/dracut-crypt-ssh/dracut-crypt-ssh.git
|
||||||
|
dest: /opt/src/dracut-crypt-ssh
|
||||||
|
version: master
|
||||||
|
notify: Build dracut-crypt-ssh
|
||||||
|
|
||||||
|
- name: Flush handlers
|
||||||
|
ansible.builtin.meta: flush_handlers
|
||||||
|
|
||||||
|
- name: Create small dracut module
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /usr/lib/dracut/modules.d/99cryptsetup
|
||||||
|
state: directory
|
||||||
|
mode: 0755
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
seuser: system_u
|
||||||
|
serole: object_r
|
||||||
|
setype: bin_t
|
||||||
|
selevel: s0
|
||||||
|
|
||||||
|
- name: Ensure cryptsetup is installed in dracut
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /usr/lib/dracut/modules.d/99cryptsetup/module-setup.sh
|
||||||
|
content: |
|
||||||
|
#!/bin/bash
|
||||||
|
check() {
|
||||||
|
require_binaries cryptsetup || return 1
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
depends() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
install() {
|
||||||
|
inst cryptsetup
|
||||||
|
dracut_need_initqueue
|
||||||
|
}
|
||||||
|
|
||||||
|
mode: 0755
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
seuser: system_u
|
||||||
|
serole: object_r
|
||||||
|
setype: bin_t
|
||||||
|
selevel: s0
|
||||||
|
notify: Regenerate initramfs
|
||||||
|
|
||||||
|
- name: Configure dracut-crypt-ssh
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/dracut.conf.d/crypt-ssh.conf
|
||||||
|
content: |
|
||||||
|
dropbear_port="{{ unlock_port }}"
|
||||||
|
# System keys are in an OpenSSH-specific format (not PEM).
|
||||||
|
# So let's stick with default GENERATE or conver all key with
|
||||||
|
# ssh-keygen -m PEM -p -f <key file>
|
||||||
|
# dropbear_rsa_key="SYSTEM"
|
||||||
|
# dropbear_ecdsa_key="SYSTEM"
|
||||||
|
# dropbear_ed25519_key="SYSTEM"
|
||||||
|
dropbear_acl="/etc/dracut.conf.d/authorized_keys"
|
||||||
|
mode: 0644
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
seuser: unconfined_u
|
||||||
|
serole: object_r
|
||||||
|
setype: etc_t
|
||||||
|
selevel: s0
|
||||||
|
notify: Regenerate initramfs
|
||||||
|
|
||||||
|
- name: Configure dracut authorized_keys
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/dracut.conf.d/authorized_keys
|
||||||
|
content: |
|
||||||
|
{% for ssh_key in ssh_keys %}
|
||||||
|
{{ ssh_key }}
|
||||||
|
{% endfor %}
|
||||||
|
mode: 0600
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
seuser: unconfined_u
|
||||||
|
serole: object_r
|
||||||
|
setype: etc_t
|
||||||
|
selevel: s0
|
||||||
|
notify: Regenerate initramfs
|
||||||
|
|
||||||
|
- name: Get GRUB defaults
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: /etc/default/grub
|
||||||
|
register: tmp_grub
|
||||||
|
|
||||||
|
- name: Configure GRUB
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/default/grub
|
||||||
|
content: "{{
|
||||||
|
tmp_grub['content'] | b64decode |
|
||||||
|
regex_replace('rd\\.neednet=\\S+\\s', '') |
|
||||||
|
regex_replace('ip=\\S+\\s', '') |
|
||||||
|
replace('quiet', 'rd.neednet=1 ip=dhcp quiet')
|
||||||
|
}}"
|
||||||
|
mode: 0644
|
||||||
|
notify: Regenerate GRUB
|
||||||
12
roles/remote_unlock/tasks/unlock.yml
Normal file
12
roles/remote_unlock/tasks/unlock.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
- name: Unlock LUKS via dracut
|
||||||
|
ansible.builtin.raw: |
|
||||||
|
cat << EOF | unlock && /sbin/unlock-reap-success
|
||||||
|
{{ luks_passphrase }}
|
||||||
|
EOF
|
||||||
|
register: unlock
|
||||||
|
changed_when: unlock['rc'] == 0
|
||||||
|
vars:
|
||||||
|
ansible_user: root
|
||||||
|
ansible_ssh_extra_args: '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
|
||||||
|
ansible_ssh_port: "{{ unlock_port }}"
|
||||||
27
roles/remote_unlock/tests/unlock_test.yml
Normal file
27
roles/remote_unlock/tests/unlock_test.yml
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
- name: Remote Unlock Test
|
||||||
|
hosts: all
|
||||||
|
vars:
|
||||||
|
unlock_port: 2224
|
||||||
|
luks_passphrase: '123456'
|
||||||
|
tasks:
|
||||||
|
- name: Prepare Unlock
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: copyrights.on_premises.remote_unlock
|
||||||
|
tasks_from: prepare.yml
|
||||||
|
vars:
|
||||||
|
ansible_become: true
|
||||||
|
|
||||||
|
- name: Flush handlers
|
||||||
|
ansible.builtin.meta: flush_handlers
|
||||||
|
|
||||||
|
- name: Restart
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: shutdown -r +1
|
||||||
|
become: true
|
||||||
|
changed_when: result['rc'] == 0
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Unlock after reboot
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: copyrights.on_premises.remote_unlock
|
||||||
Loading…
Reference in a new issue