test_gpg.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. import copy
  2. import logging
  3. import pathlib
  4. import shutil
  5. import subprocess
  6. import pytest
  7. import salt.pillar
  8. import salt.utils.stringutils
  9. from saltfactories.utils.processes import ProcessResult
  10. from tests.support.helpers import slowTest
  11. pytestmark = [
  12. pytest.mark.windows_whitelisted,
  13. pytest.mark.skip_if_binaries_missing("gpg"),
  14. ]
  15. log = logging.getLogger(__name__)
  16. TEST_KEY = """\
  17. -----BEGIN PGP PRIVATE KEY BLOCK-----
  18. lQOYBFiKrcYBCADAj92+fz20uKxxH0ffMwcryGG9IogkiUi2QrNYilB4hwrY5Qt7
  19. Sbywlk/mSDMcABxMxS0vegqc5pgglvAnsi9w7j//9nfjiirsyiTYOOD1akTFQr7b
  20. qT6zuGFA4oYmYHvfBOena485qvlyitYLKYT9h27TDiiH6Jgt4xSRbjeyhTf3/fKD
  21. JzHA9ii5oeVi1pH/8/4USgXanBdKwO0JKQtci+PF0qe/nkzRswqTIkdgx1oyNUqL
  22. tYJ0XPOy+UyOC4J4QDIt9PQbAmiur8By4g2lLYWlGOCjs7Fcj3n5meWKzf1pmXoY
  23. lAnSab8kUZSSkoWQoTO7RbjFypULKCZui45/ABEBAAEAB/wM1wsAMtfYfx/wgxd1
  24. yJ9HyhrKU80kMotIq/Xth3uKLecJQ2yakfYlCEDXqCTQTymT7OnwaoDeqXmnYqks
  25. 3HLRYvGdjb+8ym/GTkxapqBJfQaM6MB1QTnPHhJOE0zCrlhULK2NulxYihAMFTnk
  26. kKYviaJYLG+DcH0FQkkS0XihTKcqnsoJiS6iNd5SME3pa0qijR0D5f78fkvNzzEE
  27. 9vgAX1TgQ5PDJGN6nYlW2bWxTcg+FR2cUAQPTiP9wXCH6VyJoQay7KHVr3r/7SsU
  28. 89otfcx5HVDYPrez6xnP6wN0P/mKxCDbkERLDjZjWOmNXg2zn+/t3u02e+ybfAIp
  29. kTTxBADY/FmPgLpJ2bpcPH141twpHwhKIbENlTB9745Qknr6aLA0QVCkz49/3joO
  30. Sj+SZ7Jhl6cfbynrfHwX3b1bOFTzBUH2Tsi0HX40PezEFH0apf55FLZuMOBt/lc1
  31. ET6evpIHF0dcM+BvZa7E7MyTyEq8S7Cc9RoJyfeGbS7MG5FfuwQA4y9QOb/OQglq
  32. ZffkVItwY52RKWb/b2WQmt+IcVax/j7DmBva765SIfPDvOCMrYhJBI/uYHQ0Zia7
  33. SnC9+ez55wdYqgHkYojc21CIOnUvsPSj+rOpryoXzmcTuvKeVIyIA0h/mQyWjimR
  34. ENrikC4+O8GBMY6V4uvS4EFhLfHE9g0D/20lNOKkpAKPenr8iAPWcl0/pijJCGxF
  35. agnT7O2GQ9Lr5hSjW86agkevbGktu2ja5t/fHq0wpLQ4DVLMrR0/poaprTr307kW
  36. AlQV3z/C2cMHNysz4ulOgQrudQbhUEz2A8nQxRtIfWunkEugKLr1QiCkE1LJW8Np
  37. ZLxE6Qp0/KzdQva0HVNhbHQgR1BHIDxlcmlrQHNhbHRzdGFjay5jb20+iQFUBBMB
  38. CAA+FiEE+AxQ1ELHGEyFTZPYw5x3k9EbHGsFAliKrcYCGwMFCQPCZwAFCwkIBwIG
  39. FQgJCgsCBBYCAwECHgECF4AACgkQw5x3k9EbHGubUAf+PLdp1oTLVokockZgLyIQ
  40. wxOd3ofNOgNk4QoAkSMNSbtnYoQFKumRw/yGyPSIoHMsOC/ga98r8TAJEKfx3DLA
  41. rsD34oMAaYUT+XUd0KoSmlHqBrtDD1+eBASKYsCosHpCiKuQFfLKSxvpEr2YyL8L
  42. X3Q2TY5zFlGA9Eeq5g+rlb++yRZrruFN28EWtY/pyXFZgIB30ReDwPkM9hrioPZM
  43. 0Qf3+dWZSK1rWViclB51oNy4un9stTiFZptAqz4NTNssU5A4AcNQPwBwnKIYoE58
  44. Y/Zyv8HzILGykT+qFebqRlRBI/13eHdzgJOL1iPRfjTk5Cvr+vcyIxAklXOP81ja
  45. B50DmARYiq3GAQgArnzu4SPCCQGNcCNxN4QlMP5TNvRsm5KrPbcO9j8HPfB+DRXs
  46. 6B3mnuR6OJg7YuC0C2A/m2dSHJKkF0f2AwFRpxLjJ2iAFbrZAW/N0vZDx8zO+YAU
  47. HyLu0V04wdCE5DTLkgfWNR+0uMa8qZ4Kn56Gv7O+OFE7zgTHeZ7psWlxdafeW7u6
  48. zlC/3DWksNtuNb0vQDNMM4vgXbnORIfXdyh41zvEEnr/rKw8DuJAmo20mcv6Qi51
  49. PqqyM62ddQOEVfiMs9l4vmwZAjGFNFNInyPXnogL6UPCDmizb6hh8aX/MwG/XFIG
  50. KMJWbAVGpyBuqljKIt3qLu/s8ouPqkEN+f+nGwARAQABAAf+NA36d/kieGxZpTQ1
  51. oQHP1Jty+OiXhBwP8SPtF0J7ZxuZh07cs+zDsfBok/y6bsepfuFSaIq84OBQis+B
  52. kajxkp3cXZPb7l+lQLv5k++7Dd7Ien+ewSE7TQN6HLwYATrM5n5nBcc1M5C6lQGc
  53. mr0A5yz42TVG2bHsTpi9kBtsaVRSPUHSh8A8T6eOyCrT+/CAJVEEf7JyNyaqH1dy
  54. LuxI1VF3ySDEtFzuwN8EZQP9Yz/4AVyEQEA7WkNEwSQsBi2bWgWEdG+qjqnL+YKa
  55. vwe7/aJYPeL1zICnP/Osd/UcpDxR78MbozstbRljML0fTLj7UJ+XDazwv+Kl0193
  56. 2ZK2QQQAwgXvS19MYNkHO7kbNVLt1VE2ll901iC9GFHBpFUam6gmoHXpCarB+ShH
  57. 8x25aoUu4MxHmFxXd+Zq3d6q2yb57doWoPgvqcefpGmigaITnb1jhV2rt65V8deA
  58. SQazZNqBEBbZNIhfn6ObxHXXvaYaqq/UOEQ7uKyR9WMJT/rmqMEEAOY5h1R1t7AB
  59. JZ5VnhyAhdsNWw1gTcXB3o8gKz4vjdnPm0F4aVIPfB3BukETDc3sc2tKmCfUF7I7
  60. oOrh7iRez5F0RIC3KDzXF8qUuWBfPViww45JgftdKsecCIlEEYCoc+3goX0su2bP
  61. V1MDuHijMGTJCBABDgizNb0oynW5xcrbA/0QnKfpTwi7G3oRcJWv2YebVDRcU+SP
  62. dOYhq6SnmWPizEIljRG/X7FHJB+W7tzryO3sCDTAYwxFrfMwvJ2PwnAYI4349zYd
  63. lC28HowUkBYNhwBXc48xCfyhPZtD0aLx/OX1oLZ/vi8gd8TusgGupV/JjkFVO+Nd
  64. +shN/UEAldwqkkY2iQE8BBgBCAAmFiEE+AxQ1ELHGEyFTZPYw5x3k9EbHGsFAliK
  65. rcYCGwwFCQPCZwAACgkQw5x3k9EbHGu4wwf/dRFat91BRX1TJfwJl5otoAXpItYM
  66. 6kdWWf1Eb1BicAvXhI078MSH4WXdKkJjJr1fFP8Ynil513H4Mzb0rotMAhb0jLSA
  67. lSRkMbhMvPxoS2kaYzioaBpp8yXpGiNo7dF+PJXSm/Uwp3AkcFjoVbBOqDWGgxMi
  68. DvDAstzLZ9dIcmr+OmcRQykKOKXlhEl3HnR5CyuPrA8hdVup4oeVwdkJhfJFKLLb
  69. 3fR26wxJOmIOAt24eAUy721WfQ9txNAmhdy8mY842ODZESw6WatrQjRfuqosDgrk
  70. jc0cCHsEqJNZ2AB+1uEl3tcH0tyAFJa33F0znSonP17SS1Ff9sgHYBVLUg==
  71. =06Tz
  72. -----END PGP PRIVATE KEY BLOCK-----
  73. """
  74. GPG_PILLAR_YAML = """\
  75. secrets:
  76. vault:
  77. foo: |
  78. -----BEGIN PGP MESSAGE-----
  79. hQEMAw2B674HRhwSAQgAhTrN8NizwUv/VunVrqa4/X8t6EUulrnhKcSeb8sZS4th
  80. W1Qz3K2NjL4lkUHCQHKZVx/VoZY7zsddBIFvvoGGfj8+2wjkEDwFmFjGE4DEsS74
  81. ZLRFIFJC1iB/O0AiQ+oU745skQkU6OEKxqavmKMrKo3rvJ8ZCXDC470+i2/Hqrp7
  82. +KWGmaDOO422JaSKRm5D9bQZr9oX7KqnrPG9I1+UbJyQSJdsdtquPWmeIpamEVHb
  83. VMDNQRjSezZ1yKC4kCWm3YQbBF76qTHzG1VlLF5qOzuGI9VkyvlMaLfMibriqY73
  84. zBbPzf6Bkp2+Y9qyzuveYMmwS4sEOuZL/PetqisWe9JGAWD/O+slQ2KRu9hNww06
  85. KMDPJRdyj5bRuBVE4hHkkP23KrYr7SuhW2vpe7O/MvWEJ9uDNegpMLhTWruGngJh
  86. iFndxegN9w==
  87. =bAuo
  88. -----END PGP MESSAGE-----
  89. bar: this was unencrypted already
  90. baz: |
  91. -----BEGIN PGP MESSAGE-----
  92. hQEMAw2B674HRhwSAQf+Ne+IfsP2IcPDrUWct8sTJrga47jQvlPCmO+7zJjOVcqz
  93. gLjUKvMajrbI/jorBWxyAbF+5E7WdG9WHHVnuoywsyTB9rbmzuPqYCJCe+ZVyqWf
  94. 9qgJ+oUjcvYIFmH3h7H68ldqbxaAUkAOQbTRHdr253wwaTIC91ZeX0SCj64HfTg7
  95. Izwk383CRWonEktXJpientApQFSUWNeLUWagEr/YPNFA3vzpPF5/Ia9X8/z/6oO2
  96. q+D5W5mVsns3i2HHbg2A8Y+pm4TWnH6mTSh/gdxPqssi9qIrzGQ6H1tEoFFOEq1V
  97. kJBe0izlfudqMq62XswzuRB4CYT5Iqw1c97T+1RqENJCASG0Wz8AGhinTdlU5iQl
  98. JkLKqBxcBz4L70LYWyHhYwYROJWjHgKAywX5T67ftq0wi8APuZl9olnOkwSK+wrY
  99. 1OZi
  100. =7epf
  101. -----END PGP MESSAGE-----
  102. qux:
  103. - foo
  104. - bar
  105. - |
  106. -----BEGIN PGP MESSAGE-----
  107. hQEMAw2B674HRhwSAQgAg1YCmokrweoOI1c9HO0BLamWBaFPTMblOaTo0WJLZoTS
  108. ksbQ3OJAMkrkn3BnnM/djJc5C7vNs86ZfSJ+pvE8Sp1Rhtuxh25EKMqGOn/SBedI
  109. gR6N5vGUNiIpG5Tf3DuYAMNFDUqw8uY0MyDJI+ZW3o3xrMUABzTH0ew+Piz85FDA
  110. YrVgwZfqyL+9OQuu6T66jOIdwQNRX2NPFZqvon8liZUPus5VzD8E5cAL9OPxQ3sF
  111. f7/zE91YIXUTimrv3L7eCgU1dSxKhhfvA2bEUi+AskMWFXFuETYVrIhFJAKnkFmE
  112. uZx+O9R9hADW3hM5hWHKH9/CRtb0/cC84I9oCWIQPdI+AaPtICxtsD2N8Q98hhhd
  113. 4M7I0sLZhV+4ZJqzpUsOnSpaGyfh1Zy/1d3ijJi99/l+uVHuvmMllsNmgR+ZTj0=
  114. =LrCQ
  115. -----END PGP MESSAGE-----
  116. """
  117. GPG_PILLAR_ENCRYPTED = {
  118. "secrets": {
  119. "vault": {
  120. "foo": "-----BEGIN PGP MESSAGE-----\n"
  121. "\n"
  122. "hQEMAw2B674HRhwSAQgAhTrN8NizwUv/VunVrqa4/X8t6EUulrnhKcSeb8sZS4th\n"
  123. "W1Qz3K2NjL4lkUHCQHKZVx/VoZY7zsddBIFvvoGGfj8+2wjkEDwFmFjGE4DEsS74\n"
  124. "ZLRFIFJC1iB/O0AiQ+oU745skQkU6OEKxqavmKMrKo3rvJ8ZCXDC470+i2/Hqrp7\n"
  125. "+KWGmaDOO422JaSKRm5D9bQZr9oX7KqnrPG9I1+UbJyQSJdsdtquPWmeIpamEVHb\n"
  126. "VMDNQRjSezZ1yKC4kCWm3YQbBF76qTHzG1VlLF5qOzuGI9VkyvlMaLfMibriqY73\n"
  127. "zBbPzf6Bkp2+Y9qyzuveYMmwS4sEOuZL/PetqisWe9JGAWD/O+slQ2KRu9hNww06\n"
  128. "KMDPJRdyj5bRuBVE4hHkkP23KrYr7SuhW2vpe7O/MvWEJ9uDNegpMLhTWruGngJh\n"
  129. "iFndxegN9w==\n"
  130. "=bAuo\n"
  131. "-----END PGP MESSAGE-----\n",
  132. "bar": "this was unencrypted already",
  133. "baz": "-----BEGIN PGP MESSAGE-----\n"
  134. "\n"
  135. "hQEMAw2B674HRhwSAQf+Ne+IfsP2IcPDrUWct8sTJrga47jQvlPCmO+7zJjOVcqz\n"
  136. "gLjUKvMajrbI/jorBWxyAbF+5E7WdG9WHHVnuoywsyTB9rbmzuPqYCJCe+ZVyqWf\n"
  137. "9qgJ+oUjcvYIFmH3h7H68ldqbxaAUkAOQbTRHdr253wwaTIC91ZeX0SCj64HfTg7\n"
  138. "Izwk383CRWonEktXJpientApQFSUWNeLUWagEr/YPNFA3vzpPF5/Ia9X8/z/6oO2\n"
  139. "q+D5W5mVsns3i2HHbg2A8Y+pm4TWnH6mTSh/gdxPqssi9qIrzGQ6H1tEoFFOEq1V\n"
  140. "kJBe0izlfudqMq62XswzuRB4CYT5Iqw1c97T+1RqENJCASG0Wz8AGhinTdlU5iQl\n"
  141. "JkLKqBxcBz4L70LYWyHhYwYROJWjHgKAywX5T67ftq0wi8APuZl9olnOkwSK+wrY\n"
  142. "1OZi\n"
  143. "=7epf\n"
  144. "-----END PGP MESSAGE-----\n",
  145. "qux": [
  146. "foo",
  147. "bar",
  148. "-----BEGIN PGP MESSAGE-----\n"
  149. "\n"
  150. "hQEMAw2B674HRhwSAQgAg1YCmokrweoOI1c9HO0BLamWBaFPTMblOaTo0WJLZoTS\n"
  151. "ksbQ3OJAMkrkn3BnnM/djJc5C7vNs86ZfSJ+pvE8Sp1Rhtuxh25EKMqGOn/SBedI\n"
  152. "gR6N5vGUNiIpG5Tf3DuYAMNFDUqw8uY0MyDJI+ZW3o3xrMUABzTH0ew+Piz85FDA\n"
  153. "YrVgwZfqyL+9OQuu6T66jOIdwQNRX2NPFZqvon8liZUPus5VzD8E5cAL9OPxQ3sF\n"
  154. "f7/zE91YIXUTimrv3L7eCgU1dSxKhhfvA2bEUi+AskMWFXFuETYVrIhFJAKnkFmE\n"
  155. "uZx+O9R9hADW3hM5hWHKH9/CRtb0/cC84I9oCWIQPdI+AaPtICxtsD2N8Q98hhhd\n"
  156. "4M7I0sLZhV+4ZJqzpUsOnSpaGyfh1Zy/1d3ijJi99/l+uVHuvmMllsNmgR+ZTj0=\n"
  157. "=LrCQ\n"
  158. "-----END PGP MESSAGE-----\n",
  159. ],
  160. },
  161. },
  162. }
  163. GPG_PILLAR_DECRYPTED = {
  164. "secrets": {
  165. "vault": {
  166. "foo": "supersecret",
  167. "bar": "this was unencrypted already",
  168. "baz": "rosebud",
  169. "qux": ["foo", "bar", "baz"],
  170. },
  171. },
  172. }
  173. @pytest.fixture(scope="package", autouse=True)
  174. def gpg_homedir(salt_master, pillar_state_tree):
  175. _gpg_homedir = pathlib.Path(salt_master.config_dir) / "gpgkeys"
  176. _gpg_homedir.mkdir(0o700)
  177. agent_started = False
  178. try:
  179. cmd_prefix = ["gpg", "--homedir", str(_gpg_homedir)]
  180. cmd = cmd_prefix + ["--list-keys"]
  181. proc = subprocess.run(
  182. cmd,
  183. stdout=subprocess.PIPE,
  184. stderr=subprocess.STDOUT,
  185. check=True,
  186. universal_newlines=True,
  187. )
  188. ret = ProcessResult(
  189. exitcode=proc.returncode,
  190. stdout=proc.stdout,
  191. stderr=proc.stderr,
  192. cmdline=proc.args,
  193. )
  194. log.debug("Instantiating gpg keyring...\n%s", ret)
  195. cmd = cmd_prefix + ["--import", "--allow-secret-key-import"]
  196. proc = subprocess.run(
  197. cmd,
  198. stdout=subprocess.PIPE,
  199. stderr=subprocess.STDOUT,
  200. check=True,
  201. universal_newlines=True,
  202. input=TEST_KEY,
  203. )
  204. ret = ProcessResult(
  205. exitcode=proc.returncode,
  206. stdout=proc.stdout,
  207. stderr=proc.stderr,
  208. cmdline=proc.args,
  209. )
  210. log.debug("Importing keypair...:\n%s", ret)
  211. agent_started = True
  212. top_file_contents = """
  213. base:
  214. '*':
  215. - gpg
  216. """
  217. with pytest.helpers.temp_file(
  218. "top.sls", top_file_contents, pillar_state_tree
  219. ), pytest.helpers.temp_file("gpg.sls", GPG_PILLAR_YAML, pillar_state_tree):
  220. yield _gpg_homedir
  221. finally:
  222. if agent_started:
  223. try:
  224. cmd = ["gpg-connect-agent", "--homedir", str(_gpg_homedir)]
  225. proc = subprocess.run(
  226. cmd,
  227. stdout=subprocess.PIPE,
  228. stderr=subprocess.STDOUT,
  229. check=True,
  230. universal_newlines=True,
  231. input="KILLAGENT",
  232. )
  233. ret = ProcessResult(
  234. exitcode=proc.returncode,
  235. stdout=proc.stdout,
  236. stderr=proc.stderr,
  237. cmdline=proc.args,
  238. )
  239. log.debug("Killed gpg-agent...\n%s", ret)
  240. except (OSError, subprocess.CalledProcessError):
  241. log.debug("No need to kill: old gnupg doesn't start the agent.")
  242. shutil.rmtree(str(_gpg_homedir), ignore_errors=True)
  243. def test_decrypt_pillar_default_renderer(salt_master, grains):
  244. """
  245. Test recursive decryption of secrets:vault as well as the fallback to
  246. default decryption renderer.
  247. """
  248. opts = salt_master.config.copy()
  249. opts["decrypt_pillar"] = ["secrets:vault"]
  250. pillar_obj = salt.pillar.Pillar(opts, grains, "test", "base")
  251. ret = pillar_obj.compile_pillar()
  252. assert ret == GPG_PILLAR_DECRYPTED
  253. @slowTest
  254. def test_decrypt_pillar_alternate_delimiter(salt_master, grains):
  255. """
  256. Test recursive decryption of secrets:vault using a pipe instead of a
  257. colon as the nesting delimiter.
  258. decrypt_pillar_delimiter: '|'
  259. decrypt_pillar:
  260. - 'secrets|vault'
  261. """
  262. opts = salt_master.config.copy()
  263. opts["decrypt_pillar"] = ["secrets|vault"]
  264. opts["decrypt_pillar_delimiter"] = "|"
  265. pillar_obj = salt.pillar.Pillar(opts, grains, "test", "base")
  266. ret = pillar_obj.compile_pillar()
  267. assert ret == GPG_PILLAR_DECRYPTED
  268. def test_decrypt_pillar_deeper_nesting(salt_master, grains):
  269. """
  270. Test recursive decryption, only with a more deeply-nested target. This
  271. should leave the other keys in secrets:vault encrypted.
  272. decrypt_pillar:
  273. - 'secrets:vault:qux'
  274. """
  275. opts = salt_master.config.copy()
  276. opts["decrypt_pillar"] = ["secrets:vault:qux"]
  277. pillar_obj = salt.pillar.Pillar(opts, grains, "test", "base")
  278. ret = pillar_obj.compile_pillar()
  279. expected = copy.deepcopy(GPG_PILLAR_ENCRYPTED)
  280. expected["secrets"]["vault"]["qux"][-1] = GPG_PILLAR_DECRYPTED["secrets"]["vault"][
  281. "qux"
  282. ][-1]
  283. assert ret == expected
  284. def test_decrypt_pillar_explicit_renderer(salt_master, grains):
  285. """
  286. Test recursive decryption of secrets:vault, with the renderer
  287. explicitly defined, overriding the default. Setting the default to a
  288. nonexistent renderer so we can be sure that the override happened.
  289. decrypt_pillar_default: asdf
  290. decrypt_pillar_renderers:
  291. - asdf
  292. - gpg
  293. decrypt_pillar:
  294. - 'secrets:vault': gpg
  295. """
  296. opts = salt_master.config.copy()
  297. opts["decrypt_pillar"] = [{"secrets:vault": "gpg"}]
  298. opts["decrypt_pillar_default"] = "asdf"
  299. opts["decrypt_pillar_renderers"] = ["asdf", "gpg"]
  300. pillar_obj = salt.pillar.Pillar(opts, grains, "test", "base")
  301. ret = pillar_obj.compile_pillar()
  302. assert ret == GPG_PILLAR_DECRYPTED
  303. def test_decrypt_pillar_missing_renderer(salt_master, grains):
  304. """
  305. Test decryption using a missing renderer. It should fail, leaving the
  306. encrypted keys intact, and add an error to the pillar dictionary.
  307. decrypt_pillar_default: asdf
  308. decrypt_pillar_renderers:
  309. - asdf
  310. decrypt_pillar:
  311. - 'secrets:vault'
  312. """
  313. opts = salt_master.config.copy()
  314. opts["decrypt_pillar"] = ["secrets:vault"]
  315. opts["decrypt_pillar_default"] = "asdf"
  316. opts["decrypt_pillar_renderers"] = ["asdf"]
  317. pillar_obj = salt.pillar.Pillar(opts, grains, "test", "base")
  318. ret = pillar_obj.compile_pillar()
  319. expected = copy.deepcopy(GPG_PILLAR_ENCRYPTED)
  320. expected["_errors"] = [
  321. "Failed to decrypt pillar key 'secrets:vault': Decryption renderer 'asdf' is not available"
  322. ]
  323. assert ret["_errors"] == expected["_errors"]
  324. assert ret["secrets"]["vault"]["foo"] == expected["secrets"]["vault"]["foo"]
  325. assert ret["secrets"]["vault"]["bar"] == expected["secrets"]["vault"]["bar"]
  326. assert ret["secrets"]["vault"]["baz"] == expected["secrets"]["vault"]["baz"]
  327. assert ret["secrets"]["vault"]["qux"] == expected["secrets"]["vault"]["qux"]
  328. def test_decrypt_pillar_invalid_renderer(salt_master, grains):
  329. """
  330. Test decryption using a renderer which is not permitted. It should
  331. fail, leaving the encrypted keys intact, and add an error to the pillar
  332. dictionary.
  333. decrypt_pillar_default: foo
  334. decrypt_pillar_renderers:
  335. - foo
  336. - bar
  337. decrypt_pillar:
  338. - 'secrets:vault': gpg
  339. """
  340. opts = salt_master.config.copy()
  341. opts["decrypt_pillar"] = [{"secrets:vault": "gpg"}]
  342. opts["decrypt_pillar_default"] = "foo"
  343. opts["decrypt_pillar_renderers"] = ["foo", "bar"]
  344. pillar_obj = salt.pillar.Pillar(opts, grains, "test", "base")
  345. ret = pillar_obj.compile_pillar()
  346. expected = copy.deepcopy(GPG_PILLAR_ENCRYPTED)
  347. expected["_errors"] = [
  348. "Failed to decrypt pillar key 'secrets:vault': 'gpg' is not a valid decryption renderer. "
  349. "Valid choices are: foo, bar"
  350. ]
  351. assert ret["_errors"] == expected["_errors"]
  352. assert ret["secrets"]["vault"]["foo"] == expected["secrets"]["vault"]["foo"]
  353. assert ret["secrets"]["vault"]["bar"] == expected["secrets"]["vault"]["bar"]
  354. assert ret["secrets"]["vault"]["baz"] == expected["secrets"]["vault"]["baz"]
  355. assert ret["secrets"]["vault"]["qux"] == expected["secrets"]["vault"]["qux"]