Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch username/password during playbook execution #1386

Merged
merged 3 commits into from
Sep 4, 2024

Conversation

BGmot
Copy link
Collaborator

@BGmot BGmot commented Sep 4, 2024

SUMMARY

Fixes #1209

ISSUE TYPE
  • Feature Pull Request
COMPONENT NAME

httpapi connection plugin

ADDITIONAL INFORMATION

Here is how you can disable default Admin account and add new admin user

---
- name: Ensure telemetry server is set up and running
  hosts: all
  gather_facts: false
  tasks:

    - name: Configure zabbix server
      vars:
        ansible_network_os: community.zabbix.zabbix
        ansible_connection: httpapi
        ansible_httpapi_port: 8080
        ansible_httpapi_use_ssl: no
        ansible_zabbix_url_path: ""
        ansible_user: "super"
        ansible_httpapi_pass: "verysecretpass"
      block:
        - name: Try to login with new (non-existent user)
          block:
            - name: Check status of default admin
              community.zabbix.zabbix_user_info:
                username: Admin 

          # If new admin user does not exist
          rescue:
            - name: Configure new primary admin user
              vars:
                # Connect with existing user
                ansible_user: "Admin"
                ansible_httpapi_pass: "zabbix"
              community.zabbix.zabbix_user:
                username: "super"
                state: present   
                name: "New Super"
                surname: "User"   
                passwd: "verysecretpass"
                role_name: Super admin role
                usrgrps:
                  - Zabbix administrators
                  - Internal 
                autologin: no  
                autologout: "0"

            - name: Disable default admin user
              vars:
                # Connect with new admin user
                ansible_user: "super"
                ansible_httpapi_pass: "verysecretpass"
              community.zabbix.zabbix_user:
                username: "Admin"
                passwd: "zabbix"
                usrgrps:
                  - "Disabled"

Copy link

codecov bot commented Sep 4, 2024

Codecov Report

Attention: Patch coverage is 0% with 22 lines in your changes missing coverage. Please review.

Project coverage is 78.07%. Comparing base (a09cb00) to head (f71c5ee).
Report is 11 commits behind head on main.

Files with missing lines Patch % Lines
plugins/httpapi/zabbix.py 0.00% 21 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1386      +/-   ##
==========================================
+ Coverage   76.29%   78.07%   +1.77%     
==========================================
  Files          45       45              
  Lines        5619     5641      +22     
  Branches     1423     1427       +4     
==========================================
+ Hits         4287     4404     +117     
+ Misses        836      769      -67     
+ Partials      496      468      -28     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@BGmot BGmot marked this pull request as draft September 4, 2024 12:52
@CircuitCipher
Copy link
Contributor

@BGmot Unfortunately, it seems to fail for my use-case.

In my zabbix provisioning setup I have a set of tasks like the following:

- name: Determine if admin password already set
  block:
  # Make a request to test if new creds in place
  - name: A request with our desired admin creds
    vars: &zabbix_api_args
      ansible_user: "{{ zabbix_admin_user }}"
      ansible_httpapi_pass: "{{ zabbix_admin_pass }}"
    community.zabbix.zabbix_user_info:
      username: "{{ zabbix_admin_user }}"
    register: new_creds_req
    failed_when: false

  - name: set is_admin_pass_set
    set_fact:
      is_admin_pass_set: "{{ new_creds_req.exception is not defined }}"
  
  # This shows that I'm passing in the default admin password as I expect
  - debug:
      msg: "{{ zabbix_admin_pass if is_admin_pass_set else zabbix_default_admin_pass }}"
    
- name: Configure E-mail
  vars: *zabbix_api_args
  block:

  # This task still uses the updated password even when I expect it to use the default admin pass
  - name: "Create an email mediatype with SMTP authentication"
    vars:
      ansible_httpapi_pass: "{{ zabbix_admin_pass if is_admin_pass_set else zabbix_default_admin_pass }}"
  1. Do a test login to see if we changed the "Admin" user's password yet
  2. Create an e-mail mediatype and pass in either the default admin password or new pass based on results above
    a. I create the email mediatype so that Its available before doing the next task of modifying the admin user

The e-mail template task fails with:

  ...
  "msg": "connection error occurred: REST API returned {'code': -32500, 'message': 'Application error.',
 'data': 'Incorrect user name or password or account is temporarily blocked.'} 
when sending {\"jsonrpc\": \"2.0\", \"method\": \"user.login\", 
\"id\": \"2d14071e-16f0-4587-a976-d9974645f65b\", 
\"params\": {\"username\": \"Admin\", \"password\": \"TheNewPassword\"}}"
}

It seems its still using the cached new password from the login check

Looking deeper into this. Maybe instead of caching the password yourself in the httpapi, you could always get the latest versions from the connection objects options:

self.login(self.connection.get_option('remote_user'), self.connection.get_option('password'))

Making the above change to your code seems to make it work for my use-case

# Provide "fake" auth so netcommon.connection does not replace our headers
self.connection._auth = {'auth': 'fake'}
# Need to login with new username/password
self.login(self.username, self.password)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of caching the password yourself in the httpapi, you could always get the latest versions from the connection objects options:

self.login(self.connection.get_option('remote_user'), self.connection.get_option('password'))

Making the above change to your code seems to make it work for my use-case

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind. Let me test and make the change.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed the change, please test.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested, this works for my use-case!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for testing, merging.

@BGmot BGmot marked this pull request as ready for review September 4, 2024 14:25
@BGmot BGmot merged commit e48220d into ansible-collections:main Sep 4, 2024
40 of 41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Zabbix httpapi does not honor reset_connection
3 participants