Add support for setting executable name through environment variables,
thus allowing to use gopass or other pass-compatible alternatives. Make bitwarden support work without the need for prefixing queries and without requiring GPaste. Improve README, in particular to show how to configure behavior with env vars.
This commit is contained in:
parent
2acdad58c0
commit
42508b271f
90
README.md
90
README.md
@ -1,8 +1,16 @@
|
||||
A search provider for GNOME Shell that adds support for searching passwords in zx2c4/[pass](https://www.passwordstore.org/) or in the [rbw](https://github.com/doy/rbw) Bitwarden/Vaultwarden client.
|
||||
A search provider for GNOME Shell that adds support for searching in:
|
||||
|
||||
Names of passwords will show up in GNOME Shell searches, choosing one will copy the corresponding content to the clipboard.
|
||||
* zx2c4/[pass](https://www.passwordstore.org/)
|
||||
* compatible alternatives such as [gopass](https://www.gopass.pw/)
|
||||
* or the [rbw](https://github.com/doy/rbw) Bitwarden/Vaultwarden client
|
||||
|
||||
Can use the [GPaste](https://github.com/Keruspe/GPaste) clipboard manager, supports OTP and fields (pass only, requires GPaste).
|
||||
Names of entries will show up in GNOME Shell searches, choosing one will copy the corresponding content to the clipboard.
|
||||
|
||||
Supports:
|
||||
|
||||
* using the [GPaste](https://github.com/Keruspe/GPaste) clipboard manager
|
||||
* OTP with the [pass-otp](https://github.com/tadfisher/pass-otp) extension
|
||||
* fields (cf below for syntax)
|
||||
|
||||

|
||||
|
||||
@ -49,7 +57,13 @@ The search provider will be loaded automatically when doing a search.
|
||||
|
||||
You should see it enabled in GNOME Settings, in the Search pane. This is also where you can move it up or down in the list of results relatively to other search providers.
|
||||
|
||||
# Fields
|
||||
# Advanced usage
|
||||
|
||||
## OTP
|
||||
|
||||
The [pass-otp](https://github.com/tadfisher/pass-otp) extension is supported. Searches starting with `otp` will copy the otp token to the clipboard.
|
||||
|
||||
## Fields
|
||||
|
||||
To copy other values than the password in the first line from a pass file, start the search with `:NAME search...`. The field name must be a full but case insensitive match. This requires `GPaste`.
|
||||
|
||||
@ -62,38 +76,72 @@ pin: 123456
|
||||
|
||||
To copy the pin start the search with `:pin` and for the username with `:user`.
|
||||
|
||||
# OTP
|
||||
# Alternative password providers
|
||||
|
||||
The [pass-otp](https://github.com/tadfisher/pass-otp) extension is supported. Searches starting with `otp` will copy the otp token to the clipboard.
|
||||
## Gopass and other pass-compatible tools
|
||||
|
||||
# Bitwarden/Vaultwarden
|
||||
If you want to use [gopass](https://www.gopass.pw/) or another `pass` compatible tool instead of `pass`, you need to set the proper environment variables to point to the executable and password store directory to use.
|
||||
|
||||
If [rbw](https://github.com/doy/rbw) is installed, it can be used instead of pass by prefixing a search with `bw`. Non prefixed searches will still go through pass if present.
|
||||
For example, on a systemd-based OS, you can run `systemctl --user edit org.gnome.Pass.SearchProvider.service` and add in the file:
|
||||
|
||||
# Environment variables
|
||||
```
|
||||
[Service]
|
||||
Environment=PASSWORD_EXECUTABLE=gopass
|
||||
Environment=PASSWORD_STORE_DIR=/home/jonathan/.local/share/gopass/stores/root
|
||||
```
|
||||
(be careful not leave a trailing "/" at the end of the `PASSWORD_STORE_DIR` path)
|
||||
|
||||
Then save and restart the service with `systemctl --user restart org.gnome.Pass.SearchProvider.service`.
|
||||
|
||||
On other systems, you might want to use `~/.profile` or another mechanism to set these environment variables.
|
||||
|
||||
## Bitwarden/Vaultwarden
|
||||
|
||||
To search in Bitwarden/Vaultwarden instead of `pass`, you will need to setup [rbw](https://github.com/doy/rbw). You'll also need to install `wl-clipboard` or another clipboard utility (such as `xclip`), unless you use GPaste.
|
||||
|
||||
You need to set the proper environment variables to point to the executables and specify to operate in Bitwarden mode.
|
||||
|
||||
For example, on a systemd-based OS, you can run `systemctl --user edit org.gnome.Pass.SearchProvider.service` and add in the file:
|
||||
|
||||
```
|
||||
[Service]
|
||||
Environment=PASSWORD_EXECUTABLE=rbw
|
||||
Environment=PASSWORD_MODE=bw
|
||||
Environment=CLIPBOARD_EXECUTABLE=wl-copy
|
||||
```
|
||||
Then save and restart the service with `systemctl --user restart org.gnome.Pass.SearchProvider.service`.
|
||||
|
||||
On other systems, you might want to use `~/.profile` or another mechanism to set these environment variables.
|
||||
|
||||
# Clipboard managers
|
||||
|
||||
By default, passwords are sent to the clipboard using `pass -c`, which defaults to expiration after 45 seconds.
|
||||
|
||||
If [GPaste](https://github.com/Keruspe/GPaste) is installed, passwords be sent to it marked as passwords through its API, thus ensuring they are not visible in the UI.
|
||||
|
||||
# Compatibility
|
||||
|
||||
This implements the `org.gnome.Shell.SearchProvider2` D-Bus API and has been tested with GNOME Shell 3.22 to 42. This uses the `org.gnome.GPaste1` or `org.gnome.GPaste2` versions of the GPaste D-Bus API to add passwords to GPaste.
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
## Environment variables have no effect
|
||||
|
||||
If you are configuring `pass` through environment variables, such as `PASSWORD_STORE_DIR`, make sure to set them in a way that will propagate to the search provider executable, not just in your shell.
|
||||
|
||||
Setting them in `~/.profile` (or `~/.pam_environment` if supported by your OS) should be sufficient, but stuff in shell-specific files such as `~/.bashrc` will not be picked up by gnome-shell.
|
||||
Setting them in `~/.profile` should be sufficient, but keep in mind that stuff in shell-specific files such as `~/.bashrc` only affects the command-line shell and will not propagate to the script. On systemd-based OSes, you can also directly set them in `~/.config/environment.d/*.conf` (see `man environment.d`).
|
||||
|
||||
If your values have no effect, make sure they propagate to the script environment. You can check this with ps:
|
||||
If your values have no effect, make sure they propagate to the script environment. You can check this by displaying the process environment with `ps` and looking for your values here:
|
||||
```
|
||||
ps auxeww | grep [g]nome-pass-search-provider.py
|
||||
```
|
||||
|
||||
# Clipboard managers
|
||||
|
||||
If you are using GPaste, passwords will be sent to it marked as passwords, thus ensuring they are not visible.
|
||||
Otherwise they are sent to the clipboard using `pass -c` which defaults to expiration after 45 seconds.
|
||||
|
||||
# Compatibility
|
||||
|
||||
This implements the `org.gnome.Shell.SearchProvider2` D-Bus API and has been tested with GNOME Shell 3.22 to 40. This uses the `org.gnome.GPaste1` or `org.gnome.GPaste2` versions of the GPaste D-Bus API to add passwords to GPaste.
|
||||
|
||||
# Troubleshooting
|
||||
## Passphrase is not requested to unlock store
|
||||
|
||||
If you don't see passphrase prompts when your key is locked, it might be because GPG is not using the right pinentry program. You can force gpg-agent to use pinentry-gnome3 by adding `pinentry-program /usr/bin/pinentry-gnome3` to `~/.gnupg/gpg-agent.conf`.
|
||||
|
||||
## Other problems
|
||||
|
||||
If you encounter problems, make sure to look in the logs of GNOME and D-Bus. On systems that use systemd, you can do this using `journalctl --user`.
|
||||
|
||||
Don't hesitate to open an issue.
|
||||
|
@ -56,7 +56,6 @@ class SearchPassService(dbus.service.Object):
|
||||
|
||||
bus_name = "org.gnome.Pass.SearchProvider"
|
||||
_object_path = "/" + bus_name.replace(".", "/")
|
||||
use_bw = False
|
||||
|
||||
def __init__(self):
|
||||
self.session_bus = dbus.SessionBus()
|
||||
@ -65,6 +64,9 @@ class SearchPassService(dbus.service.Object):
|
||||
self.password_store = getenv("PASSWORD_STORE_DIR") or expanduser(
|
||||
"~/.password-store"
|
||||
)
|
||||
self.password_executable = getenv("PASSWORD_EXECUTABLE") or "pass"
|
||||
self.password_mode = getenv("PASSWORD_MODE") or "pass"
|
||||
self.clipboard_executable = getenv("CLIPBOARD_EXECUTABLE") or "wl-copy"
|
||||
|
||||
@dbus.service.method(in_signature="sasu", **sbn)
|
||||
def ActivateResult(self, id, terms, timestamp):
|
||||
@ -72,14 +74,10 @@ class SearchPassService(dbus.service.Object):
|
||||
|
||||
@dbus.service.method(in_signature="as", out_signature="as", **sbn)
|
||||
def GetInitialResultSet(self, terms):
|
||||
try:
|
||||
if terms[0] == "bw":
|
||||
self.use_bw = True
|
||||
return self.get_bw_result_set(terms)
|
||||
except NameError:
|
||||
pass
|
||||
self.use_bw = False
|
||||
return self.get_pass_result_set(terms)
|
||||
if self.password_mode == "bw":
|
||||
return self.get_bw_result_set(terms)
|
||||
else:
|
||||
return self.get_pass_result_set(terms)
|
||||
|
||||
@dbus.service.method(in_signature="as", out_signature="aa{sv}", **sbn)
|
||||
def GetResultMetas(self, ids):
|
||||
@ -94,7 +92,7 @@ class SearchPassService(dbus.service.Object):
|
||||
|
||||
@dbus.service.method(in_signature="asas", out_signature="as", **sbn)
|
||||
def GetSubsearchResultSet(self, previous_results, new_terms):
|
||||
if self.use_bw:
|
||||
if self.password_mode == "bw":
|
||||
return self.get_bw_result_set(new_terms)
|
||||
else:
|
||||
return self.get_pass_result_set(new_terms)
|
||||
@ -104,10 +102,10 @@ class SearchPassService(dbus.service.Object):
|
||||
pass
|
||||
|
||||
def get_bw_result_set(self, terms):
|
||||
name = "".join(terms[1:])
|
||||
name = "".join(terms)
|
||||
|
||||
password_list = subprocess.check_output(
|
||||
["rbw", "list"], universal_newlines=True
|
||||
[self.password_executable, "list"], universal_newlines=True
|
||||
).split("\n")[:-1]
|
||||
|
||||
results = [
|
||||
@ -158,12 +156,10 @@ class SearchPassService(dbus.service.Object):
|
||||
"org.gnome.GPaste.Daemon", "/org/gnome/GPaste"
|
||||
)
|
||||
|
||||
output = subprocess.check_output(
|
||||
base_args + [name], universal_newlines=True
|
||||
)
|
||||
output = subprocess.check_output(base_args + [name], universal_newlines=True)
|
||||
if field is not None:
|
||||
match = re.search(
|
||||
fr"^{field}:\s*(?P<value>.+?)$", output, flags=re.I | re.M
|
||||
rf"^{field}:\s*(?P<value>.+?)$", output, flags=re.I | re.M
|
||||
)
|
||||
if match:
|
||||
password = match.group("value")
|
||||
@ -177,24 +173,32 @@ class SearchPassService(dbus.service.Object):
|
||||
gpaste.AddPassword(name, password, dbus_interface="org.gnome.GPaste2")
|
||||
|
||||
def send_password_to_native_clipboard(self, base_args, name, field=None):
|
||||
if field is not None or self.use_bw:
|
||||
if field is not None:
|
||||
raise RuntimeError("This feature requires GPaste.")
|
||||
|
||||
result = subprocess.run(base_args + ["-c", name])
|
||||
if result.returncode:
|
||||
raise RuntimeError(
|
||||
f"Error while running pass: got return code {result.returncode}."
|
||||
)
|
||||
if self.password_mode == "bw":
|
||||
p1 = subprocess.Popen(base_args + [name], stdout=subprocess.PIPE)
|
||||
p2 = subprocess.run(self.clipboard_executable, stdin=p1.stdout)
|
||||
if p1.returncode or p2.returncode:
|
||||
raise RuntimeError(
|
||||
f"Error while running rbw: got return codes: {p1.returncode} {p2.returncode}."
|
||||
)
|
||||
else:
|
||||
result = subprocess.run(base_args + ["-c", name])
|
||||
if result.returncode:
|
||||
raise RuntimeError(
|
||||
f"Error while running pass: got return code: {result.returncode}."
|
||||
)
|
||||
|
||||
def send_password_to_clipboard(self, name):
|
||||
field = None
|
||||
if self.use_bw:
|
||||
base_args = ["rbw", "get"]
|
||||
if self.password_mode == "bw":
|
||||
base_args = [self.password_executable, "get"]
|
||||
elif name.startswith("otp "):
|
||||
base_args = ["pass", "otp", "code"]
|
||||
base_args = [self.password_executable, "otp", "code"]
|
||||
name = name[4:]
|
||||
else:
|
||||
base_args = ["pass", "show"]
|
||||
base_args = [self.password_executable, "show"]
|
||||
if name.startswith(":"):
|
||||
field, name = name.split(" ", 1)
|
||||
field = field[1:]
|
||||
|
@ -16,7 +16,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
%global debug_package %{nil}
|
||||
|
||||
%description
|
||||
A Gnome Shell passwords search provider for zx2c4/pass (passwordstore.org) and Bitwarden/Vaultwarden that sends passwords to clipboard (or GPaste).
|
||||
A Gnome Shell passwords search provider for zx2c4/pass (passwordstore.org) or compatibles and Bitwarden/Vaultwarden that sends passwords to clipboard (or GPaste).
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
|
Loading…
x
Reference in New Issue
Block a user