Closed eulenleber closed 1 year ago
Files identified in the description:
plugins/lookup/bitwarden.py
plugins/lookup/cartesian.py
plugins/lookup/chef_databag.py
plugins/lookup/collection_version.py
plugins/lookup/consul_kv.py
plugins/lookup/credstash.py
plugins/lookup/cyberarkpassword.py
plugins/lookup/dependent.py
plugins/lookup/dig.py
plugins/lookup/dnstxt.py
plugins/lookup/dsv.py
plugins/lookup/etcd.py
plugins/lookup/etcd3.py
plugins/lookup/filetree.py
plugins/lookup/flattened.py
plugins/lookup/hiera.py
plugins/lookup/keyring.py
plugins/lookup/lastpass.py
plugins/lookup/lmdb_kv.py
plugins/lookup/manifold.py
plugins/lookup/onepassword.py
plugins/lookup/onepassword_raw.py
plugins/lookup/passwordstore.py
plugins/lookup/random_pet.py
plugins/lookup/random_string.py
plugins/lookup/random_words.py
plugins/lookup/redis.py
plugins/lookup/revbitspss.py
plugins/lookup/shelvefile.py
plugins/lookup/tss.py
tests/unit/plugins/lookup/onepassword_common.py
tests/unit/plugins/lookup/onepassword_conftest.py
tests/unit/plugins/lookup/onepassword_fixtures/v1_out_01.json.license
tests/unit/plugins/lookup/onepassword_fixtures/v1_out_02.json.license
tests/unit/plugins/lookup/onepassword_fixtures/v1_out_03.json.license
tests/unit/plugins/lookup/onepassword_fixtures/v2_out_01.json.license
tests/unit/plugins/lookup/onepassword_fixtures/v2_out_02.json.license
tests/unit/plugins/lookup/onepassword_fixtures/v2_out_03.json.license
tests/unit/plugins/lookup/test_bitwarden.py
tests/unit/plugins/lookup/test_dependent.py
tests/unit/plugins/lookup/test_dsv.py
tests/unit/plugins/lookup/test_etcd3.py
tests/unit/plugins/lookup/test_lastpass.py
tests/unit/plugins/lookup/test_manifold.py
tests/unit/plugins/lookup/test_onepassword.py
tests/unit/plugins/lookup/test_revbitspss.py
tests/unit/plugins/lookup/test_tss.py
If these files are incorrect, please update the component name
section of the description or use the !component
bot command.
cc @Akasurde @None @RevBits @azenk @dagwieers @delineaKrehl @eric-belhomme @felixfontein @galanoff @jparrill @jpmens @konstruktoid @lungj @samdoran @scottsb @tylerezimmerman click here for bot help
!component =plugins/lookup/passwordstore.py
CC @grembo
Files identified in the description:
If these files are incorrect, please update the component name
section of the description or use the !component
bot command.
locktimeout
is how long the script waits to obtain a lock when synchronizing operations. It does not control how long gpg-agent is waiting to get input. The comment in documentation about it being related to gpg-agent's timeouts is about locktimeout
ideally being longer than pinentry-timeout
. It's only relevant if more than one secret is required at the same time and actual synchronization needs to happen.
So the actual issue you're having is gpg not respecting the timeout you configured (for whatever reason).
In case you're actually having concurrent open requests, this could be caused by gpg-agent not having enough secure memory (which makes some requests fail automatically).
In this case, adding
auto-expand-secmem 32
to gpg-agent.conf helps.
I usually use pinentry-gtk - in case you can provide a minimum working example (simple play) to test with, I can try to reproduce locally.
I see, I suggest an improvement in documentation in that case.
Still, the passwordstore_lookup
behaves differently than plain shell - which is odd, as the pinentry-program
is respected.
pinentry-timeout
is neither respected if set to 3
in which case the pin entry should timeout after 3 seconds...
The timeout problem happens with pinentry-gtk as well
@grembo
I usually use pinentry-gtk - in case you can provide a minimum working example (simple play) to test with, I can try to reproduce locally.
cd /tmp
mkdir passwordstore gpg
chmod 700 gpg secrets
export GPG_TTY=$(tty)
export PASSWORD_STORE_DIR=$(realpath passwordstore)
export GNUPGHOME=$(realpath gpg)
cat>gpg/gpg-agent.conf <<EOF
pinentry-timeout 0
pinentry-program /usr/bin/pinentry-tty
EOF
gpg --full-gen-key --batch <<EOF
Key-Type: 1
Key-Length: 4096
Subkey-Type: 1
Subkey-Length: 4096
Name-Real: root
Name-Email: root@localhost
Expire-Date: 0
EOF
pass init root@localhost
# create password
ansible localhost -m debug -a "msg={{ lookup('passwordstore', 'passwordstore/test', missing='create') }}"
# ask for password
time ansible localhost -m debug -a "msg={{ lookup('passwordstore', 'passwordstore/test', missing='create') }}"
localhost | FAILED! => {
"msg": "An unhandled exception occurred while running the lookup plugin 'passwordstore'. Error was a <class 'ansible.errors.AnsibleError'>, original message: exit code 2 while running ['pass', 'show', 'passwordstore/test']. Error output: gpg: decryption failed: No secret key\n. exit code 2 while running ['pass', 'show', 'passwordstore/test']. Error output: gpg: decryption failed: No secret key\n "
}
ansible localhost -m debug -a 2.19s user 0.29s system 4% cpu 1:00.59 total
Interesting though that pinentry-timeout 5
will result in user 0.09s
Thanks for providing an example, I reduced the test to:
time gpg2 -d --use-agent /tmp/passwordstore/passwordstore/test.gpg
pinentry-timeout 0
results in the behavior you perceived (dies after 60 seconds).pinentry-timeout 5
(and killing gpg-agent) results in pinentry ending after 5 second.Testing with pass
directly (like you did in the bug description above) yields the same results though:
$ time pass show passwordstore/test
Please enter the passphrase to unlock the OpenPGP secret key:
"root <root@localhost>"
4096-bit RSA key, ID 6B97EC90F794BC6A,
created 2023-03-15 (main key ID 60A530606C118FFF).
Passphrase:
gpg: public key decryption failed: Timeout
gpg: decryption failed: Timeout
60.27 real 0.01 user 0.02 sys
So it's unclear why that test would have worked for you (as in: "no timeout was applied").
Part of the solution is found on the gpg-agent man page / in gnupg's documentation:
--pinentry-timeout n This option asks the Pinentry to timeout after n seconds with no user input. The default value of 0 does not ask the pinentry to timeout, however a Pinentry may use its own default timeout value in this case. A Pinentry may or may not honor this request.
So pinentry-timeout 0
doesn't mean "unlimited", but "use whatever that pinentry implementation's default setting is".
I checked gpg-agent sources to confirm that the SETTIMEOUT
command is only sent to pinentry in case pinentry_timeout != 0
: https://github.com/gpg/gnupg/blob/283ccbc824d8062b86e27818a84ab5a29facd7a5/agent/call-pinentry.c#L593-L603
Knowing this, I checked where the 60 seconds come from: https://github.com/gpg/pinentry/blob/6b697bd3e9f859cea338936894079241f2e15ffc/pinentry/pinentry.c#L182
So it seems like, basically all pinentry programs use a default timeout of 60 seconds.
Therefore the solution to your problem is specifying a long pinentry timeout in gpg-agent.conf (don't forget to restart gpg-agent afterwards), e.g.:
pinentry-timeout 3600
pinentry-program /usr/bin/pinentry-tty
(personally, I use 120 seconds).
Hope that helps.
you are right, I can not reproduce the infinite wait. I honestly dont know why I got that impression. Thanks very much for your analysis. And sorry for wasting your time.
Summary
does wait though
gpg-agent.conf
The config is respected, as pinentry-tty is used in favor of ncures
ansible.cfg
Here at least 30 minutes should pass before timing out...
Issue Type
Bug Report
Component Name
https://github.com/ansible-collections/community.general/blob/e8a7c27cab302565f4f0bc8e5522e63497f0be6e/plugins/lookup/passwordstore.py#L363
Ansible Version
Community.general Version
Configuration
weirdly no password_store section is shown
OS / Environment
archlinux
Steps to Reproduce
Expected Results
I expected that the timeout time is respected but it fails after approx 1 min
Actual Results
Code of Conduct