The ansible-vault command provided by Ansible normally runs inside a vi window. This makes it easy for users to edit a single file. However, what happens when a user wants to change multiple files the same way at once. Well, the vi editor makes this extremely difficult. You normally can’t put ansible-vault edits in a loop. But we have a solution for it now using “ed”…
Ansible is a configuration management tool that lets system administrators manage hundreds or thousands of boxes more efficiently. It looks like code and that “code” is often stored in a company’s version control system. There are times where Ansible might need to deploy a password or other sensitive information to a file. But it is a security risk to put that information in version control for the rest of the company to see. Ansible has a vault feature that will encrypt passwords and sensitive information so that it can be safely kept in version control. However, by default the editor used makes it hard to edit multiple files at the same time.
Lets say a user wanted to make the same change to 4 files:
for i in a b c d; do ansible-vault create $i; done
The normal vi editor would require the user to hand edit the files the same way every time. 4 files, not a big deal. But what if there are dozens or hundreds? That is inefficient and slow. The ansible-vault command doesn’t have a way to accept standard input so we can’t just write out the same thing to the files.
But luckily, there is a way to make this easy:
for i in ~/*pem; do h=$(echo $i | cut -d/ -f4 | cut -d. -f1); ( echo -e "i\n---\nssl_server_cert: |" ; cat $i | sed 's/^/ /' | tr -d '\r'; echo -e '.\nw\nq'; ) | EDITOR=ed ansible-vault create $h/vault; done
In the above command I was able to create vault files containing private SSL keys for dozens of hosts without user intervention saving me a lot of cut and pasting. The trick is to change the editor that the ansible-vault command uses from the vi default to “ed”.
What is ed? Most people have never heard of it. We’ve used sed to make changes to files from the command line. ed is its older cousin. Instead of putting the changes as a command line argument it takes the input from the standard input. So, to break that command down:
- The EDITOR=ed bit tells ansible-vault to use ed as the editor for the command. It is passed in as an environment variable
- The ‘( … ) |’ part says to create a subshell of all the commands within the parens and pass the std out as one output into the ansible-vault command. All we care about here is that it executes all the commands and takes the output as one stream since a command can only have one standard input.
- The stuff in those parens output commands to ed and the contents of the file.
- The first echo starts with an i which tells ed to insert the text that comes next
- The last echo outputs the command sequence that tells ed to stop inserting text (the dot), save the file (the w), and quit (the q).
- The ed manual has more info on the ed command and what it can do.
In theory the same solution will work with editing and existing file. Just tell ed to move to the line you want to change and insert or change from there. You can even make sed type changes.