From de246c384c6fa310f9a329f3db62200b4bcc950a Mon Sep 17 00:00:00 2001 From: Johanna Dorothea Reichmann Date: Sun, 12 Jun 2022 12:08:25 +0200 Subject: [PATCH] feat(realm): add plugin for creating, updating, deleting realms --- plugins/modules/realm.py | 161 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 plugins/modules/realm.py diff --git a/plugins/modules/realm.py b/plugins/modules/realm.py new file mode 100644 index 0000000..47c8d9f --- /dev/null +++ b/plugins/modules/realm.py @@ -0,0 +1,161 @@ +#!/usr/bin/python +# coding: utf-8 + +# (c) 2022, Johanna Dorothea Reichmann + +__metaclass__ = type + +import dataclasses +import json +import traceback + +from ansible.module_utils.basic import AnsibleModule + +LIB_IMP_ERR = None +try: + from ansible_collections.finallycoffee.proxmox.plugins.module_utils.proxmox_api import * + HAS_LIB = True +except: + HAS_LIB = False + LIB_IMP_ERR = traceback.format_exc() + + +DOCUMENTATION = r''' +--- +module: realm +author: +- Johanna Dorothea Reichmann (transcaffeine@finally.coffee) +requirements: + - python >= 3.9 +short_description: Configures an authentication realm in a proxmox node +description: + - "Configue realm in a proxmox instance" +options: + proxmox_instance: + description: Location of the proxmox API with scheme, domain name/ip and port, e.g. https://localhost:8006 + type: str + required: true + proxmox_api_token_id: + description: The token ID containing username, realm and token name (format: user@realm!name) + type: str + required: true + proxmox_api_secret: + description: The secret + type: str + required: true + proxmox_api_verify_cert: + description: If the certificate presented for `proxmox_instance_url` should be verified + type: bool + required: false + default: true + name: + description: Realm to retrieve information about. If left omitted, return all realms + type: str + required: false + config: + description: Configuration of the realm, including it's `type`. See https://pve.proxmox.com/pve-docs/api-viewer/index.html#/access/domains for a list of config options + type: dict[str, str] + required: true + state: + description: If the realm should be present or absent + type: str + choices: [present, absent] + default: present + required: false +''' + +EXAMPLES = r''' +- name: Configure LDAP realm + finallycoffee.proxmox.realm: + proxmox_instance: https://my.proxmox-node.local:8006 + promox_api_token_id: root@pam!token + proxmox_api_secret: supersecuretokencontent + realms: org_ldap + config: + type: ldap + comment: Long description of the authentication source + base_dn: dc=myorg,dc=de + bind_dn: uid=proxmox,dc=services,dc=myorg,dc=de + passwort: supersecret + mode: ldap + server1: ldap.myorg.de + port: 389 + default: 1 + user_attr: uid +- name: Configure OIDC realm + finallycoffee.proxmox.realm: + proxmox_instance: https://my.proxmox-node.local:8006 + promox_api_token_id: root@pam!token + proxmox_api_secret: supersecuretokencontent + realm: external_oidc + config: + type: openid + issuer-url: https://idp.my-org.de/issuer + client_id: myapp + client_key: secret + scopes: profile email + username-claim: sub +''' + +RETURN = r''' +realm: + description: The updated/created realm + returned: When realms were found (matching the filter) + type: list + elements: dict[str, str, str, str] + +''' + + +def main(): + _ = dict + module = AnsibleModule( + argument_spec=_( + proxmox_instance=_(required=True, type='str'), + proxmox_api_token_id=_(required=True, type='str'), + proxmox_api_secret=_(type='str', required=True, no_log=True), + proxmox_api_verify_cert=_(type='bool', required=False, default=True), + name=_(required=True, type='str'), + config=_(required=True, type='dict'), + state=_(type='str', required=False, default='present', choices=['present', 'absent']) + ), + supports_check_mode=True + ) + + result = _( + changed=False, + diff={}, + message='' + ) + + realms = [] + try: + realm_change = set_realm_data(ProxmoxAuthInfo( + module.params['proxmox_instance'], + module.params['proxmox_api_token_id'], + module.params['proxmox_api_secret'], + module.params['proxmox_api_verify_cert'], + ), + module.params['name'], + module.params['config'], + module.check_mode, + module.params['state']) + except IOError as owie: + result['msg'] = owie + module.exit_json(**result) + + diff_excluded_keys = ['name', 'password', 'digest'] + result['realm'] = realm_change[1] + result['diff'] = { + 'before_header': f"{realm_change[0].get('name', module.params['name'])}@{realm_change[0]['type']}" if realm_change[0] and 'type' in realm_change[0] else '', + 'after_header': f"{realm_change[1].get('name', module.params['name'])}@{realm_change[1]['type']}" if realm_change[1] and 'type' in realm_change[1] else '', + 'before': {k: v for k, v in realm_change[0].items() if k not in diff_excluded_keys} if realm_change[0] else realm_change[0], + 'after': {k: v for k, v in realm_change[1].items() if k not in diff_excluded_keys} if realm_change[1] else realm_change[1], + } + result['changed'] = realm_change[0] != realm_change[1] + + module.exit_json(**result) + + +if __name__ == '__main__': + main()