README.md 4.39 KB
Newer Older
ale's avatar
ale committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
keystore
========

KeyStore holds *unencrypted* secrets on behalf of users in memory for
a short time (of the order of a SSO session lifespan). User secrets
can be *opened* with a password (used to decrypt the key, which is
stored encrypted in a database), *queried* by presenting a suitable
authentication token, and *closed* (wiped and forgotten).

The database can provide multiple versions of the encrypted key (to
support multiple decryption passwords), in which case we'll try
them all sequentially until one of them decrypts successfully with
the provided password.

In order to query the KeyStore, you need to present a valid SSO
token for the user whose secrets you would like to obtain.

# API

The server exports an API over HTTP/HTTPS. All requests should be made
using the POST method and a Content-Type of *application/json*. The
request body should contain a JSON-encoded object. Responses will be
similarly JSON-encoded.

`/api/open` (*OpenRequest*)

Retrieve the encrypted key for a user, decrypt it with the provided
password, and store it in memory.

30
OpenRequest is an object with the following attributes:
ale's avatar
ale committed
31
32
33
34
35
36

* `username`
* `password` to decrypt the user's key with
* `ttl` (seconds) time after which the credentials are automatically
  forgotten

37
38
39
40
If the user has no encrypted keys in the database, the request will
still return successfully: no action will be performed, and no errors
will be returned.

ale's avatar
ale committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
`/api/get` (*GetRequest*) -> *GetResponse*

Retrieve the key for a user. GetRequest must contain the following
attributes:

* `username` whose key you wish to retrieve
* `sso_ticket` with a valid SSO ticket for the *keystore* service

If the request is successfully authenticated, GetResponse will contain
a single attribute *key*.

`/api/close` (*CloseRequest*)

Forget the key for a given user.
ale's avatar
ale committed
55
56
57
58
59
60
61
62
63
64

# Dovecot integration

The final consumer for user encryption keys is the Dovecot
service. The *dovecot-keylookupd* daemon can read the user public and
private keys from LDAP, and serve the *unencrypted* keys to Dovecot
using its [dict proxy
protocol](https://wiki2.dovecot.org/AuthDatabase/Dict).

TODO: explain the lookup protocol.
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

# Configuration

The *keystored* daemon loads its configuration from a YAML-encoded
file, */etc/keystore/config.yml* by default. It can contain the
following attributes:

* `sso_public_key_file`: path to the SSO Ed25519 public key
* `sso_service`: SSO service for this application
* `sso_domain`: SSO domain
* `ldap`: LDAP backend configuration
  * `uri`: LDAP server URI
  * `bind_dn`: bind DN (for simple bind, SASL is not supported)
  * `bind_pw`: bind password
  * `bind_pw_file`: bind password (load from this file), in
    alternative to *bind_pw*
  * `query`: Parameters for the LDAP search query
    * `search_base`: base DN for the search
    * `search_filter`: search filter. The filter string may contain a
      literal `%s` token somewhere, that will be replaced with the
      (escaped) username.
    * `scope`: search scope, one of *sub* (default), *one* or *base*
    * `public_key_attr`: attribute that contains the user's public key
    * `private_key_attr`: attribute that contains the user's encrypted
      key(s)
* `http_server`: HTTP server configuration
  * `tls`: contains the server-side TLS configuration:
    * `cert`: path to the server certificate
    * `key`: path to the server's private key
    * `ca`: path to the CA used to validate clients
    * `acl`: specifies TLS-based access controls, a list of entries
      with the following attributes:
      * `path`: regular expression to match the request URL path
      * `cn`: regular expression that must match the CommonName part
        of the subject of the client certificate
  * `max_inflight_requests`: maximum number of in-flight requests to
    allow before server-side throttling kicks in

The *dovecot-keylookupd* daemon uses a similar configuration, read by
default from */etc/keystore/dovecot.yml*:

* `ldap`: LDAP backend configuration, see above
* `keystore`: configures the connection to the keystore service
  * `url`: URL for the keystore service
109
110
  * `sharded`: if true, requests to the keystore service will be
    partitioned according to the user's *shard* attribute
111
112
113
114
  * `tls_config`: client TLS configuration
    * `cert`: path to the client certificate
    * `key`: path to the private key
    * `ca`: path to the CA used to validate the server
115
116
* `shard`: shard identifier for the local host. Must be set if
  keystore.sharded is true.