From 77da0dbf1650e9676fdc978857da421edebbea25 Mon Sep 17 00:00:00 2001 From: jeanluc Date: Mon, 5 Dec 2022 14:01:23 +0100 Subject: [PATCH] Use gnupg for trust_key if available --- salt/modules/gpg.py | 122 ++++++++++++++++++++++++-------------------- salt/states/gpg.py | 50 +++++++++--------- 2 files changed, 91 insertions(+), 81 deletions(-) diff --git a/salt/modules/gpg.py b/salt/modules/gpg.py index 9df012496e4..1987de110de 100644 --- a/salt/modules/gpg.py +++ b/salt/modules/gpg.py @@ -19,6 +19,7 @@ import os import re import time +import salt.utils.data import salt.utils.files import salt.utils.path import salt.utils.stringutils @@ -67,6 +68,15 @@ VERIFY_TRUST_LEVELS = { "4": "Ultimate", } +TRUST_KEYS_TRUST_LEVELS = { + "expired": "TRUST_EXPIRED", + "unknown": "TRUST_UNDEFINED", + "never": "TRUST_NEVER", + "marginally": "TRUST_MARGINAL", + "fully": "TRUST_FULLY", + "ultimately": "TRUST_ULTIMATE", +} + _DEFAULT_KEY_SERVER = "keys.openpgp.org" try: @@ -1096,73 +1106,75 @@ def trust_key( """ ret = {"res": True, "message": ""} - _VALID_TRUST_LEVELS = [ - "expired", - "unknown", - "not_trusted", - "marginally", - "fully", - "ultimately", - ] + if not salt.utils.data.exactly_one((keyid, fingerprint)): + raise SaltInvocationError("Exactly one of keyid or fingerprint is required") - if fingerprint and keyid: - ret["res"] = False - ret["message"] = "Only specify one argument, fingerprint or keyid" - return ret + if trust_level not in NUM_TRUST_DICT: + raise SaltInvocationError( + "ERROR: Valid trust levels - {}".format(",".join(NUM_TRUST_DICT.keys())) + ) if not fingerprint: - if keyid: - key = get_key(keyid, user=user, gnupghome=gnupghome, keyring=keyring) - if key: - if "fingerprint" not in key: - ret["res"] = False - ret["message"] = f"Fingerprint not found for keyid {keyid}" - return ret - fingerprint = key["fingerprint"] - else: + key = get_key(keyid, user=user, gnupghome=gnupghome, keyring=keyring) + if key: + if "fingerprint" not in key: ret["res"] = False - ret["message"] = f"KeyID {keyid} not in GPG keychain" + ret["message"] = f"Fingerprint not found for keyid {keyid}" return ret + fingerprint = key["fingerprint"] else: ret["res"] = False - ret["message"] = "Required argument, fingerprint or keyid" + ret["message"] = f"KeyID {keyid} not in GPG keychain" return ret - if trust_level not in _VALID_TRUST_LEVELS: - return "ERROR: Valid trust levels - {}".format(",".join(_VALID_TRUST_LEVELS)) + gpg = _create_gpg(user=user, gnupghome=gnupghome, keyring=keyring) + try: + res = gpg.trust_keys(fingerprint, TRUST_KEYS_TRUST_LEVELS[trust_level]) + except AttributeError: + # python-gnupg < 0.4.2 + stdin = f"{fingerprint}:{NUM_TRUST_DICT[trust_level]}\n" + gnupghome = gnupghome or _get_user_gnupghome(user) + cmd = [_gpg(), "--homedir", gnupghome, "--import-ownertrust"] + _user = user if user != "salt" else None - stdin = f"{fingerprint}:{NUM_TRUST_DICT[trust_level]}\n" - gnupghome = gnupghome or _get_user_gnupghome(user) - cmd = [_gpg(), "--homedir", gnupghome, "--import-ownertrust"] - _user = user if user != "salt" else None - - if keyring: - if not isinstance(keyring, str): - raise SaltInvocationError( - "Please pass keyring as a string. Multiple keyrings are not allowed" - ) - cmd.extend(["--no-default-keyring", "--keyring", keyring]) - - res = __salt__["cmd.run_all"](cmd, stdin=stdin, runas=_user, python_shell=False) - - if not res["retcode"] == 0: - ret["res"] = False - ret["message"] = res["stderr"] - else: - if res["stderr"]: - _match = re.findall(r"\d", res["stderr"]) - if len(_match) == 2: - ret["fingerprint"] = fingerprint - ret["message"] = "Changing ownership trust from {} to {}.".format( - INV_NUM_TRUST_DICT[_match[0]], INV_NUM_TRUST_DICT[_match[1]] + if keyring: + if not isinstance(keyring, str): + raise SaltInvocationError( + "Please pass keyring as a string. Multiple keyrings are not allowed" ) - else: - ret["fingerprint"] = fingerprint - ret["message"] = "Setting ownership trust to {}.".format( - INV_NUM_TRUST_DICT[_match[0]] - ) - else: + cmd.extend(["--no-default-keyring", "--keyring", keyring]) + + res = __salt__["cmd.run_all"](cmd, stdin=stdin, runas=_user, python_shell=False) + + if not res["retcode"] == 0: + ret["res"] = False ret["message"] = res["stderr"] + else: + if res["stderr"]: + _match = re.findall(r"\d", res["stderr"]) + if len(_match) == 2: + ret["fingerprint"] = fingerprint + ret["message"] = "Changing ownership trust from {} to {}.".format( + INV_NUM_TRUST_DICT[_match[0]], INV_NUM_TRUST_DICT[_match[1]] + ) + else: + ret["fingerprint"] = fingerprint + ret["message"] = "Setting ownership trust to {}.".format( + INV_NUM_TRUST_DICT[_match[0]] + ) + else: + ret["message"] = res["stderr"] + else: + if res.status == "ok": + ret["res"] = True + ret["fingerprint"] = fingerprint + ret["message"] = "Setting ownership trust to {}.".format( + INV_NUM_TRUST_DICT[NUM_TRUST_DICT[trust_level]] + ) + else: + ret["res"] = False + ret["message"] = res.problem_reason + return ret diff --git a/salt/states/gpg.py b/salt/states/gpg.py index e6fe7a1a691..47f728e11a2 100644 --- a/salt/states/gpg.py +++ b/salt/states/gpg.py @@ -9,18 +9,10 @@ Management of the GPG keychains import logging import salt.utils.dictupdate +from salt.exceptions import SaltInvocationError log = logging.getLogger(__name__) -_VALID_TRUST_VALUES = [ - "expired", - "unknown", - "not_trusted", - "marginally", - "fully", - "ultimately", -] - TRUST_MAP = { "expired": "Expired", "unknown": "Unknown", @@ -93,7 +85,7 @@ def present( for key in keys: if key in current_keys.keys(): if trust: - if trust in _VALID_TRUST_VALUES: + if trust in TRUST_MAP: if current_keys[key]["trust"] != TRUST_MAP[trust]: if __opts__["test"]: ret["result"] = None @@ -104,14 +96,17 @@ def present( ret, f"changes:{key}:trust", trust ) continue - # update trust level - result = __salt__["gpg.trust_key"]( - keyid=key, - trust_level=trust, - user=user, - gnupghome=gnupghome, - keyring=keyring, - ) + try: + # update trust level + result = __salt__["gpg.trust_key"]( + keyid=key, + trust_level=trust, + user=user, + gnupghome=gnupghome, + keyring=keyring, + ) + except SaltInvocationError as err: + result = {"res": False, "message": str(err)} if result["res"] is False: ret["result"] = result["res"] ret["comment"].append(result["message"]) @@ -156,14 +151,17 @@ def present( ) if trust: - if trust in _VALID_TRUST_VALUES: - result = __salt__["gpg.trust_key"]( - keyid=key, - trust_level=trust, - user=user, - gnupghome=gnupghome, - keyring=keyring, - ) + if trust in TRUST_MAP: + try: + result = __salt__["gpg.trust_key"]( + keyid=key, + trust_level=trust, + user=user, + gnupghome=gnupghome, + keyring=keyring, + ) + except SaltInvocationError as err: + result = {"res": False, "message": str(err)} if result["res"] is False: ret["result"] = result["res"] ret["comment"].append(result["message"])