pass
– менеджер паролей для Linux/UNIX, наверно один из старейших.
Хранит данные в древовидной структуре каталогов и файлов, а сами файлы с секретами шифрует с помощью GPG-ключа.
В Arch Linux есть из коробки, в Debian можно установить с помощь apt
из дефолтных репозиториев:
[simterm]
$ sudo apt install pass
[/simterm]
В macOS – с помощью Homebrew:
[simterm]
$ brew install pass
[/simterm]
Хотя я сомневаюсь, что Mac-пользователи будут им пользоваться 🙂
Являет собой просто bash-скрипт:
[simterm]
$ head /usr/bin/pass #!/usr/bin/env bash # Copyright (C) 2012 - 2018 Jason A. Donenfeld <[email protected]>. All Rights Reserved. # This file is licensed under the GPLv2+. Please see COPYING for more information. umask "${PASSWORD_STORE_UMASK:-077}" set -o pipefail GPG_OPTS=( $PASSWORD_STORE_GPG_OPTS "--quiet" "--yes" "--compress-algo=none" "--no-encrypt-to" ) GPG="gpg"
[/simterm]
Содержание
GPG ключи
Создание ключа
Для работы pass
потребуется GPG-ключ, создаём его (см. Linux: GnuPG — управление GPG ключами):
[simterm]
$ gpg --full-gen-key ... Please select what kind of key you want: (1) RSA and RSA (default) // оставляем по-умолчанию RSA and RSA (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) // оставляем по-умолчанию 2048 Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) // оставляем по-умолчанию 0 - без валиден навеки Key does not expire at all Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: example Email address: [email protected] Comment: You selected this USER-ID: "example <[email protected]>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. ...
[/simterm]
Появится окно с запросом на ввод пароля для доступа к ключу:
Вводим пароль, и завершаем создание ключа:
[simterm]
... We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. gpg: key 714F9CBFDA191430 marked as ultimately trusted gpg: revocation certificate stored as '/home/setevoy/.gnupg/openpgp-revocs.d/E130BB49AAA234F2BE2A7F96714F9CBFDA191430.rev' public and secret key created and signed. pub rsa2048 2019-04-25 [SC] E130BB49AAA234F2BE2A7F96714F9CBFDA191430 uid example <[email protected]> sub rsa2048 2019-04-25 [E]
[/simterm]
Проверяем список публичных ключей:
[simterm]
$ gpg --list-keys gpg: checking the trustdb gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u /home/setevoy/.gnupg/pubring.kbx -------------------------------- pub rsa2048 2010-02-11 [SC] 1C61A2656FB57B7E4DE0F4C1FC918B335044912E uid [ unknown] Dropbox Automatic Signing Key <[email protected]> pub rsa2048 2011-04-26 [SC] FCF986EA15E6E293A5644F10B4322F04D67658D8 uid [ unknown] FFmpeg release signing key <[email protected]> sub rsa2048 2011-04-26 [E] pub rsa4096 2018-04-02 [SC] ABBAD1CB484F53024CF5868B69332F9203F21F5C uid [ unknown] Andrew Richards (cancel) <[email protected]> sub rsa2048 2019-01-28 [S] sub rsa4096 2018-04-02 [E] pub rsa2048 2019-04-25 [SC] DEB0D4AD41CC2612B1944D448D22D6610B2F6067 uid [ultimate] setevoy (my main) <[email protected]> sub rsa2048 2019-04-25 [E] pub rsa2048 2019-04-25 [SC] E130BB49AAA234F2BE2A7F96714F9CBFDA191430 uid [ultimate] example <[email protected]> sub rsa2048 2019-04-25 [E]
[/simterm]
И своих приватных:
[simterm]
$ gpg --list-secret-keys /home/setevoy/.gnupg/pubring.kbx -------------------------------- sec rsa2048 2019-04-25 [SC] DEB0D4AD41CC2612B1944D448D22D6610B2F6067 uid [ultimate] setevoy (my main) <[email protected]> ssb rsa2048 2019-04-25 [E]
[/simterm]
Удаление ключа
Что бы удалить ключ – надо удалить его приватную часть, после чего можно удалить публичную.
Удаляем приватный ключ:
[simterm]
$ gpg --delete-secret-key E130BB49AAA234F2BE2A7F96714F9CBFDA191430 gpg (GnuPG) 2.2.15; Copyright (C) 2019 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. sec rsa2048/714F9CBFDA191430 2019-04-25 example <[email protected]> Delete this key from the keyring? (y/N) y This is a secret key! - really delete? (y/N) y
[/simterm]
Аргументом --delete-secret-key
можно передать либо отпечаток (fingerprint), либо имя, в данном примере – “example“.
Теперь можно удалить и публичный ключ, используя --delete-key
:
[simterm]
$ gpg --delete-key E130BB49AAA234F2BE2A7F96714F9CBFDA191430 gpg (GnuPG) 2.2.15; Copyright (C) 2019 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. pub rsa2048/714F9CBFDA191430 2019-04-25 example <[email protected]> Delete this key from the keyring? (y/N) y
[/simterm]
Резервное копирование GPG-ключей
Т.к. ключём будет шифроваться хранилище паролей – то терять этот ключ не хочется.
Забекапить ключи можно либо просто скопировав весь каталог ~/.gnupg
(в случае, если используется GnuPG):
[simterm]
$ ll .gnupg/ total 52 drwx------ 2 setevoy setevoy 4096 Jan 22 12:44 crls.d drwx------ 2 setevoy setevoy 4096 Apr 25 10:04 openpgp-revocs.d drwx------ 2 setevoy setevoy 4096 Apr 25 10:11 private-keys-v1.d -rw-r--r-- 1 setevoy setevoy 13732 Apr 25 10:14 pubring.kbx -rw-r--r-- 1 setevoy setevoy 12317 Apr 25 09:58 pubring.kbx~ -rw-r----- 1 setevoy setevoy 676 Apr 25 09:54 sshcontrol -rw------- 1 setevoy setevoy 1440 Apr 25 10:14 trustdb.gpg
[/simterm]
Либо экспортировав приватные ключи в отдельное хранилище:
[simterm]
$ gpg --export-secret-keys > ~/Dropbox/Backups/gpg-setevoy-arch-work-secret-backup.gpg
[/simterm]
При экспорте будет запрошен пароль от вашего секретного ключа/ей:
А восстановить его можно с помощью --import
.
Удалим имеющийся ключ:
[simterm]
$ gpg --delete-secret-key setevoy
[/simterm]
И восстановим его из бекапа:
$ gpg --import ~/Dropbox/Backups/gpg-setevoy-arch-work-secret-backup.gpg gpg: key 8D22D6610B2F6067: "setevoy (my main) <[email protected]>" not changed gpg: key 8D22D6610B2F6067: secret key imported gpg: Total number processed: 1 gpg: unchanged: 1 gpg: secret keys read: 1 gpg: secret keys imported: 1
[/simterm]
Проверяем:
[simterm]
$ gpg --list-secret-keys /home/setevoy/.gnupg/pubring.kbx -------------------------------- sec rsa2048 2019-04-25 [SC] DEB0D4AD41CC2612B1944D448D22D6610B2F6067 uid [ultimate] setevoy (my main) <[email protected]> ssb rsa2048 2019-04-25 [E]
[/simterm]
pass
Создание хранилища
Инициализируем хранилище, используя имя (ID) или почту вашего GPG-ключа:
[simterm]
$ pass init setevoy Password store initialized for setevoy
[/simterm]
pass
создаст файл идентификации – ~/.password-store/.gpg-id
:
[simterm]
$ cat .password-store/.gpg-id setevoy
[/simterm]
pass
Git и Github
Кроме стандартного хранилища – pass
может создать его в виде git-репозитория, и вести историю всех изменений.
Если глобальные настройки Git-пользователя ещё не сделаны – выполняем:
[simterm]
$ git config --global user.email [email protected] $ git config --global user.name "setevoy"
[/simterm]
Создаём git-репозиторий для уже созданного хранилища:
[simterm]
$ pass git init Initialized empty Git repository in /home/setevoy/.password-store/.git/ [master (root-commit) 7e19ab0] Add current contents of password store. 1 file changed, 1 insertion(+) create mode 100644 .gpg-id [master 19aaf2c] Configure git repository for gpg file diff. 1 file changed, 1 insertion(+) create mode 100644 .gitattributes
[/simterm]
И теперь доступна вся история, как с обычным Git:
[simterm]
$ cd .password-store/ $ git log commit d8f791453fd1e8be7cf6126cde7f32df3bd351cc (HEAD -> master) Author: setevoy <[email protected]> Date: Thu Apr 25 11:08:19 2019 +0300 Configure git repository for gpg file diff. commit d49c886510221f31268f22cd74d0859965bafb7b Author: setevoy <[email protected]> Date: Thu Apr 25 11:08:19 2019 +0300 Add current contents of password store.
[/simterm]
Далее можно создать приватный репозиторий в Github или Bitbucket, добавить вашу базу pass
в него, и синхронизировать базы между разными компьютерами через единый git-репозиторий, выполняет git push
/git pull
.
Хотя мысль о том, что бы хранить все свои пароли пусть и в приватном репозитории, пусть в зашифрованных файлах, но в Github – имхо идея очень так себе.
Другой вариант – поднять Git-сервер где-то у себя, и синхронизировать через него.
Тем не менее, для примера – создаём репозиторий в Github:
Копируем его адрес, тут это [email protected]:setevoy2/pass-example.git:
Переходим в каталог хранилища на своей машине:
[simterm]
$ cd ~/.password-store/
[/simterm]
Обновляем настройки репозиторий – добавляем remote
:
[simterm]
$ git remote add origin [email protected]:setevoy2/pass-example.git
[/simterm]
Проверяем:
[simterm]
$ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [diff "gpg"] binary = true textconv = gpg2 -d --quiet --yes --compress-algo=none --no-encrypt-to --batch --use-agent [remote "origin"] url = [email protected]:setevoy2/pass-example.git fetch = +refs/heads/*:refs/remotes/origin/*
[/simterm]
И пушим в Github:
[simterm]
$ git push origin master ... To github.com:setevoy2/pass-example.git * [new branch] master -> master
[/simterm]
Проверяем:
Добавление пароля
Для добавления используем insert
, затем путь в виде каталога(ов) и имя пользователя.
Например, для RTFM добавление могло бы выглядеть так:
[simterm]
$ pass insert rtfm.co.ua/admin/setevoy mkdir: created directory '/home/setevoy/.password-store/rtfm.co.ua' mkdir: created directory '/home/setevoy/.password-store/rtfm.co.ua/admin' Enter password for rtfm.co.ua/admin/setevoy: Retype password for rtfm.co.ua/admin/setevoy: [master 7ae47c9] Add given password for rtfm.co.ua/admin/setevoy to store. 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rtfm.co.ua/admin/setevoy.gpg
[/simterm]
Просмотр и получение секретов
Теперь структура хранилища выглядит так:
[simterm]
$ pass Password Store └── rtfm.co.ua └── admin └── setevoy
[/simterm]
Для получения пароля – указываем полный путь к файлу, и вводим пароль GPG-ключа:
[simterm]
$ pass rtfm.co.ua/admin/setevoy p@ssw0rd
Можно сразу скопировать его в буфер обмена – добавляем -c
:
[simterm]
$ pass -c rtfm.co.ua/admin/setevoy Copied rtfm.co.ua/admin/setevoy to clipboard. Will clear in 45 seconds.
[/simterm]
И история git
:
[simterm]
$ git log commit 7ae47c9535eabddc64c89df39c7db720a2cd5244 (HEAD -> master) Author: setevoy <[email protected]> Date: Thu Apr 25 11:12:16 2019 +0300 Add given password for rtfm.co.ua/admin/setevoy to store. ...
[/simterm]
Многострочные записи
Кроме просто пароля – можно добавить различную информацию.
Что бы внести несколько строк в файл – используем -m
. При этом сам пароль указывайте первой строкой – -c
использует её для копирования в буфер:
[simterm]
$ pass insert -m rtfm.co.ua/admin/setevoy An entry already exists for rtfm.co.ua/admin/setevoy. Overwrite it? [y/N] y Enter contents of rtfm.co.ua/admin/setevoy and press Ctrl+D when finished: p@ssw0rd Username: setevoy URL: rtfm.co.ua [master fc43a4c] Add given password for rtfm.co.ua/admin/setevoy to store. 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rtfm.co.ua/admin/setevoy.gpg
[/simterm]
Проверяем:
[simterm]
$ pass show rtfm.co.ua/admin/setevoy p@ssw0rd Username: setevoy URL: rtfm.co.ua
[/simterm]
Поиск паролей
Для поиска у pass
есть две опции – find
, и grep
.
find
выполняет поиск по именам каталогов и файлов:
[simterm]
$ pass find setevoy Search Terms: setevoy ├── rtfm.co.ua └── admin └── setevoy
[/simterm]
А grep
– по тексту всех файлов:
[simterm]
$ pass grep rtfm. rtfm.co.ua/admin/setevoy: URL: rtfm.co.ua ...
Удаление пароля
Вызываем pass
с опцией rm
:
[simterm]
$ pass rm rtfm.co.ua/admin/setevoy Are you sure you would like to delete rtfm.co.ua/admin/setevoy? [y/N] y removed '/home/setevoy/.password-store/rtfm.co.ua/admin/setevoy.gpg' [master 7a23ede] Remove rtfm.co.ua/admin/setevoy from store. 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 rtfm.co.ua/admin/setevoy.gpg
[/simterm]
Для удаления каталога – используйте rm -r
:
[simterm]
$ pass rm -r Main Are you sure you would like to delete Main? [y/N] y removed '/home/setevoy/.password-store/Main/Work/blabla.com.gpg' ...
[/simterm]
Импорт из KeePass
Собственно, pass
я добавил как резервное хранилище паролей.
В основном используется KeePass (точнее – KeePassXC), база хранится в Dropbox и синхронизирует KeePass между разными компьютерами.
На случай, если в один прекрасный день его база поломается – потерять пароли не хочется, поэтому импортируем их в pass
.
Используем pass-import
, который умеет выполнять импорт из различных хранилищ, в том числе из XML-файла, сгенерированного KeePass.
На Arch Linux можно установить из AUR:
[simterm]
$ yaourt -S pass-import
[/simterm]
Создаём копию (из KeePass – KeePassXC не умеет в XML):
И выполняем импорт: указываем менеджер паролей (тут – keepass) и путь к файлу:
[simterm]
$ pass import keepass ~/Backups/KeePassBKP/KeePass-Main-25-04-2019-bkp.xml (*) Importing passwords from keepass . File: /home/setevoy/Backups/KeePassBKP/KeePass-Main-25-04-2019-bkp.xml . Number of password imported: 294 . Passwords imported: Main/AWS/AWS root user Main/AWS/AWS setevoy Main/Cards/Aval Credit ...
[/simterm]
Проверяем хранилище pass
теперь:
[simterm]
$ pass Password Store ├── Main │ ├── AWS │ │ ├── AWS root user │ │ └── AWS setevoy │ ├── Cards │ │ ├── Aval Credit │ │ ├── OtherCards │ │ │ ├── Masha │ │ │ ├── Stromenko etabak ...
[/simterm]
QtPass
Консоль – хорошо, но иногда хочется UI.
Для pass
есть QtPass.
В Arch Linux устаналивается из стандартного репозитория:
[simterm]
$ sudo pacman -S qtpass
[/simterm]
Запускаем:
Готово.