diff options
Diffstat (limited to 'plugins/modules/vyos_user.py.preview')
| -rw-r--r-- | plugins/modules/vyos_user.py.preview | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/plugins/modules/vyos_user.py.preview b/plugins/modules/vyos_user.py.preview new file mode 100644 index 0000000..41e014d --- /dev/null +++ b/plugins/modules/vyos_user.py.preview @@ -0,0 +1,282 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# GNU General Public License v3.0+ + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +DOCUMENTATION = r""" +--- +module: vyos_user +short_description: Manage local users on VyOS via the REST API. +description: + - Manages local user accounts on VyOS devices using the HTTPS REST API. + - Mirrors C(vyos.vyos.vyos_user) but uses the HTTP API. +version_added: "1.0.0" +author: + - VyOS Community (@vyos) +options: + aggregate: + description: List of user definitions. Mutually exclusive with I(name). + type: list + elements: dict + aliases: [users, collection] + suboptions: + name: + description: Username. + type: str + required: true + full_name: + description: Full name. + type: str + configured_password: + description: Plaintext password (will be hashed on device). + type: str + no_log: true + encrypted_password: + description: Pre-hashed password string. + type: str + no_log: true + update_password: + description: When to update the password. + type: str + choices: [always, on_create] + level: + description: User privilege level. + type: str + choices: [admin, operator] + public_keys: + description: SSH public keys for authentication. + type: list + elements: dict + suboptions: + name: + description: Key identifier (e.g. user@host). + type: str + required: true + key: + description: Base64-encoded public key. + type: str + required: true + type: + description: Key type. + type: str + required: true + choices: [ssh-dss, ssh-rsa, ecdsa-sha2-nistp256, + ecdsa-sha2-nistp384, ssh-ed25519, ecdsa-sha2-nistp521] + state: + description: Present or absent. + type: str + choices: [present, absent] + name: + description: Single username. Mutually exclusive with I(aggregate). + type: str + full_name: + description: Full name for the single user. + type: str + configured_password: + description: Plaintext password. + type: str + no_log: true + encrypted_password: + description: Pre-hashed password. + type: str + no_log: true + update_password: + type: str + choices: [always, on_create] + level: + type: str + choices: [admin, operator] + public_keys: + type: list + elements: dict + suboptions: + name: + type: str + required: true + key: + type: str + required: true + type: + type: str + required: true + state: + description: Whether to create (present) or remove (absent) the user. + type: str + choices: [present, absent] + default: present + hostname: + type: str + required: true + port: + type: int + default: 443 + api_key: + type: str + required: true + no_log: true + timeout: + type: int + default: 30 + verify_ssl: + type: bool + default: false +""" + +RETURN = r""" +commands: + description: set/delete commands issued. + returned: always + type: list +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import ( + VYOS_REST_CONNECTION_ARGSPEC, + VyOSRestClient, + VyOSRestError, +) + + +_KEY_TYPES = [ + "ssh-dss", + "ssh-rsa", + "ecdsa-sha2-nistp256", + "ecdsa-sha2-nistp384", + "ssh-ed25519", + "ecdsa-sha2-nistp521", +] + + +def _apply_user(client, user_def, commands, update_password="always"): + name = user_def["name"] + base = ["system", "login", "user", name] + client.configure_set(base) + commands.append("set system login user {n}".format(n=name)) + + if user_def.get("full_name"): + client.configure_set(base + ["full-name"], user_def["full_name"]) + if user_def.get("level"): + client.configure_set(base + ["level"], user_def["level"]) + if user_def.get("configured_password") and update_password in ("always",): + client.configure_set( + base + ["authentication", "plaintext-password"], + user_def["configured_password"], + ) + commands.append( + "set system login user {n} authentication plaintext-password".format(n=name), + ) + if user_def.get("encrypted_password"): + client.configure_set( + base + ["authentication", "encrypted-password"], + user_def["encrypted_password"], + ) + for pk in user_def.get("public_keys") or []: + kb = base + ["authentication", "public-keys", pk["name"]] + client.configure_set(kb + ["key"], pk["key"]) + client.configure_set(kb + ["type"], pk["type"]) + commands.append( + "set system login user {n} authentication public-keys {k}".format( + n=name, + k=pk["name"], + ), + ) + + +def _delete_user(client, name, commands): + try: + client.configure_delete(["system", "login", "user", name]) + commands.append("delete system login user {n}".format(n=name)) + except VyOSRestError: + pass + + +def main(): + pk_spec = dict( + type="list", + elements="dict", + options=dict( + name=dict(type="str", required=True), + key=dict(type="str", required=True), + type=dict(type="str", required=True, choices=_KEY_TYPES), + ), + ) + user_spec = dict( + name=dict(type="str", required=True), + full_name=dict(type="str"), + configured_password=dict(type="str", no_log=True), + encrypted_password=dict(type="str", no_log=True), + update_password=dict(type="str", choices=["always", "on_create"]), + level=dict(type="str", choices=["admin", "operator"]), + public_keys=pk_spec, + state=dict(type="str", choices=["present", "absent"]), + ) + argument_spec = dict( + aggregate=dict( + type="list", + elements="dict", + aliases=["users", "collection"], + options=user_spec, + ), + name=dict(type="str"), + full_name=dict(type="str"), + configured_password=dict(type="str", no_log=True), + encrypted_password=dict(type="str", no_log=True), + update_password=dict(type="str", choices=["always", "on_create"]), + level=dict(type="str", choices=["admin", "operator"]), + public_keys=pk_spec, + state=dict(type="str", default="present", choices=["present", "absent"]), + ) + argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC) + module = AnsibleModule( + argument_spec=argument_spec, + mutually_exclusive=[["aggregate", "name"]], + supports_check_mode=True, + ) + if module.check_mode: + module.exit_json(changed=True, commands=["(check mode)"]) + + client = VyOSRestClient(module) + commands = [] + changed = False + + # Build unified user list + users = module.params.get("aggregate") or [] + if module.params.get("name"): + users = [ + { + "name": module.params["name"], + "full_name": module.params.get("full_name"), + "configured_password": module.params.get("configured_password"), + "encrypted_password": module.params.get("encrypted_password"), + "update_password": module.params.get("update_password", "always"), + "level": module.params.get("level"), + "public_keys": module.params.get("public_keys"), + "state": module.params.get("state", "present"), + }, + ] + + try: + for u in users: + u_state = u.get("state") or module.params.get("state", "present") + if u_state == "absent": + _delete_user(client, u["name"], commands) + else: + _apply_user( + client, + u, + commands, + update_password=u.get("update_password") or "always", + ) + changed = True + except VyOSRestError as exc: + module.fail_json(msg=str(exc)) + + module.exit_json(changed=changed, commands=commands) + + +if __name__ == "__main__": + main() |
