ansible cisco ios_command module "unable to set terminal parameters" - ansible

I am running ansible v 2.5 and trying to run a basic "show clock" command on my switch.
How ever it errors out saying that it is unable to set terminal parameters,
following is my yml File:
---
- hosts: ios_devices
gather_facts: no
connection: local
vars_prompt:
- name: "mgmt_username"
prompt: "Username"
private: no
- name: "mgmt_password"
prompt: "Password"
tasks:
- name: SYS | Define provider
set_fact:
provider:
host: "{{ inventory_hostname }}"
username: "{{ mgmt_username }}"
password: "{{ mgmt_password }}"
- name: IOS | Show clock
ios_command:
provider: "{{ provider }}"
commands:
- show clock
register: clock
- debug: msg="{{ clock.stdout }}"
and on running the playbook i receive the following error:
fatal: [x.x.x.x]: FAILED! => {"msg": "unable to set terminal parameters"}

The error unable to set terminal parameters means that one (or both) of the following commands failed:
terminal length 0
terminal width 512
Try running those commands manually on your Cisco IOS switch to check they are supported.

I have faced the same problem but solved it after using "asa_command" module:
- hosts: ASA
connection: local
gather_facts: no
vars:
cli:
host: "{{ ansible_host }}"
username: "{{ ansible_user }}"
password: "{{ ansible_password }}"
authorize: yes
auth_pass: "{{ ansible_password }}"
tasks:
- name: run multiple commands and evaluate the output
asa_command:
commands:
- show service-policy
- show running-config
provider: "{{ cli }}"
register: output
- debug:
msg: "{{ output.stdout_lines }}"

Yes, have to be able to set the following two command:
terminal length 0
and
terminal width 512
You don't need specific privileges to be able to issue these commands. Both can be issued from the Cisco's regular CLI exec mode.
Check your username "commands" authorization privileges, that could be the issue. You may have a limited command authorization configured on your IOS device. If you have access to "show running" command, try checking aaa authorization using the following:
show run | i aaa authorization commands
If you see it defined on your router/switch, you'll need to talk to your network admin and make sure they allow you or the ansible user you are using to be able to issue "terminal length" and "terminal width" commands. I am not aware of any other way around this.
Just FYI, the "terminal" command is only limited to the user current active session, and will NOT affect any router operational parameters in any way. Once you logout, the terminal parameters will reset to its default.
As for the asa_command workaround, that's not recommended really. asa and ios have different output formatting, so, although may work for some cases, it is guaranteed to fail in other cases.
If you are using an ASA with PIXOS and having the same problem, use the "Pager" command to set the length of your terminal.
Please check out the following Cisco Community link for more information on setting terminal length on different Cisco devices:
Show the Complete Configuration without Breaks/Pauses on Cisco Router/Switches, ASA Firewall and WLC (Wireless LAN Controller)

I just happened to get this issue as well but for IOS XR. the problem for me is that i have created a set of new and unique credentials just for Ansible to access my devices and did not set the proper privileges for these. In my specific case, configuring the new set of credentials to be part of the "sysadmin" group solved the problem for me:
Cisco-IOS-XR Device
username ansible
secret ansible
**group sysadmin**
In case of the IOS / IOS XE devices should check the aaa configuration for the proper privileges as well.
Last but not least, for ASA, i assume it would be the exact same.

Related

snmp user configuration using Ansible

I Need to configure snmp user by checking the hosts os and wherever snmp user is blank add the snmp user
Steps Mentioned below :
Check if devices are accessible by SSH or not
The one's which are accessible, identify OS version and device Type
Based on the OS version and Device type, check
SNMP Configuration
run command on device : Show snmp user
if output received, no changes to be done.
if output not received, device eligble for
change
run command : Show run | include ^snmp-server
if network-admin and network-operator groups existing, then only implement the change to add lines "snmp-user group_name"
I did write anisble playbook which segregate the hosts on IOS and nx-os operating system bbut having difficulty to use multiple when conditions so that I can proceed for ios_config change
---
- name : configure snmp user
hosts: all
gather_facts: false
connection: network_cli
vars:
provider:
timeout: 60
tasks:
- name: show version of devices
nxos_command:
commands: show version
register: command_output
- name: check the snmp user nxos_command
nxos_command:
commands: "sh snmp user"
provider: "{{provider}}"
register: nxos_command_run
when: "'NX-OS' in command_output.stdout.0"
- name : display command ouput #running this to get correct values
debug: var=item
when: "'network-admin' in item"
loop:"{{nxos_command_run.stdout_lines.0}}"
#when: "'NX-OS' in command_output.stdout.0" - here I am unable to use two when conditions
so can someone please help me apply the logic for the required conditions

Ansible Failed to set permissions on the temporary files

I'd like to make a playbook that shows me the user currently in use.
this is my ansible cfg:
[defaults]
inventory=inventory
remote_user=adminek
[privilege_escalation]
become=true
[ssh_connection]
allow_world_readable_tmpfiles = True
ssh_args = -o ControlMaster=no -o ControlPath=none -o ControlPersist=no
pipelining = false
and this is my playbook
---
- name: show currenty users
hosts: server_a
tasks:
- name: test user - root
shell: "whoami"
register: myvar_root
- name: test user - user2
become: true
become_user: user2
shell: "whoami"
register: myvar_user2
- name: print myvar root
debug:
var: myvar_root.stdout_lines
- name: print myvar user2
debug:
var: myvar_user2.stdout
taks "test user - root" work fine and give me output
ok: [172.22.0.134] => {
"myvar_root.stdout_lines": [
"root"
]
}
taks "test user - user2" give me output
fatal: [172.22.0.134]: FAILED! => {"msg": "Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user (rc: 1, err: chown: changing ownership `/var/tmp/ansible-tmp-1621340458.2-11599-141854654478770/': Operation permited\nchown: changing ownership `/var/tmp/ansible-tmp-1621340458.2-11599-141854654478770/AnsiballZ_command.py': Operation permited\n}). For information on working around this, see https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user"}
Explanation:
adminek- sudoer user
User2 - non sudoers users
OS - Scientific Linux release 6.9
Additionaly I hgad similar problem on ubuntu 18.04 but when i installed acl begun works
Someone know what is wrong?
Thanks for help!
One of the following options should fix your issue:
Ensure sudo is installed on the remote host
Ensure acl is installed on the remote host
Uncomment the following lines in /etc/ansible/ansible.cfg:
allow_world_readable_tmpfiles = True
pipelining = True
#F1ko thanks for reply.
I did what you wont and I installed acl on my host, but steal was wrong.
I added to visudo.
Defaults:user2 !requiretty
Defaults:adminek !requiretty
I dont know it's ok and secure but work.
for me it worked installing the acl package in host
- name: Install required packaged
yum:
name: "{{ item }}"
state: present
with_items:
- acl
- python3-pip
in my case I used centos/07, if you use ubuntu, change yum to apt.

Switching user for delegation to host outside of inventory with Ansible/awx

I am trying to do the following using Ansible 2.8.4 and awx:
Read some facts from Cisco IOS devices (works)
Put results into a local file using a template (works)
Copy/Move the resulting file to a different server
Since I have to use a different user to access IOS devices and servers, and the servers in question aren't part of the inventory used for the playbook, I am trying to achieve this using become_user and delegate_to.
The initial user (defined in the awx template) is allowed to connect to the IOS devices, while different_user can connect to servers using a ssh private key.
The playbook:
---
- name: Read Switch Infos
hosts: all
gather_facts: no
tasks:
- name: Gather IOS Facts
ios_facts:
- debug: var=ansible_net_version
- name: Set Facts IOS
set_fact:
ios_version: "{{ ansible_net_version }}"
- name: Create Output file
file: path=/tmp/test state=directory mode=0755
delegate_to: 127.0.0.1
run_once: true
- name: Run Template
template:
src: ios_firmware_check.j2
dest: /tmp/test/output.txt
delegate_to: 127.0.0.1
run_once: true
- name: Set up keys
become: yes
become_method: su
become_user: different_user
authorized_key:
user: different_user
state: present
key: "{{ lookup('file', '/home/different_user/.ssh/key_file') }}"
delegate_to: 127.0.0.1
run_once: true
- name: Copy to remote server
remote_user: different_user
copy:
src: /tmp/test/output.txt
dest: /tmp/test/output.txt
delegate_to: remote.server.fqdn
run_once: true
When run, the playbook fails in the Set up keys task trying to access the home directory with the ssh key:
TASK [Set up keys] *************************************************************
task path: /tmp/awx_2206_mz90qvh9/project/IOS/ios_version.yml:23
[WARNING]: Unable to find '/home/different_user/.ssh/key_file' in expected paths
(use -vvvvv to see paths)
File lookup using None as file
fatal: [host]: FAILED! => {
"msg": "An unhandled exception occurred while running the lookup plugin 'file'. Error was a <class 'ansible.errors.AnsibleError'>, original message: could not locate file in lookup: /home/different_user/.ssh/key_file"
}
I'm assuming my mistake is somehow related to which user is trying to access the /home/ directory on which device.
Is there a better/more elegant/working way of connecting to a different server using an ssh key to move around files?
I know one possibility would be to just scp using the shell module, but that always feels a bit hacky.
(sort of) solved using encrypted variables in hostvars with Ansible vault.
How to get there:
Encrypting the passwords:
This needs to be done from any commandline with Ansible installed, for some reason this can't be done in tower/awx
ansible-vault encrypt_string "password"
You'll be prompted for a password to encrypt/decrypt.
If you're doing this for Cisco devices, you'll want to encrypt both the ssh and the enable password using this method.
Add encrypted passwords to inventory
For testing, I put it in hostvars for a single switch, should be fine to put it into groupvars and use it on multiple switches as well.
ansible_ssh_pass should be the password to access the switch, ansible_become_pass is the enable password.
---
all:
children:
Cisco:
children:
switches:
switches:
hosts:
HOSTNAME:
ansible_host: ip-address
ansible_user: username
ansible_ssh_pass: !vault |
$ANSIBLE_VAULT;1.1;AES256
[encrypted string]
ansible_connection: network_cli
ansible_network_os: ios
ansible_become: yes
ansible_become_method: enable
ansible_become_pass: !vault |
$ANSIBLE_VAULT;1.1;AES256
[encrypted string]
Adding the vault password to tower/awx
Add a new credential with credential type "Vault" and the password you used earlier to encrypt the strings.
Now, all you need to do is add the credential to your job template (the template can have one "normal" credential (machine, network, etc.) and multiple vaults).
The playbook then automagically accesses the vault credential to decrypt the strings in the inventory.
Playbook to get Switch Infos and drop template file on a server
The playbook now looks something like below, and does the following:
Gather Facts on all Switches in Inventory
Write all facts into a .csv using a template, save the file on the ansible host
Copy said file to a different server using a different user
The template is configured with the user able to access the server, the user used to access switches with a password is stored in the inventory as seen above.
---
- name: Read Switch Infos
hosts: all
gather_facts: no
tasks:
- name: Create Output file
file: path=/output/directory state=directory mode=0755
delegate_to: 127.0.0.1
run_once: true
- debug:
var: network
- name: Gather IOS Facts
remote_user: username
ios_facts:
- debug: var=ansible_net_version
- name: Set Facts IOS
set_fact:
ios_version: "{{ ansible_net_version }}"
- name: Run Template
template:
src: ios_firmware_check.csv.j2
dest: /output/directory/filename.csv
delegate_to: 127.0.0.1
run_once: true
- name: Create Destination folder on remote server outside inventory
remote_user: different_username
file: path=/destination/directory mode=0755
delegate_to: remote.server.fqdn
run_once: true
- name: Copy to remote server outside inventory
remote_user: different_username
copy:
src: /output/directory/filename.csv
dest: /destination/directory/filename.csv
delegate_to: remote.server.fqdn
run_once: true

How to make Ansible display the host name before asking for the sudo password?

I have an Ansible playbook to update my Debian based servers. For simplicity and security reasons, I don't want to use a vault for the passwords and I also don't want to store them in a publically accessible config file. So I ask for the password for every client with
become: yes
become_method: sudo
Now, when the playbook runs, it seems the first thing Ansible does is ask for the sudo password, but I don't know for which server (the passwords are different). Is there a way to get Ansible to print the current host name before it asks for the password?
The update playbook is similar to this:
---
- hosts:
all
gather_facts: no
vars:
verbose: false
log_dir: "log/dist-upgrade/{{ inventory_hostname }}"
pre_tasks:
- block:
- setup:
rescue:
- name: "Install required python-minimal package"
raw: "apt-get update && apt-get install -y --force-yes python-apt python-minimal"
- setup:
tasks:
- name: Update packages
apt:
update_cache: yes
upgrade: dist
autoremove: yes
register: output
- name: Check changes
set_fact:
updated: true
when: not output.stdout | search("0 upgraded, 0 newly installed")
- name: Display changes
debug:
msg: "{{ output.stdout_lines }}"
when: verbose or updated is defined
- block:
- name: "Create log directory"
file:
path: "{{ log_dir }}"
state: directory
changed_when: false
- name: "Write changes to logfile"
copy:
content: "{{ output.stdout }}"
dest: "{{ log_dir }}/dist-upgrade_{{ ansible_date_time.iso8601 }}.log"
changed_when: false
when: updated is defined
connection: local
(source: http://www.panticz.de/Debian-Ubuntu-mass-dist-upgrade-with-Ansible)
Your above become configuration does not make ansible ask you for a become password: it just advises it to use become with the sudo method (which will work without any password if your have the correct keys configured for example).
If you are asked for a become password, it's because (it's a guess but I'm rather confident...) you used the --ask-become-pass option when running ansible-playbook.
In this case, you are prompted only once at the beginning of the playbook operations and this default become password will be used on all servers you connect to except if you defined an other one in your inventory for a specific host/group.
If you have different become passwords depending on your machines, you don't really have an other option: you need to declare those passwords in your inventory (and it is strongly advised to use ansible-vault encryption) or use some other mechanisms to get them out of an external application (hashicorp vault, dynamic inventory, cyberark...)

Ansible launch ssh-copy-id before running play?

I want to use Ansible to disable selinux in some remote servers. I don't know yet the full list of the servers, it will come from time to time.
That would be great if the ssh-copy-id phase would be integrated somehow in the playbook - you would expect that from an automation system ? I don't mind getting asked for the password one time per server.
With various reading, I understand I can run a local_action in my task:
---
- name: Disable SELinux
hosts: all
remote_user: root
gather_facts: False
tasks:
- local_action: command ssh-copy-id {{remote_user}}#{{hostname}}
- selinux:
state: disabled
However:
It fails because {{remote_user}} and {{hostname}} are not accessible in this context.
I need to gather_factsto False, because it's executed before local_action
Any idea if that's possible within Ansible playbooks ?
You may try this:
- hosts: all
gather_facts: no
tasks:
- set_fact:
rem_user: "{{ ansible_user | default(lookup('env','USER')) }}"
rem_host: "{{ ansible_host }}"
- local_action: command ssh-copy-id {{ rem_user }}#{{ rem_host }}
- setup:
- selinux:
state: disabled
Define remote user and remote host first, then make local action, then enforce fact gathering with setup.

Resources