summaryrefslogtreecommitdiff
path: root/posts
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2015-04-07 19:37:36 +0200
committerGregor Kleen <gkleen@yggdrasil.li>2015-04-07 19:37:36 +0200
commitf057a724dd57be73d705ae20f06ab270bb67e666 (patch)
tree75575ae08e5603c977a6fc7673eda724d68fe798 /posts
parent42c0849549032ca665c165ca7ffb19bb59692431 (diff)
downloaddirty-haskell.org-f057a724dd57be73d705ae20f06ab270bb67e666.tar
dirty-haskell.org-f057a724dd57be73d705ae20f06ab270bb67e666.tar.gz
dirty-haskell.org-f057a724dd57be73d705ae20f06ab270bb67e666.tar.bz2
dirty-haskell.org-f057a724dd57be73d705ae20f06ab270bb67e666.tar.xz
dirty-haskell.org-f057a724dd57be73d705ae20f06ab270bb67e666.zip
pwutil
Diffstat (limited to 'posts')
-rw-r--r--posts/pwutil.md132
1 files changed, 132 insertions, 0 deletions
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 @@
1% A Tool to Manage a Set of YAML Objects Representing Account Information — pwutil
2
3A 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.
4
5[pwutil](git://git.yggdrasil.li/pwutil) is the newest iteration in this line of bunches of scripts.
6
7## Features
8
9 * Support for embedding common operation in any kind of record keeping
10
11 Thus support for almost any encryption known to man (with absolutely no online security), version control, and synchronisation
12 * [Human readable](https://en.wikipedia.org/wiki/YAML) backstore
13 * [Command Line Interface](https://en.wikipedia.org/wiki/Command-line_interface)-only
14 * 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
15
16## Documentation
17
18I shall document the project in a partial and file-wise fashion—amendments available on request.
19
20### Structure
21
22~~~ {#DirTree}
23pwutil
24├── default.nix
25├── PWAdd.hs
26├── PWGet.hs
27├── PWUtil
28│   ├── Encfs.hs
29│   ├── Extra
30│   │   ├── PWGen.hs
31│   │   └── SSHCmd.hs
32│   ├── Types.hs
33│   └── Util.hs
34├── pwutil.hs
35├── PWUtil.hs
36└── pwutil.nix
37~~~
38
39### `pwutil.nix`
40is a [nix](https://nixos.org/nix) expression allowing easy installation using the nix package manager.
41A `~/.nixpkgs/config.nix` allowing one to do so might look thus:
42~~~ {.numberLines}
43{
44 packageOverrides = pkgs: {
45 pwutil = pkgs.callPackage /path/to/pwutil.nix {};
46 };
47}
48~~~
49
50### `Types.hs`
51
52`PWLocation` describes the location of a file containing a YAML object mapping human readable identifiers to account information.
53`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.
54This 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.
55`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).
56
57~~~ {#Types.hs .haskell .numberLines}
58module PWUtil.Types (
59 PWLocation(..),
60 Encryption(..),
61 PW(..),
62 PWConfig(..),
63 Generator(..)
64 ) where
65
66import System.IO (Handle(..), IOMode(..))
67import Control.Monad.State
68import qualified Data.Map as M
69import Data.Yaml
70
71data PWLocation = PWLocation
72 { path :: FilePath
73 , encryption :: Encryption
74 , create :: IO ()
75 }
76
77instance Show PWLocation where
78 show loc = show $ path loc
79
80type Encryption = FilePath -> IOMode -> (Handle -> IO ()) -> IO ()
81
82type PW = StateT PWConfig IO
83
84data PWConfig = PWConfig
85 { location :: PWLocation
86 , generators :: M.Map String Generator
87 }
88
89type Generator = [String] -> IO Value
90~~~
91
92
93### `pwutil.hs`
94
95is, in a [xmonad](http://xmonad.org) kind of way, the configuration file.
96
97~~~ {#pwutil.hs .haskell .numberLines}
98import PWUtil
99
100import System.FilePath ((</>))
101import qualified Data.Map as M
102import System.Directory (getHomeDirectory)
103
104pWLocation :: IO PWLocation
105pWLocation = do
106 h <- getHomeDirectory
107 return PWLocation { path = h </> "accounts.yaml"
108 , encryption = plain
109 , create = createFile $ h </> "accounts.yaml"
110 }
111
112myGenerators :: M.Map String Generator
113myGenerators = M.empty
114
115main :: IO ()
116main = do
117 myLocation <- pWLocation
118 runPW (PWConfig { location = myLocation, generators = myGenerators }) pwutil
119~~~
120
121### `Encfs.hs`
122
123shall serve as an example for a module providing an encryption wrapper.
124It exports
125
126~~~{.haskell}
127encfs :: Encfs -> Encryption
128encfs (Encfs backStore mountpoint) = …
129~~~
130
131Upon execution it checks whether `mountpoint` is already mounted.
132If not it executes `encfs backStore mountpoint` interactively and calls `fusermount -u` after completion.