2

Update: As @yaobin pointed out. It appears they removed the part about the multiple passwords being in a single file. It was here as can be seen from web archive:
https://web.archive.org/web/20201202040251/https://docs.ansible.com/ansible/latest/user_guide/vault.html
But now it is gone:
https://web.archive.org/web/20210128225633/https://docs.ansible.com/ansible/latest/user_guide/vault.html
So I am not sure if this problem can be solved anymore the way that was described in the manual at the time. It was apparently a manual bug :(


The manual says at storing passwords in files section:

To store a vault password in a file, enter the password as a string on a single line in the file. Make sure the permissions on the file are appropriate. Do not add password files to source control. If you have multiple passwords, you can store them all in a single file, as long as they all have vault IDs. For each password, create a separate line and enter the vault ID, a space, then the password as a string. For example:

and there is an example:

dev my_dev_pass
test my_test_pass
prod my_prod_pass

However there is no usage exampes for this file. I tried many different ways. If I use --vault-password-file the ansible-vault sees only default entry independent of the number of entries in file. With --encrypt-vault-id=test I get:

ERROR! Did not find a match for --encrypt-vault-id=test in the known vault-ids ['default']

If I use --vault-id abc@file_path with --encrypt-vault-id=test then I get error

ERROR! Did not find a match for --encrypt-vault-id=test in the known vault-ids ['abc']

What is the purpose of the password file described in the Ansible manual and how does one use it?

Thanks!

1
  • 1
    Do you mind adding the link to the quoted documentation? It looks like you quoted from this section which says "To store a vault password in a file, ... Do not add password files to source control." But I can't find the words of "If you have multiple passwords, you can store them all in a single file..." Were you using a different version of Ansible? (Or maybe they updated the page so your quoted words no longer exist.)
    – yaobin
    Feb 8 at 22:21
3

This afternoon I also struggled on this. I think I've understood it a little bit more so I'd like to share it. But I'm also new to Ansible Vault so what I say here may not be completely correct. I used [1] as my main source of learning.

What May Have Confused You

[1] says a vault ID has the pattern label@source. But the symbol @ delivers the meaning of "inside", "at", or "of" which makes people think a vault ID test@password_file means a line inside the file password_file with the label test.

But this is the gotcha: according to my test, the entire content in password_file is used as the password. In your example above, the password you think is "my_test_pass"; but the password Ansible Vault sees is dev my_dev_pass\ntest my_test_pass\nprod my_prod_pass (note the white spaces and the End-of-Lines).

Therefore, test@file_path does not select the line "my_test_pass". It actually means the following:

  • At encryption, it means "use the entire content in file_path as the password to encrypt the given message and marks the result with the label test".
  • At decryption, it means "use the entire content in file_path as the password to decrypt everything that is marked with the label test".

Using Multiple Password Files

Therefore, if you want to use different password files, you need to do it this way:

  • Create three files (I put them at different folders intentionally for demo): ~/pass_dev.txt, /tmp/pass_test.txt, ./pass_prod.txt.
  • Put the passwords into the correct files. Example: my_dev_pass into pass_dev.txt.
  • When you encrypt the file my_dev_file.yml, you have two options:
    • You can specify just one vault ID: ansible-vault encrypt --vault-id dev@~/pass_dev.txt my_dev_file.yml
    • You can specify multiple vault IDs but must also use --encrypt-valut-id to tell ansible-vault which one should actually be used to encrypt the file: ansible-vault encrypt --vault-id dev@~/pass_dev.txt test@/tmp/pass_test.txt prod@./pass_prod.txt --encrypt-vault-id dev my_dev_file.yml

When you need to decrypt some content, you may or may not know what password the content was encrypted with. In this case, you can pass in all the possible vault IDs: ansible-vault decrypt dev@~/pass_dev.txt test@/tmp/pass_test.txt prod@./pass_prod.txt some_encrypted_file.yml. And vault will automatically figure out which password to use. This is talked about in this section of [1].

This also explains why the label part is only used as a hint. In fact, you can pass in the vault IDs with completely wrong labels:

ansible-vault decrypt prod@~/pass_dev.txt dev@/tmp/pass_test.txt test@./pass_prod.txt some_encrypted_file.yml

And ansible-vault is still able to decrypt the file, because, essentially, ansible-vault uses the label as the hint to see which password should be tried first. If it doesn't succeed, it tries the other passwords.

But if you define the environment variable ANSIBLE_VAULT_ID_MATCH, ansible-vault will take the labels seriously and only try the passwords with matching labels, so the following will fail:

ANSIBLE_VAULT_ID_MATCH=1 ansible-vault decrypt prod@~/pass_dev.txt dev@/tmp/pass_test.txt test@./pass_prod.txt some_encrypted_file.yml

Other Things in Your Question

I may not be completely correct in this part: I guess ansible-vault maintains an internal list of "currently available vault IDs". If no --vault-id is present on the command line, the only available vault ID is default. When --vault-id arguments are given, the default is overridden by whatever is provided.

Therefore, when you encrypted the target file using a --vault-password-file, without any other --vault-id, the only available vault ID was default. But by providing --encrypt-vault-id=test you were asking ansible-vault to encrypt the target file using a vault ID of "test" which was not available, hence the error "Did not find a match".

Later, when you provided ansible-vault with only --vault-id abc@file_path but asked it to encrypt the target file using test, ansible-vault still couldn't find the required vault ID, hence the error "Did not find a match" again.

You made the mistake because you thought test@file_path selects one password from all the available passwords in file_path, so by providing one password file, you thought you had provided multiple passwords. But that doesn't seem to be how ansible-vault works. You need to provide multiple password files (or, technically, multiple password sources which could also be prompts and scripts).

References

1
  • 1
    Your answer is very detailed. Thanks. But the question was about how to store multiple passwords in a single file. As you pointed out, now Ansible team silently removed this text from the manual. So the correct answer is simply "this is not possible because it was a bug in the manual". Having multiple files could be fine also but I don't get why one can't give a folder to ansible and ansible reads the file names as vault IDs. They could improve that.
    – yurtesen
    Feb 9 at 7:30
2

I totally misunderstood you. Here is a new attempt to actually answer your question. :)

  1. Create a passwords file:
root@2ca77340d571:/# cat .passvaults
dev my_dev_pass
test my_test_pass
prod my_prod_pas
  1. Create a file to encrypt:
root@2ca77340d571:/# cat extravaulty.yml
chocolate:banana
  1. Encrypt the file:
root@2ca77340d571:/# ansible-vault encrypt --vault-id=dev@.passvaults extravaulty.yml
Encryption successful
  1. View the raw file:
root@2ca77340d571:/# cat extravaulty.yml
$ANSIBLE_VAULT;1.2;AES256;dev
33336336336238326137393764316333623231336238323931306166626434653164326330656566
3561356333343435663538623661363661373461356461300a663361666331323031623530343930
62633230636566643339663637386438336539383162346634393031633165333033396238363163
6134383233346538330a326266626261346638303738313862656337396237343231326231656139
34376334663664343164303462356431306539316232323761386164643735376330

and the decrypted file:

root@2ca77340d571:/# ansible-vault view --vault-id=dev@.passvaults extravaulty.yml
chocolate:banana

As I understand it, when you use --vault-id=dev@.passvaults you are telling it to use dev as a hint (not the vault password) and .passvaults as the file where the encrypt/decrypt password is.

This means that you can also do this:

root@2ca77340d571:/# ansible-vault view --vault-id=prod@.passvaults extravaulty.yml
chocolate:banana

Or this

root@2ca77340d571:/# ansible-vault view --vault-id=.passvaults extravaulty.yml
chocolate:banana

Which is not intuitive to me. Does this help?

2
  • Nice try... But if you encrypt using ansible-vault encrypt --vault-id=test@.passvaults extravaulty.yml you can still decrypt it using ansible-vault view --vault-id=prod@.passvaults extravaulty.yml. On top of that, you can even encrypt using a non-existent vault id ansible-vault encrypt --vault-id=blah@.passvaults extravaulty.yml. It seems to me that it use the .passvaults file as a whole, because any character change in any vault id line cause decryption problem. So, next time you may want to test your solution :)
    – yurtesen
    Dec 7 '20 at 19:57
  • Hi. I did test the solution and this is what I said above: As I understand it, when you use --vault-id=dev@.passvaults you are telling it to use dev as a hint (not the vault password) and .passvaults as the file where the encrypt/decrypt password is.. I think that the first part of the @ bit is a hint and not the vault id necessarily. Dec 9 '20 at 11:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.