F5Networks / f5-ansible

Imperative Ansible modules for F5 BIG-IP products
GNU General Public License v3.0
375 stars 231 forks source link

bigip_user won't allow you to change default admin password #1669

Closed lorinwyatt closed 4 years ago

lorinwyatt commented 4 years ago
ISSUE TYPE
COMPONENT NAME

bigip_user

ANSIBLE VERSION
ansible 2.9.3
PYTHON VERSION
Python 2.7.16
BIGIP VERSION
Sys::Version
Main Package
  Product     BIG-IP
  Version     15.0.1
  Build       0.0.11
  Edition     Final
  Date        Fri Aug  2 21:38:03 PDT 2019
CONFIGURATION

N/A

OS / ENVIRONMENT

N/A

SUMMARY

We are attempting to configure a new system from scratch using Ansible without accessing the GUI. If configuring the F5 from scratch the default behavior it to immediately require a password change when logging in. We are simply trying to do this with Ansible and not logging into the GUI.

STEPS TO REPRODUCE
  tasks:
    - include_vars: foo.yml
    - name: Update Admin Password
      bigip_user:
        state: present
        username_credential: "admin"
        password_credential: "{{ local_admin_password }}"
        provider:
          user: admin
          password: admin
          server: "{{ inventory_hostname }}"
          validate_certs: no
EXPECTED RESULTS

For the default admin password to change

ACTUAL RESULTS

The playbook fails as shown in traceback:

The full traceback is:
WARNING: The below traceback may *not* be related to the actual failure.
  File "/var/folders/lj/jr47dv7s0rzclywqzqsnl970f670hx/T/ansible_bigip_user_payload_A78OEu/ansible_bigip_user_payload.zip/ansible/modules/network/f5/bigip_user.py", line 1109, in main
  File "/var/folders/lj/jr47dv7s0rzclywqzqsnl970f670hx/T/ansible_bigip_user_payload_A78OEu/ansible_bigip_user_payload.zip/ansible/modules/network/f5/bigip_user.py", line 470, in exec_module
  File "/var/folders/lj/jr47dv7s0rzclywqzqsnl970f670hx/T/ansible_bigip_user_payload_A78OEu/ansible_bigip_user_payload.zip/ansible/modules/network/f5/bigip_user.py", line 492, in is_version_less_than_13
  File "/var/folders/lj/jr47dv7s0rzclywqzqsnl970f670hx/T/ansible_bigip_user_payload_A78OEu/ansible_bigip_user_payload.zip/ansible/module_utils/network/f5/icontrol.py", line 529, in tmos_version
    resp = client.api.get(uri)
  File "/var/folders/lj/jr47dv7s0rzclywqzqsnl970f670hx/T/ansible_bigip_user_payload_A78OEu/ansible_bigip_user_payload.zip/ansible/module_utils/network/f5/bigip.py", line 38, in api
    raise F5ModuleError(err)

fatal: [10.15.193.114]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "full_name": null,
            "partition": "Common",
            "partition_access": null,
            "password_credential": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "provider": {
                "auth_provider": null,
                "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                "server": "foo",
                "server_port": null,
                "ssh_keyfile": null,
                "timeout": null,
                "transport": "rest",
                "user": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                "validate_certs": false
            },
            "shell": null,
            "state": "present",
            "update_password": "always",
            "username_credential": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
        }
    },
    "msg": "{\"code\":401,\"message\":\"Authentication failed: Password expired. Update password via /mgmt/shared/authz/users.\",\"restOperationId\":6528704,\"kind\":\":resterrorresponse\"}"
}
wojtek0806 commented 4 years ago

Unfortunately this is not possible with the Ansible modules you need to have username and password defined prior to using the modules as that is what the REST interface is using.

C0missar commented 4 years ago

@lorinwyatt , I've asked for this same feature. My solution thus far has been to SSH in to the device using an SSH key (via the Ansible 'command' module), then issue a 'tmsh modify auth user admin password xxxx shell tmsh' and a 'passwd root xxxx'.

If the image was created with something like an AWS CFT or the Azure equivalent, there is an SSH key placed on the box during the build. If it's vCMP or VE, you get the additional step of SSH to the device without a key, then using an expect script to go through the root password forced change dialog, then doing the admin password change via CLI as above, creating dependencies on both code version and timing.

It would be nice if this could be done via the CFT by specifying a default password, but as you can't even specify the device name there (also requested), that would be asking a lot. Granted, using the CFT leaves open the possibility that the password could be exposed somewhere, but once it's manageable via automation, we then change it to a "real" password anyway. As it is, there are probably more risks of exposure via hacks like mine than there are via template, but that's what we are left with - bad security in the name of security.

Drop me a PM if you'd like any of that code. Stan

zhang-shengping commented 4 years ago

Hello, @lorinwyatt I guess you can use this way to change the password first, then you can move forward.

---

- name: Activate a BigIP device license
  hosts: f5-activate
  connection: local

  vars:
      init_provider:
          server: "{{ bigip_host }}"
          server_port: "{{ bigip_port }}"
          user: "{{ bigip_username }}"
          password: "{{ old_bigip_password }}"
          validate_certs: no

      provider:
          server: "{{ bigip_host }}"
          server_port: "{{ bigip_port }}"
          user: "{{ bigip_username }}"
          password: "{{ new_bigip_password }}"
          validate_certs: "{{ validate_certs }}"

  tasks:

#      - name: Reset the BIG-IP
#        bigip_config:
#            reset: yes
#            save: True
#            provider: "{{ init_provider }}"

      - name: After reset, configure the expired admin password
        uri:
            url: "https://{{ bigip_host }}/mgmt/shared/authz/users/admin"
            method: PATCH
            body: '{"oldPassword":"{{ old_bigip_password }}","password":"{{ new_bigip_password }}"}'
            body_format: json
            validate_certs: no
            force_basic_auth: yes
            user: admin
            password: admin
            headers:
                Content-Type: "application/json"

      - name: Last part of config reset - configure the root password
        bigip_user:
            full_name: root
            username_credential: root
            password_credential: "{{ new_bigip_root_password }}"
            update_password: always
            provider: "{{ provider }}"

      - name: Activate bigip license
        bigip_device_license:
            license_key: "{{ bigip_license_key }}"
            license_server: "{{ bigip_license_server }}"
            accept_eula: yes
            provider: "{{ provider }}"
        register: action_result
        retries: 6
        delay: 20
        until: action_result is success

Note: the same password only can be changed once.

refer: https://techdocs.f5.com/en-us/bigip-15-1-0/big-ip-system-secure-password-policy-enforcement/secure-password-policy-chapter-title/secure-password-policy-enforcement-ansible.html