Cisco IOS md5 check ansible module fails - ansible

Running ansible 2.6
This error happens when I try to run the command:
verify /md5 flash:/{ios_file}
This is the output of the command:
TASK [IOS - MD5 CHECK - PASS1] **************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ansible.module_utils.connection.ConnectionError: timeout trying to send command: verify /md5 c2960x-universalk9-mz.152-2.E8.bin
fatal: [pdctestisesw7]: FAILED! => changed=false
module_stderr: |-
Traceback (most recent call last):
File "/tmp/ansible_cr7Tgd/ansible_module_ios_command.py", line 247, in <module>
main()
File "/tmp/ansible_cr7Tgd/ansible_module_ios_command.py", line 217, in main
responses = run_commands(module, commands)
File "/tmp/ansible_cr7Tgd/ansible_modlib.zip/ansible/module_utils/network/ios/ios.py", line 148, in run_commands
File "/tmp/ansible_cr7Tgd/ansible_modlib.zip/ansible/module_utils/connection.py", line 174, in __rpc__
ansible.module_utils.connection.ConnectionError: timeout trying to send command: verify /md5 c2960x-universalk9-mz.152-2.E8.bin
module_stdout: ''
msg: MODULE FAILURE
rc: 1
to retry, use: --limit #/export/home/e130885/playbooks/ios-switch-upgrade/upgrade_ios_switch_v1.retry
Here is the task being executed:
- name: IOS - MD5 CHECK - PASS1
ios_command:
commands:
- command: "verify /md5 {{ compliant_ios_file }}"
register: md5_response
vars:
ansible_command_timeout: 3000
when: 'compliant_ios_file in dir_response.stdout[0]'
This only seems to happen on commands that take more than a second to execute.

There are different ways to achieve it, the following works fine for me. The timeout values varies depending on router type.
> - name: VERIFY_IMAGE
> ios_command:
> commands:
> - "verify /md5 flash:c800-universalk9-mz.SPA.154-3.M10.bin"
> wait_for:
> - result[0] contains "a8216179d49e598579e21b7e5abc9046"
> retries: 1
> vars:
> ansible_command_timeout: 120

Related

Loading environment variables from YAML file (using include_vars) in Ansible

I am trying to load variables from a YAML file to be used as environment variables in a later task of the same playbook. This is what I am doing:
Template host vars in YAML format:
- name: builtin | template | template host variables file
ansible.builtin.template:
src: templates/django/hostvars.j2
dest: "host_vars/{{ inventory_hostname_short }}.yml"
mode: 0640
output_encoding: "utf-8"
delegate_to: localhost
This is producing the following file:
--
# Host variables to be set as environment variables in tasks that need it
POSTGRES_PASSWORD: "<password>"
POSTGRES_USER: "dbuser"
POSTGRES_DB: "dbname"
POSTGRES_HOST: "dbhost"
POSTGRES_PORT: 5432
POSTGRES_SSLMODE: "verify-full"
POSTGRES_SSLCA: "/etc/ssl/certs/ISRG_Root_X1.pem"
POSTGRES_APPNAME: "myproject"
DJANGO_SITE_NAME: "mysite"
DJANGO_SITE_PASSWORD: "mypassword"
DJANGO_SITE_USER: "myuser"
DJANGO_SITE_ID: 2
DJANGO_SECRET_KEY: "<very-long-and-random-secret>"
[..]
Use include_vars to load the vars into the playbook:
- name: builtin | include_vars | load host vars
ansible.builtin.include_vars:
file: "host_vars/{{ inventory_hostname_short }}.yml"
name: envvars
Later on the playbook, check that the variables are there:
- name: builtin | debug | print variable 'envvars'
ansible.builtin.debug:
var: envvars
This is working as intended (apparently) and a list of KEY: value variables is being printed, such as:
TASK [builtin | debug | print variable 'envvars'] ***************************************************************
ok: [django1.mydomain.com] => {
"envvars": {
"DJANGO_DEBUG": 0,
"DJANGO_LOGS_DIR": "/opt/django/logs",
"DJANGO_MEDIA_BASE": "/opt/django/media",
"DJANGO_SECRET_KEY": "<very-long-and-random-secret>",
[..]
Use django_manage to update the database schema:
- name: community.general | django_manage | update database schema
community.general.django_manage:
command: migrate
settings: myproject.settings
project_path: "/opt/django/src"
virtualenv: "/opt/django/venv"
become: true
become_user: django
become_method: su
environment: "{{ envvars }}"
This, unfortunately, is failing. Django is complaining that it cannot find the SECRET_KEY environment variable, which it should build based on one of the variables in the abovementioned list (especifically, DJANGO_SECRET_KEY).
Incidentally, if I run the following task, nothing is printed out:
- name: print environment variables
ansible.builtin.command: env
become: true
become_user: django
become_method: su
environment: "{{ envvars }}"
And I don't understand why. I've tried to debug using -vvv and they are being sent by Ansible though the SSH connection (at least so it seems).
Any hints on what bit I am doing wrong?
EDIT 1
I've changed the tasks list file where I use django_manage into the following code:
- name: builtin | shell | capture DJANGO_ environment variables
debugger: on_failed
ansible.builtin.shell:
cmd: "env | grep DJANGO_"
register: out
environment: "{{ envvars }}"
become: true
become_user: django
become_method: su
- name: builtin | debug | pinrt content of out.stdout
ansible.builtin.debug:
var: out.stdout
- name: builtin | debug | print variable 'envvars'
ansible.builtin.debug:
var: envvars
- name: community.general | django_manage | populate the static subdirectory
community.general.django_manage:
command: collectstatic
clear: yes
project_path: "/opt/django/src"
virtualenv: "/opt/django/venv"
become: true
become_user: django
become_method: su
environment: "{{ envvars }}"
The second and third tasks both print the values of the variables (the first one from the env | grep DJANGO_ command sent via shell and the second is the value of the envvars variable which is being sent via the environment: directive.
This is the error of the last task:
TASK [builtin | shell | capture DJANGO_ environment variables] *************************************************************************************************************
changed: [django1.donmain.com]
TASK [builtin | debug | pinrt content of out.stdout] ***********************************************************************************************************************
ok: [django1.django.com] => {
"out.stdout": "DJANGO_SITE_USER=mysite\nDJANGO_MEDIA_BASE=/opt/django/media\nDJANGO_SITE_NAME=mysite\nDJANGO_SITE_ID=2\nDJANGO_SECRET_KEY=<very-secret-key>\nDJANGO_LOGS_DIR=/opt/django/logs\nDJANGO_SETTINGS_MODULE=myproject.settings.production\nDJANGO_DEBUG=0\nDJANGO_STATIC_BASE=/opt/django/static\nDJANGO_SITE_PASSWORD=mypassword\nDJANGO_SITE_VERSION=57a2f3c168d86243f03809e5d02a0f50a8fa892e"
}
TASK [builtin | debug | print variable 'envvars'] **************************************************************************************************************************
ok: [django1.domain.com] => {
"envvars": {
"DJANGO_DEBUG": 0,
"DJANGO_LOGS_DIR": "/opt/django/logs",
"DJANGO_MEDIA_BASE": "/opt/django/media",
"DJANGO_SECRET_KEY": "<very-secret-key>",
"DJANGO_SETTINGS_MODULE": "myproject.settings.production",
"DJANGO_SITE_ID": 2,
"DJANGO_SITE_NAME": "mysite",
"DJANGO_SITE_PASSWORD": "mypassword",
"DJANGO_SITE_USER": "myuser",
[..]
}
}
TASK [community.general | django_manage | populate the static subdirectory] ************************************************************************************************
fatal: [django1.domain.com]: FAILED! => {"changed": false, "cmd": ["./manage.py", "collectstatic", "--noinput", "--clear"], "msg": "\n:stderr: Traceback (most recent call last):\n File \"/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py\", line 204, in fetch_command\n app_name = commands[subcommand]\nKeyError: 'collectstatic'\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/opt/django/src/./manage.py\", line 22, in <module>\n execute_from_command_line(sys.argv)\n File \"/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py\", line 381, in execute_from_command_line\n utility.execute()\n File \"/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py\", line 375, in execute\n self.fetch_command(subcommand).run_from_argv(self.argv)\n File \"/opt/django/venv/lib/python3.9/site-packages/django/core/management/__init__.py\", line 211, in fetch_command\n settings.INSTALLED_APPS\n File \"/opt/django/venv/lib/python3.9/site-packages/django/conf/__init__.py\", line 57, in __getattr__\n self._setup(name)\n File \"/opt/django/venv/lib/python3.9/site-packages/django/conf/__init__.py\", line 44, in _setup\n self._wrapped = Settings(settings_module)\n File \"/opt/django/venv/lib/python3.9/site-packages/django/conf/__init__.py\", line 107, in __init__\n mod = importlib.import_module(self.SETTINGS_MODULE)\n File \"/usr/lib/python3.9/importlib/__init__.py\", line 127, in import_module\n return _bootstrap._gcd_import(name[level:], package, level)\n File \"<frozen importlib._bootstrap>\", line 1030, in _gcd_import\n File \"<frozen importlib._bootstrap>\", line 1007, in _find_and_load\n File \"<frozen importlib._bootstrap>\", line 986, in _find_and_load_unlocked\n File \"<frozen importlib._bootstrap>\", line 680, in _load_unlocked\n File \"<frozen importlib._bootstrap_external>\", line 790, in exec_module\n File \"<frozen importlib._bootstrap>\", line 228, in _call_with_frames_removed\n File \"/opt/django/src/black_pearl/settings/production.py\", line 3, in <module>\n from black_pearl.settings.common import *\n File \"/opt/django/src/black_pearl/settings/common.py\", line 301, in <module>\n path_app = import_module(app).__path__\n File \"/usr/lib/python3.9/importlib/__init__.py\", line 127, in import_module\n return _bootstrap._gcd_import(name[level:], package, level)\nModuleNotFoundError: No module named 'None'\n", "path": "/opt/django/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "syspath": ["/tmp/ansible_community.general.django_manage_payload_l53eeo4g/ansible_community.general.django_manage_payload.zip", "/usr/lib/python39.zip", "/usr/lib/python3.9", "/usr/lib/python3.9/lib-dynload", "/usr/local/lib/python3.9/dist-packages", "/usr/lib/python3/dist-packages"]}
PLAY RECAP *****************************************************************************************************************************************************************
django1.domain.com : ok=14 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Thanks in advance.
Q: "Nothing is printed out."
A: Register the output if you want to see it. For example
- hosts: localhost
tasks:
- command: echo $DJANGO_DEBUG
register: out
environment:
DJANGO_DEBUG: 0
- debug:
var: out.stdout
gives (abridged)
out.stdout: '0'
This should work for you. Step by step add the complexity to your code and isolate the problem. For example, the playbook below should display the environment at the remote host
- hosts: test_11
vars:
env:
DJANGO_DEBUG: 0
DJANGO_SITE_NAME: mysite
DJANGO_SITE_PASSWORD: mypassword
DJANGO_SITE_USER: myuser
DJANGO_SITE_ID: 2
tasks:
- shell: env | grep DJANGO_
register: out
environment: "{{ env }}"
- debug:
var: out.stdout

Ansible vaulted variables with quotes in it

I am using Ansible 2.4.
I can't get following ansible-playbook to run:
test.yml
---
- hosts: "localhost"
become: no
vars:
foo_withsinglequote: !vault |
$ANSIBLE_VAULT;1.1;AES256
39313737636336313832376165636465346162366333663137373165363662316263336166393666
3566643732663063386333303638633962363863306463610a643931396636613361353165653265
38376630313939626637623538613432373336646663636563623062636238313731326263336263
3138643931323662620a336534383964663562353162393930613965386465616630363335326138
3431
foo_withdoublequote: !vault |
$ANSIBLE_VAULT;1.1;AES256
64633863363838326664323238313866616161313937323563636430326432393638336334303336
3533653339663438356238613937336466623834666537630a646139643033653237353262616662
30643732313861373130633036346361663130326332303932616433643761633739306137333237
6263653365386132620a633738663336313532366637613533313361646339623137393461383363
3332
tasks:
- name: Echo foo_withsinglequote
command: echo "{{ foo_withsinglequote }}"
- name: Echo foo_withdoublequote
command: echo "{{ foo_withdoublequote }}"
To generate the vault variables I used following:
$ echo 123 > vlt.txt
$ ansible-vault --vault-password-file=vlt.txt encrypt_string "abc\"def"
$ ansible-vault --vault-password-file=vlt.txt encrypt_string "abc\'def"
To run the playbook:
$ ansible-playbook --vault-password-file=vlt.txt test.yml
This gives following error:
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ValueError: No closing quotation
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_8uz23O/ansible_module_command.py\", line 213, in \n main()\n File \"/tmp/ansible_8uz23O/ansible_module_command.py\", line 182, in main\n args = shlex.split(args)\n File \"/usr/lib/python2.7/shlex.py\", line 279, in split\n return list(lex)\n File \"/usr/lib/python2.7/shlex.py\", line 269, in next\n token = self.get_token()\n File \"/usr/lib/python2.7/shlex.py\", line 96, in get_token\n raw = self.read_token()\n File \"/usr/lib/python2.7/shlex.py\", line 172, in read_token\n raise ValueError, \"No closing quotation\"\nValueError: No closing quotation\n", "module_stdout": "", "msg": "MODULE FAILURE", "rc": 0}
How can I quote the vaulted variables correctly? Because I don't know in advance, if the vaulted variables will contain single or double quotes.
Your problem description, despite being well written, unfortunately wrongly attributes the problem to Ansible Vault.
In fact, the problem you reported, comes simply from trying to execute the task which effectively becomes:
- command: echo abc"def
Ansible Vault plays no role in causing this problem -- if you defined the variable directly with foo: abc\"def you'd get the same error message.
The solution is simply to quote the string in the echo command:
- command: echo '{{ foo }}'
Other than that you can use quote filter, but for Vault-protected variable you need to first set a static fact:
- set_fact:
bar: "{{ foo }}"
- command: echo {{ bar|quote }}
Finally, the simplest solution to the underlying problem is: do not use special characters in passwords. Increase the length instead.

Use Hashicorp Vault with Ansible - plugin setup

I want to use Hashicorp Vault with Ansible to retrieve username/password which I will use in Ansible playbook.
Vault is setup - I created a secret. What are the steps to integrate both? the documentation around plugins isn't that great. I tried the file lookup from ansible and this works but how to use 3rd party plugins? Can somebody help me with the steps to follow?
Install the plugin, pip install ansible-modules-hashivault
What is the difference with https://github.com/jhaals/ansible-vault
2.a The environment variables (VAULT ADDR & VAULT TOKEN) I put where?
Change ansible.cfg to point to vault.py which is located in "plugin" folder of my Ansible Project
To test basic integration, can I use the following playbook?
https://pypi.python.org/pypi/ansible-modules-hashivault
- hosts: localhost
-tasks:
- hashivault_status:
register: 'vault_status'
Tried this but I get:
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 119, in run
res = self._execute()
File "/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 431, in _execute
self._task.post_validate(templar=templar)
File "/usr/lib/python2.7/site-packages/ansible/playbook/task.py", line 248, in post_validate
super(Task, self).post_validate(templar)
File "/usr/lib/python2.7/site-packages/ansible/playbook/base.py", line 371, in post_validate
value = templar.template(getattr(self, name))
File "/usr/lib/python2.7/site-packages/ansible/template/__init__.py", line 359, in template
d[k] = self.template(variable[k], preserve_trailing_newlines=preserve_trailing_newlines, fail_on_undefined=fail_on_undefined, overrides=overrides)
File "/usr/lib/python2.7/site-packages/ansible/template/__init__.py", line 331, in template
result = self._do_template(variable, preserve_trailing_newlines=preserve_trailing_newlines, escape_backslashes=escape_backslashes, fail_on_undefined=fail_on_undefined, overrides=overrides)
File "/usr/lib/python2.7/site-packages/ansible/template/__init__.py", line 507, in _do_template
res = j2_concat(rf)
File "<template>", line 8, in root
File "/usr/lib/python2.7/site-packages/jinja2/runtime.py", line 193, in call
return __obj(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/ansible/template/__init__.py", line 420, in _lookup
instance = self._lookup_loader.get(name.lower(), loader=self._loader, templar=self)
File "/usr/lib/python2.7/site-packages/ansible/plugins/__init__.py", line 339, in get
self._module_cache[path] = self._load_module_source('.'.join([self.package, name]), path)
File "/usr/lib/python2.7/site-packages/ansible/plugins/__init__.py", line 324, in _load_module_source
module = imp.load_source(name, path, module_file)
File "/etc/ansible/ProjectA/lookup_plugins/vault.py", line 5
<!DOCTYPE html>
^
SyntaxError: invalid syntax
fatal: [win01]: FAILED! => {
"failed": true,
"msg": "Unexpected failure during module execution.",
"stdout": ""
Since you put so many eggs into the post, that I have no clue what the question is really about, here's something to get you going with the native lookup plugin and jhaals/ansible-vault.
you can create lookup_plugins in the current directory and save vault.py inside;
the VAULT_ADDR and VAULT_TOKEN environment variables are as you see them in the script;
The Bash script below (it uses screen and jq, you might need to install them) runs Vault in dev mode, sets the secret, and runs Ansible playbook which queries the secret with two lookup plugins:
#!/bin/bash
set -euo pipefail
export VAULT_ADDR=http://127.0.0.1:8200
if [[ ! $(pgrep -f "vault server -dev") ]]; then
echo \"vault server -dev\" not running, starting...
screen -S vault -d -m vault server -dev
printf "sleeping for 3 seconds\n"
sleep 3
else
echo \"vault server -dev\" already running, leaving as is...
fi
vault write secret/hello value=world excited=yes
export VAULT_TOKEN=$(vault token-create -format=json | jq -r .auth.client_token)
ansible-playbook playbook.yml --extra-vars="vault_token=${VAULT_TOKEN}"
and playbook.yml:
---
- hosts: localhost
connection: local
tasks:
- name: Retrieve secret/hello using native hashi_vault plugin
debug: msg="{{ lookup('hashi_vault', 'secret=secret/hello token={{ vault_token }} url=http://127.0.0.1:8200') }}"
- name: Retrieve secret/hello using jhaals vault lookup
debug: msg="{{ lookup('vault', 'secret/hello') }}"
In the end you should get:
TASK [Retrieve secret/hello using native hashi_vault plugin] *******************
ok: [localhost] => {
"msg": "world"
}
TASK [Retrieve secret/hello using jhaals vault lookup] *************************
ok: [localhost] => {
"msg": {
"excited": "yes",
"value": "world"
}
}
The word world was fetched from Vault.

junos_command module not returning output

I have an Ansible script where i am simply using junos_command module to get users list from Juniper switch, below is the snippet of my code. I keep getting the RuntimeWarning whenever i try to run this. Moreover I have been successfully able to run commands like 'show version' using the below code itself. Please help
Script:
name: / GET USERS / Get list of all the current users on switch
action: junos_command
args: { commands: 'show configuration system login',
provider: "{{ netconf }}" }
register: curr_users_on_switch
Error:
TASK [/ GET USERS / Get list of all the current users on switch] ***************
fatal: [rlab-er1]: FAILED! => {"changed": false, "failed": true, "module_stderr": "/home/mbhadoria/.local/lib/python2.7/site-packages/jnpr/junos/device.py:429: RuntimeWarning: CLI command is for debug use only!
\n warnings.warn(\"CLI command is for debug use only!\", RuntimeWarning)\nTraceback (most recent call last):
\n File \"/tmp/ansible_lVOmPp/ansible_module_junos_command.py\", line 261, in <module>
\n main()
\n File \"/tmp/ansible_lVOmPp/ansible_module_junos_command.py\", line 233, in main
\n xmlout.append(xml_to_string(response[index]))
\n File \"/tmp/ansible_lVOmPp/ansible_modlib.zip/ansible/module_utils/junos.py\", line 79, in xml_to_string\n File \"src/lxml/lxml.etree.pyx\", line 3350, in lxml.etree.tostring (src/lxml/lxml.etree.c:84534)\nTypeError: Type 'str' cannot be serialized.
\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
junos_command only support operation junos commands. What you are trying to run is configurational command. Hence you see "show version" which is operational command working but not "show configuration system login".
For such configuration data you can should use rpc option (get-configuration) with junos_command.
junos_command:
rpcs:
- "get_configuration
You can also use junos_get_config.
http://junos-ansible-modules.readthedocs.io/en/latest/junos_get_config.html
or junos_rpc
https://github.com/Juniper/ansible-junos-stdlib/blob/master/library/junos_rpc
ex:
- name: Junos OS version
hosts: all
connection: local
gather_facts: no
tasks:
- name: Get rpc run
junos_rpc:
host={{ inventory_hostname }}
user=xxxx
passwd=xxx
rpc=get-config
dest=get_config.conf
filter_xml="<configuration><system><login/></system></configuration>"
register: junos
or
tasks:
- name: Get rpc run
junos_get_config:
host: "{{ inventory_hostname }}"
user: xxxx
passwd: xxxx
logfile: get_config.log
dest: "{{ inventory_hostname }}.xml"
format: xml
filter: "system/login"
TASK [Get rpc run] *************************************************************
......
PLAY RECAP *********************************************************************
xxxk : ok=1 changed=1 unreachable=0 failed=0

Ansible: `RequirementParseError` when feeding a variable to `pip: name=pkg version="{{ v }}"`

When I have this role:
# playbooks/roles/ansible/tasks/main.yml
- name: Install Ansible
pip:
state: present
name: ansible
version: "{{ ansible_version }}"
# playbooks/roles/ansible/defaults/main.yml
ansible_version: 1.9.4
I get this error while running ansible-playbook version 1.9.4 or 2.0.0.2:
TASK: [ansible | Install Ansible] *********************************************
failed: [localhost] => {"cmd": "/usr/local/bin/pip install ansible=={'major': 1, 'full': '1.9.4', 'string': '1.9.4\\n configured module search path = None', 'minor': 9, 'revision': 4}", "failed": true}
msg:
:stderr: Invalid requirement: 'ansible=={major:'
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/pip/req/req_install.py", line 73, in __init__
req = pkg_resources.Requirement.parse(req)
File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/pkg_resources/__init__.py", line 3036, in parse
req, = parse_requirements(s)
File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/pkg_resources/__init__.py", line 2980, in parse_requirements
"version spec")
File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/pkg_resources/__init__.py", line 2945, in scan_list
raise RequirementParseError(msg, line, "at", line[p:])
RequirementParseError: Expected version spec in ansible=={major: at =={major:
This is the playbook:
- name: Install Sensu
serial: "100%"
hosts: all
sudo: yes
roles:
- role: "ansible-pull"
server_type: "sensu"
ansible_version: "2"
Where the ansible-pull role depends on the ansible role in meta/main.yml.
Am I injecting the variable incorrectly in this case? Is there some problem with setting the variable in the dependent ansible-pull roll rather than directly in the ansible role?
It turns out that ansible_version is a magic variable set by Ansible.
Who knew?
Using an arbitrarily different but unused variable name does the trick.

Resources