1"""
2Management of the GPG keychains
3===============================
4
5.. versionadded:: 2016.3.0
6
7"""
8
9import logging
10
11log = logging.getLogger(__name__)
12
13_VALID_TRUST_VALUES = [
14    "expired",
15    "unknown",
16    "not_trusted",
17    "marginally",
18    "fully",
19    "ultimately",
20]
21
22TRUST_MAP = {
23    "expired": "Expired",
24    "unknown": "Unknown",
25    "not_trusted": "Not Trusted",
26    "marginally": "Marginally",
27    "fully": "Fully Trusted",
28    "ultimately": "Ultimately Trusted",
29}
30
31
32def present(
33    name, keys=None, user=None, keyserver=None, gnupghome=None, trust=None, **kwargs
34):
35    """
36    Ensure GPG public key is present in keychain
37
38    name
39        The unique name or keyid for the GPG public key.
40
41    keys
42        The keyId or keyIds to add to the GPG keychain.
43
44    user
45        Add GPG keys to the specified user's keychain
46
47    keyserver
48        The keyserver to retrieve the keys from.
49
50    gnupghome
51        Override GNUPG Home directory
52
53    trust
54        Trust level for the key in the keychain,
55        ignored by default.  Valid trust levels:
56        expired, unknown, not_trusted, marginally,
57        fully, ultimately
58
59
60    """
61
62    ret = {"name": name, "result": True, "changes": {}, "comment": []}
63
64    _current_keys = __salt__["gpg.list_keys"](user=user, gnupghome=gnupghome)
65
66    current_keys = {}
67    for key in _current_keys:
68        keyid = key["keyid"]
69        current_keys[keyid] = {}
70        current_keys[keyid]["trust"] = key["trust"]
71
72    if not keys:
73        keys = name
74
75    if isinstance(keys, str):
76        keys = [keys]
77
78    for key in keys:
79        if key in current_keys.keys():
80            if trust:
81                if trust in _VALID_TRUST_VALUES:
82                    if current_keys[key]["trust"] != TRUST_MAP[trust]:
83                        # update trust level
84                        result = __salt__["gpg.trust_key"](
85                            keyid=key,
86                            trust_level=trust,
87                            user=user,
88                        )
89                        if "result" in result and not result["result"]:
90                            ret["result"] = result["result"]
91                            ret["comment"].append(result["comment"])
92                        else:
93                            ret["comment"].append(
94                                "Set trust level for {} to {}".format(key, trust)
95                            )
96                    else:
97                        ret["comment"].append(
98                            "GPG Public Key {} already in correct trust state".format(
99                                key
100                            )
101                        )
102                else:
103                    ret["comment"].append("Invalid trust level {}".format(trust))
104
105            ret["comment"].append("GPG Public Key {} already in keychain ".format(key))
106
107        else:
108            result = __salt__["gpg.receive_keys"](
109                keyserver,
110                key,
111                user,
112                gnupghome,
113            )
114            if "result" in result and not result["result"]:
115                ret["result"] = result["result"]
116                ret["comment"].append(result["comment"])
117            else:
118                ret["comment"].append("Adding {} to GPG keychain".format(name))
119
120            if trust:
121                if trust in _VALID_TRUST_VALUES:
122                    result = __salt__["gpg.trust_key"](
123                        keyid=key,
124                        trust_level=trust,
125                        user=user,
126                    )
127                    if "result" in result and not result["result"]:
128                        ret["result"] = result["result"]
129                        ret["comment"].append(result["comment"])
130                    else:
131                        ret["comment"].append(
132                            "Set trust level for {} to {}".format(key, trust)
133                        )
134                else:
135                    ret["comment"].append("Invalid trust level {}".format(trust))
136
137    ret["comment"] = "\n".join(ret["comment"])
138    return ret
139
140
141def absent(name, keys=None, user=None, gnupghome=None, **kwargs):
142    """
143    Ensure GPG public key is absent in keychain
144
145    name
146        The unique name or keyid for the GPG public key.
147
148    keys
149        The keyId or keyIds to add to the GPG keychain.
150
151    user
152        Remove GPG keys from the specified user's keychain
153
154    gnupghome
155        Override GNUPG Home directory
156
157    """
158
159    ret = {"name": name, "result": True, "changes": {}, "comment": []}
160
161    _current_keys = __salt__["gpg.list_keys"]()
162
163    current_keys = []
164    for key in _current_keys:
165        current_keys.append(key["keyid"])
166
167    if not keys:
168        keys = name
169
170    if isinstance(keys, str):
171        keys = [keys]
172
173    for key in keys:
174        if key in current_keys:
175            result = __salt__["gpg.delete_key"](
176                key,
177                user,
178                gnupghome,
179            )
180            if "result" in result and not result["result"]:
181                ret["result"] = result["result"]
182                ret["comment"].append(result["comment"])
183            else:
184                ret["comment"].append("Deleting {} from GPG keychain".format(name))
185        else:
186            ret["comment"].append("{} not found in GPG keychain".format(name))
187    ret["comment"] = "\n".join(ret["comment"])
188    return ret
189