Procedure to mount a LUKS encrypted device into a Container Optimized OS.
- Create a disk and attach to a plain VM
- Create format and mount as LUKS
- Write file to LUKS mount path
- Detach disk from VM
- Create COS VM and attach disk (in this case, as
/dev/sdb
) - Start container with cloud-init and map device
/usr/bin/docker run --rm -u 0 --privileged --device /dev/sdb:/dev/sdb --name=mycloudservice docker.io/
- Mount disk
- Initialize as LUKS
- Access file
ref: Mounting CSEK protected disk with LUKS encryption on Google Compute Engine
### Create VM
$ gcloud compute instances create instance-2 \
--zone=us-central1-a --no-service-account \
--no-scopes --image=debian-10-buster-v20201014 \
--image-project=debian-cloud --boot-disk-size=10GB \
--boot-disk-type=pd-standard --boot-disk-device-name=instance-2
### Create and attach disk
$ gcloud beta compute disks create luks-direct --type=pd-standard --size=10GB --zone=us-central1-a
$ gcloud compute instances attach-disk instance-2 --disk luks-direct
### SSH to VM
$ gcloud compute ssh instance-2
$ export DEBIAN_FRONTEND=noninteractive
$ apt-get update && apt-get install -y cryptsetup
### Check block devices
$ lsblk -a
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 10G 0 disk
├─sda1 8:1 0 9.9G 0 part /
├─sda14 8:14 0 3M 0 part
└─sda15 8:15 0 124M 0 part /boot/efi
sdb 8:16 0 10G 0 disk < Disk
### Init LUKS /dev/sdb
$ export luks_key=`openssl rand 16 | xxd -p`
$ echo $luks_key
# Static
$ export luks_key=e8e580f16de5d34ba73f66151bd4363a
$ echo -n $luks_key | cryptsetup luksFormat --type luks1 /dev/sdb -
$ echo -n $luks_key | cryptsetup luksOpen /dev/sdb my_encrypted_volume -
$ mkdir -p /mnt/disks/test-direct
$ mkfs.ext4 /dev/mapper/my_encrypted_volume
$ mount /dev/mapper/my_encrypted_volume /mnt/disks/test-direct
$ lsblk -a
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 10G 0 disk
├─sda1 8:1 0 9.9G 0 part /
├─sda14 8:14 0 3M 0 part
└─sda15 8:15 0 124M 0 part /boot/efi
sdb 8:16 0 10G 0 disk < Disk
└─my_encrypted_volume 254:0 0 10G 0 crypt /mnt/disks/test-dir < LUKS
### Write file
$ echo fooobar > /mnt/disks/test-direct/a.txt
$ umount /mnt/disks/test-direct
$ cryptsetup luksClose /dev/mapper/my_encrypted_volume
$ lsblk -a
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 10G 0 disk
├─sda1 8:1 0 9.9G 0 part /
├─sda14 8:14 0 3M 0 part
└─sda15 8:15 0 124M 0 part /boot/efi
sdb 8:16 0 10G 0 disk
gcloud compute instances detach-disk instance-2 --disk luks-direct
Note image ExecStart mounts device directly
gcloud compute instances create cos-2 \
--image cos-stable-81-12871-130-0 \
--image-project cos-cloud \
--disk=auto-delete=no,boot=no,device-name=sdb,mode=rw,name=luks-direct \
--zone us-central1-a --machine-type n1-standard-1 \
--metadata-from-file user-data=cloud-init.yaml
COS initscript runs container to mount disk and LUKS
Normally the container image would perform the steps contained within
/home/cloudservice/luksmount/mount.sh
cos-init.yaml
:
#cloud-config
users:
- name: cloudservice
uid: 2000
write_files:
- path: /home/cloudservice/luksmount/mount.sh
permissions: 0644
owner: root
content: |
export DEBIAN_FRONTEND=noninteractive
apt-get update && apt-get install -yq cryptsetup
export luks_key=e8e580f16de5d34ba73f66151bd4363a
echo -n $luks_key | cryptsetup luksOpen /dev/sdb my_encrypted_volume -
mkdir -p /mnt/disks/test-direct
mount /dev/mapper/my_encrypted_volume /mnt/disks/test-direct
sleep 10000
- path: /etc/systemd/system/cloudservice.service
permissions: 0644
owner: root
content: |
[Unit]
Description=Start a simple docker container
Wants=gcr-online.target
After=gcr-online.target
[Service]
Environment="HOME=/home/cloudservice"
ExecStartPre=/usr/bin/docker-credential-gcr configure-docker
ExecStart=/usr/bin/docker run --rm -u 0 --privileged --device /dev/sdb:/dev/sdb -v /home/cloudservice/luksmount/:/luksmount --name=mycloudservice docker.io/debian:buster /bin/bash /luksmount/mount.sh
ExecStop=/usr/bin/docker stop mycloudservice
ExecStopPost=/usr/bin/docker rm mycloudservice
# bootcmd:
# - iptables -D INPUT -p tcp -m tcp --dport 22 -j ACCEPT
# - systemctl mask --now serial-getty@ttyS0.service
runcmd:
- systemctl daemon-reload
- systemctl start cloudservice.service
$ gcloud compute ssh cos-1
cos-2 ~ # lsblk -a
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 0 loop
loop1 7:1 0 0 loop
loop2 7:2 0 0 loop
loop3 7:3 0 0 loop
loop4 7:4 0 0 loop
loop5 7:5 0 0 loop
loop6 7:6 0 0 loop
loop7 7:7 0 0 loop
sda 8:0 0 10G 0 disk
|-sda1 8:1 5.9G 0 part /mnt/stateful_partition
|-sda2 8:2 0 16M 0 part
|-sda3 8:3 0 2G 0 part
|-sda4 8:4 0 16M 0 part
|-sda5 8:5 0 2G 0 part
|-sda6 8:6 512B 0 part
|-sda7 8:7 0 512B 0 part
|-sda8 8:8 16M 0 part /usr/share/oem
|-sda9 8:9 0 512B 0 part
|-sda10 8:10 0 512B 0 part
|-sda11 8:11 8M 0 part
`-sda12 8:12 0 32M 0 part
sdb 8:16 0 10G 0 disk < Disk
`-my_encrypted_volume 253:1 0 10G 0 crypt < LUKS
md0 9:0 0 0 md
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec33a523ea9a debian:buster "/bin/bash /luksmoun…" About a minute ago Up About a minute mycloudservice
$ docker exec -ti ec33a523ea9a /bin/bash
root@ec33a523ea9a:/# df -kh
Filesystem Size Used Avail Use% Mounted on
overlay 5.7G 262M 5.5G 5% /
tmpfs 64M 0 64M 0% /dev
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
shm 64M 0 64M 0% /dev/shm
/dev/sda1 5.7G 262M 5.5G 5% /luksmount
/dev/mapper/my_encrypted_volume 9.8G 37M 9.3G 1% /mnt/disks/test-direct
root@ec33a523ea9a:/$ cd /mnt/disks/test-direct
root@ec33a523ea9a:/mnt/disks/test-direct$ ls
a.txt lost+found
root@ec33a523ea9a:/mnt/disks/test-direct$ cat a.txt
fooobar