Skip to content

Commit 6199f46

Browse files
author
Lukas Puehringer
committed
Use stdlib subprocess.run for gpg processes
This commit replaces calls to the custom process.run function, in favor of the stdlib subprocess.run. The former is a very thin wrapper around the latter, which was more useful when we still needed Py2/3 case-handling. Which is not the case anymore. NOTE: This commit replicates the prior behavior, most notably the following subprocess.run arguments: - *popenargs: we still use shlex.split to turn the full command string into a list - check Signed-off-by: Lukas Puehringer <[email protected]>
1 parent fd3c71f commit 6199f46

File tree

4 files changed

+44
-28
lines changed

4 files changed

+44
-28
lines changed

securesystemslib/gpg/constants.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
import functools
1919
import logging
2020
import os
21+
import shlex
2122
import subprocess # nosec
22-
23-
from securesystemslib import process
23+
from typing import List
2424

2525
log = logging.getLogger(__name__)
2626

@@ -30,13 +30,14 @@
3030
@functools.lru_cache(maxsize=3)
3131
def is_available_gnupg(gnupg: str, timeout=GPG_TIMEOUT) -> bool:
3232
"""Returns whether gnupg points to a gpg binary."""
33-
gpg_version_cmd = gnupg + " --version"
33+
gpg_version_cmd = shlex.split(f"{gnupg} --version")
3434
try:
35-
process.run(
35+
subprocess.run(
3636
gpg_version_cmd,
37-
stdout=process.PIPE,
38-
stderr=process.PIPE,
37+
stdout=subprocess.PIPE,
38+
stderr=subprocess.PIPE,
3939
timeout=timeout,
40+
check=True,
4041
)
4142
return True
4243
except (OSError, subprocess.TimeoutExpired):
@@ -68,9 +69,9 @@ def have_gpg() -> bool:
6869
return bool(gpg_command())
6970

7071

71-
def gpg_version_command() -> str:
72+
def gpg_version_command() -> List[str]:
7273
"""Returns the command to get the current GPG version."""
73-
return f"{gpg_command()} --version"
74+
return shlex.split(f"{gpg_command()} --version")
7475

7576

7677
FULLY_SUPPORTED_MIN_VERSION = "2.1.0"
@@ -80,16 +81,16 @@ def gpg_version_command() -> str:
8081
)
8182

8283

83-
def gpg_sign_command(keyarg: str, homearg: str) -> str:
84+
def gpg_sign_command(keyarg: str, homearg: str) -> List[str]:
8485
"""Returns the command to use GPG to sign STDIN."""
85-
return (
86+
return shlex.split(
8687
f"{gpg_command()} --detach-sign --digest-algo SHA256 {keyarg} {homearg}"
8788
)
8889

8990

90-
def gpg_export_pubkey_command(homearg: str, keyid: str):
91+
def gpg_export_pubkey_command(homearg: str, keyid: str) -> List[str]:
9192
"""Returns the GPG command to export a public key."""
92-
return f"{gpg_command()} {homearg} --export {keyid}"
93+
return shlex.split(f"{gpg_command()} {homearg} --export {keyid}")
9394

9495

9596
# See RFC4880 section 4.3. Packet Tags for a list of all packet types The

securesystemslib/gpg/functions.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
verifying signatures.
1717
"""
1818
import logging
19+
import subprocess # nosec
1920
import time
2021

21-
from securesystemslib import exceptions, formats, process
22+
from securesystemslib import exceptions, formats
2223
from securesystemslib.gpg.common import (
2324
get_pubkey_bundle,
2425
parse_signature_packet,
@@ -125,12 +126,12 @@ def create_signature(content, keyid=None, homedir=None, timeout=GPG_TIMEOUT):
125126

126127
command = gpg_sign_command(keyarg=keyarg, homearg=homearg)
127128

128-
gpg_process = process.run(
129+
gpg_process = subprocess.run(
129130
command,
130131
input=content,
131132
check=False,
132-
stdout=process.PIPE,
133-
stderr=process.PIPE,
133+
stdout=subprocess.PIPE,
134+
stderr=subprocess.PIPE,
134135
timeout=timeout,
135136
)
136137

@@ -313,9 +314,12 @@ def export_pubkey(keyid, homedir=None, timeout=GPG_TIMEOUT):
313314
# TODO: Consider adopting command error handling from `create_signature`
314315
# above, e.g. in a common 'run gpg command' utility function
315316
command = gpg_export_pubkey_command(keyid=keyid, homearg=homearg)
316-
317-
gpg_process = process.run(
318-
command, stdout=process.PIPE, stderr=process.PIPE, timeout=timeout
317+
gpg_process = subprocess.run(
318+
command,
319+
stdout=subprocess.PIPE,
320+
stderr=subprocess.PIPE,
321+
timeout=timeout,
322+
check=True,
319323
)
320324

321325
key_packet = gpg_process.stdout

securesystemslib/gpg/util.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import logging
2020
import re
2121
import struct
22+
import subprocess # nosec
2223

2324
CRYPTO = True
2425
NO_CRYPTO_MSG = "gpg.utils requires the cryptography library"
@@ -29,7 +30,7 @@
2930
CRYPTO = False
3031

3132
# pylint: disable=wrong-import-position
32-
from securesystemslib import exceptions, process
33+
from securesystemslib import exceptions
3334
from securesystemslib.gpg import constants
3435
from securesystemslib.gpg.exceptions import PacketParsingError
3536

@@ -375,12 +376,13 @@ def get_version() -> Version:
375376
raise exceptions.UnsupportedLibraryError(constants.NO_GPG_MSG)
376377

377378
command = constants.gpg_version_command()
378-
gpg_process = process.run(
379+
gpg_process = subprocess.run(
379380
command,
380-
stdout=process.PIPE,
381-
stderr=process.PIPE,
381+
stdout=subprocess.PIPE,
382+
stderr=subprocess.PIPE,
382383
universal_newlines=True,
383384
timeout=constants.GPG_TIMEOUT,
385+
check=True,
384386
)
385387

386388
full_version_info = gpg_process.stdout

tests/test_gpg.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import os
2323
import shutil
24+
import subprocess # nosec
2425
import tempfile
2526
import unittest
2627

@@ -33,7 +34,7 @@
3334
from cryptography.hazmat import backends
3435
from cryptography.hazmat.primitives import serialization
3536

36-
from securesystemslib import exceptions, process
37+
from securesystemslib import exceptions
3738
from securesystemslib.formats import ANY_PUBKEY_DICT_SCHEMA, GPG_PUBKEY_SCHEMA
3839
from securesystemslib.gpg.common import (
3940
_assign_certified_key_info,
@@ -235,17 +236,25 @@ def setUpClass(self): # pylint: disable=bad-classmethod-argument
235236
# erroneous gpg data in tests below.
236237
keyid = "F557D0FF451DEF45372591429EA70BD13D883381"
237238
cmd = gpg_export_pubkey_command(keyid=keyid, homearg=homearg)
238-
proc = process.run(
239-
cmd, stdout=process.PIPE, stderr=process.PIPE, timeout=GPG_TIMEOUT
239+
proc = subprocess.run(
240+
cmd,
241+
stdout=subprocess.PIPE,
242+
stderr=subprocess.PIPE,
243+
timeout=GPG_TIMEOUT,
244+
check=True,
240245
)
241246
self.raw_key_data = proc.stdout
242247
self.raw_key_bundle = parse_pubkey_bundle(self.raw_key_data)
243248

244249
# Export pubkey bundle with expired key for key expiration tests
245250
keyid = "E8AC80C924116DABB51D4B987CB07D6D2C199C7C"
246251
cmd = gpg_export_pubkey_command(keyid=keyid, homearg=homearg)
247-
proc = process.run(
248-
cmd, stdout=process.PIPE, stderr=process.PIPE, timeout=GPG_TIMEOUT
252+
proc = subprocess.run(
253+
cmd,
254+
stdout=subprocess.PIPE,
255+
stderr=subprocess.PIPE,
256+
timeout=GPG_TIMEOUT,
257+
check=True,
249258
)
250259
self.raw_expired_key_bundle = parse_pubkey_bundle(proc.stdout)
251260

0 commit comments

Comments
 (0)