Hide last authors
Jan Rhebergen 1.1 1 All the servers and laptop have been installed with Pop!_OS. The reason being the special attention Pop!_OS is givng to Nvidia GPU support. We want good and flexible NVidia GPU support because we plan to use the CUDA libraries for machine learning applications. Pop!_OS is an Ubuntu derivative with a little more than just "re-theming".
2
3 Laptops are all configured using encrypted storage devices. This is a safety precaution as laptops are mobile devices and are regularly moved between locations. A stolen or lost laptop hence should not pose a security threat. Although the data on the laptop is non-confidential the mere fact that this is a Defence owned laptop will create an embarrassment. This we don't want even though there is no real security issue at stake here.
4
5 Server are supposed to be at a fixed secure location. Storage device encryption is not deemed necessary. If a server happens to be a laptop (yes this can be) we still implement storage level encryption.
6
7 Although strictly speaking not needed for laptops where possible we employ the ##btrfs## filesystem. This has several advantages:
8
9 * Flexibility (expandability)
10 * Snapshots
11
12 Btrfs filesystems are by now considered mature and offer more flexibility than other enterprise grade filesystem such as ##zfs##. For small deployments therefore ##btrfs## is a better fit.
13
14 The possibility to create instant snapshots offer great way to safeguard against accidental loss through inadvertenty deleting file or other minor mishaps that can be annoying and cost substantial amounts of time to recover from.
15
16 The following guide [[https:~~/~~/mutschler.eu/linux/install-guides/pop-os-btrfs/>>https://mutschler.eu/linux/install-guides/pop-os-btrfs/]] was used although adapted to our specific case, i.e. no virtual machine and depending on use case either encryption or not.
17
18 = Encryption =
19
20 Only laptops are going to be encrypted because they may in theory be transported and used elsewhere and could  be stolen or lost. The embarrassment to have this happen to an unencrypted Defence laptop is reason enough to warrant encrypting the hard drive.
21
22 The mere form factor of a laptop does not preclude it from functioning as a server. There is however a small problem. When you are logged in remotely and you update/upgrade the operating system you may need to reboot the laptop. Due to the encryption you have to physically be present at the same location as the laptop to enter the pass-phrase that starts decryption on booting. Of course this is not possible when you are working remote. The answer to this problem is to create solution where an external USB flash drive is detected on booting the system and used to store/retrieve a key that enables decryption. The boot menu will still contain a back-up boot option that works with a physically entered pass-phrase. The default boot option will look for the USB flash drive with decryption key. A better way to achieve the same goal is to use a ##ubikey## [[https:~~/~~/www.yubico.com/>>https://www.yubico.com/]] It has some additional advantages like two factor authentication, etc. In case the USB flash drive with key is lost or stolen, one can simple remove the respective key from the keyslot on the encrypted device thus keeping it secure.
23
24 == Implementation ==
25
26 As stated above one normally enters a passphrase to unlock the encrypted device and boot the system. The alternative is to use a key to do the job. This key is read automatically from a device and is used to decrypt the hard drive which contains the operating system and file system with user directories home.
27
28 === Procedure outline ===
29
30 1. Create an alternate backup systemd-boot boot option (for safety/emergency reasons).
31 1. Create and save a suitable keyfile, either a binary or a character sequence.
32 1. Add the keyfile to a key-slot on the encrypted device (the hard drive with the root and home filesystem)
33 1. Prepare a USB device, obtain device partition ID and copy the keyfile to it.
34 1. Create a script that is called at boot time and searches for the USB ID and copy it to## /boot/##.
35 1. Edit ##/etc/crypttab ##to enable the ##keyfile.sh## script and regenerate ##initrd.img##
36
37 Finally Test by rebooting with USB flash drive inserted
38
39 === 1. Create a fallback boot option ===
40
41 To create a fallback boot option do the following:
42
43 (% class="box" %)
44 {{{cd /boot/efi/EFI/Pop_OS-eea7a2f5-b204-4de3-b605-3696ed323544
45 cp vmlinuz.efi vmlinuz-backup.efi
46 cp initrd.img initrd.img-backup
47
48 cd /boot/efi/loader/entries
49 cp Pop_OS-current.conf Pop_OS-backup.conf
50 }}}
51
52 Then edit the file Pop_OS-backup.conf like shown below:
53
54 (% class="box" %)
55 {{{title Pop!_OS
56 linux /EFI/Pop_OS-eea7a2f5-b204-4de3-b605-3696ed323544/vmlinuz-backup.efi
57 initrd /EFI/Pop_OS-eea7a2f5-b204-4de3-b605-3696ed323544/initrd.img-backup
58 options root=UUID=eea7a2f5-b204-4de3-b605-3696ed323544 ro quiet loglevel=0 systemd.show_status=false splash rootflags=subvol=@
59 }}}
60
61 Changing the title is optional. **NB: it is important to reboot and test this option now!**
62
63 === 2. Create the secret keyfile ===
64
65 The key can be a sequence of printable (visible) characters or any binary sequence of a certain length. Below examples of how to generate these:
66
67 **binary sequence:**
68
69 (% class="box" %)
70 {{{dd if=/dev/urandom of=/etc/luks-keys/mykey.bin bs=512 count=4}}}
71
72 **character sequence:**
73
74 Either this one:
75
76 (% class="box" %)
77 {{{head -c 2048 /dev/urandom | base64 -w 0 > mykey.txt
78 chmod -v 0400 mykey.txt
79 }}}
80
81 or slightly better, this one:
82
83 (% class="box" %)
84 {{{dd bs=256 count=8 if=/dev/random | base64 -w 0 > mykey.txt
85 chmod -v 0400 mykey.txt
86 }}}
87
88 Either key is fine, but if you would like to be able to type it in via the keyboard, the latter option is preferred for obvious reasons. The key will reside on a USB flash drive. However this flash drive may be removed intentionally or unintentionally. Hence deploying the key based automated decryption method we still want to create a fallback option in case the key is not available. This fallback boot option uses an untainted kernel and initrd image (i.e. originals) to be used with the regular pass phrase that is to be entered at the prompt before booting the system.
89
90 === 3. Add key to keyslot on encrypted device ===
91
92 Be careful to choose the correct device for adding the key. Using parted## /dev/nvme0n1 ##one can inspect the partition layout of the first device (in this case an SSD).
93
94 (% class="box" %)
95 {{{root@schumann:~# parted /dev/nvme0n1
96 GNU Parted 3.3
97 Using /dev/nvme0n1
98 Welcome to GNU Parted! Type 'help' to view a list of commands.
99 (parted) p
100 Model: INTEL SSDPEKNW512G8H (nvme)
101 Disk /dev/nvme0n1: 512GB
102 Sector size (logical/physical): 512B/512B
103 Partition Table: gpt
104 Disk Flags:
105
106 Number Start End Size File system Name Flags
107 1 1049kB 538MB 537MB fat32 SYSTEM boot, esp
108 2 538MB 555MB 16.8MB Microsoft reserved partition msftres
109 3 555MB 105GB 105GB ntfs Basic data partition msftdata
110 5 105GB 512GB 406GB cryptdata
111 4 512GB 512GB 503MB ntfs Basic data partition hidden, diag
112
113 (parted)
114
115 }}}
116
117 (% class="box" %)
118 {{{cryptsetup -v luksAddKey /dev/nvme0n1p5 mykey.txt
119 }}}
120
121 === 4. Store the keyfile on the USB flash drive ===
122
123 Upon boot the key needs to be retrieved from the USB flash drive so we need to store it there first. The USB flash drive is prepared in such a way as to obfuscate the fact that a key is present. The text below shows the partition layout of the USB flash drive. There is a small hidden 1MiB partition which we will use to hold the key. One could also decide to obfuscate a little more by not making a true partition but simply start the first partition at an offset of 1MiB beyond the partition table and store the key at a known (predetermined) offset within that 1MiB space. However this we consider potentially error prone and needs to be tested well before deciding to adopt this approach.
124
125 (% class="box" %)
126 {{{root@schumann:~# parted /dev/sda
127 GNU Parted 3.3
128 Using /dev/sda
129 Welcome to GNU Parted! Type 'help' to view a list of commands.
130 (parted) p
131 Model: USB BAR (scsi)
132 Disk /dev/sda: 65.4MB
133 Sector size (logical/physical): 512B/512B
134 Partition Table: gpt
135 Disk Flags:
136
137 Number Start End Size File system Name Flags
138 1 1049kB 2097kB 1049kB KEY hidden
139 2 2097kB 65.4MB 63.3MB fat16 SILVER msftdata
140
141 (parted)
142 }}}
143
144 To be able to detect the USB flash drive when inserted at boot time we need to know it's device ID.
145
146 (% class="box" %)
147 {{{root@schumann:~# ls -l /dev/disk/by-id | grep sda2
148 lrwxrwxrwx 1 root root 10 Apr 21 10:07 usb-USB_USB_BAR-0:0-part2 -> ../../sda2
149 }}}
150
151 We also need to know (confirm) the size of the key file.
152
153 (% class="box" %)
154 {{{root@schumann:~# ls -l
155 total 4
156 drwxr-xr-x 1 root root 32 Apr 21 09:38 bin
157 drwxr-xr-x 1 root root 28 Apr 19 12:06 docs
158 -rw-r--r-- 1 root root 2732 Apr 21 10:45 mykey.txt
159 }}}
160
161 (% class="box" %)
162 {{{root@schumann:~# dd if=mykey.txt of=/dev/disk/by-id/usb-USB_USB_BAR-0:0-part1 bs=1 count=2732
163 2732+0 records in
164 2732+0 records out
165 2732 bytes (2.7 kB, 2.7 KiB) copied, 0.00868143 s, 315 kB/s
166 }}}
167
168 === 5. Create the ##keyfile## script to get key to ##stdout## ===
169
170 The script below will wait for our USB device to become available and read the key from the respective number of bytes (2732) on partition 1. The script ##keyfile.sh## is (for now) stored in the ##/bin/## directory.
171
172 (% class="box" %)
173 {{{for TRY in {1..60}
174 do
175 if ! [ -e /dev/disk/by-id/usb-USB_USB_BAR-0:0-part2 ]; then
176 # echo $TRY
177 sleep 1
178 fi
179 done # for TRY
180 if [ -e /dev/disk/by-id/usb-USB_USB_BAR-0:0-part1 ]; then
181 dd if=/dev/disk/by-id/usb-USB_USB_BAR-0:0-part1 bs=1 skip=0 count=2732 2>/dev/null
182 fi
183 }}}
184
185 Let's see if the key that is read by the script is identical to the original one in our home directory.
186
187 (% class="box" %)
188 {{{{ [[ "$(~/bin/keyfile.sh)" == "$(cat ~/mykey.txt)" ]] && echo 'SUCCESS.'; } || echo 'FAILURE: NOT THE SAME.';
189 }}}
190
191 Make sure the ##keyfile.sh## script is executable (should already be).
192
193 (% class="box" %)
194 {{{chmod +x keyfile.sh
195 chmod -v 0500 keyfile.sh
196 cp keyfile.sh /boot/
197 }}}
198
199 === 6. Edit ##/etc/crypttab ##to enable the key script and regenerate ##initrd.img## ===
200
201 Now modify ##/etc/crypttab## from:
202
203 (% class="box" %)
204 {{{cryptdata UUID=bacc09ab-6e12-4365-be8f-d7b09ae0c0a5 none luks
205 }}}
206
207 to:
208
209 (% class="box" %)
210 {{{cryptdata UUID=bacc09ab-6e12-4365-be8f-d7b09ae0c0a5 /dev/disk/by-id/usb-USB_USB_BAR-0:0-part1 luks,keyscript=/boot/keyfile.sh
211 }}}
212
213 and update ##initrd.img##
214
215 (% class="box" %)
216 {{{update-initramfs -u
217 }}}

Need help?

If you need help with XWiki you can contact: