blob: 8d12829557e3b72f64804b41eaa456750157d7b3 [file] [log] [blame]
# -*- coding: utf-8 -*-
# _state/aptkey.py
"""
Manage apt keys
"""
from __future__ import absolute_import, print_function, unicode_literals
from base64 import b64encode, b64decode
from binascii import Error as binasciiError
def __virtual__():
"""Only load if 'pkg' (aptpkg) module has necessary functions"""
if not 'pkg.add_repo_key' in __salt__ or not 'pkg.get_repo_keys' in __salt__:
return False, "'pkg.add_repo_key' and 'pkg.get_repo_keys' functions are required"
return True
def _get_fingerprints(input_text):
"""Get fingerprint(s) for given text
:param str input_text: text to get fingerprint(s) from it
:return:
A list of found fingerprint(s)
:rtype list:
"""
fingerprints = []
cmd = 'apt-key adv --with-fingerprint --with-colons --dry-run -'
out = __salt__['cmd.run_stdout'](cmd, stdin=input_text, python_shell=False)
for line in out.split('\n'):
line = line.split(':')
if line[0] == 'fpr':
fingerprints.append(line[-2])
return fingerprints
def added(name, key_text=None, key_url=None):
"""Ensure that given key added to APT's key storage
:param str name:
Just an ID, it does not used at all.
:param str key_text:
Key to add as a plain text or base64-encoded.
:param str key_url:
URL from which key should be fetched. Supported URLs: salt://, http://,
https:// and file://.
Examples:
.. code-block:: yaml
# Base64 encoded key
{% set repo_key = salt['hashutil.base64_b64encode'](repo.key) %}
linux_repo_ubuntu_key:
aptkey.added:
- key_text: {{ repo_key }}
.. code-block:: yaml
# Plaintext key
linux_repo_ubuntu_key:
aptkey.added:
- key_text: '{{ repo.key | replace("\n", "\\n") }}'
.. code-block:: yaml
linux_repo_ubuntu_key:
aptkey.added:
- key_url: 'https://example.com/key.asc'
"""
ret = {'name': name,
'result': None if __opts__['test'] else True,
'changes': {},
'comment': ''}
if not key_text and not key_url:
ret['result'] = False,
ret['comment'] = 'No key to add provided'
return ret
if key_text and key_url:
ret['result'] = False
ret['comment'] = 'Only one of key_text or key_url is permitted'
return ret
# If key_url provided fetch it before proceeding
if key_url:
# This only supports salt://, http://, https:// and file:// URLs
key_text = __salt__['cp.get_url'](key_url, dest=None)
# Try to apply base64 decoding to key_text, just in case...
try:
# Decode key_text if it is base64 encoded string
decoded_key_text = b64decode(key_text)
# the simplest available check that given string was base64 encoded
if b64encode(decoded_key_text) == key_text:
key_text = decoded_key_text
except TypeError, binasciiError: # the first is for py2, the second for py3
pass
# Get apt's keys and their fingerprints
apt_keys = __salt__['pkg.get_repo_keys']()
apt_fingerprints = [key.get('fingerprint') for _, key in apt_keys.items()]
key_fingerprints = _get_fingerprints(key_text)
# If any of given fingerprints does not present in apt keys
# then add all of them
if not set(key_fingerprints).issubset(set(apt_fingerprints)):
if __opts__['test']:
ret['result'] = None
ret['changes'] = {'key': key_text}
return ret
success = __salt__['pkg.add_repo_key'](text=key_text)
if success:
ret['result'] = True
ret['changes'] = {'key': key_text}
else:
ret['result'] = False
ret['comment'] = 'Key was not added because of errors'
return ret