Skip to content

Commit

Permalink
add type5_pw
Browse files Browse the repository at this point in the history
  • Loading branch information
KB-perByte committed Aug 8, 2023
1 parent 80a2662 commit bfd6442
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 1 deletion.
2 changes: 1 addition & 1 deletion plugins/filter/parse_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
required: True
template:
description:
- The first line of the list can be first_line_len characters long.
- The template to compare it with.
- For example C(xml_data | ansible.netcommon.parse_xml(template.yml)),
in this case C(xml_data) represents this option.
type: raw
Expand Down
100 changes: 100 additions & 0 deletions plugins/filter/type5_pw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#

"""
The type5_pw filter plugin
"""
from __future__ import absolute_import, division, print_function


__metaclass__ = type

DOCUMENTATION = """
name: type5_pw
author: Ansible Network Community (@ansible-network)
version_added: "5.1.0"
short_description: type5_pw filter plugin.
description:
- The filter plugin extends vlans when data.
- Using the parameters below - C(xml_data | ansible.netcommon.type5_pw(template.yml))
notes:
- The filter plugin extends vlans when data provided in range or comma separated.
options:
password:
description:
- This source xml on which type5_pw invokes.
- For example C(xml_data | ansible.netcommon.type5_pw),
in this case C(xml_data) represents this option.
type: str
required: True
salt:
description:
- The template to compare it with.
- For example C(xml_data | ansible.netcommon.type5_pw(template.yml)),
in this case C(xml_data) represents this option.
type: str
"""

EXAMPLES = r"""
# Using type5_pw
- name: The facts
ansible.builtin.set_fact:
password: "cisco@123"
- name: Filter type5_pw invocation
ansible.builtin.debug:
msg: "{{ password | ansible.netcommon.type5_pw(salt='avs') }}"
# Task Output
# -----------
#
# TASK [The facts]
# ok: [host] => changed=false
# ansible_facts:
# password: cisco@123
# TASK [Filter type5_pw invocation]
# ok: [host] =>
# msg: $1$avs$uSTOEMh65qzvpb9yBMpzd/
"""

from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)

from ansible_collections.ansible.netcommon.plugins.plugin_utils.type5_pw import type5_pw


try:
from jinja2.filters import pass_environment
except ImportError:
from jinja2.filters import environmentfilter as pass_environment


@pass_environment
def _type5_pw(*args, **kwargs):
"""Extend vlan data"""

keys = ["password", "salt"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="type5_pw")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return type5_pw(**updated_data)


class FilterModule(object):
"""type5_pw"""

def filters(self):
"""a mapping of filter names to functions"""
return {"type5_pw": _type5_pw}
54 changes: 54 additions & 0 deletions plugins/plugin_utils/type5_pw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#

"""
The type5_pw plugin code
"""
from __future__ import absolute_import, division, print_function


__metaclass__ = type

import string

from ansible.errors import AnsibleFilterError
from ansible.module_utils.six import string_types
from ansible.module_utils._text import to_text
from ansible.utils.encrypt import passlib_or_crypt, random_password


def _raise_error(msg):
"""Raise an error message, prepend with filter name
:param msg: The message
:type msg: str
:raises: AnsibleError
"""
error = "Error when using plugin 'type5_pw': {msg}".format(msg=msg)
raise AnsibleFilterError(error)


def type5_pw(password, salt=None):
if not isinstance(password, string_types):
_raise_error(
"type5_pw password input should be a string, but was given a input of %s"
% (type(password).__name__)
)

salt_chars = "".join((to_text(string.ascii_letters), to_text(string.digits), "./"))
if salt is not None and not isinstance(salt, string_types):
_raise_error(
"type5_pw salt input should be a string, but was given a input of %s"
% (type(salt).__name__)
)
elif not salt:
salt = random_password(length=4, chars=salt_chars)
elif not set(salt) <= set(salt_chars):
_raise_error("type5_pw salt used inproper characters, must be one of %s" % (salt_chars))

encrypted_password = passlib_or_crypt(password, "md5_crypt", salt=salt)

return encrypted_password
39 changes: 39 additions & 0 deletions tests/unit/plugins/filter/test_type5_pw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# 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 unittest

from ansible.errors import AnsibleFilterError

from ansible_collections.ansible.netcommon.plugins.plugin_utils.type5_pw import type5_pw


class TestType5_pw(unittest.TestCase):
def setUp(self):
pass

def test_type5_pw_plugin_1(self):
password = "cisco"
salt = "nTc1"
args = [password, salt]
result = type5_pw(*args)
self.assertEqual(
"$1$nTc1$Z28sUTcWfXlvVe2x.3XAa.",
result,
)

def test_type5_pw_plugin_2(self):
password = "cisco"
args = [password]
result = type5_pw(*args)
self.assertEqual(
len(result),
30,
)

0 comments on commit bfd6442

Please sign in to comment.