]> git.wincent.com - passage.git/blob - README.md
doc: Fix minor typo in README
[passage.git] / README.md
1 # Passage
2
3 ## Overview
4
5 Passage (short for "Pass Agent") is a Go process that serves as caching proxy for macOS keychain items.
6
7 It is intended to fulfil the use case where you have a command-line process that needs to periodically access a passphrase in the keychain, but you don't want to have to click "Allow" every single time (too cumbersome), nor "Always Allow" (too coarse). For more information, see **Security**, below.
8
9 ## Setup
10
11 ### Installing
12
13 If you have a working Go environment and `$GOPATH` is set, you can do:
14
15 ```
16 go get github.com/wincent/passage
17 ```
18
19 Additionally, you will need to install the [keybase/go-keychain](https://github.com/keybase/go-keychain) library as a dependency:
20
21 ```
22 go get github.com/keybase/go-keychain
23 ```
24
25 To build manually:
26
27 ```
28 cd $GOPATH/src/wincent/passage
29 go build
30 ```
31
32 ## Running automatically as a launch agent
33
34 ```
35 sudo cp passage /usr/local/bin
36 cp contrib/com.wincent.passage.plist ~/Library/LaunchAgents
37
38 # NOTE: This won't work if run inside a tmux session:
39 launchctl load -w -S Aqua ~/Library/LaunchAgents/com.wincent.passage.plist
40 ```
41
42 ## Usage
43
44 Send a JSON object with keys "service" and "account" to the Passage socket at `~/.passage.sock`. On the first request, you may see a keychain permission dialog, but on subsequent requests, you'll get a cached result back immediately.
45
46 ```
47 echo '{"service":"test item","account":"test name"}' | nc -U ~/.passage.sock
48 ```
49
50 The resulting password is written back over the socket. You could call this a "write of Passage" (ha!). In the event that the item is missing or there is an error, the connection closes without any output, although errors do get printed to the standard output of the Passage process itself. This is for convenient consumption by clients (ie. so that they don't have to implement JSON parsing themselves).
51
52 ### Invalidating the cache
53
54 There are two ways to invalidate the cache. One is to just restart the Passage process. The other is to send it a `SIGUSR1` signal.
55
56 You'll need the process PID in order to do that, and you can get it in several ways:
57
58 ```
59 # The old-fashioned way:
60 ps xww | grep passage
61
62 # Or to be more specific, assuming you installed and ran from `/usr/local/bin/`:
63 ps xww | grep /usr/local/bin/passage | grep -v grep
64
65 # The first column so you can extract it like this:
66 ps xww | grep /usr/local/bin/passage | grep -v grep | awk '{print $1}'
67
68 # If you launched using launchctl (but note: only works outside tmux):
69 launchctl list | grep passage
70
71 # The PID is the first column in the output of `launchctl list`, so you can
72 # extract it like this:
73 launchctl list | grep passage | awk '{print $1}'
74
75 # Once you've got the PID, say in a variable $PID, send the signal like this:
76 kill -USR1 $PID
77
78 # A more clever way using launchctl that works anywhere (including inside tmux)
79 # and doesn't just get the PID but actually sends the signal as well:
80 launchctl kill SIGUSR1 "gui/$(id -u)/com.wincent.passage"
81 ```
82
83 ### Configuration
84
85 There are no options. This was quickly hacked together to address a specific need.
86
87 ## Security
88
89 The `~/.passage.sock` socket is created with user-only (`0700`) permissions, but can still be accessed by privileged users and processes running on the system. As such, it falls somewhere in the middle of the spectrum of password storage (ordered approximately from most to least secure):
90
91 * **Storage in the system keychain, requiring explicit "Allow" intervention for each access:** This is the most secure, but also the most onerous. Key material only leaves the key chain with active approval (interaction with an intrusive GUI dialog).
92 * **Temporary storage in a process like `ssh-agent`:** This is quite secure not only because of the limited storage duration, but because the key material *never* leaves the agent; rather, other processes delegate work to be done by the agent. For example, when `ssh` tries to connect to a server, it will ask `ssh-agent` to perform the operations for private-key authentication, but there is no straightforward way to extract the actual private key material for the agent. However, this is not viable for situations like those in which you *do* need access to the private key.
93 * **Temporary storage in the memory of the `passage` process:** Passphrases can only be inserted into `passage` via explicit approval, and only remain there for the duration of the session. You can shorten the duration in various ways, such as:
94   1. Terminating the app or logging out.
95   2. Setting up a cron job to periodically send a `SIGUSR1` to `passage` to cause it to drop its cache; you can do this with `crontab -e` and a method like the `launchctl kill` one documented above.
96   3. Arranging to send `SIGUSR1` whenever the screensaver kicks in or the screen locks (something you should be able to do with a tool like [Hammerspoon](http://www.hammerspoon.org/).
97 * **Storage in the system keychain, having previously granted "Always Allow" access:** This is problematic if you're using the `security` command-line tool provided by Apple, because once you've granted "Always Allow", you will never be asked for permission again. Even if you intended to grant access only to `my-special-script.sh`, the permission will actually be associated with the `security` tool, which any process can call. So here the security is contingent on a hostile attack not being able to run code as you (or trick/coerce you into running it).
98 * **Storage in plain-text on the filesystem:** The security here is only so good as the security of the filesystem: privileged users will be able to retrieve the password regardless of filesystem permission. An unprivileged, determined attacker with local access will be able to elevate privileges by one means or another and gain access, even in the face of restrictive permissions.
99
100 ## Limitations
101
102 Passage uses the [keybase/go-keychain](https://github.com/keybase/go-keychain) library to access the keychain, which currently only knows how to read "generic" (A.K.A. "application") passwords, not "Internet" passwords.
103
104 # Authors
105
106 Passage is written and maintained by Greg Hurrell (greg@hurrell.net).
107
108 ## Development
109
110 The official Passage source code repo is at:
111
112 - http://git.wincent.com/passage.git
113
114 Mirrors exist at:
115
116 - https://github.com/wincent/passage
117 - https://gitlab.com/wincent/passage
118 - https://bitbucket.org/ghurrell/passage
119
120 Patches are welcome via the usual mechanisms (pull requests, email, posting to the project issue tracker etc).
121
122 ## Website
123
124 The official website for Passage is:
125
126 - https://github.com/wincent/passage
127
128 Bug reports should be submitted to the issue tracker at:
129
130 - https://github.com/wincent/passage/issues
131
132 ## History
133
134 Please see [`CHANGELOG.md`](CHANGELOG.md) in this repository.
135
136 ## License
137
138 Copyright 2016-present Greg Hurrell. All rights reserved.
139
140 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
141
142 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
143 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
144
145 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.