feature(keyringctl): use sq to split a keyring into individual certificates

Lets use sequoia as well to split an input into individual certificates
instead of creating a custom made function for this job.

Pass down the name of the original input file to `convert_certificate`
in case no override has been defined.
This commit is contained in:
Levente Polyak 2021-10-12 19:20:33 +02:00
parent 4e24fe5da4
commit 92f07f0d4b
No known key found for this signature in database
GPG Key ID: FC1B547C8D8172C8

View File

@ -632,45 +632,29 @@ def packet_dump_field(packet: Path, field: str) -> str:
return lines[0].split(maxsplit=1)[1] return lines[0].split(maxsplit=1)[1]
def sanitize_certificate_file(working_dir: Path, certificate: Path) -> List[Path]: def keyring_split(working_dir: Path, keyring: Path) -> Iterable[Path]:
"""Sanitize a certificate file, potentially containing several certificates """Split a file containing a PGP keyring into separate certificate files
If the input file holds several certificates, they are split into respective files below working_dir and their The file is split using sq
paths are returned. Else the path to the input certificate file is returned.
This is done to be able to read all certificates contained in a file (`sq` only reads the first).
Parameters Parameters
---------- ----------
working_dir: Path working_dir: Path
The path of the working directory below which to create split certificates The path of the working directory below which to create the output files
certificate: Path keyring: Path
The absolute path of a file containing one or several PGP certificates The path of a file containing a PGP keyring
Returns Returns
------- -------
List[Path] Iterable[Path]
A list of paths that either contain the input certificate or several split certificates An iterable over the naturally sorted list of certificate files derived from a keyring
""" """
begin_cert = "-----BEGIN PGP PUBLIC KEY BLOCK-----" keyring_dir = Path(mkdtemp(dir=working_dir, prefix='keyring-')).absolute()
end_cert = "-----END PGP PUBLIC KEY BLOCK-----"
certificate_list: List[Path] = []
with open(file=certificate, mode="r") as certificate_file: with cwd(keyring_dir):
file = certificate_file.read() system(['sq', 'keyring', 'split', '--prefix', '', str(keyring)])
if file.count(begin_cert) > 1 and file.count(end_cert) > 1: return natural_sort_path(keyring_dir.iterdir())
debug(f"Several public keys detected in file: {certificate}")
for split_cert in [f"{cert}{end_cert}\n" for cert in list(filter(None, file.split(f"{end_cert}\n")))]:
split_cert_dir = Path(mkdtemp(dir=working_dir)).absolute()
split_cert_path = split_cert_dir / certificate.name
with open(file=split_cert_path, mode="w") as split_cert_file:
split_cert_file.write(split_cert)
debug(f"Writing split cert to file: {split_cert_path}")
certificate_list.append(split_cert_path)
return certificate_list
else:
return [certificate]
def packet_split(working_dir: Path, certificate: Path) -> Iterable[Path]: def packet_split(working_dir: Path, certificate: Path) -> Iterable[Path]:
@ -746,9 +730,9 @@ def convert(
target_dir: Path, target_dir: Path,
name_override: Optional[str] = None, name_override: Optional[str] = None,
) -> Path: ) -> Path:
"""Convert a path containing PGP public key material to a decomposed directory structure """Convert a path containing PGP certificate material to a decomposed directory structure
Any PGP public key material described by source is first sanitized (split) by `sanitize_certificate_file()`. Any input is first split by `keyring_split()` into individual certificates.
Parameters Parameters
---------- ----------
@ -770,14 +754,16 @@ def convert(
directories: List[Path] = [] directories: List[Path] = []
if source.is_dir(): if source.is_dir():
for key in source.iterdir(): for key in source.iterdir():
for sane_cert in sanitize_certificate_file(working_dir=working_dir, certificate=key): name = name_override or key.stem
for cert in keyring_split(working_dir=working_dir, keyring=key):
directories.append( directories.append(
convert_certificate(working_dir=working_dir, certificate=sane_cert, name_override=name_override) convert_certificate(working_dir=working_dir, certificate=cert, name_override=name)
) )
else: else:
for sane_cert in sanitize_certificate_file(working_dir=working_dir, certificate=source): name = name_override or source.stem
for cert in keyring_split(working_dir=working_dir, keyring=source):
directories.append( directories.append(
convert_certificate(working_dir=working_dir, certificate=sane_cert, name_override=name_override) convert_certificate(working_dir=working_dir, certificate=cert, name_override=name)
) )
for path in directories: for path in directories: