- Access exclusive content
- Connect with peers
- Share your expertise
- Find support resources
05-03-2018 02:59 PM - edited 05-03-2018 03:04 PM
I'm getting a timeout on the panos_import command.
I see a reference to xapi.keygen() in the traceback... Showing my playbook and the traceback below.
Thanks for any tips,
Chris.
(spoiler tags? code blocks?)
The Playbook:
--- - name: Initialize the Palo Alto Networks firewall hosts: localhost connection: local gather_facts: False roles: - role: PaloAltoNetworks.paloaltonetworks vars: config_file: "/opt/ansible/files/pan/PA-test-Preliminary.xml" ip_address: 10.255.5.45 username: "admin" password: "wackydoo" tasks: - name: set admin password panos_admpwd: ip_address: "{{ ip_address }}" key_filename: "/home/me/.ssh/my.pem" username: "{{ username }}" newpassword: "{{ password }}" - name: import configuration xml file into PAN-OS panos_import: ip_address: "{{ ip_address }}" username: "{{ username }}" password: "{{ password }}" file: "{{ config_file }}" category: "configuration" register: result - name: load configuration panos_loadcfg: ip_address: "{{ ip_address }}" password: "{{ password }}" file: "{{result.filename}}"
The error with -vvv on the command line:
The full traceback is: File "/tmp/ansible_aAF16c/ansible_module_panos_import.py", line 179, in main changed, filename = import_file(xapi, module, ip_address, file_, category) File "/tmp/ansible_aAF16c/ansible_module_panos_import.py", line 98, in import_file xapi.keygen() File "/usr/lib/python2.7/site-packages/pan/xapi.py", line 637, in keygen raise PanXapiError(self.status_detail) fatal: [localhost]: FAILED! => { "changed": false, "invocation": { "module_args": { "category": "configuration", "file": "/opt/ansible/files/pan/PA-test-Preliminary.xml", "ip_address": "10.255.5.45", "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", "url": null, "username": "admin" } }, "msg": "URLError: reason: [Errno 110] Connection timed out" }
05-04-2018 06:51 AM
Hi there!
I'm not sure about the error you are getting.
If it was my case, I would start by testing the import with something that works.
I downloaded the cfg of the firewall, made some changes, imported the cfg and it worked like a charm.
I did the same with the OS file too. (600MB)
Go to Device -> Setup -> Operations -> Save named config.. -> use a short name with no spaces (firewall_cfg)
Then Device -> Setup -> Operations -> Export named config.. -> use the same name
This is the playbook I'm using:
--- # how to run this # ansible-playbook panos_pbk_11_load_cfg.yml --extra-vars "hosts_to_use='fwpa01' cfg_location_to_use='../test_files/dxcfwpasbx01_fresh_config'" -vvvv # to solve ssl issue see file ../how_to_fix_ssl_certificate_issue.txt # to delete a saved configuration file # delete config saved <filename> - name: Load configuration on PAN-OS device hosts: "{{ hosts_to_use }}" gather_facts: false connection: local vars_files: - /home/MYUSERNAME/ansible/vault.yml # - ../vault.yml tasks: # Import and load config file from URL. The import is a separated module - name: import configuration. panos_import: ip_address: "{{ansible_host}}" username: "{{vault_fwpa01_username}}" password: "{{vault_fwpa01_password}}" # url: "{{cfg_location_to_use}}" # url must be like http:///home/MYUSERNAME/ansible/panos_dependencies/testcfg_dxcfwpasbx01 file: "{{cfg_location_to_use}}" category: "configuration" register: result - name: load configuration panos_loadcfg: ip_address: "{{ansible_host}}" username: "{{vault_fwpa01_username}}" password: "{{vault_fwpa01_password}}" file: "{{result.filename}}" commit: "False"
This is the module I'm using: (Just in case it is different for some reason)
cat /usr/lib/python2.7/site-packages/ansible/modules/network/panos/panos_import.py
#!/usr/bin/env python # Copyright 2016 Palo Alto Networks, Inc # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. DOCUMENTATION = ''' --- module: panos_import short_description: import file on PAN-OS devices description: - Import file on PAN-OS device author: "Luigi Mori (@jtschichold), Ivan Bojer (@ivanbojer)" version_added: "2.3" requirements: - pan-python - requests - requests_toolbelt options: ip_address: description: - IP address (or hostname) of PAN-OS device. required: true password: description: - Password for device authentication. required: true username: description: - Username for device authentication. required: false default: "admin" category: description: - Category of file uploaded. The default is software. required: false default: software file: description: - Location of the file to import into device. required: false default: None url: description: - URL of the file that will be imported to device. required: false default: None ''' EXAMPLES = ''' # import software image PanOS_vm-6.1.1 on 192.168.1.1 - name: import software image into PAN-OS panos_import: ip_address: 192.168.1.1 username: admin password: admin file: /tmp/PanOS_vm-6.1.1 category: software ''' RETURN=''' # Default return values ''' ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import get_exception import os.path import xml.etree import tempfile import shutil import os try: import pan.xapi import requests import requests_toolbelt HAS_LIB = True except ImportError: HAS_LIB = False def import_file(xapi, module, ip_address, file_, category): xapi.keygen() params = { 'type': 'import', 'category': category, 'key': xapi.api_key } filename = os.path.basename(file_) mef = requests_toolbelt.MultipartEncoder( fields={ 'file': (filename, open(file_, 'rb'), 'application/octet-stream') } ) r = requests.post( 'https://'+ip_address+'/api/', verify=False, params=params, headers={'Content-Type': mef.content_type}, data=mef ) # if something goes wrong just raise an exception r.raise_for_status() resp = xml.etree.ElementTree.fromstring(r.content) if resp.attrib['status'] == 'error': module.fail_json(msg=r.content) return True, filename def download_file(url): r = requests.get(url, stream=True) fo = tempfile.NamedTemporaryFile(prefix='ai', delete=False) shutil.copyfileobj(r.raw, fo) fo.close() return fo.name def delete_file(path): os.remove(path) def main(): argument_spec = dict( ip_address=dict(required=True), password=dict(required=True, no_log=True), username=dict(default='admin'), category=dict(default='software'), file=dict(), url=dict() ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, required_one_of=[['file', 'url']]) if not HAS_LIB: module.fail_json(msg='pan-python, requests, and requests_toolbelt are required for this module') ip_address = module.params["ip_address"] password = module.params["password"] username = module.params['username'] xapi = pan.xapi.PanXapi( hostname=ip_address, api_username=username, api_password=password ) file_ = module.params['file'] url = module.params['url'] category = module.params['category'] # we can get file from URL or local storage if url is not None: file_ = download_file(url) try: changed, filename = import_file(xapi, module, ip_address, file_, category) except Exception: exc = get_exception() module.fail_json(msg=exc.message) # cleanup and delete file if local if url is not None: delete_file(file_) module.exit_json(changed=changed, filename=filename, msg="okey dokey") if __name__ == '__main__': main()
On my inventory file (called hosts) I'm using:
#Palo Alto Firewall VM [firewalls] fwpa01 ansible_host=XXX.XXX.XXX.XXX ansible_user=testadmin
And on my vault:
--- vault_fwpa01_username: 'adminaccount' vault_fwpa01_password: 'accountpassword'
You could give it a try with that and see if it works.
Also, I remember I used a dsa key on my firewall for authentication, but I think it is not used on this scenario.
05-04-2018 06:51 AM
Hi there!
I'm not sure about the error you are getting.
If it was my case, I would start by testing the import with something that works.
I downloaded the cfg of the firewall, made some changes, imported the cfg and it worked like a charm.
I did the same with the OS file too. (600MB)
Go to Device -> Setup -> Operations -> Save named config.. -> use a short name with no spaces (firewall_cfg)
Then Device -> Setup -> Operations -> Export named config.. -> use the same name
This is the playbook I'm using:
--- # how to run this # ansible-playbook panos_pbk_11_load_cfg.yml --extra-vars "hosts_to_use='fwpa01' cfg_location_to_use='../test_files/dxcfwpasbx01_fresh_config'" -vvvv # to solve ssl issue see file ../how_to_fix_ssl_certificate_issue.txt # to delete a saved configuration file # delete config saved <filename> - name: Load configuration on PAN-OS device hosts: "{{ hosts_to_use }}" gather_facts: false connection: local vars_files: - /home/MYUSERNAME/ansible/vault.yml # - ../vault.yml tasks: # Import and load config file from URL. The import is a separated module - name: import configuration. panos_import: ip_address: "{{ansible_host}}" username: "{{vault_fwpa01_username}}" password: "{{vault_fwpa01_password}}" # url: "{{cfg_location_to_use}}" # url must be like http:///home/MYUSERNAME/ansible/panos_dependencies/testcfg_dxcfwpasbx01 file: "{{cfg_location_to_use}}" category: "configuration" register: result - name: load configuration panos_loadcfg: ip_address: "{{ansible_host}}" username: "{{vault_fwpa01_username}}" password: "{{vault_fwpa01_password}}" file: "{{result.filename}}" commit: "False"
This is the module I'm using: (Just in case it is different for some reason)
cat /usr/lib/python2.7/site-packages/ansible/modules/network/panos/panos_import.py
#!/usr/bin/env python # Copyright 2016 Palo Alto Networks, Inc # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. DOCUMENTATION = ''' --- module: panos_import short_description: import file on PAN-OS devices description: - Import file on PAN-OS device author: "Luigi Mori (@jtschichold), Ivan Bojer (@ivanbojer)" version_added: "2.3" requirements: - pan-python - requests - requests_toolbelt options: ip_address: description: - IP address (or hostname) of PAN-OS device. required: true password: description: - Password for device authentication. required: true username: description: - Username for device authentication. required: false default: "admin" category: description: - Category of file uploaded. The default is software. required: false default: software file: description: - Location of the file to import into device. required: false default: None url: description: - URL of the file that will be imported to device. required: false default: None ''' EXAMPLES = ''' # import software image PanOS_vm-6.1.1 on 192.168.1.1 - name: import software image into PAN-OS panos_import: ip_address: 192.168.1.1 username: admin password: admin file: /tmp/PanOS_vm-6.1.1 category: software ''' RETURN=''' # Default return values ''' ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import get_exception import os.path import xml.etree import tempfile import shutil import os try: import pan.xapi import requests import requests_toolbelt HAS_LIB = True except ImportError: HAS_LIB = False def import_file(xapi, module, ip_address, file_, category): xapi.keygen() params = { 'type': 'import', 'category': category, 'key': xapi.api_key } filename = os.path.basename(file_) mef = requests_toolbelt.MultipartEncoder( fields={ 'file': (filename, open(file_, 'rb'), 'application/octet-stream') } ) r = requests.post( 'https://'+ip_address+'/api/', verify=False, params=params, headers={'Content-Type': mef.content_type}, data=mef ) # if something goes wrong just raise an exception r.raise_for_status() resp = xml.etree.ElementTree.fromstring(r.content) if resp.attrib['status'] == 'error': module.fail_json(msg=r.content) return True, filename def download_file(url): r = requests.get(url, stream=True) fo = tempfile.NamedTemporaryFile(prefix='ai', delete=False) shutil.copyfileobj(r.raw, fo) fo.close() return fo.name def delete_file(path): os.remove(path) def main(): argument_spec = dict( ip_address=dict(required=True), password=dict(required=True, no_log=True), username=dict(default='admin'), category=dict(default='software'), file=dict(), url=dict() ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, required_one_of=[['file', 'url']]) if not HAS_LIB: module.fail_json(msg='pan-python, requests, and requests_toolbelt are required for this module') ip_address = module.params["ip_address"] password = module.params["password"] username = module.params['username'] xapi = pan.xapi.PanXapi( hostname=ip_address, api_username=username, api_password=password ) file_ = module.params['file'] url = module.params['url'] category = module.params['category'] # we can get file from URL or local storage if url is not None: file_ = download_file(url) try: changed, filename = import_file(xapi, module, ip_address, file_, category) except Exception: exc = get_exception() module.fail_json(msg=exc.message) # cleanup and delete file if local if url is not None: delete_file(file_) module.exit_json(changed=changed, filename=filename, msg="okey dokey") if __name__ == '__main__': main()
On my inventory file (called hosts) I'm using:
#Palo Alto Firewall VM [firewalls] fwpa01 ansible_host=XXX.XXX.XXX.XXX ansible_user=testadmin
And on my vault:
--- vault_fwpa01_username: 'adminaccount' vault_fwpa01_password: 'accountpassword'
You could give it a try with that and see if it works.
Also, I remember I used a dsa key on my firewall for authentication, but I think it is not used on this scenario.
Click Accept as Solution to acknowledge that the answer to your question has been provided.
The button appears next to the replies on topics you’ve started. The member who gave the solution and all future visitors to this topic will appreciate it!
These simple actions take just seconds of your time, but go a long way in showing appreciation for community members and the LIVEcommunity as a whole!
The LIVEcommunity thanks you for your participation!