--- title: A Tool to Manage a Set of YAML Objects Representing Account Information — pwutil published: 2015-04-07 --- 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. ## Features * 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 synchronisation * [Human read- and writeable](https://en.wikipedia.org/wiki/YAML) backstore * Machine parseable output * [Command Line Interface](https://en.wikipedia.org/wiki/Command-line_interface)-only * New accounts can be partially generated by user defined functions with out of the box support for [pwgen](http://sourceforge.net/projects/pwgen/) and SSH ## Usage ~~~ pwget [ …] Looks up and returns all accounts which contain any anywhere in their representation — case insensitive. pwadd [[--gen- [ …] …] --] [ …] Adds an account to the store — does not overwrite. ~~~ ## Documentation I shall document the project in a partial and file-wise fashion—amendments available on request. ### Structure ~~~ {#DirTree} 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](https://nixos.org/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` ~ Overwrite `pwutil.hs` with a file path `with ? false` ~ `` is one of Pwgen, or Ssh a the current time. If `true` wraps executables to have `$PATH` include ``. ### `Types.hs` Introducing `PW` (much as [xmonad](https://xmonad.org) 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`). ~~~ {#Types.hs .haskell} 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](http://xmonad.org) kind of way, the configuration file—the shipped default is reproduced below as a template for custom configs. ~~~ {#pwutil.hs .haskell} import PWUtil import System.FilePath (()) import System.Directory (getHomeDirectory) main :: IO () main = do h <- getHomeDirectory runPW (emptyConfig { backstore = plain (h "accounts.yaml") }) pwutil ~~~