1#!/usr/bin/python 2# -*- coding: utf-8 -*- 3# 4# Ansible module to manage PaloAltoNetworks Firewall 5# (c) 2016, techbizdev <techbizdev@paloaltonetworks.com> 6# 7# This file is part of Ansible 8# 9# Ansible is free software: you can redistribute it and/or modify 10# it under the terms of the GNU General Public License as published by 11# the Free Software Foundation, either version 3 of the License, or 12# (at your option) any later version. 13# 14# Ansible is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17# GNU General Public License for more details. 18# 19# You should have received a copy of the GNU General Public License 20# along with Ansible. If not, see <http://www.gnu.org/licenses/>. 21 22ANSIBLE_METADATA = {'metadata_version': '1.1', 23 'status': ['deprecated'], 24 'supported_by': 'community'} 25 26 27DOCUMENTATION = ''' 28--- 29module: panos_admin 30short_description: Add or modify PAN-OS user accounts password. 31description: 32 - PanOS module that allows changes to the user account passwords by doing 33 API calls to the Firewall using pan-api as the protocol. 34author: "Luigi Mori (@jtschichold), Ivan Bojer (@ivanbojer)" 35version_added: "2.3" 36requirements: 37 - pan-python 38deprecated: 39 alternative: Use U(https://galaxy.ansible.com/PaloAltoNetworks/paloaltonetworks) instead. 40 removed_in: "2.12" 41 why: Consolidating code base. 42options: 43 admin_username: 44 description: 45 - username for admin user 46 default: "admin" 47 admin_password: 48 description: 49 - password for admin user 50 required: true 51 role: 52 description: 53 - role for admin user 54 commit: 55 description: 56 - commit if changed 57 type: bool 58 default: 'yes' 59extends_documentation_fragment: panos 60''' 61 62EXAMPLES = ''' 63# Set the password of user admin to "badpassword" 64# Doesn't commit the candidate config 65 - name: set admin password 66 panos_admin: 67 ip_address: "192.168.1.1" 68 password: "admin" 69 admin_username: admin 70 admin_password: "badpassword" 71 commit: False 72''' 73 74RETURN = ''' 75status: 76 description: success status 77 returned: success 78 type: str 79 sample: "okey dokey" 80''' 81from ansible.module_utils.basic import AnsibleModule 82 83try: 84 import pan.xapi 85 HAS_LIB = True 86except ImportError: 87 HAS_LIB = False 88 89_ADMIN_XPATH = "/config/mgt-config/users/entry[@name='%s']" 90 91 92def admin_exists(xapi, admin_username): 93 xapi.get(_ADMIN_XPATH % admin_username) 94 e = xapi.element_root.find('.//entry') 95 return e 96 97 98def admin_set(xapi, module, admin_username, admin_password, role): 99 if admin_password is not None: 100 xapi.op(cmd='request password-hash password "%s"' % admin_password, 101 cmd_xml=True) 102 r = xapi.element_root 103 phash = r.find('.//phash').text 104 if role is not None: 105 rbval = "yes" 106 if role != "superuser" and role != 'superreader': 107 rbval = "" 108 109 ea = admin_exists(xapi, admin_username) 110 if ea is not None: 111 # user exists 112 changed = False 113 114 if role is not None: 115 rb = ea.find('.//role-based') 116 if rb is not None: 117 if rb[0].tag != role: 118 changed = True 119 xpath = _ADMIN_XPATH % admin_username 120 xpath += '/permissions/role-based/%s' % rb[0].tag 121 xapi.delete(xpath=xpath) 122 123 xpath = _ADMIN_XPATH % admin_username 124 xpath += '/permissions/role-based' 125 xapi.set(xpath=xpath, 126 element='<%s>%s</%s>' % (role, rbval, role)) 127 128 if admin_password is not None: 129 xapi.edit(xpath=_ADMIN_XPATH % admin_username + '/phash', 130 element='<phash>%s</phash>' % phash) 131 changed = True 132 133 return changed 134 135 # setup the non encrypted part of the monitor 136 exml = [] 137 138 exml.append('<phash>%s</phash>' % phash) 139 exml.append('<permissions><role-based><%s>%s</%s>' 140 '</role-based></permissions>' % (role, rbval, role)) 141 142 exml = ''.join(exml) 143 # module.fail_json(msg=exml) 144 145 xapi.set(xpath=_ADMIN_XPATH % admin_username, element=exml) 146 147 return True 148 149 150def main(): 151 argument_spec = dict( 152 ip_address=dict(), 153 password=dict(no_log=True), 154 username=dict(default='admin'), 155 admin_username=dict(default='admin'), 156 admin_password=dict(no_log=True), 157 role=dict(), 158 commit=dict(type='bool', default=True) 159 ) 160 module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) 161 162 if not HAS_LIB: 163 module.fail_json(msg='pan-python required for this module') 164 165 ip_address = module.params["ip_address"] 166 if not ip_address: 167 module.fail_json(msg="ip_address should be specified") 168 password = module.params["password"] 169 if not password: 170 module.fail_json(msg="password is required") 171 username = module.params['username'] 172 173 xapi = pan.xapi.PanXapi( 174 hostname=ip_address, 175 api_username=username, 176 api_password=password 177 ) 178 179 admin_username = module.params['admin_username'] 180 if admin_username is None: 181 module.fail_json(msg="admin_username is required") 182 admin_password = module.params['admin_password'] 183 role = module.params['role'] 184 commit = module.params['commit'] 185 186 changed = admin_set(xapi, module, admin_username, admin_password, role) 187 188 if changed and commit: 189 xapi.commit(cmd="<commit></commit>", sync=True, interval=1) 190 191 module.exit_json(changed=changed, msg="okey dokey") 192 193 194if __name__ == '__main__': 195 main() 196