Skip to content

Instantly share code, notes, and snippets.

@sivel
Last active September 28, 2021 13:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sivel/f72ef00347d54b5524592786fddcd8da to your computer and use it in GitHub Desktop.
Save sivel/f72ef00347d54b5524592786fddcd8da to your computer and use it in GitHub Desktop.
Ansible filter plugin to encrypt a string with yescrypt
# Copyright (c) 2021 Matt Martz <matt@sivel.net>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import ctypes
from ansible.errors import AnsibleFilterError
from ansible.module_utils.common.text.converters import to_bytes, to_text
from ansible.utils.encrypt import random_salt
try:
_libcrypt = ctypes.CDLL('libcrypt.so.1')
HAS_LIBCRYPT = True
except OSError:
HAS_LIBCRYPT = False
else:
crypt_gensalt = _libcrypt.crypt_gensalt
crypt_gensalt.argtypes = [ctypes.c_char_p, ctypes.c_long, ctypes.c_char_p, ctypes.c_int]
crypt_gensalt.restype = ctypes.c_char_p
crypt = _libcrypt.crypt
crypt.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
crypt.restype = ctypes.c_char_p
def yescrypt(word, salt=None, salt_length=20):
if not HAS_LIBCRYPT:
raise AnsibleFilterError('cannot locate libcrypt.so.1')
if not salt:
setting = crypt_gensalt(
b'$y$',
9,
to_bytes(random_salt(salt_length)),
salt_length
)
else:
setting = b'$y$jDT$%s' % to_bytes(salt)
try:
return to_text(crypt(to_bytes(word), setting))
except ctypes.ArgumentError as e:
raise AnsibleFilterError('libcrypt likely missing yescrypt support: %s' % e)
class FilterModule(object):
def filters(self):
return {
'yescrypt': yescrypt,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment