cisco.nxos.nxos_snmp_server - state overridden
jorgenspange opened this issue · 7 comments
SUMMARY
Idemptoncy breaks when you apply password in clear text.
ISSUE TYPE
- Bug Report
COMPONENT NAME
cisco.nxos.nxos_snmp_server
ANSIBLE VERSION
ansible [core 2.16.1]
config file = /Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg
configured module search path = ['/Users/jorgenspange/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /opt/homebrew/Cellar/ansible/9.1.0/libexec/lib/python3.12/site-packages/ansible
ansible collection location = /Users/jorgenspange/.ansible/collections:/usr/share/ansible/collections
executable location = /opt/homebrew/bin/ansible
python version = 3.12.1 (main, Dec 7 2023, 20:45:44) [Clang 15.0.0 (clang-1500.0.40.1)] (/opt/homebrew/Cellar/ansible/9.1.0/libexec/bin/python)
jinja version = 3.1.3
libyaml = True
COLLECTION VERSION
[jorgenspange@Jorgens-MBP git/ansible-network-automation (main) ]$ ansible-galaxy collection list cisco.nxos
# /Users/jorgenspange/.ansible/collections/ansible_collections
Collection Version
---------- -------
cisco.nxos 6.0.0
CONFIGURATION
[jorgenspange@Jorgens-MBP git/ansible-network-automation (main) ]$ ansible-config dump --only-changed
ANSIBLE_COW_PATH(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = /opt/homebrew/bin/cowsay
ANSIBLE_COW_SELECTION(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = small
ANSIBLE_NOCOWS(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = False
ANSIBLE_PIPELINING(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = True
CONFIG_FILE() = /Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg
DEFAULT_FORKS(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = 10
DEFAULT_GATHERING(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = smart
DEFAULT_HOST_LIST(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = ['/Users/jorgenspange/Docum>
DEFAULT_ROLES_PATH(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = ['/Users/jorgenspange/Docu>
DEFAULT_STDOUT_CALLBACK(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = yaml
DEFAULT_TIMEOUT(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = 120
DEFAULT_VAULT_PASSWORD_FILE(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = /Users/jorgenspan>
DISPLAY_SKIPPED_HOSTS(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = False
HOST_KEY_CHECKING(/Users/jorgenspange/Documents/git/ansible-network-automation/ansible.cfg) = False
OS / ENVIRONMENT
Macbook Pro 2021 M1
STEPS TO REPRODUCE
- name: configure_cisco.nxos.nxos | Set snmpv3 configuration.
cisco.nxos.nxos_snmp_server:
config:
contact: {{ snmp_contact }}
location: {{ snmp_location }}
users:
auth:
- authentication:
algorithm: sha
localized_key: false
password: {{ authentication_password }}
priv:
aes_128: true
privacy_password: {{ encryption_password }}
group: network-admin
user: snmp_rw
use_acls:
- ipv4: SNMP
user: snmp_rw
state: overridden
EXPECTED RESULTS
Should define users if they are not there, should not delete them if password mismatches, because password is salted hash.
ACTUAL RESULTS
When you apply multiple times it deletes the user when you have password specified as clear text and not the salted hash which is in the running config on the switch.
1th run
commands:
- snmp-server user snmp_rw network-admin auth sha xx priv aes-128 xx
- no snmp-server user admin
- snmp-server user dnb_snmp_rw use-ipv4acl DNB-SNMP
2nd run
commands:
- snmp-server user dnb_snmp_rw network-admin auth sha xx priv aes-128 xx
- no snmp-server user admin
- no snmp-server user dnb_snmp_rw
It also tries to delete the default admin user which is not possible to delete:
n93180yc-fx(config)# no snmp-server user admin
admin account cannot be deactivated
@jorgenspange @NilashishC I already created #794 and addressed this issue in PR #795. Nevertheless there are still unresolved issues as you can read in this comment. The issue is not only about snmp_server
, but also about the user
module where I copied the code from. Both share the same problem.
Due to the fact that I still got no answer from the developers this issue can not be resolved.
@jorgenspange I'm not sure if I understand the expected results here.
Should define users if they are not there, should not delete them if password mismatches, because password is salted hash.
Since the OS uses salted hashes to store passwords, I don't think we can compute that from plain-text passwords with Ansible and use the salted hash to compare if there's a diff or not. If we do not consider passwords when calculating diff, we will be missing out on cases where there's actually a diff and we need to send updates.
Coming to the specific task you shared, the actual results are in line with how it should behave with state: overridden
.
In the 1st run, it's adding the new user, the new ACL and removing (or attempting to remove) the admin user because that's not specified in your task. I understand that the device doesn't allow that, and I'll push a fix for that.
For the 2nd run, it is important to understand that the user along with all it's properties are considered to be the "unique key", since the plain text password mentioned in your task doesn't match with the salted hash in running-config. The user in running-config is marked as superfluous and a negate command is sent to remove it. The admin
user is tried to be removed again for the reason mentioned above.
In short, this is how overridden is meant to behave. You can either use state: merged
to avoid the user deletion problem, or continue to use state: overridden
, with the entire snmp configuration fetched through state: gathered
and stored in a flat-file.
Does that answer some of your questions?
Yeah my question is answered, thing is that I would like to negate all config that is not in my ansible task, other than the user.
Would be nice if we could define a parameter like this:
user_override: false
or something so that one could granulate this.
@jorgenspange can you share a sample before config and after config based on what you're looking for?
n9k-n93180yc-fx# show run snmp
!Command: show running-config snmp
!Running configuration last done at: Mon Jun 3 10:04:07 2024
!Time: Thu Jun 6 14:10:51 2024
version 9.3(12) Bios:version 05.47
snmp-server contact {{ snmp_contact }}
snmp-server location {{ snmp_location }}}
snmp-server user admin network-admin auth sha blabla priv aes-128 blabla localizedV2key
snmp-server user snmp_ro network-operator auth sha blabla priv aes-128 blabla localizedV2key
snmp-server user snmp_rw network-admin auth sha blabla priv aes-128 blabla localizedV2key
snmp-server user admin use-ipv4acl black_hole
snmp-server user snmp_ro use-ipv4acl snmp-acl
snmp-server user snmp_rw use-ipv4acl snmp-acl
Unfortunately I dont have any before configuration as the snmp config across my nexuses has been cleaned up.
But here is how it looks now, basically everything else then what I've defined in my ansible task is deleted. Would be nice to run override all the time and not affect the users to ensure that this is the config I'm running with.
If I need to change the password on my user I could then run
user_override: true
And it would change the users.
@jorgenspange Understood! In that case, you'd have to follow the same gather
->store
->update
->override
workflow to achieve this. Once your current configuration is gathered and stored in a flat-file, you can remove all entries, except the users. When you run your override task, it'd negated everything except the users. This provides a true IaaC approach to managing network configuration and is what we've been aiming to achieve with resource modules. These weren't meant to provide granular deletion (which can be achieved with the *_config modules).
We have higher-level solutions to help with this as well. For example, you can explore the network.base validated content. Out of the many operations it supports, one is persist, which provides an agnostic way to build brownfield inventory, either locally or in a remote SCM repo. Once the brownfield inventory is ready, it can be modified and the updates can be pushed with the deploy
operation. The way this structures the source-of-truth, makes it very easy to consume and leverage automation at scale.
I'd highly encourage you to give it a try and share your feedback.
I'll be closing this ticket with the above explanation. But, I'll be more than happy to continue this conversation with you. Please feel free to reach out over ansiblenetwork.slack.com or https://matrix.to/#/#network:ansible.com.
Thank you!