Skip to content

Commit

Permalink
Allow user to specify a passphrase on pool start
Browse files Browse the repository at this point in the history
Signed-off-by: mulhern <[email protected]>
  • Loading branch information
mulkieran committed Jul 12, 2024
1 parent eb21d4c commit 72aca2c
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 14 deletions.
8 changes: 6 additions & 2 deletions docs/stratis.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,14 @@ pool create [--key-desc <key_desc>] [--clevis <(nbde|tang|tpm2)> [--tang-url <ta
pool stop <(--uuid <uuid> |--name <name>)>::
Stop a pool, specifying the pool by its UUID or by its name. Tear down
the storage stack but leave all metadata intact.
pool start <(--uuid <uuid> |--name <name>)> --unlock-method <(keyring | clevis)>::
pool start [--keyfile-path KEYFILE_PATH | --capture-key] --unlock-method <(any | clevis | keyring)> <(--uuid <uuid> |--name <name>)>::
Start a pool, specifying the pool by its UUID or by its name. Use the
--unlock-method option to specify method of unlocking the pool if it is
encrypted.
encrypted. If an unlock method of any is specified the pool will be
unlocked with any facility available that allows the pool to be unlocked.
If --keyfile-path or --capture-key is specified, then the pool will use
only the passphrase and method specified, so that the pool will not be
unlocked unless the passphrase is correct.
pool list [--stopped] [(--uuid <uuid> |--name <name>)]::
List pools. If the --stopped option is used, list only stopped pools.
Otherwise, list only started pools. If a UUID or name is specified, print
Expand Down
37 changes: 29 additions & 8 deletions src/stratis_cli/_actions/_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# isort: THIRDPARTY
from justbytes import Range

from .._constants import Id, IdType
from .._constants import Id, IdType, UnlockMethod
from .._error_codes import PoolErrorCode
from .._errors import (
StratisCliEngineError,
Expand All @@ -46,7 +46,7 @@
from ._constants import TOP_OBJECT
from ._formatting import get_property, get_uuid_formatter
from ._list_pool import list_pools
from ._utils import ClevisInfo, PoolSelector
from ._utils import ClevisInfo, PoolSelector, get_passphrase_fd


def _generate_pools_to_blockdevs(managed_objects, to_be_added, tier):
Expand Down Expand Up @@ -270,20 +270,41 @@ def start_pool(namespace):
else (namespace.name, "name")
)

if namespace.capture_key or namespace.keyfile_path is not None:
fd_argument, fd_to_close = get_passphrase_fd(
keyfile_path=namespace.keyfile_path
)
key_fd_arg = (True, fd_argument)
unlock_method = (
True,
str(
UnlockMethod.ANY
if namespace.unlock_method is None
else namespace.unlock_method
),
)
else:
fd_to_close = None
key_fd_arg = (False, 0)
unlock_method = (
(False, "")
if namespace.unlock_method is None
else (True, str(namespace.unlock_method))
)

((started, _), return_code, message) = Manager.Methods.StartPool(
proxy,
{
"id": pool_id,
"id_type": id_type,
"unlock_method": (
(False, "")
if namespace.unlock_method is None
else (True, str(namespace.unlock_method))
),
"key_fd": (False, 0),
"unlock_method": unlock_method,
"key_fd": key_fd_arg,
},
)

if fd_to_close is not None:
os.close(fd_to_close)

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

Expand Down
13 changes: 13 additions & 0 deletions src/stratis_cli/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,19 @@ def __str__(self):
return self.value


class UnlockMethod(Enum):
"""
Unlock method.
"""

ANY = "any"
CLEVIS = "clevis"
KEYRING = "keyring"

def __str__(self):
return self.value


class Clevis(Enum):
"""
Clevis encryption methods.
Expand Down
34 changes: 30 additions & 4 deletions src/stratis_cli/_parser/_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from uuid import UUID

from .._actions import BindActions, PoolActions
from .._constants import Clevis, EncryptionMethod, YesOrNo
from .._constants import Clevis, EncryptionMethod, UnlockMethod, YesOrNo
from .._error_codes import PoolErrorCode
from ._bind import BIND_SUBCMDS, REBIND_SUBCMDS
from ._debug import POOL_DEBUG_SUBCMDS
Expand Down Expand Up @@ -227,6 +227,32 @@ def _ensure_nat(arg):
"start",
{
"help": "Start a pool.",
"groups": [
(
"Key Specification",
{
"description": "Arguments to allow specifying a key",
"mut_ex_args": [
(
False,
[
(
"--keyfile-path",
{"help": "Path to a key file containing a key"},
),
(
"--capture-key",
{
"action": "store_true",
"help": "Read key from stdin",
},
),
],
),
],
},
)
],
"mut_ex_args": [
(
True,
Expand All @@ -243,15 +269,15 @@ def _ensure_nat(arg):
{"help": "name of the pool to start"},
),
],
)
),
],
"args": [
(
"--unlock-method",
{
"choices": list(EncryptionMethod),
"choices": list(UnlockMethod),
"help": "Method to use to unlock the pool if encrypted.",
"type": EncryptionMethod,
"type": UnlockMethod,
},
),
],
Expand Down
11 changes: 11 additions & 0 deletions tests/whitebox/integration/pool/test_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,14 @@ def test_good_name(self):
RUNNER(command_line)

self.check_error(StratisCliNoChangeError, command_line, _ERROR)

def test_capture_key(self):
"""
Test trying to start an unencrypted pool with a verified passphrase.
"""
command_line = ["pool", "stop", f"--name={self._POOLNAME}"]
RUNNER(command_line)
command_line = self._MENU + [f"--name={self._POOLNAME}", "--capture-key"]
self.check_error(
StratisCliEngineError, command_line, _ERROR, stdin="password\npassword\n"
)

0 comments on commit 72aca2c

Please sign in to comment.