Try to respect custom GNUPGHOME env var

This commit is contained in:
jeanluc 2024-04-04 11:50:55 +02:00 committed by Daniel Wozniak
parent 596924e510
commit 4294a82322
3 changed files with 81 additions and 7 deletions

View file

@ -0,0 +1 @@
Made gpg modules respect user's GNUPGHOME if set in shell environment

View file

@ -11,6 +11,13 @@ Sign, encrypt, sign plus encrypt and verify text and files.
Be aware that the alternate ``gnupg`` and ``pretty-bad-protocol``
libraries are not supported.
.. versionchanged:: 3008.0
When ``gnupghome`` is not set explicitly, this module now tries to
respect a custom ``GNUPGHOME`` environmental variable.
If a ``user`` is not passed, the current process' environment is queried,
otherwise the user's configured shell environment is taken as a reference
in the same way the ``cmd`` modules operate.
"""
import functools
@ -23,6 +30,7 @@ import salt.utils.data
import salt.utils.files
import salt.utils.immutabletypes as immutabletypes
import salt.utils.path
import salt.utils.platform
import salt.utils.stringutils
import salt.utils.versions
from salt.exceptions import SaltInvocationError
@ -153,11 +161,25 @@ def _get_user_gnupghome(user):
Return default GnuPG home directory path for a user
"""
if user == "salt":
gnupghome = os.path.join(__salt__["config.get"]("config_dir"), "gpgkeys")
else:
gnupghome = os.path.join(_get_user_info(user)["home"], ".gnupg")
return os.path.join(__salt__["config.get"]("config_dir"), "gpgkeys")
return gnupghome
# Try to respect GNUPGHOME environment variable.
if user is None:
gnupghome_env = __salt__["environ.get"]("GNUPGHOME")
else:
cmd = 'echo -n "$GNUPGHOME"'
if salt.utils.platform.is_windows():
cmd = "echo %GNUPGHOME%"
gnupghome_env = __salt__["cmd.run_stdout"](
cmd, python_shell=True, runas=user
).strip()
if gnupghome_env.startswith("~"):
# This does not resolve `~` since that potentially complicates things a lot.
# It should have been resolved by the shell anyways.
log.warning("Found GNUPGHOME beginning with tilde, ignoring")
gnupghome_env = ""
return gnupghome_env or os.path.join(_get_user_info(user)["home"], ".gnupg")
def _restore_ownership(func):

View file

@ -10,6 +10,7 @@ import shutil
import subprocess
import time
import types
from pathlib import Path
import psutil
import pytest
@ -204,7 +205,14 @@ def gpghome(tmp_path):
@pytest.fixture
def configure_loader_modules(gpghome):
return {gpg: {}}
return {
gpg: {
"__salt__": {
"environ.get": lambda *x: "",
"cmd.run_stdout": lambda *x, **y: "",
}
}
}
def test_list_keys():
@ -1101,7 +1109,9 @@ def _import_result_mock(request):
indirect=True,
)
def test_gpg_receive_keys_no_user_id(_import_result_mock):
with patch("salt.modules.gpg._create_gpg") as create:
with patch("salt.modules.gpg._create_gpg") as create, patch(
"salt.modules.gpg._create_gnupghome"
):
with patch.dict(
gpg.__salt__, {"user.info": MagicMock(), "config.option": Mock()}
):
@ -1123,7 +1133,9 @@ def test_gpg_receive_keys_no_user_id(_import_result_mock):
indirect=True,
)
def test_gpg_receive_keys_keyserver_unavailable(_import_result_mock):
with patch("salt.modules.gpg._create_gpg") as create:
with patch("salt.modules.gpg._create_gpg") as create, patch(
"salt.modules.gpg._create_gnupghome"
):
with patch.dict(
gpg.__salt__, {"user.info": MagicMock(), "config.option": Mock()}
):
@ -1131,3 +1143,42 @@ def test_gpg_receive_keys_keyserver_unavailable(_import_result_mock):
res = gpg.receive_keys(keys="abc", user="abc")
assert res["res"] is False
assert any("No keyserver available" in x for x in res["message"])
@pytest.mark.parametrize(
"user,envvar",
(
("testuser", ""),
("testuser", "/home/testuser/local/share/gnupg"),
(None, ""),
(None, "/home/testuser/local/share/gnupg"),
("salt", ""),
("salt", "/this/should/not/matter"),
),
)
def test_get_user_gnupghome_respects_shell_env_setup(user, envvar):
config_dir = "/etc/salt" # minion_opts["config_dir"] is not set, only conf_dir (?)
user = user or "testuser"
if user == "salt":
homedir = "/opt/saltstack/salt"
expected = str(Path(config_dir) / "gpgkeys")
else:
homedir = f"/home/{user}"
expected = envvar or str(Path(homedir) / ".gnupg")
userinfo = {
"home": homedir,
"uid": 1000,
"gid": 1000,
"shell": "/bin/bash",
}
with patch.dict(
gpg.__salt__,
{
"user.info": lambda *x: userinfo,
"environ.get": lambda *x: envvar,
"cmd.run_stdout": lambda *x, **y: envvar,
"config.get": lambda *x: config_dir,
},
):
res = gpg._get_user_gnupghome(user)
assert res == expected