A long time ago I wrote a bunch of scripts (first in bash, then zsh, and later perl) to manage a, sometimes encrypted, file containing account information I get asked to create and remember on a daily basis—accounts for shopping websites spring to mind.
pwutil is the newest iteration in this line of bunches of scripts.
Support for embedding common operation in any kind of record keeping
Thus support for almost any encryption known to man (with absolutely no online security), version control, and synchronisationNew accounts can be partially generated by user defined functions with out of the box support for pwgen and SSH
pwget [<searchTerm> …]
Looks up and returns all accounts which contain any <searchTerm> anywhere in their representation — case insensitive.
pwadd [[--gen-<generator> [<generatorArgument> …] …] --] <identifier> [<attributeKey> <attributeValue> …]
Adds an account to the store — does not overwrite.
I shall document the project in a partial and file-wise fashion—amendments available on request.
pwutil
├── default.nix
├── PWAdd.hs
├── PWGet.hs
├── PWUtil
│ ├── Extra
│ │ ├── PWGen.hs
│ │ └── SSHCmd.hs
│ ├── Types.hs
│ └── Util.hs
├── pwutil.hs
├── PWUtil.hs
└── pwutil.nix
pwutil.nix
is a nix expression allowing easy installation using the nix package manager. A ~/.nixpkgs/config.nix
allowing one to do so might look thus:
{
packageOverrides = pkgs: {
pwutil = pkgs.callPackage /path/to/pwutil.nix {};
};
}
The derivation takes some arguments (write those in {}
above):
main ? null
pwutil.hs
with a file path
with<Package> ? false
<Package>
is one of Pwgen, or Ssh a the current time. If true
wraps executables to have $PATH
include <Package>
.
Types.hs
Introducing PW
(much as xmonad did with X
) is an easy way to keep track of the PWConfig
without resorting to function arguments. BackStore
is our (new and improved) way of encapsulating store access in a totally customisable way—plain
, which is essential readFile
and writeFile
as provided by ByteString
, is provided for convenience in Util.hs
. PWConfig
most importantly contains a definition of generators (called by passing --gen-…
to pwadd
).
module PWUtil.Types (
PW(..),
BackStore(..),
PWConfig(..),
Generator(..)
) where
import Control.Monad.State
import qualified Data.Map as M
import Data.Yaml
import Data.ByteString
type PW = StateT PWConfig IO
data BackStore = BackStore
{ readContents :: PW ByteString
, writeContents :: ByteString -> PW ()
}
data PWConfig = PWConfig
{ generators :: M.Map String Generator
, backstore :: BackStore
}
type Generator = [String] -> PW Value
pwutil.hs
is, in a xmonad kind of way, the configuration file—the shipped default is reproduced below as a template for custom configs.
import PWUtil
import System.FilePath ((</>))
import System.Directory (getHomeDirectory)
main :: IO ()
main = do
h <- getHomeDirectory
runPW (emptyConfig { backstore = plain (h </> "accounts.yaml") }) pwutil