Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue stratisd 3598 #1116

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
061de13
Make _fetch_stopped_pools_property shareable
mulkieran Jan 15, 2025
94ef627
Change clevis subgroup to encryption subgroup
mulkieran Jan 7, 2025
3b64a79
Update introspection data
mulkieran Jan 7, 2025
8acc3a4
TEMPORARY
mulkieran Jan 7, 2025
254a904
Deal with multiple instances of encryption information
mulkieran Jan 8, 2025
dfcada0
Change expectations for rebinding twice with TPM2
mulkieran Jan 13, 2025
0a8d748
Add token slot option to unbind and rebind commands
mulkieran Jan 13, 2025
adc3949
Fix a test so it expects a different error type
mulkieran Jan 14, 2025
c563aab
Add an additional test for unbind
mulkieran Jan 14, 2025
924fabd
Add a "no cover" annotation to one method
mulkieran Jan 14, 2025
7cbbd81
Add token-slot option to pool start
mulkieran Jan 14, 2025
3534295
Add v2 restriction for token slot help text
mulkieran Jan 14, 2025
19635e9
Use token_slot option to select unlock method D-Bus arg
mulkieran Jan 15, 2025
a50f0d9
A few more tests for additional coverage
mulkieran Jan 15, 2025
e65e65d
Modify start pool implementation to pass correct token slot
mulkieran Jan 15, 2025
6521f88
Add some tests of invalid option combination
mulkieran Jan 16, 2025
a1e6489
Add legacy_token_slot for UnlockMethod
mulkieran Jan 16, 2025
44b3b64
Add no cover pragma
mulkieran Jan 16, 2025
9479da4
Add no cover pragma
mulkieran Jan 16, 2025
251ad3e
Add an additional test
mulkieran Jan 16, 2025
ac58078
Set to ANY if inputting key and nothing else set
mulkieran Jan 16, 2025
19513af
Restore previous interpretation of encryption for V1 pools
mulkieran Jan 16, 2025
a35ad85
When unlocking, don't reqire passphrase twice
mulkieran Jan 21, 2025
a77e38b
When interpreting v1 pools use the *s properties
mulkieran Feb 5, 2025
5bdb403
Update introspection data
mulkieran Feb 5, 2025
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
10 changes: 10 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ jobs:
toolchain: 1.74.0 # LOWEST SUPPORTED RUST TOOLCHAIN
- name: Check out stratisd
run: git clone https://github.com/stratis-storage/stratisd.git
- name: Switch
run: |
git checkout -b jbaublitz-issue-stratisd-3598 master
git pull https://github.com/jbaublitz/stratisd.git issue-stratisd-3598
working-directory: ./stratisd
- name: Build stratisd
run: PROFILEDIR=debug make build-all
working-directory: ./stratisd
Expand Down Expand Up @@ -188,6 +193,11 @@ jobs:
toolchain: 1.74.0 # LOWEST SUPPORTED RUST TOOLCHAIN
- name: Check out stratisd
run: git clone https://github.com/stratis-storage/stratisd.git
- name: Switch
run: |
git checkout -b jbaublitz-issue-stratisd-3598 master
git pull https://github.com/jbaublitz/stratisd.git issue-stratisd-3598
working-directory: ./stratisd
- name: Build stratisd
run: PROFILEDIR=debug make build-all
working-directory: ./stratisd
Expand Down
35 changes: 31 additions & 4 deletions src/stratis_cli/_actions/_bind.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,17 @@ def _bind_clevis(namespace, clevis_info):
{
"pin": clevis_info.pin,
"json": json.dumps(clevis_info.config),
"token_slot": (False, 0),
},
)

if return_code != StratisdErrors.OK:
raise StratisCliEngineError(return_code, return_msg)

if not changed:
# stratisd does not do idempotency checks when binding with Clevis;
# because there are multiple token slots, a new Clevis binding will
# just find the next token slot.
if not changed: # pragma: no cover
raise StratisCliNoChangeError("bind", pool_name)

@staticmethod
Expand Down Expand Up @@ -120,6 +124,7 @@ def bind_keyring(namespace):
get_object(pool_object_path),
{
"key_desc": namespace.keydesc,
"token_slot": (False, 0),
},
)

Expand Down Expand Up @@ -156,7 +161,14 @@ def unbind(namespace):
)

(changed, return_code, return_msg) = unbind_method(
get_object(pool_object_path), {}
get_object(pool_object_path),
{
"token_slot": (
(False, 0)
if namespace.token_slot is None
else (True, namespace.token_slot)
)
},
)

if return_code != StratisdErrors.OK:
Expand Down Expand Up @@ -189,7 +201,14 @@ def rebind_clevis(namespace):
.search(managed_objects)
)
(changed, return_code, return_msg) = Pool.Methods.RebindClevis(
get_object(pool_object_path), {}
get_object(pool_object_path),
{
"token_slot": (
(False, 0)
if namespace.token_slot is None
else (True, namespace.token_slot)
)
},
)

if return_code != StratisdErrors.OK:
Expand Down Expand Up @@ -219,7 +238,15 @@ def rebind_keyring(namespace):
)

(changed, return_code, return_msg) = Pool.Methods.RebindKeyring(
get_object(pool_object_path), {"key_desc": keydesc}
get_object(pool_object_path),
{
"key_desc": keydesc,
"token_slot": (
(False, 0)
if namespace.token_slot is None
else (True, namespace.token_slot)
),
},
)

if return_code != StratisdErrors.OK:
Expand Down
16 changes: 11 additions & 5 deletions src/stratis_cli/_actions/_introspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
<method name="CreatePool">
<arg name="name" type="s" direction="in" />
<arg name="devices" type="as" direction="in" />
<arg name="key_desc" type="(bs)" direction="in" />
<arg name="clevis_info" type="(b(ss))" direction="in" />
<arg name="key_desc" type="a((bu)s)" direction="in" />
<arg name="clevis_info" type="a((bu)ss)" direction="in" />
<arg name="journal_size" type="(bt)" direction="in" />
<arg name="tag_spec" type="(bs)" direction="in" />
<arg name="allocate_superblock" type="(bb)" direction="in" />
Expand Down Expand Up @@ -50,7 +50,7 @@
<method name="StartPool">
<arg name="id" type="s" direction="in" />
<arg name="id_type" type="s" direction="in" />
<arg name="unlock_method" type="(bs)" direction="in" />
<arg name="unlock_method" type="(b(bu))" direction="in" />
<arg name="key_fd" type="(bh)" direction="in" />
<arg name="result" type="(b(oaoao))" direction="out" />
<arg name="return_code" type="q" direction="out" />
Expand Down Expand Up @@ -158,12 +158,14 @@
<method name="BindClevis">
<arg name="pin" type="s" direction="in" />
<arg name="json" type="s" direction="in" />
<arg name="token_slot" type="(bu)" direction="in" />
<arg name="results" type="b" direction="out" />
<arg name="return_code" type="q" direction="out" />
<arg name="return_string" type="s" direction="out" />
</method>
<method name="BindKeyring">
<arg name="key_desc" type="s" direction="in" />
<arg name="token_slot" type="(bu)" direction="in" />
<arg name="results" type="b" direction="out" />
<arg name="return_code" type="q" direction="out" />
<arg name="return_string" type="s" direction="out" />
Expand Down Expand Up @@ -206,12 +208,14 @@
<arg name="return_string" type="s" direction="out" />
</method>
<method name="RebindClevis">
<arg name="token_slot" type="(bu)" direction="in" />
<arg name="results" type="b" direction="out" />
<arg name="return_code" type="q" direction="out" />
<arg name="return_string" type="s" direction="out" />
</method>
<method name="RebindKeyring">
<arg name="key_desc" type="s" direction="in" />
<arg name="token_slot" type="(bu)" direction="in" />
<arg name="results" type="b" direction="out" />
<arg name="return_code" type="q" direction="out" />
<arg name="return_string" type="s" direction="out" />
Expand All @@ -230,24 +234,26 @@
<arg name="return_string" type="s" direction="out" />
</method>
<method name="UnbindClevis">
<arg name="token_slot" type="(bu)" direction="in" />
<arg name="results" type="b" direction="out" />
<arg name="return_code" type="q" direction="out" />
<arg name="return_string" type="s" direction="out" />
</method>
<method name="UnbindKeyring">
<arg name="token_slot" type="(bu)" direction="in" />
<arg name="results" type="b" direction="out" />
<arg name="return_code" type="q" direction="out" />
<arg name="return_string" type="s" direction="out" />
</method>
<property name="AllocatedSize" type="s" access="read" />
<property name="AvailableActions" type="s" access="read" />
<property name="ClevisInfo" type="(b(b(ss)))" access="read" />
<property name="ClevisInfos" type="v" access="read" />
<property name="Encrypted" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const" />
</property>
<property name="FsLimit" type="t" access="readwrite" />
<property name="HasCache" type="b" access="read" />
<property name="KeyDescription" type="(b(bs))" access="read" />
<property name="KeyDescriptions" type="v" access="read" />
<property name="MetadataVersion" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const" />
</property>
Expand Down
99 changes: 71 additions & 28 deletions src/stratis_cli/_actions/_list_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"""

# isort: STDLIB
import json
import os
from abc import ABC, abstractmethod

# isort: THIRDPARTY
Expand All @@ -38,31 +40,18 @@
EncryptionInfoKeyDescription,
PoolFeature,
StoppedPool,
fetch_stopped_pools_property,
)


def _fetch_stopped_pools_property(proxy):
"""
Fetch the StoppedPools property from stratisd.
:param proxy: proxy to the top object in stratisd
:return: a representation of stopped devices
:rtype: dict
:raises StratisCliEngineError:
"""

# pylint: disable=import-outside-toplevel
from ._data import Manager

return Manager.Properties.StoppedPools.Get(proxy)


# This method is only used with legacy pools
def _non_existent_or_inconsistent_to_str(
value,
*,
inconsistent_str="inconsistent",
non_existent_str="N/A",
interp=lambda x: str(x), # pylint: disable=unnecessary-lambda
):
): # pragma: no cover
"""
Process dbus result that encodes both inconsistency and existence of the
value.
Expand All @@ -74,7 +63,7 @@ def _non_existent_or_inconsistent_to_str(
:returns: a string to print
:rtype: str
"""
if not value.consistent(): # pragma: no cover
if not value.consistent():
return inconsistent_str

value = value.value
Expand All @@ -85,6 +74,40 @@ def _non_existent_or_inconsistent_to_str(
return interp(value)


class TokenSlotInfo: # pylint: disable=too-few-public-methods
"""
Just a class to merge info about two different ways of occupying LUKS
token slots into one, so that the two different ways can be sorted by
token and then printed.
"""

def __init__(self, token_slot, *, key=None, clevis=None):
"""
Initialize either information about a key or about a Clevis
configuration for purposes of printing later.

:param int token_slot: token slot
:param str key: key
:param clevis: clevis configuration
:type clevis: pair of pin and configuration, str * json
"""
assert (key is None) ^ (clevis is None)

self.token_slot = token_slot
self.key = key
self.clevis = clevis

def __str__(self):
return f"Token Slot: {self.token_slot}{os.linesep}" + (
f" Key Description: {self.key}"
if self.clevis is None
else (
f" Clevis Pin: {self.clevis[0]}{os.linesep}"
f" Clevis Configuration: {self.clevis[1]}"
)
)


def list_pools(uuid_formatter, *, stopped=False, selection=None):
"""
List the specified information about pools.
Expand Down Expand Up @@ -281,17 +304,37 @@ def _print_detail_view(self, mopool, size_change_codes):
if encrypted:
print("Encryption Enabled: Yes")

key_description_str = _non_existent_or_inconsistent_to_str(
EncryptionInfoKeyDescription(mopool.KeyDescription())
)
print(f" Key Description: {key_description_str}")
if metadata_version is MetadataVersion.V1: # pragma: no cover
key_description_str = _non_existent_or_inconsistent_to_str(
EncryptionInfoKeyDescription(mopool.KeyDescriptions())
)
print(f" Key Description: {key_description_str}")

clevis_info_str = _non_existent_or_inconsistent_to_str(
EncryptionInfoClevis(mopool.ClevisInfo()),
interp=_clevis_to_str,
)
print(f" Clevis Configuration: {clevis_info_str}")
clevis_info_str = _non_existent_or_inconsistent_to_str(
EncryptionInfoClevis(mopool.ClevisInfos()),
interp=_clevis_to_str,
)
print(f" Clevis Configuration: {clevis_info_str}")
elif metadata_version is MetadataVersion.V2:
encryption_infos = sorted(
[
TokenSlotInfo(token_slot, key=str(description))
for token_slot, description in mopool.KeyDescriptions()
]
+ [
TokenSlotInfo(
token_slot, clevis=(str(pin), json.loads(str(config)))
)
for token_slot, (pin, config) in mopool.ClevisInfos()
],
key=lambda x: x.token_slot,
)

for info in encryption_infos:
for line in str(info).split(os.linesep):
print(f" {line}")
else: # pragma: no cover
pass
else:
print("Encryption Enabled: No")

Expand Down Expand Up @@ -553,7 +596,7 @@ def display(self):
"""

proxy = get_object(TOP_OBJECT)
stopped_pools = _fetch_stopped_pools_property(proxy)
stopped_pools = fetch_stopped_pools_property(proxy)
selection_func = self.selection.stopped_pools_func()

stopped_pool = next(
Expand Down Expand Up @@ -592,7 +635,7 @@ def display(self):
"""
proxy = get_object(TOP_OBJECT)

stopped_pools = _fetch_stopped_pools_property(proxy)
stopped_pools = fetch_stopped_pools_property(proxy)

def clevis_str(value, metadata_version, features):
if metadata_version is MetadataVersion.V2:
Expand Down
Loading