mirror of
https://github.com/gryf/mkinitramfs.git
synced 2026-04-27 06:21:25 +02:00
Compare commits
4 Commits
84f93c519f
...
4633e0bc66
| Author | SHA1 | Date | |
|---|---|---|---|
| 4633e0bc66 | |||
| e1aef8338b | |||
| 7ecdc90baf | |||
| 7efac1607f |
+84
-28
@@ -7,46 +7,40 @@ Usage
|
||||
-----
|
||||
|
||||
- Create encrypted disk or partition using `cryptsetup`_
|
||||
- Create ``~/.config/mkinitramfs/disks.json`` file with similar content to:
|
||||
- Create ``~/.config/mkinitramfs.toml`` file with similar content to:
|
||||
|
||||
.. code:: json
|
||||
.. code:: toml
|
||||
|
||||
{
|
||||
"name": {
|
||||
"uuid": "disk-uuid",
|
||||
"key": "key-filename"
|
||||
},
|
||||
...
|
||||
}
|
||||
[name]
|
||||
uuid = "disk-uuid"
|
||||
key = "key-filename"
|
||||
|
||||
where every entry have disk name (**name** in this case), which have two
|
||||
attributes - disk/partition UUID and key filename.
|
||||
...
|
||||
|
||||
where every entry have disk name (**name** in this case), which have at least
|
||||
two attributes - disk/partition UUID and key filename.
|
||||
- Provide a key file for the disk/partition. Assumption is, that it is an
|
||||
encrypted file using `ccrypt`_ instead of plain file or password protected
|
||||
luks. Keys will be looked using provided path, i.e.
|
||||
|
||||
.. code:: json
|
||||
.. code:: toml
|
||||
|
||||
{
|
||||
"laptop": {
|
||||
"uuid": "88b99002-028f-4744-94e7-45e4580e2ddd",
|
||||
"key": "/full/path/to/the/laptop.key"
|
||||
},
|
||||
"desktop": {
|
||||
"uuid": "23e31327-1411-491c-ab00-c36f74c441f1",
|
||||
"key": "desktop.key"
|
||||
},
|
||||
"pendrive": {
|
||||
"uuid": "1453a45e-ca3f-4d39-8fd7-a6a96873c25c",
|
||||
"key": "../pendrive.key"
|
||||
}
|
||||
}
|
||||
[laptop]
|
||||
uuid = "88b99002-028f-4744-94e7-45e4580e2ddd"
|
||||
key = "/full/path/to/the/laptop.key"
|
||||
|
||||
[desktop]
|
||||
uuid = "23e31327-1411-491c-ab00-c36f74c441f1"
|
||||
key = "desktop.key"
|
||||
|
||||
[pendrive]
|
||||
uuid = "1453a45e-ca3f-4d39-8fd7-a6a96873c25c"
|
||||
key = "../pendrive.key"
|
||||
|
||||
so yes - it is possible to use key file in absolute or relative paths. If no
|
||||
key will be found, it's been looking for in path specified by
|
||||
``--key-path | -k`` parameter, which by default is in
|
||||
``$XDG_CONFIG_HOME/mkinitramfs/keys`` (usually in
|
||||
``~/.config/mkinitramfs/keys``.
|
||||
``$XDG_DATA_HOME/keys`` (usually it will be ``~/.local/share/keys``).
|
||||
- Move ``mkinitramfs.py`` script to some location in your ``$PATH`` (like
|
||||
``~/bin``)
|
||||
- Invoke ``mkinitramfs.py`` script:
|
||||
@@ -62,6 +56,41 @@ Usage
|
||||
on ``/boot`` with appropriate links. Note, that old images (they have
|
||||
``.old`` suffix in the filename) will be removed in that case.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Other than key path and device UUID, configuration can hold additional options
|
||||
similar to those passed via commandline. Consider following example:
|
||||
|
||||
.. code:: toml
|
||||
|
||||
[laptop]
|
||||
uuid = "88b99002-028f-4744-94e7-45e4580e2ddd"
|
||||
key_path = "/full/path/to/the/keys/dir"
|
||||
key = "laptop.key"
|
||||
yubikey = true
|
||||
dropbear = true
|
||||
ip = '192.168.0.1'
|
||||
gateway = '192.168.0.254'
|
||||
netmask = '24'
|
||||
user = 'gryf'
|
||||
authorized_keys = "/full/path/to/the/.ssh/authorized_keys"
|
||||
|
||||
This will inform mkinitramfs script, that dropbear and yubikey features are
|
||||
enabled. Also for network related configuration, there are last three options.
|
||||
|
||||
The complete list of supported options is listed below:
|
||||
|
||||
- ``copy_modules``
|
||||
- ``no_key``
|
||||
- ``key_path``
|
||||
- ``key``
|
||||
- ``disk_label``
|
||||
- ``sdcard``
|
||||
- ``yubikey``
|
||||
- ``dropbear``
|
||||
- ``user``
|
||||
|
||||
Using key devices
|
||||
-----------------
|
||||
|
||||
@@ -77,7 +106,34 @@ There is possibility for using key which is encrypted using response from
|
||||
challenge response using `ykchalresp`_ command. The challenge here could be
|
||||
any string, so the name of the device from config is used.
|
||||
|
||||
Dropbear
|
||||
--------
|
||||
|
||||
To unlock LUKS root filesystem remotely `dropbear`_ is used. There are expected
|
||||
configuration options in ``mkinitramfs.toml`` file:
|
||||
|
||||
- ``dropbear`` - true or false, false by default
|
||||
- ``iface`` interface name - ``eth0`` by default
|
||||
- ``ip`` - static IP address
|
||||
- ``netmask`` - netmask for the network
|
||||
- ``gateway`` - gateway for the network
|
||||
- ``user`` - username used for logging in, ``root`` by default. Note, whatever
|
||||
username will be placed here, it will be ``root`` effectively anyway
|
||||
- ``authorized_keys`` - path to ssh ``authorized_keys`` file. If there is no
|
||||
user set - which mens root username is used, by default it will look for the
|
||||
``/root/.ssh/authorized_keys``
|
||||
|
||||
You'll need to put at least ``ip``, ``netmask``, ``gateway`` to make this work
|
||||
with defaults, with assumption that interface is ``eth0`` and ``root`` user
|
||||
have needed ``authorized_keys`` file.
|
||||
|
||||
Then execute script with flag ``-b`` which include dropbear part.:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
# mkinitramfs.py -b laptop
|
||||
|
||||
.. _ccrypt: https://sourceforge.net/projects/ccrypt/
|
||||
.. _cryptsetup: https://gitlab.com/cryptsetup/cryptsetup/blob/master/README.md
|
||||
.. _ykchalresp: https://github.com/Yubico/yubikey-personalization
|
||||
.. _dropbear: https://matt.ucc.asn.au/dropbear/dropbear.html
|
||||
|
||||
+247
-58
@@ -1,21 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Python2/3 compatible initrd generating script
|
||||
Python initrd generating script
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import tomllib
|
||||
|
||||
|
||||
XDG_CONFIG_HOME = os.getenv('XDG_CONFIG_HOME', os.path.expanduser('~/.config'))
|
||||
XDG_DATA_HOME = os.getenv('XDG_DATA_HOME',
|
||||
os.path.expanduser('~/.local/share'))
|
||||
CONF_PATH = os.path.join(XDG_CONFIG_HOME, 'mkinitramfs.json')
|
||||
CONF_PATH = os.path.join(XDG_CONFIG_HOME, 'mkinitramfs.toml')
|
||||
KEYS_PATH = os.path.join(XDG_DATA_HOME, 'keys')
|
||||
ROOT_AK = '/root/.ssh/authorized_keys'
|
||||
SHEBANG = "#!/bin/bash\n"
|
||||
SHEBANG_ASH = "#!/bin/sh\n"
|
||||
DEPS = """
|
||||
@@ -25,6 +26,7 @@ DEPS=(
|
||||
/sbin/cryptsetup
|
||||
%(lvm)s
|
||||
%(yubikey)s
|
||||
%(dropbear)s
|
||||
)
|
||||
"""
|
||||
# /usr/sbin/dropbear
|
||||
@@ -45,6 +47,15 @@ for path in $(find /usr/lib/gcc|grep libgcc_s.so.1); do
|
||||
[ "$(basename $(dirname $path))" = '32' ] && continue
|
||||
cp $path lib/
|
||||
done
|
||||
|
||||
if %s; then
|
||||
if [ ! -f ~/.cache/askpass ]; then
|
||||
wget "https://bitbucket.org/piotrkarbowski/better-initramfs/downloads/askpass.c"
|
||||
gcc -Os -static askpass.c -o ~/.cache/askpass
|
||||
rm askpass.c
|
||||
fi
|
||||
cp ~/.cache/askpass bin/
|
||||
fi
|
||||
"""
|
||||
COPY_MODULES = """
|
||||
KERNEL=$(readlink /usr/src/linux)
|
||||
@@ -68,14 +79,11 @@ $CLEAR
|
||||
export PATH=/bin
|
||||
umask 0077
|
||||
|
||||
[ ! -d /proc ] && mkdir /proc
|
||||
[ ! -d /tmp ] && mkdir /tmp
|
||||
[ ! -d /mnt ] && mkdir /mnt
|
||||
[ ! -d /new-root ] && mkdir /new-root
|
||||
|
||||
mount -t devtmpfs -o nosuid,relatime,size=10240k,mode=755 devtmpfs /dev
|
||||
mount -t proc proc /proc
|
||||
mount -t sysfs sysfs /sys
|
||||
mount -t devtmpfs devtmpfs /dev
|
||||
|
||||
# clean i/o
|
||||
exec >/dev/console </dev/console 2>&1
|
||||
@@ -147,6 +155,49 @@ for counter in $(seq 3); do
|
||||
done
|
||||
"""
|
||||
|
||||
# optional: dropbear script for mounting device. It will use key if present
|
||||
# and interactively prompt for password
|
||||
DROPBEAR_SCRIPT = """
|
||||
for counter in $(seq 3); do
|
||||
sleep 1
|
||||
$CLEAR
|
||||
for dev in /dev/sd* /dev/nvme*; do
|
||||
if cryptsetup isLuks ${dev}; then
|
||||
if [ $(cryptsetup luksUUID ${dev}) = "${UUID}" ]; then
|
||||
DEVICE=$dev
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
[ -n "${DEVICE}" ] && break
|
||||
done
|
||||
|
||||
if [ -z "${DEVICE}" ]; then
|
||||
echo "No LUKS device found to boot from! Giving up."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -b /dev/mapper/root ]; then
|
||||
for i in 0 1 2 ; do
|
||||
askpass 'Enter decryption key: ' |ccrypt -c -k - $KEY | \
|
||||
cryptsetup open --allow-discards $DEVICE root
|
||||
ret=$?
|
||||
[ ${ret} -eq 0 ] && break
|
||||
done
|
||||
fi
|
||||
if [ ! -b /dev/mapper/root ]; then
|
||||
echo "Failed to open encrypted device $DEVICE"
|
||||
exit 2
|
||||
else
|
||||
echo "Successfully opened root device, continue booting."
|
||||
fi
|
||||
|
||||
# Kill the process for interactively providing password
|
||||
if [ ${ret} -eq 0 ]; then
|
||||
killall ccrypt
|
||||
fi
|
||||
"""
|
||||
|
||||
# Open encrypted fs
|
||||
INIT_OPEN = """
|
||||
for counter in $(seq 3); do
|
||||
@@ -201,14 +252,29 @@ done
|
||||
|
||||
"""
|
||||
|
||||
DROPBEAR = """\
|
||||
mkdir /dev/pts
|
||||
mount devpts /dev/pts -t devpts
|
||||
|
||||
ifconfig eth0 %(ip)s netmask %(netmask)s up
|
||||
route add default gw %(gateway)s eth0
|
||||
|
||||
dropbear -s -g -p 22
|
||||
"""
|
||||
|
||||
DECRYPT_PASSWORD = """
|
||||
if [ ! -b /dev/mapper/root ]; then
|
||||
for i in 0 1 2 ; do
|
||||
ccrypt -c $KEY | cryptsetup open --allow-discards $DEVICE root
|
||||
ret=$?
|
||||
[ ${ret} -eq 0 ] && break
|
||||
if [ -b /dev/mapper/root ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ ! -b /dev/mapper/root ]; then
|
||||
echo "Failed to open encrypted device. Rebooting in 5 seconds."
|
||||
reboot -f -d 5
|
||||
fi
|
||||
"""
|
||||
|
||||
SWROOT = """
|
||||
@@ -227,22 +293,67 @@ exec switch_root /new-root /sbin/init
|
||||
"""
|
||||
|
||||
|
||||
class Initramfs(object):
|
||||
def __init__(self, args, disks):
|
||||
self.lvm = args.lvm
|
||||
self.yk = args.yubikey
|
||||
self.name = args.disk
|
||||
self.modules = args.copy_modules
|
||||
self.key_path = args.key_path
|
||||
self.disk_label = args.disk_label
|
||||
self.sdcard = args.sdcard
|
||||
self.install = args.install
|
||||
self.no_key = args.no_key
|
||||
class Config:
|
||||
defaults = {'copy_modules': False,
|
||||
'disk_label': None,
|
||||
'dropbear': False,
|
||||
'install': False,
|
||||
'key_path': None,
|
||||
'lvm': False,
|
||||
'no_key': False,
|
||||
'sdcard': None,
|
||||
'yubikey': False}
|
||||
|
||||
def __init__(self, args, toml_conf):
|
||||
self.drive = args.get('drive')
|
||||
toml_ = toml_conf[self.drive]
|
||||
|
||||
for k, v in self.defaults.items():
|
||||
setattr(self, k, toml_.get(k, v))
|
||||
if getattr(self, k) is not args.get(k) and args.get(k) is not None:
|
||||
setattr(self, k, args[k])
|
||||
|
||||
key = None
|
||||
if not self.key_path and toml_.get('key'):
|
||||
key = toml_.get('key')
|
||||
if not os.path.exists(key):
|
||||
key = os.path.join(KEYS_PATH, key)
|
||||
if not os.path.exists(key):
|
||||
sys.stderr.write(f'Cannot find key file for '
|
||||
f'{toml_.get("key")}.\n')
|
||||
sys.exit(5)
|
||||
self.key_path = key
|
||||
|
||||
if not (self.key_path or self.no_key):
|
||||
sys.stderr.write(f'key file for {self.drive} is not provided, '
|
||||
f'while no-key option is not set.\n')
|
||||
sys.exit(6)
|
||||
|
||||
# UUID is only available via config file
|
||||
self.uuid = toml_.get('uuid')
|
||||
|
||||
# dropbear conf available only via config file
|
||||
self.ip = toml_.get('ip')
|
||||
self.gateway = toml_.get('gateway')
|
||||
self.netmask = toml_.get('netmask')
|
||||
self.iface = toml_.get('iface', 'eth0')
|
||||
self.user = toml_.get('user', 'root')
|
||||
if self.user != 'root' and not toml_.get('authorized_keys'):
|
||||
sys.stderr.write(f'User {self.user} is not authorized for '
|
||||
f'utilizing root .ssh/authorized_keys file. '
|
||||
f'Set authorized_keys file path in'
|
||||
f' configuration.')
|
||||
sys.exit(7)
|
||||
self.authorized_keys = toml_.get('authorized_keys', ROOT_AK)
|
||||
|
||||
|
||||
class Initramfs(object):
|
||||
def __init__(self, conf):
|
||||
self.conf = conf
|
||||
self.key = None
|
||||
self.dirname = None
|
||||
self.kernel_ver = os.readlink('/usr/src/linux').replace('linux-', '')
|
||||
self._make_tmp()
|
||||
self._disks = disks
|
||||
|
||||
def _make_tmp(self):
|
||||
self.dirname = tempfile.mkdtemp(prefix='init_')
|
||||
@@ -250,7 +361,7 @@ class Initramfs(object):
|
||||
|
||||
def _make_dirs(self):
|
||||
os.chdir(self.dirname)
|
||||
for dir_ in ('bin', 'dev', 'etc', 'keys', 'lib64', 'proc',
|
||||
for dir_ in ('bin', 'dev', 'etc', 'keys', 'lib64', 'proc', 'root',
|
||||
'run/cryptsetup', 'run/lock', 'sys', 'tmp'):
|
||||
os.makedirs(os.path.join(self.dirname, dir_))
|
||||
|
||||
@@ -265,11 +376,13 @@ class Initramfs(object):
|
||||
_fd, fname = tempfile.mkstemp(dir=self.dirname, suffix='.sh')
|
||||
os.close(_fd)
|
||||
with open(fname, 'w') as fobj:
|
||||
lvm = '/sbin/lvscan\n/sbin/vgchange' if self.lvm else ''
|
||||
yubikey = '/usr/bin/ykchalresp' if self.yk else ''
|
||||
lvm = '/sbin/lvscan\n/sbin/vgchange' if self.conf.lvm else ''
|
||||
yubikey = '/usr/bin/ykchalresp' if self.conf.yubikey else ''
|
||||
dropbear = '/usr/sbin/dropbear' if self.conf.dropbear else ''
|
||||
fobj.write(SHEBANG)
|
||||
fobj.write(DEPS % {'lvm': lvm, 'yubikey': yubikey})
|
||||
fobj.write(COPY_DEPS)
|
||||
fobj.write(DEPS % {'lvm': lvm, 'yubikey': yubikey,
|
||||
'dropbear': dropbear})
|
||||
fobj.write(COPY_DEPS % 'true' if self.conf.dropbear else 'false')
|
||||
|
||||
# extra crap, which seems to be needed, but is not direct dependency
|
||||
for root, _, fnames in os.walk('/usr/lib'):
|
||||
@@ -280,14 +393,62 @@ class Initramfs(object):
|
||||
if f.split('.')[0] in additional_libs:
|
||||
shutil.copy(os.path.join(root, f), 'lib64',
|
||||
follow_symlinks=False)
|
||||
self._copy_dropbear_deps()
|
||||
|
||||
os.chmod(fname, 0b111101101)
|
||||
subprocess.call([fname])
|
||||
os.unlink(fname)
|
||||
os.chdir(self.curdir)
|
||||
|
||||
def _copy_dropbear_deps(self):
|
||||
if not self.conf.dropbear:
|
||||
return
|
||||
|
||||
for dir_ in ('root/.ssh', 'etc/dropbear'):
|
||||
os.makedirs(os.path.join(self.dirname, dir_))
|
||||
|
||||
additional_libs = ['libnss_compat', 'libnss_files']
|
||||
for root, _, fnames in os.walk('/lib64'):
|
||||
for f in fnames:
|
||||
if f.split('.')[0] in additional_libs:
|
||||
shutil.copy(os.path.join(root, f), 'lib64',
|
||||
follow_symlinks=False)
|
||||
|
||||
shutil.copy('/etc/localtime', 'etc')
|
||||
|
||||
# Copy the authorized keys for your regular user you administrate with
|
||||
if (self.conf.authorized_keys and
|
||||
os.path.exists(self.conf.authorized_keys)):
|
||||
shutil.copy(self.conf.authorized_keys, 'root/.ssh')
|
||||
else:
|
||||
sys.stderr.write(f'Warning {self.conf.authorized_keys} not found!')
|
||||
|
||||
# Copy OpenSSH's host keys to keep both initramfs' and regular ssh
|
||||
# signed the same otherwise openssh clients will see different host
|
||||
# keys and chicken out. Here we only copy the ecdsa host key, because
|
||||
# ecdsa is default with OpenSSH. For RSA and others, copy adequate
|
||||
# keyfile.
|
||||
subprocess.run(['dropbearconvert', 'openssh', 'dropbear',
|
||||
'/etc/ssh/ssh_host_ecdsa_key',
|
||||
'etc/dropbear/dropbear_ecdsa_host_key'])
|
||||
|
||||
# Basic system defaults
|
||||
with open('etc/passwd', 'w') as fobj:
|
||||
fobj.write(f"{self.conf.user}:x:0:0:root:/root:/bin/sh\n")
|
||||
with open('etc/shadow', 'w') as fobj:
|
||||
fobj.write(f"{self.conf.user}:*:::::::\n")
|
||||
with open('etc/group', 'w') as fobj:
|
||||
fobj.write(f"{self.conf.user}:x:0:{self.conf.user}\n")
|
||||
with open('etc/shells', 'w') as fobj:
|
||||
fobj.write("/bin/sh\n")
|
||||
os.chmod('etc/shadow', 0b110100000)
|
||||
with open('etc/nsswitch.conf', 'w') as fobj:
|
||||
fobj.write("passwd: files\n"
|
||||
"shadow: files\n"
|
||||
"group: files\n")
|
||||
|
||||
def _copy_modules(self):
|
||||
if not self.modules:
|
||||
if not self.conf.copy_modules:
|
||||
return
|
||||
os.chdir(self.dirname)
|
||||
os.mkdir(os.path.join('lib', 'modules'))
|
||||
@@ -318,42 +479,63 @@ class Initramfs(object):
|
||||
os.symlink('busybox', command)
|
||||
|
||||
def _copy_key(self, suffix=''):
|
||||
key_path = self._disks[self.name]['key'] + suffix
|
||||
if not os.path.exists(key_path):
|
||||
key_path = os.path.join(self.key_path,
|
||||
self._disks[self.name]['key'] + suffix)
|
||||
key_path = self.conf.key_path + suffix
|
||||
|
||||
if not os.path.exists(key_path):
|
||||
self._cleanup()
|
||||
sys.stderr.write(f'Cannot find key(s) file for {self.name}.\n')
|
||||
sys.stderr.write(f'Cannot find key(s) file for '
|
||||
f'{self.conf.drive}.\n')
|
||||
sys.exit(2)
|
||||
|
||||
key_path = os.path.abspath(key_path)
|
||||
os.chdir(self.dirname)
|
||||
shutil.copy2(key_path, 'keys')
|
||||
os.chdir(self.curdir)
|
||||
if not (suffix or self.key):
|
||||
# set self.key only when:
|
||||
# - there is no key set to self
|
||||
# - suffix is empty
|
||||
# so that we could get the key name calculated for the yk
|
||||
self.key = os.path.basename(key_path)
|
||||
|
||||
def _generate_init(self):
|
||||
os.chdir(self.dirname)
|
||||
with open('init', 'w') as fobj:
|
||||
fobj.write(SHEBANG_ASH)
|
||||
fobj.write(f"UUID='{self._disks[self.name]['uuid']}'\n")
|
||||
fobj.write(f"KEY='/keys/{self._disks[self.name]['key']}'\n")
|
||||
fobj.write(f"UUID='{self.conf.uuid}'\n")
|
||||
if self.key:
|
||||
fobj.write(f"KEY='/keys/{self.key}'\n")
|
||||
fobj.write(INIT)
|
||||
fobj.write(INIT_CMD)
|
||||
if self.disk_label:
|
||||
fobj.write(INIT_LABELED % {'label': self.disk_label})
|
||||
if self.sdcard:
|
||||
if self.conf.disk_label:
|
||||
fobj.write(INIT_LABELED % {'label': self.conf.disk_label})
|
||||
if self.conf.sdcard:
|
||||
fobj.write(INIT_SD)
|
||||
fobj.write(INIT_OPEN)
|
||||
if self.disk_label or self.sdcard:
|
||||
if self.conf.disk_label or self.conf.sdcard:
|
||||
fobj.write(DECRYPT_KEYDEV)
|
||||
if self.yk:
|
||||
fobj.write(DECRYPT_YUBICP % {'disk': self.name})
|
||||
if self.conf.yubikey:
|
||||
fobj.write(DECRYPT_YUBICP % {'disk': self.conf.drive})
|
||||
if self.conf.dropbear:
|
||||
fobj.write(DROPBEAR % {'ip': self.conf.ip,
|
||||
'gateway': self.conf.gateway,
|
||||
'netmask': self.conf.netmask})
|
||||
fobj.write(DECRYPT_PASSWORD)
|
||||
if self.conf.dropbear:
|
||||
fobj.write("killall dropbear\n")
|
||||
fobj.write(SWROOT)
|
||||
|
||||
os.chmod('init', 0b111101101)
|
||||
|
||||
if self.conf.dropbear:
|
||||
with open('root/decrypt.sh', 'w') as fobj:
|
||||
fobj.write(SHEBANG_ASH)
|
||||
fobj.write(f"UUID='{self.conf.uuid}'\n")
|
||||
if self.key:
|
||||
fobj.write(f"KEY='/keys/{self.key}'\n")
|
||||
fobj.write(DROPBEAR_SCRIPT)
|
||||
os.chmod('root/decrypt.sh', 0b111101101)
|
||||
|
||||
os.chdir(self.curdir)
|
||||
|
||||
def _mkcpio_arch(self):
|
||||
@@ -372,7 +554,7 @@ class Initramfs(object):
|
||||
|
||||
os.chmod(self.cpio_arch, 0b110100100)
|
||||
|
||||
if self.install:
|
||||
if self.conf.install:
|
||||
self._make_boot_links()
|
||||
else:
|
||||
shutil.move(self.cpio_arch, 'initramfs.cpio')
|
||||
@@ -412,31 +594,31 @@ class Initramfs(object):
|
||||
self._copy_modules()
|
||||
# self._copy_wlan_modules()
|
||||
self._populate_busybox()
|
||||
if not self.no_key:
|
||||
if not self.conf.no_key:
|
||||
self._copy_key()
|
||||
if self.yk:
|
||||
if self.conf.yubikey:
|
||||
self._copy_key('.yk')
|
||||
self._generate_init()
|
||||
self._mkcpio_arch()
|
||||
self._cleanup()
|
||||
|
||||
|
||||
def _disks_msg():
|
||||
sys.stdout.write('You need to create %s json file with the '
|
||||
'contents:\n\n'
|
||||
'{\n'
|
||||
' "name": {\n'
|
||||
' "uuid": "disk-uuid",\n'
|
||||
' "key": "key-filename"\n'
|
||||
' },\n'
|
||||
' ...\n'
|
||||
'}\n' % CONF_PATH)
|
||||
def _disks_msg(msg=None):
|
||||
if not msg:
|
||||
sys.stdout.write('You need to create %s toml file with the '
|
||||
'contents:\n\n'
|
||||
'[name]\n'
|
||||
'uuid = "disk-uuid"\n'
|
||||
'key = "key-filename"\n'
|
||||
'...\n' % CONF_PATH)
|
||||
else:
|
||||
sys.stdout.write(msg + '\n')
|
||||
|
||||
|
||||
def _load_disks():
|
||||
try:
|
||||
with open(CONF_PATH) as fobj:
|
||||
return json.load(fobj)
|
||||
with open(CONF_PATH, 'rb') as fobj:
|
||||
return tomllib.load(fobj)
|
||||
except IOError:
|
||||
_disks_msg()
|
||||
sys.exit(1)
|
||||
@@ -465,7 +647,7 @@ def main():
|
||||
'assuming SD card/usb stick is the only way to open '
|
||||
'encrypted root.')
|
||||
parser.add_argument('-k', '--key-path', help='path to the location where '
|
||||
'keys are stored', default=KEYS_PATH)
|
||||
'keys are stored')
|
||||
parser.add_argument('-d', '--disk-label', help='Provide disk label '
|
||||
'to be read decription key from.')
|
||||
parser.add_argument('-s', '--sdcard', help='Use built in sdcard reader to '
|
||||
@@ -474,10 +656,17 @@ def main():
|
||||
help='Enable LVM in init.')
|
||||
parser.add_argument('-y', '--yubikey', action='store_true',
|
||||
help='Enable Yubikey challenge-response in init.')
|
||||
parser.add_argument('disk', choices=disks.keys(), help='Disk name')
|
||||
parser.add_argument('-b', '--dropbear', action='store_true',
|
||||
help='Enable dropbear ssh server for remotely connect '
|
||||
'to initrd.')
|
||||
parser.add_argument('drive', choices=disks.keys(), help='Drive name')
|
||||
|
||||
args = parser.parse_args()
|
||||
init = Initramfs(args, disks)
|
||||
if args.drive not in disks:
|
||||
_disks_msg(f'Drive {args.drive} not found in configuration')
|
||||
sys.exit(4)
|
||||
conf = Config(args.__dict__, disks)
|
||||
init = Initramfs(conf)
|
||||
init.build()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user