add output and bare functionality

This commit is contained in:
Leif Liddy 2022-10-30 15:58:03 +01:00 committed by Megan Wilhite
parent 2b20289349
commit f48161d357
3 changed files with 79 additions and 14 deletions

1
changelog/62978.added Normal file
View file

@ -0,0 +1 @@
Added output and bare functionality to export_key gpg module function

View file

@ -783,16 +783,15 @@ def import_key(text=None, filename=None, user=None, gnupghome=None):
def export_key(
keyids=None, secret=False, user=None, gnupghome=None, use_passphrase=False
keyids=None, secret=False, user=None, gnupghome=None, output=None, use_passphrase=False, bare=False,
):
"""
Export a key from the GPG keychain
keyids
The key ID(s) of the key(s) to be exported. Can be specified as a comma
separated string or a list. Anything which GnuPG itself accepts to
identify a key - for example, the key ID or the fingerprint could be
used.
separated string or a list. Anything which GnuPG itself accepts to identify a key
for example, the key ID, fingerprint, user ID or email address could be used.
secret
Export the secret key identified by the ``keyids`` information passed.
@ -805,12 +804,19 @@ def export_key(
gnupghome
Specify the location where GPG keyring and related files are stored.
output
The filename where the exported key data will be written to, default is standard out.
use_passphrase
Whether to use a passphrase with the signing key. Passphrase is received
from Pillar.
Whether to use a passphrase to export the secret key.
Passphrase is received from Pillar.
.. versionadded:: 3003
bare
If ``True``, return the (armored) exported key block as a string without the
standard comment/res dict.
CLI Example:
.. code-block:: bash
@ -822,18 +828,38 @@ def export_key(
salt '*' gpg.export_key keyids="['3FAD9F1E','3FBD8F1E']" user=username
"""
ret = {"res": True}
gpg = _create_gpg(user, gnupghome)
if isinstance(keyids, str):
keyids = keyids.split(",")
if use_passphrase:
if secret and use_passphrase:
gpg_passphrase = __salt__["pillar.get"]("gpg_passphrase")
if not gpg_passphrase:
raise SaltInvocationError("gpg_passphrase not available in pillar.")
ret = gpg.export_keys(keyids, secret, passphrase=gpg_passphrase)
result = gpg.export_keys(keyids, secret, passphrase=gpg_passphrase)
else:
ret = gpg.export_keys(keyids, secret, expect_passphrase=False)
result = gpg.export_keys(keyids, secret, expect_passphrase=False)
if output and result:
with salt.utils.files.flopen(output, "w") as fout:
fout.write(salt.utils.stringutils.to_str(result))
if result:
if not bare:
if output:
ret["comment"] = "Exported key data has been written to {}".format(output)
else:
ret["comment"] = result
else:
ret = result
else:
if not bare:
ret["res"] = False
else:
ret = False
return ret

View file

@ -5,6 +5,7 @@
import datetime
import logging
import pathlib
import shutil
import subprocess
import time
@ -578,7 +579,7 @@ def test_export_key_without_passphrase(gpghome):
"salt.modules.gpg.gnupg.GPG.export_keys",
MagicMock(return_value=GPG_TEST_PUB_KEY),
) as gnupg_export_keys:
ret = gpg.export_key("xxxxxxxxxxxxxxxx")
ret = gpg.export_key("xxxxxxxxxxxxxxxx", bare=True)
assert ret == GPG_TEST_PUB_KEY
gnupg_export_keys.assert_called_with(
["xxxxxxxxxxxxxxxx"],
@ -614,7 +615,8 @@ def test_export_multiple_keys_without_passphrase(gpghome):
MagicMock(return_value=GPG_TEST_PUB_KEY),
) as gnupg_export_keys:
ret = gpg.export_key(
"xxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzz"
"xxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzz",
bare=True,
)
assert ret == GPG_TEST_PUB_KEY
gnupg_export_keys.assert_called_with(
@ -654,7 +656,7 @@ def test_export_key_with_passphrase_without_gpg_passphrase_in_pillar(gpghome):
MagicMock(return_value=GPG_TEST_PUB_KEY),
) as gnupg_export_keys:
with pytest.raises(SaltInvocationError):
assert gpg.export_key("xxxxxxxxxxxxxxxx", use_passphrase=True)
assert gpg.export_key("xxxxxxxxxxxxxxxx", secret=True, use_passphrase=True)
gnupg_export_keys.assert_not_called()
@ -687,14 +689,50 @@ def test_export_key_with_passphrase_with_gpg_passphrase_in_pillar(gpghome):
"salt.modules.gpg.gnupg.GPG.export_keys",
MagicMock(return_value=GPG_TEST_PUB_KEY),
) as gnupg_export_keys:
ret = gpg.export_key("xxxxxxxxxxxxxxxx", use_passphrase=True)
ret = gpg.export_key("xxxxxxxxxxxxxxxx", secret=True, use_passphrase=True, bare=True)
assert ret == GPG_TEST_PUB_KEY
# expected
gnupg_export_keys.assert_called_with(
["xxxxxxxxxxxxxxxx"],
False,
True,
passphrase=GPG_TEST_KEY_PASSPHRASE,
)
def test_export_key_to_file_with_passphrase_with_gpg_passphrase_in_pillar(gpghome):
"""
Test gpg.export_key with passphrase and gpg_passphrase pillar
"""
_user_mock = {
"shell": "/bin/bash",
"workphone": "",
"uid": 0,
"passwd": "x",
"roomnumber": "",
"gid": 0,
"groups": ["root"],
"home": str(gpghome.path),
"fullname": "root",
"homephone": "",
"name": "root",
}
exported_keyfile = gpghome.path / "exported_key"
mock_opt = MagicMock(return_value="root")
pillar_mock = MagicMock(return_value=GPG_TEST_KEY_PASSPHRASE)
with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
with patch.dict(gpg.__salt__, {"config.option": mock_opt}), patch.dict(
gpg.__salt__, {"pillar.get": pillar_mock}
):
with patch(
"salt.modules.gpg.gnupg.GPG.export_keys",
MagicMock(return_value=GPG_TEST_PUB_KEY),
) as gnupg_export_keys:
ret = gpg.export_key(keyids=GPG_TEST_KEY_ID, secret=True, output=exported_keyfile, use_passphrase=True, bare=True)
assert ret == GPG_TEST_PUB_KEY
keyfile_contents = pathlib.Path(exported_keyfile).read_text()
assert keyfile_contents == GPG_TEST_PUB_KEY
def test_create_key_without_passphrase(gpghome):
"""