From f057a724dd57be73d705ae20f06ab270bb67e666 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Tue, 7 Apr 2015 19:37:36 +0200 Subject: pwutil --- lists/zz_all/003 | 1 + posts/pwutil.md | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 120000 lists/zz_all/003 create mode 100644 posts/pwutil.md diff --git a/lists/zz_all/003 b/lists/zz_all/003 new file mode 120000 index 0000000..1057f2c --- /dev/null +++ b/lists/zz_all/003 @@ -0,0 +1 @@ +../../posts/pwutil.md \ No newline at end of file diff --git a/posts/pwutil.md b/posts/pwutil.md new file mode 100644 index 0000000..61a3823 --- /dev/null +++ b/posts/pwutil.md @@ -0,0 +1,132 @@ +% A Tool to Manage a Set of YAML Objects Representing Account Information — pwutil + +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](git://git.yggdrasil.li/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 readable](https://en.wikipedia.org/wiki/YAML) backstore + * [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 + +## 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 +│   ├── Encfs.hs +│   ├── 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: +~~~ {.numberLines} +{ + packageOverrides = pkgs: { + pwutil = pkgs.callPackage /path/to/pwutil.nix {}; + }; +} +~~~ + +### `Types.hs` + +`PWLocation` describes the location of a file containing a YAML object mapping human readable identifiers to account information. +`encryption`, which has essentially the same signature as [`withFile`](http://hackage.haskell.org/package/base-4.8.0.0/docs/System-IO.html#v:withFile) wraps all access to the file. +This in an extremely powerful way to deal with any kind of encryption desired (currently I implemented automatic mounting of an [EncFs](http://en.wikipedia.org/wiki/EncFS) container and `plain`, which does nothing. +`create` is used to try and create the location once should access fail due to a file [not existing](http://hackage.haskell.org/package/base-4.8.0.0/docs/System-IO-Error.html#v:doesNotExistErrorType). + +~~~ {#Types.hs .haskell .numberLines} +module PWUtil.Types ( + PWLocation(..), + Encryption(..), + PW(..), + PWConfig(..), + Generator(..) + ) where + +import System.IO (Handle(..), IOMode(..)) +import Control.Monad.State +import qualified Data.Map as M +import Data.Yaml + +data PWLocation = PWLocation + { path :: FilePath + , encryption :: Encryption + , create :: IO () + } + +instance Show PWLocation where + show loc = show $ path loc + +type Encryption = FilePath -> IOMode -> (Handle -> IO ()) -> IO () + +type PW = StateT PWConfig IO + +data PWConfig = PWConfig + { location :: PWLocation + , generators :: M.Map String Generator + } + +type Generator = [String] -> IO Value +~~~ + + +### `pwutil.hs` + +is, in a [xmonad](http://xmonad.org) kind of way, the configuration file. + +~~~ {#pwutil.hs .haskell .numberLines} +import PWUtil + +import System.FilePath (()) +import qualified Data.Map as M +import System.Directory (getHomeDirectory) + +pWLocation :: IO PWLocation +pWLocation = do + h <- getHomeDirectory + return PWLocation { path = h "accounts.yaml" + , encryption = plain + , create = createFile $ h "accounts.yaml" + } + +myGenerators :: M.Map String Generator +myGenerators = M.empty + +main :: IO () +main = do + myLocation <- pWLocation + runPW (PWConfig { location = myLocation, generators = myGenerators }) pwutil +~~~ + +### `Encfs.hs` + +shall serve as an example for a module providing an encryption wrapper. +It exports + +~~~{.haskell} +encfs :: Encfs -> Encryption +encfs (Encfs backStore mountpoint) = … +~~~ + +Upon execution it checks whether `mountpoint` is already mounted. +If not it executes `encfs backStore mountpoint` interactively and calls `fusermount -u` after completion. -- cgit v1.2.3