Permalink
Browse files

Adding dm-crypt as core pkg

Signed-off-by: Christian Wuerdig <christian.wuerdig@gmail.com>
  • Loading branch information...
chriswue authored and Christian Wuerdig committed Dec 19, 2018
1 parent 4ee593e commit 7395a5f893b71f7378455870d7e431914bd65181
@@ -0,0 +1,86 @@
# Device encryption with dm-crypt

In the packages section you can find an image to setup dm-crypt encrypted devices in [linuxkit](https://github.com/linuxkit/linuxkit)-generated images.

## Usage

The setup is a one time step during boot:

```yaml
onboot:
- name: dm-crypt
image: linuxkit/dm-crypt:<hash>
command: ["/usr/bin/crypto", "dm_crypt_name", "/dev/sda1"]
- name: mount
image: linuxkit/mount:<hash>
command: ["/usr/bin/mountie", "/dev/mapper/dm_crypt_name", "/var/secure_storage"]
files:
- path: etc/dm-crypt/key
contents: "abcdefghijklmnopqrstuvwxyz123456"
```

The above will map `/dev/sda1` as an encrypted device under `/dev/mapper/dm_crypt_name` and mount it under `/var/secure_storage`

The `dm-crypt` container by default bind-mounts `/dev:/dev` and `/etc/dm-crypt:/etc/dm-crypt`. It expects the encryption key to be present in the file `/etc/dm-crypt/key`. You can pass an alternative location as encryption key which can be either a file path relative to `/etc/dm-crypt` or an absolute path.

Providing an alternative encryption key file name:

```yaml
onboot:
- name: dm-crypt
image: linuxkit/dm-crypt:<hash>
command: ["/usr/bin/crypto", "-k", "some_other_key", "dm_crypt_name", "/dev/sda1"]
- name: mount
image: linuxkit/mount:<hash>
command: ["/usr/bin/mountie", "/dev/mapper/dm_crypt_name", "/var/secure_storage"]
files:
- path: etc/dm-crypt/some_other_key
contents: "abcdefghijklmnopqrstuvwxyz123456"
```

Providing an alternative encryption key file name as absolute path:

```yaml
onboot:
- name: dm-crypt
image: linuxkit/dm-crypt:<hash>
command: ["/usr/bin/crypto", "-k", "/some/other/key", "dm_crypt_name", "/dev/sda1"]
binds:
- /dev:/dev
- /etc/dm-crypt/some_other_key:/some/other/key
- name: mount
image: linuxkit/mount:<hash>
command: ["/usr/bin/mountie", "/dev/mapper/dm_crypt_name", "/var/secure_storage"]
files:
- path: etc/dm-crypt/some_other_key
contents: "abcdefghijklmnopqrstuvwxyz123456"
```

Note that you have to also map `/dev:/dev` explicitly if you override the default bind-mounts.

The `dm-crypt` container

* Will create an `ext4` file system on the encrypted device if none is present.
* It will also initialize the encrypted device by filling it from `/dev/zero` prior to creating the filesystem. Which means if the device is being setup for the first time it might take a bit longer.
* Uses the `aes-cbc-essiv:sha256` cipher (it's explicitly specified in case the default ever changes)
* Consequently the encryption key is expected to be 32 bytes long, a random one can be created via
```shell
dd if=/dev/urandom of=dm-crypt.key bs=32 count=1
```
If you see the error `Cannot read requested amount of data.` next to the log message `Creating dm-crypt mapping for ...` then this means your keyfile doesn't contain enough data.

### Examples

There are two examples in the `examples/` folder:

1. `dm-crypt.yml` - formats an external disk and mounts it encrypted.
2. `dm-crypt-loop.yml` - mounts an encrypted loop device backed by a regular file sitting on an external disk

### Options

|Option|Default|Required|Notes|
|---|---|---|---|
|`-k` or `--key`|`key`|No|Encryption key file name. Must be either relative to `/etc/dm-crypt` or an absolute file path.|
|`-l` or `--luks`||No|Use LUKS format for encryption|
|`<dm_name>`||**Yes**|The device-mapper device name to use. The device will be mapped under `/dev/mapper/<dm_name>`|
|`<device>`||**Yes**|Device to encrypt.|
@@ -0,0 +1,49 @@
kernel:
image: linuxkit/kernel:4.14.88
cmdline: "console=tty0 console=ttyS0"
init:
- linuxkit/init:c563953a2277eb73a89d89f70e4b6dcdcfebc2d1
- linuxkit/runc:83d0edb4552b1a5df1f0976f05f442829eac38fe
- linuxkit/containerd:326b096cd5fbab0f864e52721d036cade67599d6
- linuxkit/ca-certificates:v0.6
onboot:
- name: sysctl
image: linuxkit/sysctl:v0.6
- name: dhcpcd
image: linuxkit/dhcpcd:v0.6
command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
- name: format
image: linuxkit/format:v0.6
command: ["/usr/bin/format", "/dev/sda"]
- name: mount
image: linuxkit/mount:v0.6
command: ["/usr/bin/mountie", "/dev/sda1", "/var/external"]
- name: loop
image: linuxkit/losetup:aaceeea49ac519bc3b87da239436dd997d67b431
command: ["/usr/bin/loopy", "--create", "/var/external/storage_file"]
- name: dm-crypt
image: linuxkit/dm-crypt:9e41a164358b0235f0c242219b1a424c6552d46c
command: ["/usr/bin/crypto", "crypt_loop_dev", "/dev/loop0"]
- name: mount
image: linuxkit/mount:v0.6
command: ["/usr/bin/mountie", "/dev/mapper/crypt_loop_dev", "/var/secure_storage"]
- name: bbox
image: busybox
command: ["sh", "-c", "echo 'secret things' >/var/secure_storage/secrets"]
binds:
- /var:/var
services:
- name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478
env:
- INSECURE=true
- name: rngd
image: linuxkit/rngd:v0.6
files:
- path: etc/dm-crypt/key
# the below key is just to keep the example self-contained
# !!! provide a proper key for production use here !!!
contents: "abcdefghijklmnopqrstuvwxyz123456"
trust:
org:
- linuxkit
@@ -0,0 +1,43 @@
kernel:
image: linuxkit/kernel:4.14.88
cmdline: "console=tty0 console=ttyS0"
init:
- linuxkit/init:c563953a2277eb73a89d89f70e4b6dcdcfebc2d1
- linuxkit/runc:83d0edb4552b1a5df1f0976f05f442829eac38fe
- linuxkit/containerd:326b096cd5fbab0f864e52721d036cade67599d6
- linuxkit/ca-certificates:v0.6
onboot:
- name: sysctl
image: linuxkit/sysctl:v0.6
- name: dhcpcd
image: linuxkit/dhcpcd:v0.6
command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
- name: format
image: linuxkit/format:v0.6
command: ["/usr/bin/format", "/dev/sda"]
- name: dm-crypt
image: linuxkit/dm-crypt:9e41a164358b0235f0c242219b1a424c6552d46c
command: ["/usr/bin/crypto", "crypt_dev", "/dev/sda1"]
- name: mount
image: linuxkit/mount:v0.6
command: ["/usr/bin/mountie", "/dev/mapper/crypt_dev", "/var/secure_storage"]
- name: bbox
image: busybox
command: ["sh", "-c", "echo 'secret things' >/var/secure_storage/secrets"]
binds:
- /var:/var
services:
- name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478
env:
- INSECURE=true
- name: rngd
image: linuxkit/rngd:v0.6
files:
- path: etc/dm-crypt/key
# the below key is just to keep the example self-contained
# !!! provide a proper key for production use here !!!
contents: "abcdefghijklmnopqrstuvwxyz123456"
trust:
org:
- linuxkit
@@ -0,0 +1,19 @@
FROM linuxkit/alpine:3683c9a66cd4da40bd7d6c7da599b2dcd738b559 AS mirror
RUN mkdir -p /out/etc/apk && cp -r /etc/apk/* /out/etc/apk/
RUN apk add --no-cache --initdb -p /out \
alpine-baselayout \
cryptsetup \
e2fsprogs

# Remove apk residuals
RUN rm -rf /out/etc/apk /out/lib/apk /out/var/cache

FROM scratch
ENTRYPOINT []
WORKDIR /
COPY --from=mirror /out/ /

COPY crypto.sh /usr/bin/crypto
RUN chmod +x /usr/bin/crypto

CMD ["/usr/bin/crypto"]
@@ -0,0 +1,8 @@
image: dm-crypt
config:
binds:
- /dev:/dev
- /etc/dm-crypt:/etc/dm-crypt
capabilities:
- CAP_SYS_ADMIN
- CAP_MKNOD
@@ -0,0 +1,84 @@
#!/bin/sh

set -e

help()
{
echo "Usage: $0 [options] <dm_name> <device>"
echo
echo "Options:"
echo " -l|--luks Use LUKS extension"
echo " -k|--key-file Name of the key file, default: key"
echo " <dm_name> Name of the device mapper file, the encrypted device will become available under /dev/mapper/<dm_name>"
echo " <device> The encrypted device (e.g. /dev/sda1, /dev/loop0, etc)"
echo
}

luks=false
key_file="key"

O=`getopt -l key-file:luks,help -- k:lh "$@"` || exit 1
eval set -- "$O"
while true; do
case "$1" in
-l|--luks) luks=true; shift;;
-k|--key-file) key_file=$2; shift 2;;
-h|--help) help; exit 0;;
--) shift; break;;
*) echo "Unknown option $1"; help; exit 1;;
esac
done

if [ -z "$1" ]; then
echo "Missing argument <dm_name>"
help
exit 1
fi

if [ -z "$2" ]; then
echo "Missing argument <device>"
help
exit 1
fi

dm_name=$1
device=$2
dmdev_name="/dev/mapper/$dm_name"
cipher="aes-cbc-essiv:sha256"

case "$key_file" in
/*) ;;
*) key_file="/etc/dm-crypt/$key_file" ;;
esac

if [ ! -f "$key_file" ]; then
echo "Couldn't find encryption keyfile $key_file!"
exit 1
fi

if [ ! -d "/run/cryptsetup" ]; then
echo "Creating cryptsetup lock directory"
mkdir /run/cryptsetup
fi

if [ $luks = true ]; then
echo "Creating dm-crypt LUKS mapping for $device under $dmdev_name"
if ! cryptsetup isLuks $device; then
echo "Device $device doesn't seem to have a valid LUKS setup so one will be created."
cryptsetup --key-file "$key_file" --cipher "$cipher" luksFormat "$device"
fi
cryptsetup --key-file "$key_file" luksOpen "$device" "$dm_name"
else
echo "Creating dm-crypt mapping for $device under $dmdev_name"
cryptsetup --key-file "$key_file" --cipher "$cipher" create "$dm_name" "$device"
fi

o=`blkid $dmdev_name`
if [ -z "$o" ]; then
echo "Device $dmdev_name doesn't seem to contain a filesystem, creating one."
# dd will write the device until it's full and then return with an error because "no space left"
dd if=/dev/zero of="$dmdev_name" || true
mkfs.ext4 "$dmdev_name"
else
echo "Device $dmdev_name seems to contain filesystem: $o"
fi
@@ -0,0 +1,10 @@
#!/bin/sh

function failed {
printf "dm-crypt test suite FAILED\n" >&1
exit 1
}

[ -b /dev/mapper/it_is_encrypted ] || failed

printf "dm-crypt test suite PASSED\n" >&1
@@ -0,0 +1,26 @@
#!/bin/sh
# SUMMARY: Check that the losetup package works
# LABELS:
# REPEAT:

set -e

# Source libraries. Uncomment if needed/defined
#. "${RT_LIB}"
. "${RT_PROJECT_ROOT}/_lib/lib.sh"

NAME=dm-crypt
DISK=disk.img

clean_up() {
rm -rf ${NAME}-* ${DISK}
}
trap clean_up EXIT

# Test code goes here
linuxkit build -format kernel+initrd -name ${NAME} test.yml
RESULT="$(linuxkit run -disk file=${DISK},size=32M ${NAME})"
echo "${RESULT}"
echo "${RESULT}" | grep -q "suite PASSED"

exit 0
@@ -0,0 +1,30 @@
kernel:
image: linuxkit/kernel:4.14.88
cmdline: "console=ttyS0 console=ttyAMA0"
init:
- linuxkit/init:c563953a2277eb73a89d89f70e4b6dcdcfebc2d1
- linuxkit/runc:83d0edb4552b1a5df1f0976f05f442829eac38fe
onboot:
- name: dm-crypt
image: linuxkit/dm-crypt:9e41a164358b0235f0c242219b1a424c6552d46c
command: ["/usr/bin/crypto", "it_is_encrypted", "/dev/sda"]
- name: test
image: alpine:3.8
net: host
binds:
- /check.sh:/check.sh
- /dev:/dev
command: ["sh", "./check.sh"]
- name: poweroff
image: linuxkit/poweroff:afe8f7dd0d47a7991c54519b0f09124cb8c4e300
command: ["/bin/sh", "/poweroff.sh", "10"]
files:
- path: check.sh
source: ./check.sh
- path: etc/dm-crypt/key
contents: "abcdefghijklmnopqrstuvwxyz123456"
trust:
org:
- linuxkit
image:
- alpine:3.8
@@ -0,0 +1,10 @@
#!/bin/sh

function failed {
printf "dm-crypt test suite FAILED\n" >&1
exit 1
}

[ -b /dev/mapper/it_is_encrypted ] || failed

printf "dm-crypt test suite PASSED\n" >&1
Oops, something went wrong.

0 comments on commit 7395a5f

Please sign in to comment.