I have a playbook that runs correctly when used with ansible-playbook.
It contains an encrypted variable. According to the manual https://docs.ansible.com/ansible/latest/user_guide/vault.html#id16, I can view the variable with
$ ansible localhost -m ansible.builtin.debug -a var="ansible_value" -e
"'debug_playbook.yml" --vault-password-file=./pw_file
But I get an error of
ERROR! failed at splitting arguments, either an unbalanced jinja2 block or quotes: 'debug_playbook.yml
As the playbook itself runs, presumably its syntax is correct.
The playbook is
- name: Run a series of debug tasks to see the value of variables
hosts: localhost
vars:
ansible_password: vault |
$ANSIBLE_VAULT;1.1;AES256
63343064633966653833383264346638303466663265363566643062623436383364376639636630
3032653839323831316361613138333999999999999999999a313439383536353737616334326636
63616162323230333635663364643935383330623637633239626632626539656434333434316631
3965373931643338370a393530323165393762656264306130386561376362353863303232346462
3039
user: myuser
tasks:
- name: show env variable HOME and LOGNAME
debug:
msg: "environment variable {{ item }}"
with_items:
- "{{ lookup('env','HOME') }}"
- "{{ lookup('env','LOGNAME') }}"
- name: now show all of the variables for the current managed machine
debug:
msg: "{{ hostvars[inventory_hostname] }}"
- name: now show all of the hosts in the group from inventory file
debug:
msg: "server {{ item }}"
with_items:
- "{{ groups.mintServers }}"
- "{{ groups.centosServers }}"
I have googled the error and nothing jumps out (to me anyway). Is the manual correct? I have seen other methods where the encrypted variable is echoed into ansible-vault decrypt but it is all a bit of a bother.
I have yamllint'd the playbook. So interested to know what the error means and a way of debugging.
Regards
Following my comments: you cannot view an encrypted var inside a playbook with the technique proposed in the documentation, for memory:
ansible localhost -m debug -a "var=your_var" \
-e #your_file.yml --ask-vault-password
This will only work if your file is a "simple" var file where the top level element is a dictionary.
What I have done in the past is use the yq command line tool (which is a wrapper above jq) that you can easily install with pip install yq. (Note that jq needs to be installed separately and is available in most linux distribution channels. On ubuntu: apt install jq).
Once the prerequisites are available you can use yq to extract the var from you playbook and decrypt it with ansible-vault directly.
For this to work, you will still need to fix your var value which is not a valid vault definition as it misses a question mark in front of the vault marker:
vars:
ansible_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
63343064633966653833383264346638303466663265363566643062623436383364376639636630
3032653839323831316361613138333999999999999999999a313439383536353737616334326636
63616162323230333635663364643935383330623637633239626632626539656434333434316631
3965373931643338370a393530323165393762656264306130386561376362353863303232346462
3039
The solution is not so trivial as yq will get the vault value adding some garbage white-space and new line at the end that will make ansible-vault literally freak out. With your above fixed playbook example, this would give:
yq -r '.[0].vars.ansible_password|rtrimstr(" \n")' your_playbook.yaml \
| ansible-vault decrypt --ask-vault-pass
Related
I have a playbook which calls a script file. It is going to pass a secret to the script file.
What I would like is for the secret not to be shown in standard out.
According to the ansible documentation, no_log: true can be used however this will not work when used in a ANSIBLE_DEBUG env variable is set true.
What I am also finding is that in the task "Set Execution File and parameters", the variables are being displayed even with no_log: true.
---
- block:
- name: Set Execution File and parameters
set_fact:
scriptfile: "{{ansible_user_dir}}\\scripts\\host_check.ps1"
params: " -servername '{{the_host_name}}' -secret {{my_secret}}"
- name: Execute script
win_command: powershell.exe "{{scriptfile}}" "{{params}}"
no_log: True
rescue:
- debug:
msg: "Play failed"
I would like to replace the my_secret variable with *******
Actually no_log: true is all you can do. Ansible will need to know your secret to use it and anybody who can set ANSIBLE_DEBUG can also just edit your playbook to display the secret. So as much as you hide it, it can always be revealed.
You have, however, the possibility to encrypt the secret using ansible-vault and pass the password to ansible, so nobody except you (or has the password) can use (and my this display) the secret.
This is how you encrypt a value (<secret-value> in this case):
ansible-vault encrypt_string --ask-vault-pass '<secret-value>' --name 'secret'
You will be asked for a password (I used test here) and then will get something that looks like this:
secret: !vault |
$ANSIBLE_VAULT;1.1;AES256
36323534396462626132653332653266393832306337336164373834626330373132363136633865
6161623130363364643138633236306334313833663535380a666261383838313631396264626534
66373637653937616231353361633635353238333630303563343630333161626137396332616263
3966356531613234370a633331333862616164386130663262613430316630373230373833313330
6265
You place that in your inventory like this (just an example what it should look like, you need to put in your hosts and other variables):
---
all:
hosts:
your-host:
vars:
secret: !vault |
$ANSIBLE_VAULT;1.1;AES256
36323534396462626132653332653266393832306337336164373834626330373132363136633865
6161623130363364643138633236306334313833663535380a666261383838313631396264626534
66373637653937616231353361633635353238333630303563343630333161626137396332616263
3966356531613234370a633331333862616164386130663262613430316630373230373833313330
6265
the_host_name: host.name
ansible_user_dir: 'C:\\some\\dir'
Then you can do this in your playbook:
---
- block:
- name: Execute script
win_command: 'powershell.exe "{{ ansible_user_dir }}\\scripts\\host_check.ps1" -servername "{{ the_host_name }}" -secret "{{ my_secret }}"'
no_log: true
rescue:
- debug:
msg: "Play failed"
You need to run it with --ask-vault-pass like this:
ansible-playbook -i your-inventory.yml your-playbook.yml --ask-vault-pass
It will ask you for the password every time you run it, so make sure to keep it somewhere.
If you are using multiple encrypted values in one run, you need to use the same password to encrypt all of them.
This is code of my ansible script .
---
- hosts: "{{ host }}"
remote_user: "{{ user }}"
ansible_become_pass: "{{ pass }}"
tasks:
- name: Creates directory to keep files on the server
file: path=/home/{{ user }}/fabric_shell state=directory
- name: Move sh file to remote
copy:
src: /home/pankaj/my_ansible_scripts/normal_script/installation/install.sh
dest: /home/{{ user }}/fabric_shell/install.sh
- name: Execute the script
command: sh /home/{{ user }}/fabric_shell/install.sh
become: yes
I am running the ansible playbook using command>>>
ansible-playbook send_run_shell.yml --extra-vars "user=sakshi host=192.168.0.238 pass=Welcome01" .
But I don't know why am getting error
ERROR! 'ansible_become_pass' is not a valid attribute for a Play
The error appears to have been in '/home/pankaj/go/src/shell_code/send_run_shell.yml': line 2, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
---
- hosts: "{{ host }}"
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
Please guide , what I am doing wrong.
Thanks in advance ...
ansible_become_pass is a connection parameter which you can set as variable:
---
- hosts: "{{ host }}"
remote_user: "{{ user }}"
vars:
ansible_become_pass: "{{ pass }}"
tasks:
# ...
That said, you can move remote_user to variables too (refer to the whole list of connection parameters), save it to a separate host_vars- or group_vars-file and encrypt with Ansible Vault.
Take a look on this thread thread and Ansible Page. I propose to use become_user in this way:
- hosts: all
tasks:
- include_tasks: task/java_tomcat_install.yml
when: activity == 'Install'
become: yes
become_user: "{{ aplication_user }}"
Try do not use pass=Welcome01,
When speaking with remote machines, Ansible by default assumes you are using SSH keys. SSH keys are encouraged but password authentication can also be used where needed by supplying the option --ask-pass. If using sudo features and when sudo requires a password, also supply --ask-become-pass (previously --ask-sudo-pass which has been deprecated).
I have a job in Rundeck, which require users to pass in database password to ansible. And ansible will take it as an extra variable.
ansible-playbook test.yml -e "password=123"
However, we would like to vault the password during the runtime, but from ansible's best practice. They would require the password to be stored in a file.
and vault the entire file using ansible-vault create.
Since we have a large number of the password to pass in, and I notice there is a function call encrypt_string. I try to call it in a playbook and try to generate a vault password on the fly, but I'm getting error below:
"ERROR! Only one --vault-id can be used for encryption. This includes
passwords from configuration and cli."
Here is my playbook test.yml:
---
- name: test
hosts: localhost
tasks:
- name: vault var
command: ansible-vault encrypt_string "{{ password }}" --vault-password-file ~/.vault_pass.txt
register: var
- name: variable
set_fact:
mypass: var
- name: test encrypt_string
debug:
msg: "{{ mypass }}"
I'm not sure if this is the correct way to do it/best practice, anyone can shed some light will be very appreciated.
Thanks,
You may update your task by removing option --vault-password-file as ansible seems getting/reading it from your environment some way.
...
...
- name: test
hosts: localhost
tasks:
- name: vault var
command: ansible-vault encrypt_string "{{ password }}"
register: var
...
...
If you prefer to keep this option in playbook, you may need to find where ansible is reading it from. Ansible may be reading it from it's default config file, generally found at ~/.ansible.cfg [look for vault_password_file] or alias or somewhere else.
You may find more details at ansible vault documentation with examples.
In ansible, is it possible to get the value of the argument to the "--limit" option within a playbook? I want to do is something like this:
---
- hosts: all
remote user: root
tasks:
- name: The value of the --limit argument
debug:
msg: "argument of --limit is {{ ansible-limit-arg }}"
Then when I run he command:
$ ansible-playbook getLimitArg.yaml --limit webhosts
I'll get this output:
argument of --limit is webhost
Of course, I made up the name of the variable "ansible-limit-arg", but is there a valid way of doing this? I could specify "webhosts" twice, the second time with --extra-args, but that seems a roundabout way of having to do this.
Since Ansible 2.5 you can access the value using a new magic variable ansible_limit, so:
- debug:
var: ansible_limit
Have you considered using the {{ ansible_play_batch }} built-in variable?
- hosts: all
become: "False"
gather_facts: "False"
tasks:
- name: The value of the --limit argument
debug:
msg: "argument of --limit is {{ ansible_play_batch }}"
delegate_to: localhost
It won't tell you exactly what was entered as the argument but it will tell you how Ansible interpreted the --limit arg.
You can't do this without additional plugin/module. If you utterly need this, write action plugin and access options via cli.options (see example).
P.S. If you try to use --limit to run playbooks agains different environments, don't do it, you can accidentally blow your whole infrastructure – use different inventories instead.
Here is the small code block to achieve the same
- block:
- shell: 'echo {{inventory_hostname}} >> /tmp/hosts'
- shell: cat /tmp/hosts
register: servers
- file:
path: /tmp/hosts
state: absent
delegate_to: 127.0.0.1
- debug: var=servers.stdout_lines
Then use stdout_lines output as u wish like mine
- add_host:
name: "{{ item }}"
groups: cluster
ansible_user: "ubuntu"
with_items:
- "{{ servers.stdout_lines }}"
I have an ansible-playbook and when i try to run this playbook i am getting this error
(specified line no longer in file, maybe it changed?)
--
- name: check if the public/private key exist at ~/.ssh/
stat:
path: /root/.ssh/id_rsa.pub
register: st
- name: run the command
command: cat /root/.ssh/id_rsa.pub|ssh -i /root/.ssh/bi_ppc.pem ubuntu#"{{items}" "cat >> .ssh/authorized_keys"
with_items:
- groups['ubuntu']
when: st.changed
~
ansible --version
ansible 2.2.0.0
config file = /home/swathi/Desktop/infrastructure/ansible.cfg
configured module search path = Default w/o overrides
You can use authorized_key module, copy pub key from local to remote.
--
- name: get public key
local_action: shell cat /home/user/.ssh/id_rsa.pub
register: pubkey
- name: check keys
debug: msg="{{ pubkey.stdout }}"
- name: add public key on the remote server
authorized_key: user=root key="{{ item[0] }}"
delegate_to: "{{ item[1] }}"
with_nested:
- "{{ pubkey.stdout }}"
- "{{groups['ubuntu']}}"
I faced the same error message from ansible:
$ ansible-playbook t.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
ERROR! Syntax Error while loading YAML.
found unexpected end of stream
The error appears to be in '/root/ansible/t.yml': line 6, column 1, but may
be elsewhere in the file depending on the exact syntax problem.
(specified line no longer in file, maybe it changed?)
The playbook is:
$ cat t.yml
---
- hosts: localhost
tasks:
- debug:
msg: "unterminated quoted string
In fact there is a YAML syntax error, at the end of the playbook missing a double quote. As it finish the playbook my editor doesn't help me by showing a different color.
Hope that will help someone else.