Skip to content

Commit

Permalink
Merge pull request #2787 from mulkieran/add-bind-tests
Browse files Browse the repository at this point in the history
Add a new test script for testing bind operations
  • Loading branch information
mulkieran committed Sep 17, 2021
2 parents 183daac + 92e4966 commit 87298a9
Show file tree
Hide file tree
Showing 4 changed files with 336 additions and 3 deletions.
66 changes: 66 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,72 @@ jobs:
make udev-tests
working-directory: ./tests/client-dbus

# PYTHON-BASED TESTS WITH TANG
python-based-checks_with_tang:
runs-on: ubuntu-18.04
container:
image: fedora:34 # CURRENT DEVELOPMENT ENVIRONMENT
options: --privileged -v /dev:/dev
services:
tang:
image: docker.pkg.github.com/stratis-storage/stratisd/tang:33
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: --privileged -p 80:80
steps:
- uses: actions/checkout@v2
- name: Install dependencies for Fedora
run: >
dnf install -y
asciidoc
clang
clevis
clevis-luks
cryptsetup-devel
curl
dbus-daemon
dbus-devel
dbus-tools
device-mapper-persistent-data
libblkid-devel
make
python3-dbus
python3-dbus-client-gen
python3-dbus-python-client-gen
python3-psutil
python3-pyudev
systemd-devel
systemd-udev
xfsprogs
- uses: actions-rs/toolchain@v1
with:
components: cargo
toolchain: 1.54.0 # CURRENT DEVELOPMENT RUST TOOLCHAIN
override: true
- name: Install all necessary Stratis files
run: PROFILEDIR=debug make -f Makefile install
- name: Start udev
run: /usr/lib/systemd/systemd-udevd &
- name: Set up for D-Bus
run: |
mkdir -p /var/lib/dbus
dbus-uuidgen > /var/lib/dbus/machine-id
mkdir -p /var/run/dbus
- name: Start D-Bus
run: >
dbus-daemon
--config-file=/usr/share/dbus-1/system.conf
--print-address
- name: Run D-Bus based bind tests
run: >
TANG_URL=tang
RUST_LOG=stratisd=debug
STRATISD=/usr/libexec/stratisd
PYTHONPATH=./src
make -f Makefile tang-tests
working-directory: ./tests/client-dbus

shell-checks:
runs-on: ubuntu-18.04
container:
Expand Down
6 changes: 5 additions & 1 deletion tests/client-dbus/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ UNITTEST_OPTS = --verbose
.PHONY: lint
lint:
pylint src/stratisd_client_dbus --ignore=_introspect.py
pylint tests
pylint tests --disable=R0801

.PHONY: misc-tests
misc-tests:
Expand All @@ -19,6 +19,10 @@ fmt-travis:
isort --diff --check-only src tests
black . --check

.PHONY: tang-tests
tang-tests:
python3 -m unittest ${UNITTEST_OPTS} tests.udev.test_bind

.PHONY: udev-tests
udev-tests:
python3 -m unittest ${UNITTEST_OPTS} tests.udev.test_udev
Expand Down
8 changes: 6 additions & 2 deletions tests/client-dbus/tests/udev/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ def random_string(length):
)


def create_pool(name, devices, *, key_description=None):
def create_pool(name, devices, *, key_description=None, clevis_info=None):
"""
Creates a stratis pool.
:param name: Name of pool
:param devices: Devices to use for pool
:param key_description: optional key description
:type key_description: str or NoneType
:param clevis_info: clevis information, pin and config
:type clevis_info: pair of str * str
:return: result of the CreatePool D-Bus method call if it succeeds
:rtype: bool * str * list of str
:raises RuntimeError: if pool is not created
Expand All @@ -83,7 +85,9 @@ def create_pool(name, devices, *, key_description=None):
"key_desc": (False, "")
if key_description is None
else (True, key_description),
"clevis_info": (False, ("", "")),
"clevis_info": (False, ("", ""))
if clevis_info is None
else (True, clevis_info),
},
)

Expand Down
259 changes: 259 additions & 0 deletions tests/client-dbus/tests/udev/test_bind.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
# Copyright 2021 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Test binding and unbinding in sequence with other actions.
"""

# isort: STDLIB
import json
import os

# isort: LOCAL
from stratisd_client_dbus import Pool, StratisdErrors, get_object

from ._utils import (
OptionalKeyServiceContextManager,
ServiceContextManager,
UdevTest,
create_pool,
random_string,
)


class TestBindingAndAddingTrustedUrl(UdevTest):
"""
Test binding to a tang server with a trusted URL and subsequently
adding data devices in various orders.
"""

_TANG_URL = os.getenv("TANG_URL")
_CLEVIS_CONFIG = {"url": _TANG_URL, "stratis:tang:trust_url": True}
_CLEVIS_CONFIG_STR = json.dumps(_CLEVIS_CONFIG)

def test_binding_and_adding(self):
"""
Verify that binding and adding succeeds when url is trusted.
"""
device_tokens = self._lb_mgr.create_devices(2)
initial_devnodes = self._lb_mgr.device_files(device_tokens)

device_tokens = self._lb_mgr.create_devices(2)
added_devnodes = self._lb_mgr.device_files(device_tokens)

(key_description, key) = ("key_spec", "data")
with OptionalKeyServiceContextManager(key_spec=[(key_description, key)]):
pool_name = random_string(5)
(_, (pool_object_path, _)) = create_pool(
pool_name, initial_devnodes, key_description=key_description
)
self.wait_for_pools(1)

(_, exit_code, message) = Pool.Methods.Bind(
get_object(pool_object_path),
{"pin": "tang", "json": self._CLEVIS_CONFIG_STR},
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

(_, exit_code, message) = Pool.Methods.AddDataDevs(
get_object(pool_object_path), {"devices": added_devnodes}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

def test_binding_unbinding_adding(self):
"""
Test that binding, unbinding, and then adding devices works.
"""
device_tokens = self._lb_mgr.create_devices(2)
initial_devnodes = self._lb_mgr.device_files(device_tokens)

device_tokens = self._lb_mgr.create_devices(2)
added_devnodes = self._lb_mgr.device_files(device_tokens)

(key_description, key) = ("key_spec", "data")
with OptionalKeyServiceContextManager(key_spec=[(key_description, key)]):
pool_name = random_string(5)
(_, (pool_object_path, _)) = create_pool(
pool_name, initial_devnodes, key_description=key_description
)
self.wait_for_pools(1)

(_, exit_code, message) = Pool.Methods.Bind(
get_object(pool_object_path),
{"pin": "tang", "json": self._CLEVIS_CONFIG_STR},
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

(_, exit_code, message) = Pool.Methods.Unbind(
get_object(pool_object_path), {}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

(_, exit_code, message) = Pool.Methods.AddDataDevs(
get_object(pool_object_path), {"devices": added_devnodes}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

def test_swap_binding(self):
"""
Test that binding with clevis, unbinding with keyring, and then
adding devices works.
"""
device_tokens = self._lb_mgr.create_devices(2)
initial_devnodes = self._lb_mgr.device_files(device_tokens)

device_tokens = self._lb_mgr.create_devices(2)
added_devnodes = self._lb_mgr.device_files(device_tokens)

(key_description, key) = ("key_spec", "data")
with OptionalKeyServiceContextManager(key_spec=[(key_description, key)]):
pool_name = random_string(5)
(_, (pool_object_path, _)) = create_pool(
pool_name, initial_devnodes, key_description=key_description
)
self.wait_for_pools(1)

(_, exit_code, message) = Pool.Methods.Bind(
get_object(pool_object_path),
{"pin": "tang", "json": self._CLEVIS_CONFIG_STR},
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

(_, exit_code, message) = Pool.Methods.UnbindKeyring(
get_object(pool_object_path), {}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

(_, exit_code, message) = Pool.Methods.AddDataDevs(
get_object(pool_object_path), {"devices": added_devnodes}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

def test_swap_binding_2(self):
"""
Test that binding with keyring, unbinding with clevis, and then
adding devices works.
"""
device_tokens = self._lb_mgr.create_devices(2)
initial_devnodes = self._lb_mgr.device_files(device_tokens)

device_tokens = self._lb_mgr.create_devices(2)
added_devnodes = self._lb_mgr.device_files(device_tokens)

(key_description, key) = ("key_spec", "data")
with OptionalKeyServiceContextManager(key_spec=[(key_description, key)]):
clevis_info = ("tang", self._CLEVIS_CONFIG_STR)

pool_name = random_string(5)
(_, (pool_object_path, _)) = create_pool(
pool_name, initial_devnodes, clevis_info=clevis_info
)
self.wait_for_pools(1)

(_, exit_code, message) = Pool.Methods.BindKeyring(
get_object(pool_object_path), {"key_desc": key_description}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

(_, exit_code, message) = Pool.Methods.Unbind(
get_object(pool_object_path), {}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

(_, exit_code, message) = Pool.Methods.AddDataDevs(
get_object(pool_object_path), {"devices": added_devnodes}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

def test_rebind_with_clevis(self):
"""
Test that binding with clevis on creation, then rebinding, and then
adding data devices works.
"""
device_tokens = self._lb_mgr.create_devices(2)
initial_devnodes = self._lb_mgr.device_files(device_tokens)

device_tokens = self._lb_mgr.create_devices(2)
added_devnodes = self._lb_mgr.device_files(device_tokens)

with ServiceContextManager():
pool_name = random_string(5)

clevis_info = ("tang", self._CLEVIS_CONFIG_STR)

(_, (pool_object_path, _)) = create_pool(
pool_name, initial_devnodes, clevis_info=clevis_info
)
self.wait_for_pools(1)

(_, exit_code, message) = Pool.Methods.RebindClevis(
get_object(pool_object_path), {}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

(_, exit_code, message) = Pool.Methods.AddDataDevs(
get_object(pool_object_path), {"devices": added_devnodes}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)


class TestBindingAndRebindingKernelKeyring(UdevTest):
"""
Test binding and rebinding with a key in the kernel keyring and adding
data devices.
"""

def test_rebind_with_new_key_description(self):
"""
Test that binding with key on creation, rebinding with different key,
and then adding data devices works.
"""
device_tokens = self._lb_mgr.create_devices(2)
initial_devnodes = self._lb_mgr.device_files(device_tokens)

device_tokens = self._lb_mgr.create_devices(2)
added_devnodes = self._lb_mgr.device_files(device_tokens)

keys = [("key_desc_1", "key_data_1"), ("key_desc_2", "key_data_2")]
with OptionalKeyServiceContextManager(key_spec=keys):
pool_name = random_string(5)
(_, (pool_object_path, _)) = create_pool(
pool_name, initial_devnodes, key_description=keys[0][0]
)
self.wait_for_pools(1)

(_, exit_code, message) = Pool.Methods.RebindKeyring(
get_object(pool_object_path), {"key_desc": keys[1][0]}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

(_, exit_code, message) = Pool.Methods.AddDataDevs(
get_object(pool_object_path), {"devices": added_devnodes}
)

self.assertEqual(exit_code, StratisdErrors.OK, message)

0 comments on commit 87298a9

Please sign in to comment.