hashi_vault pass variable/argument into the lookup query - ansible

Do you know if I'm able to pass variable into the lookup query?
password: "{{ lookup('hashi_vault', 'secret=secret/data/my_secret:data')['{{ myvar }}']}}"
where myvar is set to mypass
vault kv put secret/my_secret mypass=abcd123
I'm getting the following error.
{"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute '{{myvar}}'\n\nThe error appears to be in '.../ansible/roles/joetests/tasks/main.yml': line 23, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - debug:\n ^ here\n"}
I've tried different quotations but it doesn't seem to work
password: "{{ lookup('hashi_vault', 'secret=secret/data/my_secret:data')['"{{ myvar }}"']}}"
password: "{{ lookup('hashi_vault', 'secret=secret/data/my_secret:data')["'{{ myvar }}'"]}}"
If I use the following it returns the password successfully.
password: "{{ lookup('hashi_vault', 'secret=secret/data/my_secret:data')['mypass']}}"
I'm currently testing a very simple playbook
---
- debug:
msg:
- "{{ item }} => {{ password }}"
with_items:
- "{{ myvar }}"
where
myvar:
- user1
- user2
- user3

Every variable inside the curly braces ({{ }}) will be interpolated, so the trick here is to actually remove the quotes altogether. Try this instead:
password: "{{ lookup('hashi_vault', 'secret=secret/data/my_secret:data')[myvar] }}"

Related

Check multiple conditions in ansible when

I am giving a condition to my ansible task:
- hosts: "{{ env }}"
user: "{{ us1 }}"
gather_facts: no
tasks:
- name: Deploy Services on "{{ env }}"
shell: sh "{{ script_path }}/test.sh"
when: (package == "abc") and (env.startswith('PA_') or env.startswith('lon'))
I am running the above playbook, when the package=abc and env=PA_, its running. But when env=lon, it is giving error:
fatal: [lonxxx.abc.com]: FAILED! =>
{
"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'lonxxx'\n\nThe error appears to be in '/home/dbrun/dbRunPlaybooks/deploy_application.yml': line 25, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Deploy Services on \"{{ env }}"\"\n ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n with_items:\n - {{ foo }}\n\nShould be written as:\n\n with_items:\n - \"{{ foo }}\"\n"
}
I tried giving the when condition in below manner:
when: >
(package == "abc") and
(env.startswith('PA_')) or (env.startswith('lon'))
But giving the same error.
Please help.

Ansible Read csv file and encrypt passwords, output of command to file

I have a csv file containing ip addresses and passwords. These passwords need to be encrypted and written to a file.
This is what I have tried so far:
- name: Read csv file
read_csv:
path: files/ww.csv
fieldnames: ip,password
delimiter: ','
register: routers
delegate_to: localhost
- name: encrypt password
command: "ansible-vault encrypt_string --vault-password-file password '{{ router.password }}' --name 'password'"
loop: "{{ routers.list }}"
loop_control:
loop_var: router
register: "output"
delegate_to: localhost
- name: write file
copy:
content: "{{ output.stdout }}"
dest: "/tmp/{{ router.ip }}.yaml"
loop: "{{ routers.list }}"
loop_control:
loop_var: router
delegate_to: localhost
I want to use output.stdout but I get the following error:
TASK [robustel : write file] *********************************************************************************************************************************
fatal: [10.41.1.161]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'stdout'\n\nThe error appears to be in '/ansible/roles/routers/tasks/create_var_files.yaml': line 20, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: write file\n ^ here\n"}
How can I solve this?
You are registering a variable on a task with a loop. This changes the structure of the data as described in the documentation. Debugging output would have given you a clue.
output.results is a list where each element contains a stdout key (e.g. the first one being output.results.0.stdout). Moreover, each element also contains an item key containing the original element in the loop that was registered.
Modifying your last task like below should give you the expected result:
- name: write file
copy:
content: "{{ output_result.stdout }}"
dest: "/tmp/{{ output_result.item.ip }}.yaml"
loop: "{{ output.results }}"
loop_control:
loop_var: output_result
delegate_to: localhost

How to use ansible when condition when string contains '#'

I am writing playbook to check user principal in kerberos servers. If principal exists it should skip task and if not it should create user principal. I am not sure how to use string with when condition I am trying below but getting errors
"ERROR! Syntax Error while loading YAML.
expected <block end>, but found '<scalar>'
The error appears to be in '/home/revyas/RHELProjects/Atlas/eda-datalake/playbooks/provision-emr.yml': line 42, column 31, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
stat:
path: "{{ user_dir }}"/"{{ keytab_name }}"
^ 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 }}"
Playbook:
- name: Check if user principals exist
command: 'kadmin -w "{{ emr_kdc_admin_password }}" -p kadmin/admin listprincs'
register: user_princs
delegate_to : "{{ emr_kerberos_master }}"
tags: "emr_acct"
- name: Create user kerberos principal if not exist
command: 'kadmin -w {{ emr_kdc_admin_password }} -p kadmin/admin addprinc -randkey {{ kerberos_username }}#{{ emr_kerberos_realm }}'
when: "{{ kerberos_username }}#{{ emr_kerberos_realm }}" not in user_princs.stdout
delegate_to: "{{ emr_kerberos_master }}"
tags: "emr_acct"
User principal from kdc have format given below:
emr-test1-aren-reetika#abd.xyz.com
emr-test-aren#bd.xyz.com
emr-test-integration-test#bd.xyz.com
For the first cited issue, yaml doesn't behave like python or shell which automatically concatenate string literals together
You'll want:
stat:
path: "{{ user_dir }}/{{ keytab_name }}"
And the second error is because yaml believes the leading " is the start of a YAML literal, but in fact it's the start of a Jinja2 literal, thus:
when: '"{{ kerberos_username }}#{{ emr_kerberos_realm }}" not in user_princs.stdout'
Or you can use any of the scalar folding syntaxes, if you prefer that:
when: >-
"{{ kerberos_username }}#{{ emr_kerberos_realm }}"
not in user_princs.stdout
when: "{{ kerberos_username }}#{{ emr_kerberos_realm }}" not in user_princs.stdout
change to
when: "{{ kerberos_username }}\\#{{ emr_kerberos_realm }}" not in user_princs.stdout

Ansible: how to check if a variable is being loaded in a playbook?

I'm trying to write a playbook that will load vars from a group vars file then check if a variable exists
my playbook is like this:
---
- hosts: "{{ target }}"
roles:
- app
tasks:
- name: alert if variable does not exist
fail:
msg: "{{ item }} is not defined"
when: "{{ item }}" is not defined
with_items:
- country
- city
- street
...
My inventory file contains
[app]
ansible-slave1
ansible-slave2
[db]
ansible-db
[multi:children]
app
db
and I have the roles/app/vars/main.yml containing
country: "France"
city: "Paris"
What I was expecting is the playbook to output "street is not defined" but I have a syntax issue I can't resolve
[vagrant#ansible-master vagrant]$ ansible-playbook --inventory-file=ansible_master_hosts test_variables.yml --extra-vars "target=ansible-slave1" --syntax-check
ERROR! Syntax Error while loading YAML.
The error appears to have been in '/vagrant/test_variables.yml': line 10, column 24, but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
msg: "{{ item }} is not defined"
when: "{{ item }}" is not defined
^ 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 }}"
I'd be happy with any hints.
Thanks
You have "" in invalid place of "when" statement. This should be like this:
msg: "{{ item }} is not defined"
when: "{{ item }} is not defined"
So the output will be:
failed: [hostname] (item=street) => {"changed": false, "item": "street", "msg": "street is not defined"}
there is on open issue conditional is defined fails to capture undefined var .
as a workaround I'd suggest to change the where condition to the following:
when: "{{ item }}" == ""

How to register with_items and act on conditional check result for each item

I'd like to register the contents of bashrc for two users and edit as/if required. My play is as follows.
- name: Check bashrc
shell: cat {{ item }}/.bashrc
register: bashrc
with_items:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
- name: Configure bashrc
shell:
cmd: |
cat >> {{ item }}/.bashrc <<EOF
STUFF
EOF
with_items:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
when: '"STUFF" not in bashrc.stdout'
It fails as follows:
fatal: [ca-o3lscizuul]: FAILED! => {"failed": true, "msg": "The conditional check '\"STUFF\" not in bashrc.stdout' failed. The error was: error while evaluating conditional (\"STUFF\" not in bashrc.stdout): Unable to look up a name or access an attribute in template string ({% if \"STUFF\" not in bashrc.stdout %} True {% else %} False {% endif %}).\nMake sure your variable name does not contain invalid characters like '-': argument of type 'StrictUndefined' is not iterable\n\nThe error appears to have been in '/root/openstack-ci/infrastructure-setup/staging/zuul/create-user.yml': line 35, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Configure bashrc\n ^ here\n"}
I think, if I understand your requirement correctly, you can use the 'lineinfile' or 'blockinfile' modules and save yourself the hassle of testing for the existence of the content:
- name: Noddy example data
set_fact:
single_line: "STUFF"
multi_line: |
STUFF
STUFF
profile_dirs:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
- name: Ensure STUFF exists in file
lineinfile:
path: "{{ item }}/.bashrc"
line: "{{ single_line }}"
loop: "{{ profile_dirs }}"
- name: Ensure block of STUFF exists in file
blockinfile:
path: "{{ item }}/.bashrc"
block: "{{ multi_line }}"
loop: "{{ profile_dirs }}"
Both modules give a lot more control and you can find their docs here: lineinfile | blockinfile

Resources