add remote_unlock role

This commit is contained in:
Frank Adaemmer 2022-10-16 22:37:47 +02:00
parent afbb8cadc6
commit 94aa41bb86
9 changed files with 332 additions and 0 deletions

View 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
```

View file

@ -0,0 +1,2 @@
---
unlock_port: 222

View 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

View 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

View 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.

View 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:

View 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

View 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 }}"

View 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