hashi_vault don't work through Web Application Firewall - url

I want to retrieve a vault secret with Ansible using the hashi_vault module which doesn't seem to work through a WAF.
The hashi_vault module work when the vault server is mapped to the root url (https://address/) in the WAF but when we use a custom path (https://address/vault) the Ansible playbook return this error : "Invalid Hashicorp VaultToken Specified for hashi_vault lookup"
- hosts: localhost
tasks:
- name: set variables
set_fact:
vault_token: !vault |
$ANSIBLE_VAULT;1.1;AES256
SOMETOKEN
- name: get Configuration token from Vault
set_fact:
vault_result: "{{ lookup('hashi_vault', 'secret=secret/data/all/default/token token={{ vault_token }} url=https://address validate_certs=False' ) }}"
- name: parse result
set_fact:
TOKEN: "{{ vault_result.data.token }}"
register: TOKEN
- name: show result
debug:
msg: "{{ TOKEN }}"
I'd love to find a way to keep my custom url (https://address/vault) and get my secret !

It's not related to your WAF, it's just a variable issue...
Try something like that:
- name: get Configuration token from Vault
set_fact:
vault_result: "{{ lookup('hashi_vault', 'secret=secret/data/all/default/token token=' + vault_token + ' url=https://address validate_certs=False' ) }}"

Related

Ansible known_hosts module ssh key propagation question

I'm trying to craft a playbook that will update the known_hosts for a machine / user however I'm getting an error I can't make sense of.
---
- name: Keys
hosts: adminslaves
gather_facts: false
no_log: false
remote_user: test
#pre_tasks:
# - setup:
# gather_subset:
# - '!all'
tasks:
- name: Scan for SSH host keys.
shell: ssh-keyscan myhost.mydomain.com 2>/dev/null
changed_when: False
register: ssh_scan
# - name: show vars
# debug:
# msg: "{{ ssh_scan.stdout_lines }}"
#
- name: Update known_hosts.
known_hosts:
key: "{{ item }}"
name: "{{ ansible_host }}"
state: present
with_items: "{{ ssh_scan.stdout_lines }}"
My error is "msg": "Host parameter does not match hashed host field in supplied key"}
I think the variable has the right information (at least it does when I debug it).
My end goal is a playbook that will add ssh keys of a list of hosts to a list of hosts for Jenkins auth.
Appreciate any help.
the problem is that the output of ssh-keyscan myhost.mydomain.com 2>/dev/null usually contains more than one key so you need to process it.
Someone with the same error message raised an issue, but again the problem was with the ssh-key format. I better understood checking the code used by known_hosts task.
Here the code I use:
- name: Populate known_hosts
hosts: spectrum_scale
tags: set_known_hosts
become: true
tasks:
- name: Scan for SSH keys
ansible.builtin.shell:
cmd: "ssh-keyscan {{ hostvars[spectrum_scale].ansible_fqdn }}
{{ hostvars[spectrum_scale].ansible_hostname }}
{{ hostvars[spectrum_scale].ansible_default_ipv4.address }}
2>/dev/null"
loop: "{{ groups['spectrum_scale'] }}"
loop_control:
loop_var: spectrum_scale
register: ssh_scan
- name: Set stdout_lines array for ssh_scan
set_fact:
ssout: []
- name: Fill ssout
set_fact:
ssout: "{{ ssout + ss_r.stdout_lines }}"
loop: "{{ ssh_scan.results }}"
loop_control:
loop_var:
ss_r
when: ss_r.stdout_lines is defined
- name: Add client ssh keys to known_hosts
ansible.builtin.known_hosts:
name: "{{ hk.split()[0] }}"
key: "{{ hk }}"
state: present
loop: "{{ ssout }}"
loop_control:
loop_var: hk

Docker_swarm module - join_token parameter for ansible not working

This is my ansible playbook, the tasks are copied from docker_swarm module documentation so it should work:
- name: Init a new swarm with default parameters
docker_swarm:
state: present
advertise_addr: "{{ manager_ip }}:2377"
register: rezult
when: "ansible_default_ipv4.address == '{{ manager_ip }}'"
- name: Add nodes
docker_swarm:
state: join
advertise_addr: "{{ manager_ip }}"
join_token: rezult.swarm_facts.JoinTokens.Worker
remote_addrs: "{{ manager_ip }}:2377"
when: "ansible_default_ipv4.address != '{{ manager_ip }}'"
It inits a swarm manager with the "manager_ip" --extra-var
but it fails in the "add nodes task" with this error:
fatal: [vm2]: FAILED! => {"changed": false, "msg": "Can not join the Swarm Cluster: 500 Server Error: Internal Server Error (\"invalid join token\")"}
if I put "'{{ }}'" around "rezult.swarm_facts.JoinTokens.Worker" after join_token I get this:
fatal: [vm2]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'swarm_facts'\n\nThe error appears to be in '/home/ansible/docker-ansible/docker.yml': line 47, 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: Add nodes\n ^ here\n"}
If I put the debug msg for rezult.swarm_facts.JoinTokens.Worker I get the correct token:
ok: [opensuse1] => {
"msg": "SWMTKN-1-5p7brhxxz4gzu716t78tt5woj7h6aflq0kdwvzwlbbe7ct0ba7-e59bg0t79q67ogd61ydwxc5yq"
}
and If I use that token manually with the docker swarm join command on the server I wish to merge with manager it works. So the variable has the correct value and the connection between nodes work. But I just can't get join_token to work. I am running ansible 2.8.5 with python 2.7.5.
I know I can use the shell module but I do not want to do that.
Something like this works for me:
---
- name: Init swarm on the first node
community.general.docker_swarm:
state: present
advertise_addr: "{{ ansible_host }}"
register: result
when: inventory_hostname == groups['swarm_managers'][0]
- name: Get join-token for manager nodes
set_fact:
join_token_manager: "{{ hostvars[groups['swarm_managers'][0]].result.swarm_facts.JoinTokens.Manager }}"
- name: Get join-token for worker nodes
set_fact:
join_token_worker: "{{ hostvars[groups['swarm_managers'][0]].result.swarm_facts.JoinTokens.Worker }}"
- name: Join other managers
community.general.docker_swarm:
state: join
join_token: "{{ join_token_manager }}"
advertise_addr: "{{ ansible_host }}"
remote_addrs: "{{ hostvars[groups['swarm_managers'][0]].ansible_host }}"
when:
- inventory_hostname in groups['swarm_managers']
- inventory_hostname != groups['swarm_managers'][0]
- name: Join workers
community.general.docker_swarm:
state: join
join_token: "{{ join_token_worker }}"
advertise_addr: "{{ ansible_host }}"
remote_addrs: "{{ hostvars[groups['swarm_managers'][0]].ansible_host }}"
when:
- inventory_hostname not in groups['swarm_managers']
In swarm_managers group there are managers and all other hosts from this inventory are workers.
I think achempion was correct, the issue was that OPs variable rezult.swarm_facts.JoinTokens.Worker was not being evaluated, but rather provided as an object of sorts.
Replace rezult.swarm_facts.JoinTokens.Worker with "{{ rezult.swarm_facts.JoinTokens.Worker }}" and it should work.
I realise OP has probably already moved on but I have spent ages trying to figure out a very similar problem and this appeared to resolve it for me.
As I have not enough reputation to comment - here is an other mistake in your playbooks task. You use:
- name: Add nodes
docker_swarm:
state: join
advertise_addr: "{{ manager_ip }}"
join_token: rezult.swarm_facts.JoinTokens.Worker
remote_addrs: "{{ manager_ip }}:2377"
when: "ansible_default_ipv4.address != '{{ manager_ip }}'"
...which assigns the advertise_addr to the wrong ip address. This will still allow your nodes to join, but mess up their overlay network configuration (no node can ping each other, resulting in constant network failures). I would suggest to use the ssh connection ip instead:
- name: Add nodes
docker_swarm:
state: join
advertise_addr: "{{ ansible_ssh_host }}"
join_token: rezult.swarm_facts.JoinTokens.Worker
remote_addrs: "{{ manager_ip }}:2377"
when: "ansible_default_ipv4.address != '{{ manager_ip }}'"
Also just take a look into the documentation examples:
- name: Add nodes
community.docker.docker_swarm:
state: join
advertise_addr: 192.168.1.2
join_token: SWMTKN-1--xxxxx
remote_addrs: [ '192.168.1.1:2377' ]
...which also uses different ip addresses.
I have to admit: I also fall for it and it took several hours to solve. I hope someone else sees this answer before making the same mistake by just copying your snippet.
I think the issue here is from rezult.swarm_facts.JoinTokens.Worker. In debug info it appears as "msg": "SWMTKN-1-5p7..." but join_token: option from Ansible configuration expects it to be just plain token without additional wrappers as "msg": and so on.

is there a way to grep or parse an ansible variable

I have a variable which i need to parse to pull out a version string, is there a way to do this? Below is an example of the ansible variable.
--xxx 1.2.3-102 --yyy 2.5.10-47 --zzz 10.4.2-193
Update: Adding ansible task format
---
- hosts: localhost
tasks:
- name: Get Version
shell: echo '{{ version }}'
register: results
- set_fact:
value: "{{ results.stdout | regex_search(regexp,'') }}"
vars:
regexp: ''
- debug:
var: value
getting just the version number after "--yyy", alter the regular expression as needed for your task:
- hosts: localhost
tasks:
- name: Get Version
shell: echo '--xxx 1.2.3-102 --yyy 2.5.10-47 --zzz 10.4.2-193'
register: results
- name: set regex
set_fact:
re: '--yyy\s+(?P<digit>\d+\.\d+\.\d+-\d+)'
- set_fact:
value: "{{ results.stdout | regex_search(re, '\\g<digit>') }}"
- debug:
var: value[0]
|m-p solution works great for the latest version of ansible, unfortunately I have to use ansible pre 2.0 (1.9.6) which doesn't seem to support regex_search for some strange reason.
In that case I will use the following
"{{ results | regex_replace ('((xxx|yyy)\\s[\\S]+)|(--|zzz|\\s)','') | join }}"

Getting just volume id ansible

This has been answered before here on Stack.
ansible get aws ebs volume id which already exist
Get volume id from newly created ebs volume using ansible
For the life of me I am trying ec2_vol.volume_id and some other jmespath query bits but not getting the right output help. I just want the vol id. Nothing more.
---
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: get associated vols
ec2_vol:
instance: i-xxxxxxxxxxxxx
state: list
profile: default
region: us-east-1
register: ec2_vol
- debug:
msg: "{{ ec2_vol.volume_id }}"
also doesn't work
---
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: get associated vols
ec2_vol:
instance: i-xxxxxxxxxxxxxx
state: list
profile: default
region: us-east-1
register: ec2_vol
- debug: msg="{{ item.volume_id }}"
with_items: ec2_vol.results
Ansible 2.2 and 2.3 tested
Taking bits from the prior answer you will need to understand JMESPATH like filtering to get what you want out of the output.
Here is the answer
---
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: get associated vols
ec2_vol:
instance: i-xxxxxxxxxxxxxx
state: list
profile: default
region: us-east-1
register: ec2_vol
- debug: msg="{{ ec2_vol.volumes | map(attribute='id') | list }}"

Ansible docker_container etc_hosts with variable key

I've an ansible script through which I spawn a docker container and add few hosts entries to it, since etc_hosts takes key as host name and corresponding IP address. In my case I need to have both host name and IP address to be driven by some variable, for instance
docker_container:
name: image-name
image: image-to-be-pulled
state: started
restart_policy: always
etc_hosts:
"{{ domain_1 }}": "{{ domain_1_ip }}"
domain_2 : "{{ domain_2_ip }}"
domain_3 : "{{ domain_3_ip }}"
When I make above configuration then it makes an entry to host file as
xx.xx.xx.xxx {{ domain_1 }}
Ideally the the host file should contain host name against the IP, can someone suggest how can i achieve this. Thanks in advance
Try this syntax:
docker_container:
name: image-name
image: image-to-be-pulled
state: started
restart_policy: always
etc_hosts: >
{
"{{ domain_1 }}": "{{ domain_1_ip }}",
"domain_2" : "{{ domain_2_ip }}",
"domain_3" : "{{ domain_3_ip }}"
}
This will form dict-like string that ansible's templator will evaluate into dict.
Pay attention, that every item should be quoted and pairs are separated by commas.
I had success with...
in my play(book):
- vars:
my_etc_hosts:
{
"host1.example.com host1": 10.3.1.5,
"host2.example.com host2": 10.3.1.3
}
(no ">" character, compared to the accepted answer)
Separated from the playbook, the role with...
in the task:
- name: have the container created
docker_container:
etc_hosts: "{{ my_etc_hosts | default({}) }}"
in defaults/main.yml:
my_etc_hosts: {}
Additionally (not needed by the task above, but part of another template task):
in a template, with jinja2:
{% for host in my_etc_hosts | default([]) %}
--add-host "{{ host }}":{{ my_etc_hosts[host] }} \
{% endfor %}
(As a plus, you see how two hostnames for one IP address can be handled: "fqdn alias1". If you instead split them into two values, they will form two lines in /etc/hosts with the same IP, which is not correct according to the man page.)

Resources