Create GNUPGHOME if it does not exist

This commit is contained in:
jeanluc 2024-04-04 11:20:59 +02:00 committed by Daniel Wozniak
parent 75e1569db1
commit 596924e510
3 changed files with 81 additions and 46 deletions

1
changelog/66312.fixed.md Normal file
View file

@ -0,0 +1 @@
Made gpg modules create GNUPGHOME if it does not exist

View file

@ -173,32 +173,35 @@ def _restore_ownership(func):
userinfo = _get_user_info(user)
run_user = _get_user_info()
if not os.path.exists(gnupghome):
_create_gnupghome(user, gnupghome)
if userinfo["uid"] != run_user["uid"]:
group = None
if os.path.exists(gnupghome):
# Given user is different from one who runs Salt process,
# need to fix ownership permissions for GnuPG home dir
group = __salt__["file.gid_to_group"](run_user["gid"])
for path in [gnupghome] + __salt__["file.find"](gnupghome):
__salt__["file.chown"](path, run_user["name"], group)
# Given user is different from one who runs Salt process,
# need to fix ownership permissions for GnuPG home dir
for path in [gnupghome] + __salt__["file.find"](gnupghome):
__salt__["file.chown"](
path, user=run_user["uid"], group=run_user["gid"]
)
if keyring and os.path.exists(keyring):
if group is None:
group = __salt__["file.gid_to_group"](run_user["gid"])
__salt__["file.chown"](keyring, run_user["name"], group)
__salt__["file.chown"](
keyring, user=run_user["uid"], group=run_user["gid"]
)
# Filter special kwargs
for key in list(kwargs):
if key.startswith("__"):
del kwargs[key]
filtered_kwargs = {k: v for k, v in kwargs.items() if not k.startswith("__")}
ret = func(*args, **kwargs)
ret = func(*args, **filtered_kwargs)
if userinfo["uid"] != run_user["uid"]:
group = __salt__["file.gid_to_group"](userinfo["gid"])
for path in [gnupghome] + __salt__["file.find"](gnupghome):
__salt__["file.chown"](path, user, group)
__salt__["file.chown"](
path, user=userinfo["uid"], group=userinfo["gid"]
)
if keyring and os.path.exists(keyring):
__salt__["file.chown"](keyring, user, group)
__salt__["file.chown"](
keyring, user=userinfo["uid"], group=userinfo["gid"]
)
return ret
return func_wrapper
@ -216,11 +219,24 @@ def _create_gpg(user=None, gnupghome=None, keyring=None):
"Please pass keyring as a string. Multiple keyrings are not allowed"
)
gpg = gnupg.GPG(gnupghome=gnupghome, keyring=keyring)
try:
gpg = gnupg.GPG(gnupghome=gnupghome, keyring=keyring)
except ValueError as err:
if not str(err).startswith("gnupghome should be a directory"):
raise
_create_gnupghome(user, gnupghome)
gpg = gnupg.GPG(gnupghome=gnupghome, keyring=keyring)
return gpg
def _create_gnupghome(user, gnupghome):
user_info = _get_user_info(user)
__salt__["file.mkdir"](
gnupghome, user=user_info["uid"], group=user_info["gid"], mode="0700"
)
def _list_keys(secret=False, user=None, gnupghome=None, keyring=None):
"""
Helper function for listing keys

View file

@ -12,6 +12,37 @@ pytestmark = [
]
def _kill_gpg_agent(root):
gpg_connect_agent = shutil.which("gpg-connect-agent")
if gpg_connect_agent:
gnupghome = root / ".gnupg"
if not gnupghome.is_dir():
gnupghome = root
try:
subprocess.run(
[gpg_connect_agent, "killagent", "/bye"],
env={"GNUPGHOME": str(gnupghome)},
shell=False,
check=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
except subprocess.CalledProcessError:
# This is likely CentOS 7 or Amazon Linux 2
pass
# If the above errored or was not enough, as a last resort, let's check
# the running processes.
for proc in psutil.process_iter():
try:
if "gpg-agent" in proc.name():
for arg in proc.cmdline():
if str(root) in arg:
proc.terminate()
except Exception: # pylint: disable=broad-except
pass
@pytest.fixture
def gpghome(tmp_path):
root = tmp_path / "gpghome"
@ -20,34 +51,7 @@ def gpghome(tmp_path):
yield root
finally:
# Make sure we don't leave any gpg-agents running behind
gpg_connect_agent = shutil.which("gpg-connect-agent")
if gpg_connect_agent:
gnupghome = root / ".gnupg"
if not gnupghome.is_dir():
gnupghome = root
try:
subprocess.run(
[gpg_connect_agent, "killagent", "/bye"],
env={"GNUPGHOME": str(gnupghome)},
shell=False,
check=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
except subprocess.CalledProcessError:
# This is likely CentOS 7 or Amazon Linux 2
pass
# If the above errored or was not enough, as a last resort, let's check
# the running processes.
for proc in psutil.process_iter():
try:
if "gpg-agent" in proc.name():
for arg in proc.cmdline():
if str(root) in arg:
proc.terminate()
except Exception: # pylint: disable=broad-except
pass
_kill_gpg_agent(root)
@pytest.fixture
@ -931,3 +935,17 @@ def test_read_key_multiple(
else:
assert len(res) == 1
assert any(key["fingerprint"] == key_a_fp for key in res)
def test_missing_gnupghome(gpg, tmp_path):
"""
Ensure the directory passed as `gnupghome` is created before
python-gnupg is invoked. Issue #66312.
"""
gnupghome = tmp_path / "gnupghome"
try:
res = gpg.list_keys(gnupghome=tmp_path / "gnupghome")
assert res == []
finally:
# Make sure we don't leave any gpg-agents running behind
_kill_gpg_agent(gnupghome)