Ansible and vault - ansible

I want to store my user's public keys in vault instead of a file.
How should i change my playbook:
name: push users public_keys
authorized_key:
state: present
user: admin
key: ""{{ lookup('file', '/path/to/your/www_id_rsa.pub') }}""
Thanks

One way could be storing your vault variables in a file or encrypt a string.
I'll show the use of file:
ansible-vault create vault_vars.yml (You'll be asked to create a password)
In the vault_vars.yml you create a normal variable containing the public_key: pub_key: "rsa..."
Include the file in your playbook:
vars_files:
- vault_vars.yml
You can access the variable from the vault just like you would with a variable being defined inside the playbook: {{ pub_key }}
An example printing the variable from the vault:
- hosts: server
vars_files:
- vault_vars.yml
tasks:
- debug: msg="{{pub_key}}"
Running playbook: ansible-playbook playbook.yml --ask-vault-pass
You can either use --ask-vault-pass (being prompted for password) or --vault-password-file (storing your vault password in a file)
EDIT
After reading the question again, and you stated you did not want to use a file meaning the solution would be as suggested below: Encrypt the string.
Personally I am not a big fan of encrypting strings and then put them directly in the playbook. I prefer to encrypt the file instead, making it easier to add/change values if needed.

I don't really get the point of encrypting a public key. You usually want to do this for private keys (or any other kind of sensitive data like passwords, tokens...).
Meanwhile, if you really want to do that, you don't need to change anything to your playbook. You just have to encrypt the file containing your public key:
ansible-vault encrypt --ask-vault-pass /path/to/your/www_id_rsa.pub
Once this is done, ansible will automagically detect this is a vault encryted file when you try to use it and it will decrypt it on the fly. For this to work, you will of course have to provide the same vault password when you execute the playbook (or you will get an error saying that the vault could not be decrypted).
ansible-playbook -i my_inventory --ask-vault-pass my_playbook.yml
For more info on different options to provide the vault pass/id see: https://docs.ansible.com/ansible/latest/user_guide/vault.html

Related

Using credentials securely in ansible inventory

In order to connect to a windows host I will need to pass the credentials in an inventory file. Here's my inventory file:
[windows]
100.100.100.100
[windows:vars]
ansible_user=Adminuser
ansible_password="Mypassword"
ansible_port=5986
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
Ansible documentation says that the credentials should be encrypted with ansible-vault. Can I use a variable file that's been encrypted using ansible-vault in my inventory file? And if so, how do I pass my ansible-vault credentials to my inventory file? I will also be using credentials in my playbook like this:
- hosts: windows
gather_facts: no
vars_files:
- vars.yml
tasks:
- win_domain_membership:
dns_domain_name: my.domain.com
hostname: ansible-host
domain_admin_user: {{ admin_user }}
domain_admin_password: {{ passwd }}
domain_ou_path: "OU=Windows,OU=Servers,DC=ansible,DC=com"
state: domain
register: domain_state
I will then use ansible-vault to encrypt my variable file for this playbook.
---
admin_user:myusername#my.domain.com
passwd:mypassword
And then pass my ansible-vault credentials to my playbook at the command line:
$ ansible-playbook myplaybook.yml --ask-vault-pass
Is it possible to store both the variable file used in my inventory and the variable file used in my playbook in the same ansible-vault? That way I can pass the ansible-vault credentials for both files at the command line?
The ansible-vault command encrypts a single file. Ansible decrypts this at runtime and interprets it the same way it would if the file had been unencrypted (so you can't "store both the variable file used in my inventory and the variable file used in my playbook in the same ansible-vault" because those are two different files).
I would just remove the variable from your inventory, leaving it like this:
[windows]
100.100.100.100
And then create group_vars/windows.yml as a vaulted file with the following content (ansible-vault create groups_vars/windows.yml):
ansible_user: Adminuser
ansible_password: "Mypassword"
ansible_port: 5986
ansible_connection: winrm
ansible_winrm_server_cert_validation: ignore
Ansible will automatically apply the variables in group_vars/windows.yml when you have a play that targets the windows group.

Use ansible to create a vault file and write output to it

I want to create user accounts with corresponding passwords all in a single playbook. To do this I define the users I need for my project and want to generate passwords for them. The attached script creates a password per user and assigns it to the r variable. This all works fine, I can call the items with their passwords. However I would like to save the usernames and passwords into a vault file that is encrypted all from within the playbook. But I can't figure out a way to do this.
Currently I write the output to the userfile.txt (output is a single line of .json, would like to have it in a nicer format) but then I would have to run an extra ansible-vault encrypt command. Is there a way to do this all from within a single playbook?
vars:
users:
- testuser1
- testuser2
tasks:
- name: Generate passwords
script: generate_passwords.py "{{item}}"
register: "r"
args:
executable: python3
with_items: "{{ users }}"
# The following proves that I can call the username and password:
- debug: msg="username={{item.item}}, password={{item.stdout_lines[0]}}"
with_items: "{{r.results}}"
# This saves everything in cleartext, how to do this into a vault file?
- copy:
content: "{{r}}"
dest: userfile.txt

Run ansible-vault encrypt_string in ansible playbook

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.

Ansible - dynamically prompt vault password when needed

Context
In my company, we have a shared repository containing our ansible script for our servers. I would like to introduce vault variables to handle services password in the near future. For now, we use encrypted password prompts at the beginning of our playbooks. This solution is annoying (it asked for 3 passwords on some playbooks).
Need
As most of our ansible users are no experts, I would like them to be able to run playbooks smoothly. It means ansible-playbook commands should be short and work without any mandatory parameters (e.g. no --ask-sudo-pass and whatnot). It also means I prefer prompting for vault password at the beginning of a playbook only when it’s needed.
Moreover, I do not want to use ansible password file, because it is not easily shareable and I don’t like the idea of having a cleartext password file on all our ansible users computers.
Problem
Adding --ask-vault-pass for every concerned playbooks is not an option. Our ansible users will not understand why sometimes this parameter is needed and why sometimes it’s not. On the contrary, asking the vault password for every playbook is a burden, because we have a lot of playbooks and sudo password is already asked each time too.
I tried to achieve the following solution, using prompts and various options. Nothing seems to work. Documentation does not explain how to do this:
The best solution (according to me)
Let’s look at this main.yml file:
- import_tasks: foo.yml
tags: always
- import_tasks: bar.yml
tags: bar
# Only this tasks uses a vault encrypted variable
- import_tasks: baz.yml
tags: [baz, vault]
Now, there’s a playbook.yml, importing this main.yml file.
In a perfect world, I would like this to happen:
example1:
ansible-playbook -i prod playbook.yml
Vault password:
example2:
ansible-playbook -i prod playbook.yml --tags baz
Vault password:
example3:
ansible-playbook -i prod playbook.yml --tags foo
# it runs without asking for vault password, because no tasks needing vault
# password will be run
Question
How can I configure ansible to ask for vault password only when it is needed (meaning: every time a vault encrypted variable is encountered)? Is it even possible? If not, what workaround would be viable given my situation?
Thanks.
I found a workaround.
The idea is to always load all passwords (including sudo) from an ansible vault file, needing only the vault password for each playbook. It means all machines should have the same deployer user password. This is even simpler than before, because there’s a single master password (the vault password) to control them all.
This is how it’s done:
ansible.cfg:
[privilege_escalation]
become_ask_pass = False
become = True
[defaults]
ask_vault_pass = True
vars/vault/env:
_vault:
sudo: !vault |
$ANSIBLE_VAULT;1.1;AES256
BLAHBLAHBLAH
another_pass: !vault |
$ANSIBLE_VAULT;1.1;AES256
ANOTHERENCRYPTEDPASSWORD
And for each playbook:
# Playbook stuff
# [...]
vars:
ansible_become_pass: "{{ _vault.sudo }}"
vars_files:
# env var is set dynamically in inventory file, so I can have different password per env.
# If the file is not found, it loads an empty null file
- [ "vars/vault/{{ env }}", "vars/null"]
# [...] Loading other var files
Now, a simple ansible-playbook -i env/prod myPlayBook.yml will only ask for the vault password, no prompt for sudo or anything else. It’s consistent and easy to share (only the encrypted password file and the vault password must be shared).

Is it possible to have multi password with vault

I have a deployment project that I share with other teams. I have encrypted my secrets with vault.
I would like to encrypt the production file with a password and a staging file with an other password to avoid other teams having access to production secrets.
Is it possible to do that ?
I have done something like that. My secrets :
cat /group_vars/all/vault_production.yml (encrypt with password A)
production_password: 'test1'
cat/group_vars/all/vault_staging.yml (encrypt with password B)
staging_password: 'test2'
My environments :
cat hosts-production
[all:vars]
env_type=production
cat hosts-staging
[all:vars]
env_type=staging
My script :
- copy:
content: |
env PASS={{hostvars[inventory_hostname][env_type + '_password']}}
...
And I launch the playbook like that.
# for production
ansible-playbook -i hosts-staging test.yml --vault-password-file .password_a
# for staging
ansible-playbook -i hosts-staging test.yml --vault-password-file .password_b
But that doesn't work because there is 2 differents passwords (ERROR! Decryption failed).
Do you know how to do that ?
Thanks.
BR,
Eric
Multiple vault passwords are supported since Ansible 2.4:
ansible-playbook --vault-id dev#dev-password --vault-id prod#prompt site.yml
If multiple vault passwords are provided, by default Ansible will attempt to decrypt vault content by trying each vault secret in the order they were provided on the command line.
In the above case, the ‘dev’ password will be tried first, then the ‘prod’ password for cases where Ansible doesn’t know which vault id is used to encrypt something.
Sorry, only one vault password allowed per run today. Best way to work around this in the case where you really only need one or the other is to dynamically load a vaulted file based on a var; eg:
- hosts: localhost
vars_files:
- secretstuff-{{ env_type }}.yml
tasks:
...
or
- hosts: localhost
tasks:
- include_vars: secretstuff-{{ env_type }}.yml
...
depending on if you need the vars to survive for one play or the entire run (the latter will bring them in as facts instead of play vars).

Resources