I have created a local mysql user named “svc_ansible” via the WebUI, granted the user admin-level privileges and then generated an API token for the user. When I try to post a new device using curl to contact the API endpoint, I see the following:
curl -X POST -d '{"hostname": "10.9.1.69", "version": "v2c", "community": "public"}' -H 'X-Auth-Token: notarealtoken' -H 'Content-Type: application/json' http://hostname.domain.net/api/v0/devices
{"message":"Unauthenticated."}
If I run the same command with the token assigned to the global admin user, it works:
curl -X POST -d '{"hostname": "10.9.1.69", "version": "v2c", "community": "public"}' -H "X-Auth-Token: adifferentnotrealtoken" -H 'Content-Type: application/json' http://hostname.domain.net/api/v0/devices
{
"status": "error",
"message": "Already have host 10.9.1.69"
I would think it would still be a permissions issue with the svc_ansible user and/or token, but if I pass the token for this user into an ansible module I wrote for adding devices it works:
FAILED! =>
{
"body": "{\n \"status\": \"error\",\n \"message\": \"Already have host 10.9.1.70\"\n}",
"changed": false,
"invocation": {
"module_args": {
"community": "public ",
"hostname": "10.9.1.70",
"port": 161,
"snmpver": "v2c",
"token": "notarealtoken",
"url": "http://hostname.domain.net/api/v0/devices"
}
},
"msg": "Unable to Add Device"
}
PLAY RECAP **********************************************************************************************************************************************************************************************************************************bp3-efw01-l001 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
bp3-efw01-l002 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
the playbook:
---
- name: Test Libre NMS Custom Module in Playbook
hosts: bp3_fw # for loading inventory_hostname and other INV vars from sources
connection: local # module execution on localhost incl conn. estl.
gather_facts: no
tasks:
- name: Add Devices to LibreNMS
libre_add_device:
url: "{{ libre.base_url }}/api/v0/devices" #
hostname: "{{ ansible_host }}" #
community: "{{ libre.community }} " #
token: "{{ libre.api.token }}" #
delegate_to: localhost
group_vars/all/default.yaml:
libre:
base_url: http://hostname.domain.net
community: public
api:
user: svc_ansible
token: notarealtoken
the module:
import json
from ansible.module_utils.urls import fetch_url
from ansible.module_utils.basic import AnsibleModule
def main():
args = {
"url": {"required": True, "type": "str"},
"hostname": {"required": True,"type": "str"},
"community": {"required": True, "type": "str"},
"token": {"required": True, "type": "str"},
"port": {"required": False, "default": 161, "type": "int"},
"snmpver": {"required": False, "default": "v2c", "type": "str"}
}
module = AnsibleModule(
argument_spec=args,
supports_check_mode=False
)
json_data = {
"hostname": module.params['hostname'],
"community": module.params['community'],
"port": module.params['port'],
"version": module.params['snmpver'],
}
headers = {
"X-Auth-Token": module.params['token']
}
api = module.params['url']
resp, info = fetch_url(module, api, data=module.jsonify(json_data), headers=headers, method="POST",)
result = {}
if info['status'] == 200:
result['changed'] = True
result['status'] = info['status']
module.exit_json(**result)
else:
result['changed'] = False
result['msg'] = "Unable to Add Device"
result['body'] = info['body']
module.fail_json(**result)
if __name__ == '__main__':
main()
Since ansible returns the appropriate message in the results body when the http return code is not 200 (since this specific device is already added) and returns the “args” showing that the right values were passed in at runtime, what is the reason that when I use this token via curl it doesn’t work?