feature(keyringctl): add option to filter listing by trust
This commit is contained in:
parent
e9dc04df32
commit
c651bdc61e
@ -15,6 +15,7 @@ from .keyring import convert
|
|||||||
from .keyring import export
|
from .keyring import export
|
||||||
from .keyring import inspect_keyring
|
from .keyring import inspect_keyring
|
||||||
from .keyring import list_keyring
|
from .keyring import list_keyring
|
||||||
|
from .types import TrustFilter
|
||||||
from .util import absolute_path
|
from .util import absolute_path
|
||||||
from .util import cwd
|
from .util import cwd
|
||||||
from .verify import verify
|
from .verify import verify
|
||||||
@ -81,6 +82,12 @@ list_parser = subcommands.add_parser(
|
|||||||
help="list the certificates in the keyring",
|
help="list the certificates in the keyring",
|
||||||
)
|
)
|
||||||
list_parser.add_argument("--main", action="store_true", help="List main signing keys instead of packager keys")
|
list_parser.add_argument("--main", action="store_true", help="List main signing keys instead of packager keys")
|
||||||
|
list_parser.add_argument(
|
||||||
|
"--trust",
|
||||||
|
choices=[e.value for e in TrustFilter],
|
||||||
|
default=TrustFilter.all.value,
|
||||||
|
help="Filter the list based on trust",
|
||||||
|
)
|
||||||
list_parser.add_argument(
|
list_parser.add_argument(
|
||||||
"source",
|
"source",
|
||||||
nargs="*",
|
nargs="*",
|
||||||
@ -180,10 +187,12 @@ def main() -> None: # noqa: ignore=C901
|
|||||||
target_dir=keyring_root.parent / "build",
|
target_dir=keyring_root.parent / "build",
|
||||||
)
|
)
|
||||||
elif "list" == args.subcommand:
|
elif "list" == args.subcommand:
|
||||||
|
trust_filter = TrustFilter[args.trust]
|
||||||
list_keyring(
|
list_keyring(
|
||||||
keyring_root=keyring_root,
|
keyring_root=keyring_root,
|
||||||
sources=args.source,
|
sources=args.source,
|
||||||
main_keys=args.main,
|
main_keys=args.main,
|
||||||
|
trust_filter=trust_filter,
|
||||||
)
|
)
|
||||||
elif "inspect" == args.subcommand:
|
elif "inspect" == args.subcommand:
|
||||||
print(
|
print(
|
||||||
|
@ -25,9 +25,11 @@ from .sequoia import packet_signature_creation_time
|
|||||||
from .sequoia import packet_split
|
from .sequoia import packet_split
|
||||||
from .trust import certificate_trust
|
from .trust import certificate_trust
|
||||||
from .trust import certificate_trust_from_paths
|
from .trust import certificate_trust_from_paths
|
||||||
|
from .trust import filter_by_trust
|
||||||
from .trust import format_trust_label
|
from .trust import format_trust_label
|
||||||
from .types import Fingerprint
|
from .types import Fingerprint
|
||||||
from .types import Trust
|
from .types import Trust
|
||||||
|
from .types import TrustFilter
|
||||||
from .types import Uid
|
from .types import Uid
|
||||||
from .types import Username
|
from .types import Username
|
||||||
from .util import contains_fingerprint
|
from .util import contains_fingerprint
|
||||||
@ -1097,7 +1099,12 @@ def build(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def list_keyring(keyring_root: Path, sources: Optional[List[Path]] = None, main_keys: bool = False) -> None:
|
def list_keyring(
|
||||||
|
keyring_root: Path,
|
||||||
|
sources: Optional[List[Path]] = None,
|
||||||
|
main_keys: bool = False,
|
||||||
|
trust_filter: TrustFilter = TrustFilter.all,
|
||||||
|
) -> None:
|
||||||
"""List certificates in the keyring
|
"""List certificates in the keyring
|
||||||
|
|
||||||
If sources contains directories, all certificate below them are considered.
|
If sources contains directories, all certificate below them are considered.
|
||||||
@ -1108,6 +1115,7 @@ def list_keyring(keyring_root: Path, sources: Optional[List[Path]] = None, main_
|
|||||||
sources: A list of username, fingerprint or directories from which to read PGP packet information
|
sources: A list of username, fingerprint or directories from which to read PGP packet information
|
||||||
(defaults to `keyring_root`)
|
(defaults to `keyring_root`)
|
||||||
main_keys: List main keys instead of packager keys (defaults to False)
|
main_keys: List main keys instead of packager keys (defaults to False)
|
||||||
|
trust_filter: Filter the listing based on trust
|
||||||
"""
|
"""
|
||||||
|
|
||||||
keyring_dir = keyring_root / ("main" if main_keys else "packager")
|
keyring_dir = keyring_root / ("main" if main_keys else "packager")
|
||||||
@ -1130,6 +1138,8 @@ def list_keyring(keyring_root: Path, sources: Optional[List[Path]] = None, main_
|
|||||||
main_keys=get_fingerprints_from_paths([keyring_root / "main"]),
|
main_keys=get_fingerprints_from_paths([keyring_root / "main"]),
|
||||||
all_fingerprints=get_fingerprints_from_paths([keyring_root]),
|
all_fingerprints=get_fingerprints_from_paths([keyring_root]),
|
||||||
)
|
)
|
||||||
|
if not filter_by_trust(trust=trust, trust_filter=trust_filter):
|
||||||
|
continue
|
||||||
trust_label = format_trust_label(trust=trust)
|
trust_label = format_trust_label(trust=trust)
|
||||||
print(f"{username:<{username_length}} {certificate.name} {trust_label}")
|
print(f"{username:<{username_length}} {certificate.name} {trust_label}")
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ from typing import Set
|
|||||||
from .types import Color
|
from .types import Color
|
||||||
from .types import Fingerprint
|
from .types import Fingerprint
|
||||||
from .types import Trust
|
from .types import Trust
|
||||||
|
from .types import TrustFilter
|
||||||
from .types import Uid
|
from .types import Uid
|
||||||
from .util import contains_fingerprint
|
from .util import contains_fingerprint
|
||||||
from .util import get_cert_paths
|
from .util import get_cert_paths
|
||||||
@ -236,3 +237,26 @@ def format_trust_label(trust: Trust) -> str:
|
|||||||
Text label representing the trust status as literal and icon with colors
|
Text label representing the trust status as literal and icon with colors
|
||||||
"""
|
"""
|
||||||
return f"{trust_color(trust).value}{trust_icon(trust)} {trust.name}{Color.RST.value}"
|
return f"{trust_color(trust).value}{trust_icon(trust)} {trust.name}{Color.RST.value}"
|
||||||
|
|
||||||
|
|
||||||
|
def filter_by_trust(trust: Trust, trust_filter: TrustFilter) -> bool:
|
||||||
|
"""Filters a trust by a given filter and returns true if within the rules
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
trust: Trust to check for being filtered
|
||||||
|
trust_filter: Filter rules to check the trust against
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
True if the given trust is within the filter rules
|
||||||
|
"""
|
||||||
|
trust_map = {
|
||||||
|
TrustFilter.unknown: [Trust.unknown],
|
||||||
|
TrustFilter.marginal: [Trust.marginal],
|
||||||
|
TrustFilter.full: [Trust.full],
|
||||||
|
TrustFilter.revoked: [Trust.revoked],
|
||||||
|
TrustFilter.unrevoked: [Trust.unknown, Trust.marginal, Trust.full],
|
||||||
|
TrustFilter.all: [Trust.revoked, Trust.unknown, Trust.marginal, Trust.full],
|
||||||
|
}
|
||||||
|
return trust in trust_map[trust_filter]
|
||||||
|
@ -17,6 +17,15 @@ class Trust(Enum):
|
|||||||
full = auto()
|
full = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class TrustFilter(Enum):
|
||||||
|
unknown = "unknown"
|
||||||
|
revoked = "revoked"
|
||||||
|
marginal = "marginal"
|
||||||
|
full = "full"
|
||||||
|
unrevoked = "unrevoked"
|
||||||
|
all = "all"
|
||||||
|
|
||||||
|
|
||||||
TRUST_MAX_LENGTH: int = max([len(e.name) for e in Trust])
|
TRUST_MAX_LENGTH: int = max([len(e.name) for e in Trust])
|
||||||
|
|
||||||
|
|
||||||
|
@ -728,6 +728,12 @@ def test_list_keyring(working_dir: Path, keyring_dir: Path) -> None:
|
|||||||
keyring.list_keyring(keyring_root=keyring_dir, sources=[path], main_keys=False)
|
keyring.list_keyring(keyring_root=keyring_dir, sources=[path], main_keys=False)
|
||||||
print_args = [mock_call[1][0] for mock_call in print_mock.mock_calls]
|
print_args = [mock_call[1][0] for mock_call in print_mock.mock_calls]
|
||||||
assert name in print_args[0] and path.stem in print_args[0]
|
assert name in print_args[0] and path.stem in print_args[0]
|
||||||
|
with patch("builtins.print") as print_mock:
|
||||||
|
keyring.list_keyring(
|
||||||
|
keyring_root=keyring_dir, sources=paths, main_keys=False, trust_filter=TrustFilter.revoked
|
||||||
|
)
|
||||||
|
print_args = [mock_call[1][0] for mock_call in print_mock.mock_calls]
|
||||||
|
assert not print_args
|
||||||
|
|
||||||
|
|
||||||
@create_certificate(username=Username("main"), uids=[Uid("main <foo@bar.xyz>")], keyring_type="main")
|
@create_certificate(username=Username("main"), uids=[Uid("main <foo@bar.xyz>")], keyring_type="main")
|
||||||
|
@ -8,12 +8,14 @@ from pytest import raises
|
|||||||
|
|
||||||
from libkeyringctl.trust import certificate_trust
|
from libkeyringctl.trust import certificate_trust
|
||||||
from libkeyringctl.trust import certificate_trust_from_paths
|
from libkeyringctl.trust import certificate_trust_from_paths
|
||||||
|
from libkeyringctl.trust import filter_by_trust
|
||||||
from libkeyringctl.trust import format_trust_label
|
from libkeyringctl.trust import format_trust_label
|
||||||
from libkeyringctl.trust import trust_color
|
from libkeyringctl.trust import trust_color
|
||||||
from libkeyringctl.trust import trust_icon
|
from libkeyringctl.trust import trust_icon
|
||||||
from libkeyringctl.types import Color
|
from libkeyringctl.types import Color
|
||||||
from libkeyringctl.types import Fingerprint
|
from libkeyringctl.types import Fingerprint
|
||||||
from libkeyringctl.types import Trust
|
from libkeyringctl.types import Trust
|
||||||
|
from libkeyringctl.types import TrustFilter
|
||||||
from libkeyringctl.types import Uid
|
from libkeyringctl.types import Uid
|
||||||
from libkeyringctl.types import Username
|
from libkeyringctl.types import Username
|
||||||
|
|
||||||
@ -327,3 +329,36 @@ def test_format_trust_label(trust_color_mock: Mock, trust_icon_mock: Mock, trust
|
|||||||
trust_icon_mock.return_value = "ICON"
|
trust_icon_mock.return_value = "ICON"
|
||||||
trust_color_mock.return_value = Color.GREEN
|
trust_color_mock.return_value = Color.GREEN
|
||||||
assert f"{Color.GREEN.value}ICON {trust.name}{Color.RST.value}" == format_trust_label(trust)
|
assert f"{Color.GREEN.value}ICON {trust.name}{Color.RST.value}" == format_trust_label(trust)
|
||||||
|
|
||||||
|
|
||||||
|
@mark.parametrize(
|
||||||
|
"trust, trust_filter, result",
|
||||||
|
[
|
||||||
|
(Trust.revoked, TrustFilter.unknown, False),
|
||||||
|
(Trust.full, TrustFilter.unknown, False),
|
||||||
|
(Trust.marginal, TrustFilter.unknown, False),
|
||||||
|
(Trust.unknown, TrustFilter.unknown, True),
|
||||||
|
(Trust.revoked, TrustFilter.marginal, False),
|
||||||
|
(Trust.full, TrustFilter.marginal, False),
|
||||||
|
(Trust.marginal, TrustFilter.marginal, True),
|
||||||
|
(Trust.unknown, TrustFilter.marginal, False),
|
||||||
|
(Trust.revoked, TrustFilter.full, False),
|
||||||
|
(Trust.full, TrustFilter.full, True),
|
||||||
|
(Trust.marginal, TrustFilter.full, False),
|
||||||
|
(Trust.unknown, TrustFilter.full, False),
|
||||||
|
(Trust.revoked, TrustFilter.revoked, True),
|
||||||
|
(Trust.full, TrustFilter.revoked, False),
|
||||||
|
(Trust.marginal, TrustFilter.revoked, False),
|
||||||
|
(Trust.unknown, TrustFilter.revoked, False),
|
||||||
|
(Trust.revoked, TrustFilter.unrevoked, False),
|
||||||
|
(Trust.full, TrustFilter.unrevoked, True),
|
||||||
|
(Trust.marginal, TrustFilter.unrevoked, True),
|
||||||
|
(Trust.unknown, TrustFilter.unrevoked, True),
|
||||||
|
(Trust.revoked, TrustFilter.all, True),
|
||||||
|
(Trust.full, TrustFilter.all, True),
|
||||||
|
(Trust.marginal, TrustFilter.all, True),
|
||||||
|
(Trust.unknown, TrustFilter.all, True),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_filter_by_trust(trust: Trust, trust_filter: TrustFilter, result: bool) -> None:
|
||||||
|
assert filter_by_trust(trust=trust, trust_filter=trust_filter) == result
|
||||||
|
Loading…
Reference in New Issue
Block a user