Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ test_data:
else
echo "Installing checkbox runtime on device (from deb package)"
_run sudo add-apt-repository -y ppa:checkbox-dev/$CHANNEL
_run install_packages checkbox-ng python3-checkbox-ng checkbox-provider-base checkbox-provider-resource checkbox-provider-sru fswebcam obexftp wmctrl iperf mesa-utils vim pastebinit fwts xorg-dev gir1.2-clutter-1.0
_run install_packages checkbox-ng python3-checkbox-ng checkbox-provider-base checkbox-provider-resource checkbox-provider-sru fscrypt fswebcam obexftp wmctrl iperf mesa-utils vim pastebinit fwts xorg-dev gir1.2-clutter-1.0
# list installed checkbox-related packages to facilitate debugging
_run "apt list --installed | grep checkbox"
CHECKBOX_CLI_CMD="checkbox-cli"
Expand Down
1 change: 1 addition & 0 deletions checkbox-core-snap/series16/snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ parts:
- ethtool
- freeipmi-tools
- freeglut3
- fscrypt
- fswebcam
- gir1.2-cheese-3.0
- gir1.2-clutter-1.0
Expand Down
1 change: 1 addition & 0 deletions checkbox-core-snap/series18/snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ parts:
- ethtool
- freeipmi-tools
- freeglut3
- fscrypt
- fswebcam
- gir1.2-cheese-3.0
- gir1.2-clutter-1.0
Expand Down
1 change: 1 addition & 0 deletions checkbox-core-snap/series20/snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ parts:
- ethtool
- freeipmi-tools
- freeglut3
- fscrypt
- fswebcam
- gir1.2-cheese-3.0
- gir1.2-clutter-1.0
Expand Down
1 change: 1 addition & 0 deletions checkbox-core-snap/series22/snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ parts:
- efibootmgr
- ethtool
- freeipmi-tools
- fscrypt
- fswebcam
- gir1.2-cheese-3.0
- gir1.2-clutter-1.0
Expand Down
1 change: 1 addition & 0 deletions checkbox-core-snap/series24/snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ parts:
- efibootmgr
- ethtool
- freeipmi-tools
- fscrypt
- fswebcam
- gir1.2-cheese-3.0
- gir1.2-clutter-1.0
Expand Down
46 changes: 23 additions & 23 deletions providers/base/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,28 @@ under the units folder.
Base Provider Units
###################

+------------+-------------+-------------+------------------+-------------+----------------+
| 6lowpan | eeprom | i2c | miscellanea | serial | ubuntucore |
+------------+-------------+-------------+------------------+-------------+----------------+
| acpi | esata | image | mobilebroadband | smoke | usb |
+------------+-------------+-------------+------------------+-------------+----------------+
| audio | ethernet | info | monitor | snapd | virtualization |
+------------+-------------+-------------+------------------+-------------+----------------+
| benchmarks | expresscard | input | networking | socketcan | watchdog |
+------------+-------------+-------------+------------------+-------------+----------------+
| bluetooth | fingerprint | install | nvdimm | stress | wireless |
+------------+-------------+-------------+------------------+-------------+----------------+
| camera_ | firewire | kernel-snap | oob-management | submission | wwan |
+------------+-------------+-------------+------------------+-------------+----------------+
| canary | firmware | keys | optical | suspend | |
+------------+-------------+-------------+------------------+-------------+----------------+
| codecs | gadget | led | power-management | thunderbolt | |
+------------+-------------+-------------+------------------+-------------+----------------+
| cpu | gpio | location | rtc | touchpad | |
+------------+-------------+-------------+------------------+-------------+----------------+
| disk | graphics | mediacard | security | touchscreen | |
+------------+-------------+-------------+------------------+-------------+----------------+
| dock | hibernate | memory | self | tpm | |
+------------+-------------+-------------+------------------+-------------+----------------+
+-----------+-------------+-------------+-------------------+-------------+----------------+
| 6lowpan | eeprom | hibernate | memory | self | tmp |
+-----------+-------------+-------------+-------------------+-------------+----------------+
| acpi | esata | i2c | miscellanea | serial | ubuntucore |
+-----------+-------------+-------------+-------------------+-------------+----------------+
| audio | ethernet | image | mobilebroadband | smoke | usb |
+-----------+-------------+-------------+-------------------+-------------+----------------+
| benchmarks| expresscard | info | monitor | snapd | virtualization |
+-----------+-------------+-------------+-------------------+-------------+----------------+
| bluetooth | fingerprint | input | networking | socketcan | watchdog |
+-----------+-------------+-------------+-------------------+-------------+----------------+
| camera_ | firewire | install | nvdimm | submission | wireless |
+-----------+-------------+-------------+-------------------+-------------+----------------+
| canary | firmware | kernel-snap | oob-management | suspend | wwan |
+-----------+-------------+-------------+-------------------+-------------+----------------+
| codecs | fscrypt | keys | optical | tpm | |
+-----------+-------------+-------------+-------------------+-------------+----------------+
| cpu | gadget | led | power-management | thunderbolt | |
+-----------+-------------+-------------+-------------------+-------------+----------------+
| disk | gpio | location | rtc | touchpad | |
+-----------+-------------+-------------+-------------------+-------------+----------------+
| dock | graphics | mediacard | security | touchscreen | |
+-----------+-------------+-------------+-------------------+-------------+----------------+

.. _camera: units/camera/README.rst
150 changes: 150 additions & 0 deletions providers/base/bin/fscrypt_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#!/usr/bin/env python3
"""
script to test fscrypt support

Copyright (C) 2025 Canonical Ltd.

Authors
Alexis Cellier <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3,
as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

The purpose of this script is to make a small fscrypt test on a generated
ext4 disk image to validate the filesystem encryption support.
"""

import os
import subprocess
import tempfile
import re
from pathlib import Path


def main():
"""
Create an ext4 disk image, mount it, setup fscrypt and use it with a simple
file
"""
with tempfile.TemporaryDirectory() as tmp_path:
tmp = Path(tmp_path)
mnt = tmp / "mnt"
img = tmp / "fs.img"
key_file = tmp / "key"
test_dir = mnt / "test"
test_file = test_dir / "test.txt"
test_content = "test"
fscrypt_config = Path("/etc/fscrypt.conf")
fscrypt_setup = fscrypt_config.exists()

# Create a 50MB file
subprocess.check_call(["truncate", "-s", "50M", str(img)])

mnt.mkdir(parents=True, exist_ok=True)

# Make ext4 image with encryption support
subprocess.check_call(
["mkfs.ext4", "-F", "-O", "encrypt,stable_inodes", str(img)]
)

# Mount it
subprocess.check_call(["mount", str(img), str(mnt)])

try:
# Setup fscrypt
print("Setup fscrupt")
if not fscrypt_setup:
subprocess.run(
["fscrypt", "setup", "--force"],
input="n\n",
text=True,
check=True,
)
subprocess.run(
["fscrypt", "setup", "--force", str(mnt)],
input="n\n",
text=True,
check=True,
)

# Confirm fscrypt is enabled
output = subprocess.check_output(
["fscrypt", "status"],
text=True,
)
found = False
pattern = re.compile(
"^{}.*supported\\s*Yes$".format(re.escape(str(mnt)))
)
for line in output.splitlines():
if pattern.match(line):
found = True
break
if not found:
raise SystemExit("Failed to setup fscrypt")

# Write random key
with key_file.open("wb") as f:
f.write(os.urandom(32))

# Make test directory
test_dir.mkdir(parents=True, exist_ok=True)

# Encrypt directory
subprocess.check_call(
[
"fscrypt",
"encrypt",
"--quiet",
"--source=raw_key",
"--name=test_key",
"--key={}".format(str(key_file)),
str(test_dir),
]
)

# Write a file inside
with test_file.open("w") as f:
f.write(test_content)

# Lock the directory
subprocess.check_call(["fscrypt", "lock", str(test_dir)])

# Should not be able to list the file
if test_file.exists():
raise SystemExit("File should not be accessible when locked")
print("File correctly inaccessible when locked")

# Unlock the directory
subprocess.check_call(
[
"fscrypt",
"unlock",
"--key={}".format(str(key_file)),
str(test_dir),
]
)

with test_file.open("r") as f:
content = f.read().strip()
if content != test_content:
print("Expected: {} / Got: {}".format(test_content, content))
raise SystemExit("File contents not correct after unlock")
print("File is accessible and content is correct after unlock")
finally:
subprocess.check_call(["umount", str(mnt)])
if not fscrypt_setup and fscrypt_config.exists():
fscrypt_config.unlink()


if __name__ == "__main__":
main()
3 changes: 2 additions & 1 deletion providers/base/debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ Recommends: bonnie++,
smartmontools,
sysstat,
${plainbox:Recommends}
Suggests: fswebcam,
Suggests: fscrypt,
fswebcam,
fwts,
glmark2,
glmark2-es2,
Expand Down
88 changes: 88 additions & 0 deletions providers/base/tests/test_fscrypt_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from unittest.mock import patch
import fscrypt_test
import unittest


def _prepare_path_and_subprocess(mock_path, mock_subprocess):
mock_path.exists.side_effect = [True, False, True]
mock_path.mkdir.return_value = True
mock_path.__truediv__.return_value = mock_path
mock_path.__str__.return_value = "path"
mock_path.return_value = mock_path
mock_path.open = mock_path
mock_path.__enter__ = mock_path
mock_path.read.return_value = "test\n"
mock_subprocess.run.side_effect = [0, Exception("Should be called once")]
mock_subprocess.check_call.return_value = 0
mock_subprocess.check_output.return_value = (
"path this-is-ignore this-also supported Yes"
)


class FscryptTestCase(unittest.TestCase):
@patch("fscrypt_test.Path")
@patch("fscrypt_test.subprocess")
def test_main_success(self, mock_subprocess, mock_path):
_prepare_path_and_subprocess(
mock_path,
mock_subprocess,
)
fscrypt_test.main()

@patch("fscrypt_test.Path")
@patch("fscrypt_test.subprocess")
def test_main_failure_setup(self, mock_subprocess, mock_path):
_prepare_path_and_subprocess(
mock_path,
mock_subprocess,
)
# Fake fscrypt setup not working.
mock_subprocess.check_output.return_value = (
"path this-is-ignore this-also supported No"
)
with self.assertRaises(SystemExit) as context:
fscrypt_test.main()
self.assertEqual(str(context.exception), "Failed to setup fscrypt")

@patch("fscrypt_test.Path")
@patch("fscrypt_test.subprocess")
def test_main_failure_lock(self, mock_subprocess, mock_path):
_prepare_path_and_subprocess(
mock_path,
mock_subprocess,
)
# Fake fscrypt lock not working.
mock_path.exists.side_effect = [True, True, True]
with self.assertRaises(SystemExit) as context:
fscrypt_test.main()
self.assertEqual(
str(context.exception), "File should not be accessible when locked"
)

@patch("fscrypt_test.Path")
@patch("fscrypt_test.subprocess")
def test_main_failure_unlock(self, mock_subprocess, mock_path):
_prepare_path_and_subprocess(
mock_path,
mock_subprocess,
)
# Fake bad unlink file content.
mock_path.read.return_value = "invalid\n"
with self.assertRaises(SystemExit) as context:
fscrypt_test.main()
self.assertEqual(
str(context.exception), "File contents not correct after unlock"
)

@patch("fscrypt_test.Path")
@patch("fscrypt_test.subprocess")
def test_main_failure_not_already_setup(self, mock_subprocess, mock_path):
_prepare_path_and_subprocess(
mock_path,
mock_subprocess,
)
# Fake fscrypt.conf not already existing, so it has to be deleted.
mock_path.exists.side_effect = [False, False, True]
mock_subprocess.run.side_effect = [0, 0]
fscrypt_test.main()
self.assertTrue(mock_path.unlink.called)
3 changes: 3 additions & 0 deletions providers/base/units/fscrypt/category.pxu
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
unit: category
id: fscrypt
_name: Ubuntu filesystem encryption feature tests
18 changes: 18 additions & 0 deletions providers/base/units/fscrypt/jobs.pxu
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
id: fscrypt/check-kernel-config
plugin: shell
category_id: fscrypt
command: kernel_config.py --config-flag CONFIG_FS_ENCRYPTION
estimated_duration: 0.005
_purpose: Checks the value of the CONFIG_FS_ENCRYPTION flag in the kernel configuration
_summary: Check if the kernel is compiled with filesystem encryption support

id: fscrypt/check-support
plugin: shell
category_id: fscrypt
estimated_duration: 5s
user: root
depends: fscrypt/check-kernel-config
requires: executable.name == "fscrypt"
_summary: Check fscrypt support
_purpose: Create an ext4 image and test the filesystem encryption feature
command: fscrypt_test.py
3 changes: 3 additions & 0 deletions providers/base/units/fscrypt/packaging.pxu
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
unit: packaging meta-data
os-id: ubuntu
Depends: fscrypt
15 changes: 15 additions & 0 deletions providers/base/units/fscrypt/test-plan.pxu
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
id: fscrypt-full
unit: test plan
_name: fscrypt tests
_description: fscrypt tests
include:
nested_part:
fscrypt-automated

id: fscrypt-automated
unit: test plan
_name: automated fscrypt tests
_description: Automated fscrypt tests
include:
fscrypt/check-kernel-config
fscrypt/check-support
Loading