Can i lookup an environment variable for netbox inventory plugin - ansible

I've been using the netbox dynamic inventory plugin a lot recently, but want to make it a bit more consumable for my other team members. The config for the plugin looks like:
plugin: netbox
api_endpoint: http://our-netbox-server.com
validate_certs: False
config_context: False
token: abc123
group_by:
- device_roles
query_filters:
- role: tor-switch
- role: something
- role: something_else
I was hoping i could lookup the token section from my environment variables, so something like:
token: "{{ lookup('env', 'NETBOX_TOKEN') }}"
however this doesn't work at all. Anyone got any suggestions around how i can make this happen?

Use the community inventory plugin from https://github.com/netbox-community/ansible_modules. This already supports the environment variables. So the token and API endpoint does not need to be stored in the configuration.
api_endpoint:
description: Endpoint of the NetBox API
required: True
env:
- name: NETBOX_API
token:
required: False
description:
- NetBox API token to be able to read against NetBox.
- This may not be required depending on the NetBox setup.
env:
# in order of precedence
- name: NETBOX_TOKEN
- name: NETBOX_API_KEY

Related

Is there a way to create different repository based on a condition in the same task in Ansible playbook?

I am trying to shorten the number of tasks I have in my playbook. I am creating a yum repository on Linux hosts and adding a different baseurl depending on the OS version.
It looks like this:
vars:
my_version: "{{ hostvars[inventory_hostname].ansible_distribution | int }}"
- name: create mcrepo yum repo
yum_repository:
name: mcrepo
description: mcrepo
baseurl: "{{ yum_repo_url }}"
gpgcheck: no
enabled: yes
sslverify: no
when: my_version is version('8.0', operator='lt')
- name: create mcrepo yum repo
yum_repository:
name: mcrepo
description: mcrepo
baseurl: "{{ yum_repo_url_8 }}"
gpgcheck: no
enabled: yes
sslverify: no
when: my_version is version('8.0', operator='ge')
Is there a way to combine these two tasks into just one so one of them doesn't always get skipped? On the linux hosts I have ansible 2.9 or 2.10.
I couldn't find a way to implement a case statement or something similar.
You could use an inline if in order to get the right variable containing the yum repository URL:
baseurl: >-
{{
yum_repo_url
if my_version is version('8.0', operator='lt')
else yum_repo_url_8
}}

How is this way of writing ansible task named? Is it deprecated?

I have an old ansible repository that I forked some time ago (2 years+) where I had not much idea about ansible. There are a lot of tasks written in a form that I don't know if it is correct or if it is deprecated. They use the action: section of the task, and then they write what looks like standard ansible actions (in fact, ansible-link complains that I should use FQN for built in actions on those).
I tried searching but all the results that I find are not relevant, so I am asking here how is this module action usually referred to, and should I change it to plain yaml?
- name: Disallow password authentication
action: lineinfile dest=/etc/ssh/sshd_config regexp="^PasswordAuthentication" line="PasswordAuthentication no" state=present
notify: restart ssh
Q: "Should I change it to plain YAML?"
A: Yes. The YAML format is the best practice
- name: Disallow password authentication
lineinfile:
dest: /etc/ssh/sshd_config
regexp: "^PasswordAuthentication"
line: "PasswordAuthentication no"
state: present
notify: restart ssh
To see details and examples about lineinfile run
shell> ansible-doc -t module lineinfile
Regarding your question
How is this module action usually referred to
you may have a look into Playbook Keywords
"For example, action in task can be substituted by the name of any Ansible module."
"The ‘action’ to execute for a task, it normally translates into a C(module) or action plugin.".
Regarding your question
Is it deprecated?
Since it is referenced in the actual documenation without a note it seems to be not.
Regarding your question
There are a lot of tasks written in a form that I don't know if it is correct
Since it is referenced in the actual documenation without a note it seems to be correct syntax.
Therefore it is possible to write tasks like
- name: Gather stored entitlement from repository service
action:
module: uri
url: "https://{{ REPOSITORY_URL }}/api/system/security/certificates"
method: GET
url_username: "{{ ansible_user }}"
url_password: "{{ ansible_password }}"
validate_certs: yes
return_content: yes
status_code: 200
body_format: json
check_mode: false
register: result
- name: Show result
debug:
msg: "{{ result.json }}"
check_mode: false
which in example gather installed certificates from a JFrog Artifactory repository service via REST API call, as well
- name: Gather stored entitlement from repository service
local_action:
module: uri
...
local_action
Same as action but also implies delegate_to: localhost
for Controlling where tasks run: delegation and local actions.
Nevertheless, the YAML format is the best practice. Therefore you should change it to plain YAML if possible.

ansible: customize which password manager to use

New to Ansible here. I've been adapting an Ansible playbook to automate the setup of a Raspberry Pi to use Pi-hole as described on this blog and as per this repo.
One change I've made is to use Bitwarden instead of 1Password as the secrets manager (see details below).
But after having done it, and thinking of offering a PR to the repo in question, I realized that my use of Bitwarden is just as hard-coded as the use of 1Password in the original (hardly an improvement).
Is there a way to make the choice of secret manager configurable in an Ansible playbook or setup? Or "call a different function" based on the value of a variable?
A desirable setup would be something along the lines of:
vars:
secret_manager: bitwarden
# one of {'1password', 'bitwarden', 'lastpass', 'ansible-vault',
# 'aws-secrets', 'azure-key-vault', ...}
tasks:
- name: ...
...
value: "{{ lookup(secret_manager, item_name, field=field_name) }}"
Details
Here is an example of using bitwarden instead of 1password in a playbook.yml:
New:
roles:
- role: ansible-modules-bitwarden
tasks:
- name: "test: get 'username' from the secrets manager"
debug:
- msg: "{{ lookup('bitwarden', 'pi-hole', field='username') }}"
(and note: if the field is a custom one, one must add custom_field=true whereas with
community.general.onepassword this is not needed).
Instead of:
tasks:
- name: "test: get 'username' from the secrets manager"
debug:
- msg: "{{ lookup('community.general.onepassword', 'pi-hole', field='username') }}"
Side note and for sake of completeness, in order to make this work I needed to install Bitwarden CLI as well as (one of) the ansible-modules-bitwarden, and then of course log in and get a session token:
export BW_SESSION="$(bw unlock --raw)"
This all works fine, but I am not quite happy: now the use of Bitwarden is hard-coded instead of "1Password". I would like to make this more generic and customizable. What if someone would like to use LastPass or AWS Secrets Manager instead?
Things I've tried
using if-else:
- hosts: all
vars:
use_bitwarden: true
secret_item: pi-hole
roles:
- role: ansible-modules-bitwarden
when: use_bitwarden
tasks:
- name: get username from the secrets manager
debug:
msg: "{{ lookup('bitwarden', secret_item, field='username') if use_bitwarden \
else lookup('community.general.onepassword', secret_item, field='username') }}"
but this bloats the playbook, makes it less readable and less DRY. Also, it isn't very extensible to the many other secrets managers out there.
define which manager to use in a variable:
- hosts: all
vars:
secret_manager: bitwarden
# secret_manager: community.general.onepassword
secret_item: pi-hole
roles:
- role: ansible-modules-bitwarden
when: secret_manager == 'bitwarden'
tasks:
- name: get username from the secrets manager
debug:
msg: "{{ lookup(secret_manager, secret_item, field='username') }}"
but this doesn't work as custom fields are to be queried with custom_field=true with the Bitwarden plugin, but not with 1Password.
Other ideas (not tried)
define a new generic plugin that uses other existing ones, based on a config variable.
use a task to get all the needed variables from whatever password manager at once and insert them, encrypted, into Ansible's vault. That way the task that does that can be isolated and have conditional execution with when: secret_manager == 'that'. But it makes maintenance of the playbook more difficult.
Maybe there is a much simpler and concise way of accomplishing this?

How create users per enviroment using ansible Inventory and module "htpasswd"

I'm newbie in ansible. I wrote ansible role for creating user and password in "/etc/httpd/.htpasswd" like that:
- name: htpasswd
htpasswd:
path: /etc/httpd/.htpasswd
name: dev
password: dev
group: apache
mode: 0640
become: true
Now, I'm trying to understand, how I can set user and password placeholder variable per environment for this model using inventory(or any other way). Like, if I ran "ansible playbook -i inventories/dev" so in role of this model could be set:
- name: htpasswd
htpasswd:
path: /etc/httpd/.htpasswd
name: "{{ inventory.htpasswd.name }}"
password: "{{ inventory.htpasswd.password }}"
group: apache
mode: 0640
become: true
And in inventory folder per environment will be file "htpasswd" with name and password content like that:
name: dev
password: dev
Does Ansible have something like that? Or can someone explain me what best practices?
By default, each host is assigned to a all group by Ansible. With the following structure you can define group vars based on inventory.
inventories/dev/hosts
inventories/dev/group_vars/all.yml
inventories/staging/hosts
inventories/staging/group_vars/all.yml
In inventories/dev/group_vars/all.yml:
name: dev
password: dev
In inventories/staging/group_vars/all.yml:
name: staging
password: staging
And then in your tasks, reference the vars with their names:
- name: htpasswd
htpasswd:
path: /etc/httpd/.htpasswd
name: "{{ name }}"
password: "{{ password }}"
group: apache
mode: 0640
become: true

Can I use custom variables when conditionally calling an Ansible role?

As per ansible documentation here I am using the below syntax to trigger a role when the variable "mdb_user" starts with prod.
- hosts: category_workstation
gather_facts: False
name: common workstation applications
roles:
- apps_workstation
- { role: apps_workstation_production, when: mdb_user.startswith('prod') }
This works nicely but what i want to know is if i can do something similar to adjust the variables fed to the role in different conditions. For instance the below:
- hosts : category_workstation
name: common workstation applications
roles:
- apps_workstation
- { role: apps_workstation_production, vars={'user':'prod'}, when: mdb_user.startswith('prod')}
Currently I am having to use when and set_fact to get the right variables setup before caling a roles and this approach above (if possible) seems more concise.
You can try something like:
- hosts : category_workstation
name: common workstation applications
roles:
- apps_workstation
- { role: apps_workstation_production, user: prod, when: mdb_user.startswith('prod')}

Resources