feature(keyringctl): avoid splitting a certificate multiple times
Move the name cascade to derive the username into the `convert_certificate` function which allows to use the certificate_fingerprint directly instead of trying to find it by splitting the certificate one more time before converting.
This commit is contained in:
parent
cf6bac5fd9
commit
60ee3d6d94
75
keyringctl
75
keyringctl
@ -139,12 +139,14 @@ def system(cmd: List[str], exit_on_error: bool = True) -> str:
|
|||||||
def convert_certificate( # noqa: ignore=C901
|
def convert_certificate( # noqa: ignore=C901
|
||||||
working_dir: Path,
|
working_dir: Path,
|
||||||
certificate: Path,
|
certificate: Path,
|
||||||
|
keyring_dir: Path,
|
||||||
name_override: Optional[str] = None,
|
name_override: Optional[str] = None,
|
||||||
fingerprint_filter: Optional[Set[Fingerprint]] = None,
|
fingerprint_filter: Optional[Set[Fingerprint]] = None,
|
||||||
) -> Path:
|
) -> Path:
|
||||||
"""Convert a single file public key certificate into a decomposed directory structure of multiple PGP packets
|
"""Convert a single file public key certificate into a decomposed directory structure of multiple PGP packets
|
||||||
|
|
||||||
The output directory structure is created per user. The username is derived from the certificate (or overridden).
|
The output directory structure is created per user. The username is derived from the certificate via
|
||||||
|
`derive_username_from_fingerprint` or overridden via `name_override`.
|
||||||
Below the username directory a directory tree describes the public keys components split up into certifications
|
Below the username directory a directory tree describes the public keys components split up into certifications
|
||||||
and revocations, as well as per subkey and per uid certifications and revocations.
|
and revocations, as well as per subkey and per uid certifications and revocations.
|
||||||
|
|
||||||
@ -154,6 +156,8 @@ def convert_certificate( # noqa: ignore=C901
|
|||||||
The path of the working directory below which to create split certificates
|
The path of the working directory below which to create split certificates
|
||||||
certificate: Path
|
certificate: Path
|
||||||
The path to a public key certificate
|
The path to a public key certificate
|
||||||
|
keyring_dir: Path
|
||||||
|
The path of the keyring used to try to derive the username from the public key fingerprint
|
||||||
name_override: Optional[str]
|
name_override: Optional[str]
|
||||||
An optional string to override the username in the to be created output directory structure
|
An optional string to override the username in the to be created output directory structure
|
||||||
fingerprint_filter: Optional[Set[Fingerprint]]
|
fingerprint_filter: Optional[Set[Fingerprint]]
|
||||||
@ -189,7 +193,6 @@ def convert_certificate( # noqa: ignore=C901
|
|||||||
revocations: Dict[Uid, List[Path]] = defaultdict(list)
|
revocations: Dict[Uid, List[Path]] = defaultdict(list)
|
||||||
|
|
||||||
# intermediate variables
|
# intermediate variables
|
||||||
username: str = name_override or certificate.stem
|
|
||||||
current_packet_mode: Optional[str] = None
|
current_packet_mode: Optional[str] = None
|
||||||
current_packet_fingerprint: Optional[Fingerprint] = None
|
current_packet_fingerprint: Optional[Fingerprint] = None
|
||||||
current_packet_uid: Optional[Uid] = None
|
current_packet_uid: Optional[Uid] = None
|
||||||
@ -275,7 +278,10 @@ def convert_certificate( # noqa: ignore=C901
|
|||||||
if not pubkey:
|
if not pubkey:
|
||||||
raise Exception("missing certificate public-key")
|
raise Exception("missing certificate public-key")
|
||||||
|
|
||||||
user_dir = working_dir / username
|
name_override = name_override or derive_username_from_fingerprint(keyring_dir=keyring_dir,
|
||||||
|
certificate_fingerprint=certificate_fingerprint) or certificate.stem
|
||||||
|
|
||||||
|
user_dir = working_dir / name_override
|
||||||
key_dir = user_dir / certificate_fingerprint
|
key_dir = user_dir / certificate_fingerprint
|
||||||
key_dir.mkdir(parents=True, exist_ok=True)
|
key_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
@ -691,17 +697,15 @@ def simplify_user_id(user_id: Uid) -> Uid:
|
|||||||
return Uid(user_id_str)
|
return Uid(user_id_str)
|
||||||
|
|
||||||
|
|
||||||
def derive_user_from_target(working_dir: Path, target_dir: Path, certificate: Path) -> Optional[str]:
|
def derive_username_from_fingerprint(keyring_dir: Path, certificate_fingerprint: Fingerprint) -> Optional[str]:
|
||||||
"""Attempt to derive the username of a public key from a target directory
|
"""Attempt to derive the username of a public key fingerprint from a keyring directory
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
working_dir: Path
|
keyring_dir: Path
|
||||||
A directory to use for temporary files
|
|
||||||
target_dir: Path
|
|
||||||
The directory in which to look up a username
|
The directory in which to look up a username
|
||||||
certificate: Path
|
certificate_fingerprint: Fingerprint
|
||||||
A public key file
|
The public key fingerprint to derive the username from
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
------
|
------
|
||||||
@ -714,52 +718,18 @@ def derive_user_from_target(working_dir: Path, target_dir: Path, certificate: Pa
|
|||||||
A string representing the username a public key certificate belongs to, None otherwise
|
A string representing the username a public key certificate belongs to, None otherwise
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_certificate_fingerprint(working_dir: Path, certificate: Path) -> str:
|
matches = list(keyring_dir.glob(f"*/{certificate_fingerprint}"))
|
||||||
"""Get the certificate fingerprint from a PGP public key file
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
working_dir: Path
|
|
||||||
A directory to use for temporary files
|
|
||||||
certificate: Path
|
|
||||||
A PGP public key file
|
|
||||||
|
|
||||||
Raises
|
|
||||||
------
|
|
||||||
Exception
|
|
||||||
If no fingerprint can be found in the provided PGP public key file
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
str
|
|
||||||
The fingerprint of the PGP public key file
|
|
||||||
"""
|
|
||||||
|
|
||||||
certificate_fingerprint = ""
|
|
||||||
for packet in packet_split(working_dir=working_dir, certificate=certificate):
|
|
||||||
if packet.name.endswith("--PublicKey"):
|
|
||||||
certificate_fingerprint = packet_dump_field(packet, "Fingerprint")
|
|
||||||
|
|
||||||
if not certificate_fingerprint:
|
|
||||||
raise Exception(f"The public key file {certificate} does not provide a PublicKey fingerprint.")
|
|
||||||
|
|
||||||
return certificate_fingerprint
|
|
||||||
|
|
||||||
certificate_fingerprint = get_certificate_fingerprint(working_dir=working_dir, certificate=certificate)
|
|
||||||
debug(f"Derived fingerprint '{certificate_fingerprint}' from {certificate}")
|
|
||||||
|
|
||||||
matches = list(target_dir.glob(f"*/{certificate_fingerprint}"))
|
|
||||||
|
|
||||||
if len(matches) > 1:
|
if len(matches) > 1:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
f"More than one username found in {target_dir} when probing for fingerprint '{certificate_fingerprint}'!"
|
f"More than one username found in {keyring_dir} when probing for fingerprint '{certificate_fingerprint}': {matches}"
|
||||||
)
|
)
|
||||||
elif len(matches) == 0:
|
elif not matches:
|
||||||
debug(f"Can not derive username from target directory for certificate {certificate}")
|
debug(f"Can not derive username from target directory for fingerprint {certificate_fingerprint}")
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
username = matches[0].parent.stem
|
username = matches[0].parent.stem
|
||||||
debug(f"Successfully derived username '{username}' from target directory for certificate {certificate}")
|
debug(f"Successfully derived username '{username}' from target directory for fingerprint {certificate_fingerprint}")
|
||||||
return username
|
return username
|
||||||
|
|
||||||
|
|
||||||
@ -798,15 +768,12 @@ def convert(
|
|||||||
|
|
||||||
for key in keys:
|
for key in keys:
|
||||||
for cert in keyring_split(working_dir=working_dir, keyring=key):
|
for cert in keyring_split(working_dir=working_dir, keyring=key):
|
||||||
name = (
|
|
||||||
name_override or derive_user_from_target(working_dir=working_dir, target_dir=target_dir,
|
|
||||||
certificate=cert) or key.stem
|
|
||||||
)
|
|
||||||
directories.append(
|
directories.append(
|
||||||
convert_certificate(
|
convert_certificate(
|
||||||
working_dir=working_dir,
|
working_dir=working_dir,
|
||||||
certificate=cert,
|
certificate=cert,
|
||||||
name_override=name,
|
keyring_dir=target_dir,
|
||||||
|
name_override=name_override,
|
||||||
fingerprint_filter=fingerprint_filter,
|
fingerprint_filter=fingerprint_filter,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user