Ansible expect with ktutil - ansible

I'd like to make a kerberos keytab with ansible + expect, but the keytab file doesn't get created. What is wrong with my play ? How could I troubleshoot?
---
- hosts: localhost
connection: local
gather_facts: false
vars_prompt:
- name: "kuser"
prompt: "enter your user"
- name: "kpw"
prompt: "enter your pw"
tasks:
- name: Generate Kerberos ticket
expect:
command: ktutil
responses:
ktutil: "addent -password -p {{ kuser }}#MYDOMAIN.LOCAL -k 1 -e rc4-hmac"
Password: "{{ kpw }}"
ktutil: "wkt /username.keytab"
ktutil: "quit"
The output with -vvv
Using /etc/ansible/ansible.cfg as config file
[WARNING]: provided hosts list is empty, only localhost is available
[WARNING]: While constructing a mapping from /repo/Playbooks/test.yml, line 15, column 9, found a duplicate dict key (ktutil). Using last
defined value only.
1 plays in /repo/Playbooks/test.yml
enter your user:
enter your pw:
PLAY ***************************************************************************
TASK [Generate Kerberos ticket] ************************************************
task path: /repo/Playbooks/test.yml:11
ESTABLISH LOCAL CONNECTION FOR USER: root
127.0.0.1 EXEC ( umask 22 && mkdir -p "$( echo $HOME/.ansible/tmp/ansible-tmp-1496244261.67-88427652465239 )" && echo "$( echo $HOME/.ansible/tmp/ansible-tmp-1496244261.67-88427652465239 )" )
127.0.0.1 PUT /tmp/tmpwLW3r2 TO /root/.ansible/tmp/ansible-tmp-1496244261.67-88427652465239/expect
127.0.0.1 EXEC LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /root/.ansible/tmp/ansible-tmp-1496244261.67-88427652465239/expect; rm -rf "/root/.ansible/tmp/ansible-tmp-1496244261.67-88427652465239/" > /dev/null 2>&1
changed: [localhost] => {"changed": true, "cmd": "ktutil", "delta": "0:00:00.282785", "end": "2017-05-31 15:24:22.038164", "invocation": {"module_args": {"chdir": null, "command": "ktutil", "creates": null, "echo": false, "removes": null, "responses": {"Password": "mypw", "ktutil": "quit"}, "timeout": 30}, "module_name": "expect"}, "rc": 0, "start": "2017-05-31 15:24:21.755379", "stdout": "ktutil: ", "stdout_lines": ["ktutil: "]}
PLAY RECAP *********************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0
I don't have the keytab created following the above

The problem seems to be that you're repeating the same key for some of the responses. From the ansible expect module documentation:
"If the response is a list, successive matches return successive responses"
Replacing the kutil prompts with a list of responses should prevent the error (and deploy the keytab), eg:
responses:
ktutil:
- "addent -password -p {{ kuser }}#MYDOMAIN.LOCAL -k 1 -e rc4-hmac"
- "wkt /username.keytab"
- "quit"
Password: "{{ kpw }}"
More information: http://docs.ansible.com/ansible/expect_module.html

What actually worked for me was -
- name: addent of keytab
hosts: localhost
vars:
realm: "MYREALM.COM"
sec: "aes256-cts"
passw: "ansible"
usname: "friend"
tasks:
- name: keytab command
expect:
**command: ktutil
responses:
ktutil:
- "addent -password -p {{ usname }}#{{ realm }} -k 1 -e {{ sec }}"
- " wkt /etc/ansible/loopkey.keytab"
- "quit"
Password(.*): "{{ passw }}"**

Related

End play if database does not exits

I have created the following playbook, to check if a database exists:
- name: Check database exits
shell: |
mysql -hmysqlhost -uroot -ppassword -e "show databases" | egrep db"
register: mysql_exist
- name: Show database
debug:
msg: "{{ mysql_exist.stdout }}"
My idea is to finish the playbook if the database does not exist and show a message, I tried this but it does not work, otherwise I should continue to the next task.
- name: Check database exits
shell: |
mysql -hmysqlhost -uroot -ppassword -e "show databases" | egrep db"
register: mysql_exist
- name: End Playbook If database not exits.
meta: end_play
when: mysql_exist == 0
- name: Show database
debug:
msg: "{{ mysql_exist.stdout }}"
## other tasks
How can I create a playbook to check if a database exists and if it does not exist, it must display the message The database does not exist and finish the playbook without running other tasks?
if you want to show a message if playbook has to finish, use a block:
(you dont show the output of your register when a db doesnt exist so, i suppose your test in when condition is ok!!)
- block:
- name: "end play "
debug:
msg: "db doesnt exist"
- meta: end_play
when: mysql_exist == 0
so the playbook is finished after the message displaying
Do you need to show the message? Stopping the playbook already happens automatically if egrep does not find anything, because it exits with a non-0 code.
Playbook:
---
- hosts: srv1
become: True
tasks:
- name: x
shell: "echo nope | egrep dbname"
- name: good
shell: "echo very much"
Output (notice how "good" is not executed):
PLAY [srv1] *******************************************************************************************************************************
TASK [x] **********************************************************************************************************************************
fatal: [srv1]: FAILED! => {"changed": true, "cmd": "echo nope | egrep dbname", "delta": "0:00:00.005942", "end": "2022-02-09 15:56:56.726828", "msg": "non-zero return code", "rc": 1, "start": "2022-02-09 15:56:56.720886", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
PLAY RECAP ********************************************************************************************************************************
srv1 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
It could be approximated with something like this:
- name: x
shell: "echo nope | egrep dbname || { echo Database not found && false; }"
Which gives:
TASK [x] ***********************************************************************************************************************************
fatal: [srv1]: FAILED! => {"changed": true, "cmd": "echo nope | egrep dbname || { echo Database not found && false; }", "delta": "0:00:00.006159", "end": "2022-02-09 15:59:26.176704", "msg": "non-zero return code", "rc": 1, "start": "2022-02-09 15:59:26.170545", "stderr": "", "stderr_lines": [], "stdout": "Database not found", "stdout_lines": ["Database not found"]}

Ansible Regex: Get a integer from command & pass to other command to run

I have to execute below 2 commands whose value depends on the system.
# sysctl -w kernel.shmmax= parse_from_shm.sh script #For example 17179869184
# sysctl -w kernel.shmall= parse_from_shm.sh script #For example 4194304
./shm.sh will echo both system values required in the below format
kernel.shmmax=4185686016
kernel.shmall=1021896
So I have to parse & get integer value above result & execute ultimately below 2 commands
# sysctl -w kernel.shmmax=4185686016
# sysctl -w kernel.shmall=1021896
I have tried to register & parse the integer values using regex. But I couldn't able to process it perfectly. Any help would be of great help.
---
- hosts: fossology_test
become: true
become_user: root
environment:
HOME: /usr/ansible
gather_facts: no
tasks:
- name: run shell script
become: true
become_user: root
command: ./shm.sh
args:
chdir: /usr/local/src/
register: results
- set_fact:
shmmax: "{{ results.stdout | regex_search(shmmaxregexp, '\\1' ) }}"
shmall: "{{ results.stdout | regex_search(shmallregexp, '\\1' ) }}"
vars:
shmmaxregexp: 'shmmax=([^\"]+)'
shmallregexp: 'shmall=([^\"]+)'
- name: sysctl -w kernel.shmmax="{{ shmmax | int }}"
become: true
become_user: root
command: sysctl -w kernel.shmmax="{{ shmmax | int }}"
- name: sysctl -w kernel.shmall="{{ shmall }}"
become: true
become_user: root
command: sysctl -w kernel.shmall="{{ shmall }}"
This is the output
dinesh#dinesh-VirtualBox:~/Documents/remote/Ansible-Playbook/fossology_playbook$ ansible-playbook regex.yml -K -v
Using /etc/ansible/ansible.cfg as config file
BECOME password:
PLAY [fossology_test] ************************************************************************************
TASK [run shell script] **********************************************************************************
changed: [fossology_test] => {"changed": true, "cmd": ["./shm.sh"], "delta": "0:00:00.005912", "end": "2020-03-28 05:25:42.022156", "rc": 0, "start": "2020-03-28 05:25:42.016244", "stderr": "", "stderr_lines": [], "stdout": "kernel.shmmax=4185686016\nkernel.shmall=1021896", "stdout_lines": ["kernel.shmmax=4185686016", "kernel.shmall=1021896"]}
TASK [set_fact] ******************************************************************************************
ok: [fossology_test] => {"ansible_facts": {"shmall": ["1021896"], "shmmax": ["4185686016\nkernel.shmall=1021896"]}, "changed": false}
TASK [sysctl -w kernel.shmmax="0"] ***********************************************************************
changed: [fossology_test] => {"changed": true, "cmd": ["sysctl", "-w", "kernel.shmmax=0"], "delta": "0:00:00.003133", "end": "2020-03-28 05:25:42.574223", "rc": 0, "start": "2020-03-28 05:25:42.571090", "stderr": "", "stderr_lines": [], "stdout": "kernel.shmmax = 0", "stdout_lines": ["kernel.shmmax = 0"]}
TASK [sysctl -w kernel.shmall="[u'1021896']"] ************************************************************
changed: [fossology_test] => {"changed": true, "cmd": ["sysctl", "-w", "kernel.shmall=[u'1021896']"], "delta": "0:00:00.003558", "end": "2020-03-28 05:25:43.071811", "rc": 0, "start": "2020-03-28 05:25:43.068253", "stderr": "sysctl: setting key \"kernel.shmall\": Invalid argument", "stderr_lines": ["sysctl: setting key \"kernel.shmall\": Invalid argument"], "stdout": "kernel.shmall = [u'1021896']", "stdout_lines": ["kernel.shmall = [u'1021896']"]}
PLAY RECAP ***********************************************************************************************
fossology_test : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I am using ansible 2.9.6
dinesh#dinesh-VirtualBox:/$ ansible --version
ansible 2.9.6
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/dinesh/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.17 (default, Nov 7 2019, 10:07:09) [GCC 7.4.0]
As you can very clearly see in the set_fact results dict, the output of regexp_search is a list of matched strings, not the just the capture group. And, because your regex is imprecise, that's why your shmmax is the numbers plus a newline plus the rest of the text.
The accurate regex is shmmax=([0-9]+) because those values aren't "any character except a double quote" it's "any number after the equals sign"

Automate User Password Change using Ansible Playbook

I would like to change a user password if it exists, but I get this error
here my code
- name: Check for foo user
with_items: foo
changed_when: false
command: grep {{ item }} -q /etc/passwd
register: find_user
- name: Update foo user's Password
user:
name: foo
update_password: always
password: $6$rounds=656000$ZjMwlMPWqwGKF1nY$JbarjwHGtlr5PD3Yqfb5phz18gnHujSgmpD29DxsXQ7a7UdhuO
when: find_user is changed
TASK [Check for foo user] *****************************************************************************************************************************************************************************************
fatal: [192.168.56.124]: FAILED! => {"changed": false, "cmd": "grep -w 'foo' /etc/passwd", "delta": "0:00:00.003024", "end": "2019-07-01 12:59:45.966160", "msg": "non-zero return code", "rc": 1, "start": "2019-07-01 12:59:45.963136", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
Use getent module to test the existence of the user.
- name: Read passwd
getent:
database: passwd
- name: Update foo users password
user:
name: foo
update_password: always
password: ...
when: "'foo' in getent_passwd"
That's because the command task you have is having an exit code = 1 when the username does not exist in the /etc/passwd file:
[http_offline#greenhat-29 tests]$ grep foo -q /etc/passwd
[http_offline#greenhat-29 tests]$ echo $?
1
[http_offline#greenhat-29 tests]$ grep root -q /etc/passwd
[http_offline#greenhat-29 tests]$ echo $?
0
[http_offline#greenhat-29 tests]$
What you can do, is instruct this task to NOT fail when exit code from the grep command is not 0 or 1. To do that you need to add this clause in the command task:
failed_when: find_user.rc !=0 and find_user.rc !=1
The whole task would look like:
- name: Check for foo user
with_items: foo
changed_when: false
command: grep {{ item }} -q /etc/passwd
register: find_user
failed_when: find_user.rc !=0 and find_user.rc !=1

basic telnet script to copy to flash drive

I am trying to use ansible to telnet into cisco switches and apply a copy startup-config disk0 command.
Ansible seems to never be able to pass
(?i)"Destination filename": "work please" through the expect command
---
- hosts: all
gather_facts: false
connection: local
tasks:
- name: telnet,login and execute command
ignore_errors: true
expect:
command: telnet "{{ inventory_hostname }}"
responses:
(?i)password: "{{ password}}"
(?i)#: copy startup-config disk0
(?i)"Destination filename": "{{ lookup('pipe','date') }"
echo: yes
register: telnet_output
What i am getting as an output
ansible-playbook 2.7.6
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible-playbook
python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
Using /etc/ansible/ansible.cfg as config file
/var/lib/awx/projects/6500/hosts did not meet host_list requirements, check plugin documentation if this is unexpected
/var/lib/awx/projects/6500/hosts did not meet script requirements, check plugin documentation if this is unexpected
PLAYBOOK: copy-startup.yml *************************************************************************************************************************************************************************************************************
1 plays in copy-startup.yml
PLAY [all] *****************************************************************************************************************************************************************************************************************************
META: ran handlers
TASK [telnet,login and execute command] ************************************************************************************************************************************************************************************************
task path: /var/lib/awx/projects/6500/copy-startup.yml:6
fatal: [66.90.19.18]: FAILED! => {"changed": true, "cmd": "telnet \"66.90.19.18\"", "delta": "0:00:30.370396", "end": "2019-02-12 10:09:41.473716", "msg": "command exceeded timeout", "rc": null, "start": "2019-02-12 10:09:11.103320", "stdout": "Trying 66.90.19.18...\r\r\nConnected to 66.90.19.18.\r\r\nEscape character is '^]'.\r\r\n\r\n\r\nUser Access Verification\r\n\r\nPassword: \r\nLAB-6500-SUP2T#copy startup-config disk0\r\nDestination filename [disk0]? ", "stdout_lines": ["Trying 66.90.19.18...", "", "Connected to 66.90.19.18.", "", "Escape character is '^]'.", "", "", "", "User Access Verification", "", "Password: ", "LAB-6500-SUP2T#copy startup-config disk0", "Destination filename [disk0]? "]}
...ignoring
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
66.90.19.18 : ok=2 changed=1 unreachable=0 failed=0
It seems to never want to write the Destination Filename[disk0]?
Any ideas
(?i)"Destination filename" matches for string with double quotes.
You need:
responses:
'(?i)password': "{{ password}}"
'(?i)#': copy startup-config disk0
'(?i)Destination filename': "{{ lookup('pipe','date') }"
---
- hosts: '6500'
gather_facts: true
connection: local
tasks:
- name: telnet,login and execute command
ignore_errors: true
expect:
command: telnet "{{ inventory_hostname }}"
responses:
(?i)Password: {{ password }}
(?i)Destination filename [disk0]? : "{{ lookup('pipe','date +%Y-%m-%d-%H-%M') }} {{ inventory_hostname }}"
(?i)#: copy startup-config disk0
(?i){{COMMAND}}: exit
echo: yes
register: telnet_output
This seems to be the best solution to what I need. I changed the order of operations and it was rocking,

Concatenate variable with a fact in Ansible

I am trying to use a variable and the results of a previous task as input. Here is my code.
---
- hosts: localhost
vars:
v_hostname: XXXXXXXXXXXXX
v_datacentre: DC-UK-LON-GS
v_username: YYYYYYYY
v_password: XXXXXXXX
connection: local
gather_facts: false
tasks:
- name: Find the folder for the VM
vmware_guest_find:
hostname: "{{ v_hostname }}"
datacenter: "{{ v_datacentre }}"
username: "{{ v_username }}"
password: "{{ v_password }}"
validate_certs: no
name: MYVMNAME
register: folder
- debug:
msg:
- "{{ folder.folders }}"
- name: Gather facts from VM
connection: local
gather_facts: false
vmware_guest_facts:
hostname: "{{ v_hostname }}"
datacenter: "{{ v_datacentre }}"
username: "{{ v_username }}"
password: "{{ v_password }}"
validate_certs: no
folder: "{{ v_datacentre }}{{ folder.folders }}"
name: MYVMNAME
The last line tries to use the defined variable v_datacentre and append the value from the registered fact from the previous task. However the concatenation produces some unwanted wrapping chars:
ansible-playbook 2.4.2.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/export/home/ansible/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /bin/ansible-playbook
python version = 2.7.5 (default, May 3 2017, 07:55:04) [GCC 4.8.5 20150623 (Red Hat 4.8.5-14)]
Using /etc/ansible/ansible.cfg as config file
Parsed /export/home/ansible/inventory_prod inventory source with ini plugin
[WARNING]: Ignoring invalid attribute: gather_facts
PLAYBOOK: mainvm.yml *****************************************************************************************************************************************
1 plays in mainvm.yml
PLAY [localhost] *********************************************************************************************************************************************
META: ran handlers
TASK [TEST1] *************************************************************************************************************************************************
task path: /export/home/ansible/mainvm.yml:12
Using module file /usr/lib/python2.7/site-packages/ansible/modules/cloud/vmware/vmware_guest_find.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: ansible
<127.0.0.1> EXEC /bin/sh -c 'echo ~ && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /export/home/ansible/.ansible/tmp/ansible-tmp-1523621823.18-119950066241401 `" && echo ansible-tmp-1523621823.18-119950066241401="` echo /export/home/ansible/.ansible/tmp/ansible-tmp-1523621823.18-119950066241401 `" ) && sleep 0'
<127.0.0.1> PUT /tmp/tmpM_Pf2B TO /export/home/ansible/.ansible/tmp/ansible-tmp-1523621823.18-119950066241401/vmware_guest_find.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /export/home/ansible/.ansible/tmp/ansible-tmp-1523621823.18-119950066241401/ /export/home/ansible/.ansible/tmp/ansible-tmp-1523621823.18-119950066241401/vmware_guest_find.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python2 /export/home/ansible/.ansible/tmp/ansible-tmp-1523621823.18-119950066241401/vmware_guest_find.py; rm -rf "/export/home/ansible/.ansible/tmp/ansible-tmp-1523621823.18-119950066241401/" > /dev/null 2>&1 && sleep 0'
ok: [localhost] => {
"changed": false,
"folders": [
"/vm/LON-GS-AD/LON-GS-AD-UNIX"
],
"invocation": {
"module_args": {
"datacenter": "DC-UK-LON-GS",
"hostname": "XXXXXXXXXXXXX",
"name": "MYVMNAME",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"username": "XXXXXXXX",
"uuid": null,
"validate_certs": false
}
}
}
TASK [debug] *************************************************************************************************************************************************
task path: /export/home/ansible/mainvm.yml:23
ok: [localhost] => {
"msg": [
[
"/vm/LON-GS-AD/LON-GS-AD-UNIX"
]
]
}
TASK [Gather facts from standalone ESXi server] **************************************************************************************************************
task path: /export/home/ansible/mainvm.yml:28
Using module file /usr/lib/python2.7/site-packages/ansible/modules/cloud/vmware/vmware_guest_facts.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: ansible
<127.0.0.1> EXEC /bin/sh -c 'echo ~ && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /export/home/ansible/.ansible/tmp/ansible-tmp-1523621827.79-78942665802166 `" && echo ansible-tmp-1523621827.79-78942665802166="` echo /export/home/ansible/.ansible/tmp/ansible-tmp-1523621827.79-78942665802166 `" ) && sleep 0'
<127.0.0.1> PUT /tmp/tmp43NXf_ TO /export/home/ansible/.ansible/tmp/ansible-tmp-1523621827.79-78942665802166/vmware_guest_facts.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /export/home/ansible/.ansible/tmp/ansible-tmp-1523621827.79-78942665802166/ /export/home/ansible/.ansible/tmp/ansible-tmp-1523621827.79-78942665802166/vmware_guest_facts.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python2 /export/home/ansible/.ansible/tmp/ansible-tmp-1523621827.79-78942665802166/vmware_guest_facts.py; rm -rf "/export/home/ansible/.ansible/tmp/ansible-tmp-1523621827.79-78942665802166/" > /dev/null 2>&1 && sleep 0'
fatal: [localhost]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"datacenter": "XXXXXX",
"folder": "DC-UK-LON-GS[u'/vm/LON-GS-AD/LON-GS-AD-UNIX']",
"hostname": "XXXXXXXXXXXXX",
"name": "MYVMNAME",
"name_match": "first",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"username": "XXXXXXXX",
"uuid": null,
"validate_certs": false
}
},
"msg": "Unable to gather facts for non-existing VM MYVMNAME"
}
to retry, use: --limit #/export/home/ansible/mainvm.retry
PLAY RECAP ***************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=1
The results of folder.folders is correctly printed by debug but in the last step the concatenation gives:
"folder": "DC-UK-LON-GS[u'/vm/LON-GS-AD/LON-GS-AD-UNIX']",
I confess to being a bit of an Ansible newbie but I don't understand where the [u' and ] come from. I just want to use the combined strings as input. Can anyone please explain or show solution or point me at some beginners documents for this sort of variable use?
Thanks.
So after some further playing turns out that the vmware_guest_find returns a list (and it's in the docs!!!) so I need to either pick the 1st item if there will only be one group or loop though them.
folder: "{{ v_datacentre }}{{ folder.folders[0] }}"
This does the job.

Resources