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