extract hashicorp vault secrets as values in ansible playbook - ansible

I am trying to extract specific value from kv2 hashicorp vault in ansible playbook using hashi_vault module
- name: Return specific value from vault
ansible.builtin.set_fact:
secret: "{{ lookup('hashi_vault', 'secret=my.secrets/data/dev/heslo:value token=vault-plaintext-root-token url=http://10.47.0.235:8200/')}}" register: secret
I am getting
{"msg": ""An unhandled exception occurred while running the lookup plugin 'hashi_vault'. Error was a <class 'ansible.errors.AnsibleError'>, original message: The secret my.secrets/data/dev/heslo doesn't seem to exist for hashi_vault lookup"}
Query works for all of the secrets in path using
secret=my.secrets/data/dev/
"heslo" record exists in the path
"ansible_facts": {
"secret": {
"data": {
"heslo": "heslo",
"password": "test",
"username": "ahoj"
},
Thank you in advance

The syntax for your lookup is for the KV1 engine. We can update it for the KV2 secrets engine:
- name: Return specific value from vault
ansible.builtin.set_fact:
secret: "{{ lookup('hashi_vault', 'secret=my.secrets/data/dev token=vault-plaintext-root-token url=http://10.47.0.235:8200/') }}"
The secret fact will then be a dictionary containing all of the key value pairs at the specified secrets path my.secrets/data/dev. You can access the value of the key heslo with the normal syntax secret['heslo'].
Finally, you may also want to update to the Vault collection for Ansible with all of its newer features.

Related

Why does get "key" false work in a Helm .yaml template

I have a kubernetes template yaml file that has the following
{{ when get "db" false }}
- name: DB_PASSWORD
value: {{ .password }}
- name: DB_USERNAME
value: {{ .username }}
{{ end }}
It gets the db, password, and username from a file that looks like
db:
password: "password"
username: "username"
I understand with is changing the scope and get is a method that has 2 parameters
the dictionary to read from
the key to get the value of
I'm totally new to GO and can't find anywhere in the documentation of Helm or Sprig to explain why using a key of false works to get the password and username. I'm guessing it has to do with how go parses the yaml and assigns a key value pair of "false": interface{}.
Can anyone point me to the right place or help me understand why this works?

Ansible - Passing a dictionary to a module parameter

I'm using fortinet.fortios.system_global module as describe here: https://docs.ansible.com/ansible/latest/collections/fortinet/fortios/fortios_system_global_module.html#ansible-collections-fortinet-fortios-fortios-system-global-module
My goal is to pass a dictionary to the system_global parameter with the allowed sub-parameters. I have the dictionary as follows for example:
forti:
admin-concurrent: enable
admin-console-timeout: 0
admin-hsts-max-age: 15552000
<more key:value>
This dictionary lives in a separate file called forti.yml.
I then use include_vars to pull this yml file into my play as follows:
vars_files:
- /path/to/forti.yml
And then I use the system_global module:
- name: Configure system_global task
fortios_system_global:
access: "{{ access_token }}"
system_global: "{{ forti }}"
However, when I run the play it throws an error like so:
"msg": "Unsupported parameters for (fortios_system_global) module: system_global.admin-concurrent, system_global.admin-console-timeout, system_global.admin-hsts-max-age,<and so on>. Supported parameters include: member_path, member_state, system_global, vdom, enable_log, access_token."
I tried putting the key:value pairs in the vars: in the play level and passed it to the module the same way and it worked.
vars:
forti:
admin-concurrent: enable
admin-console-timeout: 0
admin-hsts-max-age: 15552000
<more key: value>
What am I missing? They're both type: dict, the data are exactly the same. Not sure what I'm missing here. Can someone please help?
You have - and the parameters are supposed to be _ so it is telling you the module parameter does not exist
vars:
forti:
admin-concurrent: enable
admin-console-timeout: 0
admin-hsts-max-age: 15552000
<more key: value>
should be
vars:
forti:
admin_concurrent: enable
admin_console_timeout: 0
admin_hsts_max_age: 15552000
<more key: value>
Keep on automating!
Just look at module examples here: https://docs.ansible.com/ansible/latest/collections/fortinet/fortios/fortios_system_global_module.html#ansible-collections-fortinet-fortios-fortios-system-global-module

Ansible Fact - Parsing Ansible Fact Variable to Dictionary

I'm using Ansible
os_project_facts module to gather admin project id of OpenStack.
This is the ansible_fact log:
ansible_facts:
openstack_projects:
- description: Bootstrap project for initializing the cloud.
domain_id: default
enabled: true
id: <PROJECT_ID>
is_domain: false
is_enabled: true
location:
cloud: envvars
project:
domain_id: default
domain_name: null
id: default
name: null
region_name: null
zone: null
name: admin
options: {}
parent_id: default
properties:
options: {}
tags: []
tags: []
Apparently, this is not a dictionary, and I can't get openstack_projects.id since it is not a dictionary. How can I retrieve PROJECT_ID and use it in other tasks?
Since the openstack_projects facts contains single list element with a dictionary, we can use the array indexing method to get the id, i.e. openstack_projects[0]['id'].
You can use it directly, or use something like set_fact:
- name: get the project id
set_fact:
project_id: "{{ openstack_projects[0]['id'] }}"

Ansible deep merge hash array in vars

A want declare hash array in vars/main.yml or default/main.yml of some role, e.g.:
mysql:
instances:
new:
port: 3306
dir: /mydir
config:
innodb_log_file_size: '128M'
tmp_table_size: '128M'
innodb_buffer_pool_size: '10G'
...
And I want change only some values of keys in YAML inventory or group_vars. Other values must be taken from vars/main.yml of some role:
mysql:
instances:
new:
config:
innodb_buffer_pool_size: '2G'
I want result for used in jinja2 template:
mysql:
instances:
new:
port: 3306
dir: /mydir
config:
innodb_log_file_size: '128M'
tmp_table_size: '128M'
innodb_buffer_pool_size: '2G'
...
Question: "Want to change only some values of keys in YAML inventory or group_vars. Other values must be taken from vars/main.yml of some role".
1) Service role (nginx, mysql, pgsql ...). In this role, I describe the default settings, ...
2) Then I create a project role in which I can include the service role and I will use most of the default settings described in the service role. Only a small part of the service settings can be changed in the project role.
Answer:
In the "service" roles create in defaults special variables for parameters that might be changed later. For example
mysql_port: "3306"
mysql_dir: "mydir"
mysql_innodb_log_file_size: "128M"
mysql:
instances:
new:
port: "{{ mysql_port }}"
dir: "{{ mysql_dir }}"
config:
innodb_log_file_size: "{{ mysql_innodb_log_file_size }}"
...
In the "project" role any variable with higher precedence will override the role's defaults.

Ansible Dict and Tags

I have a playbook creating EC2 by using a dictionary declared in vars: then registering the IPs into a group to be used later on.
The dict looks like this:
servers:
serv1:
name: tag1
type: t2.small
region: us-west-1
image: ami-****
serv2:
name: tag2
type: t2.medium
region: us-east-1
image: ami-****
serv3:
[...]
I would like to apply tags to this playbook in the simplest way so I can create just some of them using tags. For example, running the playbook with --tags tag1,tag3 would only start EC2 matching serv1 and serv3.
Applying tags on the dictionary doesn't seem possible and I would like to avoid doing multiplying tasks like:
Creatinge EC2
Register infos
Getting private IP from previously registered infos
adding host to group
While I already have a working loop for the case I want to create all EC2 at once, is there any way to achieve that (without relying on --extra-vars, which would need key=value) ? For example, filtering out the dictionary by keeping only what is tagged before running the EC2 loop ?
I doubt you can do this out of the box. And not sure this is good idea at all.
Because tags are used to filter tasks in Ansible, so you will have to mark all tasks with tags: always.
You can accomplish this with custom filter plugin, for example (./filter_plugins/apply_tags.py):
try:
from __main__ import cli
except ImportError:
cli = False
def apply_tags(src):
if cli:
tags = cli.options.tags.split(',')
res = {}
for k,v in src.iteritems():
keep = True
if 'name' in v:
if v['name'] not in tags:
keep = False
if keep:
res[k] = v
return res
else:
return src
class FilterModule(object):
def filters(self):
return {
'apply_tags': apply_tags
}
And in your playbook:
- debug: msg="{{ servers | apply_tags }}"
tags: always
I found a way to match my needs without touching to the rest so I'm sharing it in case other might have a similar need.
I needed to combine dictionaries depending on tags, so my "main" dictionary wouldn't be static.
Variables became :
- serv1:
- name: tag1
type: t2.small
region: us-west-1
image: ami-****
- serv2:
- name: tag2
type: t2.medium
region: us-east-1
image: ami-****
- serv3:
[...]
So instead of duplicating my tasks, I used set_fact with tags like this:
- name: Combined dict
# Declaring empty dict
set_fact:
servers: []
tags: ['always']
- name: Add Server 1
set_fact:
servers: "{{ servers + serv1 }}"
tags: ['tag1']
- name: Add Server 2
set_fact:
servers: "{{ servers + serv2 }}"
tags: ['tag2']
[..]
20 lines instead of multiply tasks for each server, change vars from dictionary to lists, a few tags and all good :) Now if I add a new server it will only take a few lines.

Resources