diff --git a/changelogs/fragments/1206-proxmox-api-token.yml b/changelogs/fragments/1206-proxmox-api-token.yml new file mode 100644 index 0000000000..bec5b17f1e --- /dev/null +++ b/changelogs/fragments/1206-proxmox-api-token.yml @@ -0,0 +1,5 @@ +--- +minor_changes: + - proxmox - add support for API tokens (https://github.com/ansible-collections/community.general/pull/1206). + - proxmox_kvm - add support for API tokens (https://github.com/ansible-collections/community.general/pull/1206). + - proxmox_template - add support for API tokens (https://github.com/ansible-collections/community.general/pull/1206). diff --git a/plugins/modules/cloud/misc/proxmox.py b/plugins/modules/cloud/misc/proxmox.py index 07ce34f75e..140d56f686 100644 --- a/plugins/modules/cloud/misc/proxmox.py +++ b/plugins/modules/cloud/misc/proxmox.py @@ -29,6 +29,16 @@ options: - the password to authenticate with - you can use PROXMOX_PASSWORD environment variable type: str + api_token_id: + description: + - Specify the token ID. + type: str + version_added: 1.3.0 + api_token_secret: + description: + - Specify the token secret. + type: str + version_added: 1.3.0 vmid: description: - the instance id @@ -496,8 +506,10 @@ def main(): module = AnsibleModule( argument_spec=dict( api_host=dict(required=True), - api_user=dict(required=True), api_password=dict(no_log=True), + api_token_id=dict(no_log=True), + api_token_secret=dict(no_log=True), + api_user=dict(required=True), vmid=dict(required=False), validate_certs=dict(type='bool', default=False), node=dict(), @@ -533,9 +545,11 @@ def main(): module.fail_json(msg='proxmoxer required for this module') state = module.params['state'] - api_user = module.params['api_user'] api_host = module.params['api_host'] api_password = module.params['api_password'] + api_token_id = module.params['api_token_id'] + api_token_secret = module.params['api_token_secret'] + api_user = module.params['api_user'] vmid = module.params['vmid'] validate_certs = module.params['validate_certs'] node = module.params['node'] @@ -570,18 +584,23 @@ def main(): if module.params[param] is None: module.params[param] = value - # If password not set get it from PROXMOX_PASSWORD env - if not api_password: - try: - api_password = os.environ['PROXMOX_PASSWORD'] - except KeyError as e: - module.fail_json(msg='You should set api_password param or use PROXMOX_PASSWORD environment variable') + auth_args = {'user': api_user} + if not (api_token_id and api_token_secret): + # If password not set get it from PROXMOX_PASSWORD env + if not api_password: + try: + api_password = os.environ['PROXMOX_PASSWORD'] + except KeyError as e: + module.fail_json(msg='You should set api_password param or use PROXMOX_PASSWORD environment variable') + auth_args['password'] = api_password + else: + auth_args['token_name'] = api_token_id + auth_args['token_value'] = api_token_secret try: - proxmox = ProxmoxAPI(api_host, user=api_user, password=api_password, verify_ssl=validate_certs) + proxmox = ProxmoxAPI(api_host, verify_ssl=validate_certs, **auth_args) global VZ_TYPE VZ_TYPE = 'openvz' if proxmox_version(proxmox) < LooseVersion('4.0') else 'lxc' - except Exception as e: module.fail_json(msg='authorization on proxmox cluster failed with exception: %s' % e) diff --git a/plugins/modules/cloud/misc/proxmox_kvm.py b/plugins/modules/cloud/misc/proxmox_kvm.py index cc7c373cfb..75212c9c84 100644 --- a/plugins/modules/cloud/misc/proxmox_kvm.py +++ b/plugins/modules/cloud/misc/proxmox_kvm.py @@ -47,6 +47,16 @@ options: - Specify the password to authenticate with. - You can use C(PROXMOX_PASSWORD) environment variable. type: str + api_token_id: + description: + - Specify the token ID. + type: str + version_added: 1.3.0 + api_token_secret: + description: + - Specify the token secret. + type: str + version_added: 1.3.0 autostart: description: - Specify if the VM should be automatically restarted after crash (currently ignored in PVE API). @@ -924,8 +934,10 @@ def main(): agent=dict(type='bool'), args=dict(type='str'), api_host=dict(required=True), - api_user=dict(required=True), api_password=dict(no_log=True), + api_token_id=dict(no_log=True), + api_token_secret=dict(no_log=True), + api_user=dict(required=True), autostart=dict(type='bool'), balloon=dict(type='int'), bios=dict(choices=['seabios', 'ovmf']), @@ -1003,9 +1015,11 @@ def main(): if not HAS_PROXMOXER: module.fail_json(msg='proxmoxer required for this module') - api_user = module.params['api_user'] api_host = module.params['api_host'] api_password = module.params['api_password'] + api_token_id = module.params['api_token_id'] + api_token_secret = module.params['api_token_secret'] + api_user = module.params['api_user'] clone = module.params['clone'] cpu = module.params['cpu'] cores = module.params['cores'] @@ -1054,15 +1068,21 @@ def main(): if module.params['format'] == 'unspecified': module.params['format'] = None - # If password not set get it from PROXMOX_PASSWORD env - if not api_password: - try: - api_password = os.environ['PROXMOX_PASSWORD'] - except KeyError as e: - module.fail_json(msg='You should set api_password param or use PROXMOX_PASSWORD environment variable') + auth_args = {'user': api_user} + if not (api_token_id and api_token_secret): + # If password not set get it from PROXMOX_PASSWORD env + if not api_password: + try: + api_password = os.environ['PROXMOX_PASSWORD'] + except KeyError as e: + module.fail_json(msg='You should set api_password param or use PROXMOX_PASSWORD environment variable') + auth_args['password'] = api_password + else: + auth_args['token_name'] = api_token_id + auth_args['token_value'] = api_token_secret try: - proxmox = ProxmoxAPI(api_host, user=api_user, password=api_password, verify_ssl=validate_certs) + proxmox = ProxmoxAPI(api_host, verify_ssl=validate_certs, **auth_args) global PVE_MAJOR_VERSION PVE_MAJOR_VERSION = 3 if proxmox_version(proxmox) < LooseVersion('4.0') else 4 except Exception as e: diff --git a/plugins/modules/cloud/misc/proxmox_template.py b/plugins/modules/cloud/misc/proxmox_template.py index 631102a212..c93c549025 100644 --- a/plugins/modules/cloud/misc/proxmox_template.py +++ b/plugins/modules/cloud/misc/proxmox_template.py @@ -30,6 +30,16 @@ options: - the password to authenticate with - you can use PROXMOX_PASSWORD environment variable type: str + api_token_id: + description: + - Specify the token ID. + type: str + version_added: 1.3.0 + api_token_secret: + description: + - Specify the token secret. + type: str + version_added: 1.3.0 validate_certs: description: - enable / disable https certificate verification @@ -196,8 +206,10 @@ def main(): module = AnsibleModule( argument_spec=dict( api_host=dict(required=True), - api_user=dict(required=True), api_password=dict(no_log=True), + api_token_id=dict(no_log=True), + api_token_secret=dict(no_log=True), + api_user=dict(required=True), validate_certs=dict(type='bool', default=False), node=dict(), src=dict(type='path'), @@ -214,23 +226,33 @@ def main(): module.fail_json(msg='proxmoxer required for this module') state = module.params['state'] - api_user = module.params['api_user'] api_host = module.params['api_host'] api_password = module.params['api_password'] + api_token_id = module.params['api_token_id'] + api_token_secret = module.params['api_token_secret'] + api_user = module.params['api_user'] validate_certs = module.params['validate_certs'] node = module.params['node'] storage = module.params['storage'] timeout = module.params['timeout'] - # If password not set get it from PROXMOX_PASSWORD env - if not api_password: - try: - api_password = os.environ['PROXMOX_PASSWORD'] - except KeyError as e: - module.fail_json(msg='You should set api_password param or use PROXMOX_PASSWORD environment variable') + auth_args = {'user': api_user} + if not (api_token_id and api_token_secret): + # If password not set get it from PROXMOX_PASSWORD env + if not api_password: + try: + api_password = os.environ['PROXMOX_PASSWORD'] + except KeyError as e: + module.fail_json(msg='You should set api_password param or use PROXMOX_PASSWORD environment variable') + auth_args['password'] = api_password + else: + auth_args['token_name'] = api_token_id + auth_args['token_value'] = api_token_secret try: - proxmox = ProxmoxAPI(api_host, user=api_user, password=api_password, verify_ssl=validate_certs) + proxmox = ProxmoxAPI(api_host, verify_ssl=validate_certs, **auth_args) + # Used to test the validity of the token if given + proxmox.version.get() except Exception as e: module.fail_json(msg='authorization on proxmox cluster failed with exception: %s' % e)