]> ruderich.org/simon Gitweb - nsscash/nsscash.git/blob - README.adoc
Add TODO.adoc
[nsscash/nsscash.git] / README.adoc
1 = README
2
3 Nsscash (a pun on cache) is a simple file-based cache for NSS similar to
4 nsscache [1]. The goal is to distribute users/groups/etc. to multiple systems
5 without having to rely on a (single) stable server. Traditional systems like
6 LDAP or NIS require a stable server or users/groups cannot be resolved. By
7 distributing the data to all systems, temporary outages of the server cause no
8 issues on the clients. In addition the local storage is much faster than
9 remote network access. To update the local caches polling via HTTP is
10 performed, for example every minute, only downloading new data if anything has
11 changed.
12
13 Nsscash consists of two parts: `nsscash`, written in Go, which downloads files
14 via HTTP or HTTPS, parses them, creates indices and writes the result to a
15 local file. The second part is the NSS module (`libnss_cash.so.2`), written in
16 C, which provides integration via `/etc/nsswitch.conf`. It's specifically
17 designed to be very simple and uses the data prepared by `nsscash` for
18 lookups. To support quick lookups, in O(log n), the files utilize indices.
19
20 Nsscash is very careful when deploying the changes:
21 - All files are updated using the standard "write to temporary file", "sync",
22   "rename" steps which is atomic on UNIX file systems. The indices are stored
23   in the same file preventing stale data during the update.
24 - All errors cause an immediate abort ("fail fast") with a proper error
25   message and a non-zero exit status. This prevents hiding possibly important
26   errors. In addition all files are fetched first and then deployed to try to
27   prevent inconsistent state if only one file can be downloaded. The state
28   file (containing last file modification and content hash) is only updated
29   when all operations were successful.
30 - To prevent unexpected permissions, `nsscash` does not create new files. The
31   user must create them first and `nsscash` will then re-use the permissions
32   (without the write bits to discourage manual modifications) and owner/group
33   when updating the file (see examples below).
34 - To prevent misconfigurations, empty files (no users/groups) are not
35   permitted and will not be written to disk. This is designed to prevent the
36   accidental loss of all users/groups on a system.
37
38 The passwd/group files have the following size restrictions:
39 - maximum number of entries: '2^64-1' (uint64_t)
40 - maximum passwd entry size: 65543 bytes (including newline)
41 - maximum group entry size: 65535 bytes (including newline, only one member)
42 - maximum members per group: depends on the user name length,
43                              with 9 bytes per user: 5460 users
44 - `nsscash` checks for these restrictions and aborts with an error if they are
45   violated
46
47 nsscash has an extensive test suite for both the Go and C part testing general
48 requirements and various corner cases. See TODO.adoc for a list of known
49 issues and possible improvements.
50
51 nsscash is licensed under AGPL version 3 or later.
52
53 [1] https://github.com/google/nsscache
54
55
56 == REQUIREMENTS
57
58 - Go, for `nsscash`
59   - github.com/pkg/errors
60   - github.com/BurntSushi/toml
61 - C compiler, for `libnss_cash.so.2`
62
63 - HTTP(S) server to provide the passwd/group/etc. files
64
65 Tested on Debian Buster, but should work on any GNU/Linux system. With
66 adaptations to the NSS module it should work on any UNIX-like system which
67 uses NSS.
68
69
70 == USAGE
71
72 Install `libnss_cash.so.2` somewhere in your library search path (see
73 `/etc/ld.so.conf`), e.g. `/usr/lib/x86_64-linux-gnu/`.
74
75 Update `/etc/nsswitch.conf` to include the cash module; `passwd` and `group`
76 are currently supported. For example:
77
78     passwd:         files cash
79     group:          files cash
80     [...]
81
82 Create the cache files with the proper permissions (`nsscash fetch` won't
83 create new files to prevent using incorrect permissions):
84
85     touch /etc/passwd.nsscash
86     touch /etc/group.nsscash
87     chmod 0644 /etc/passwd.nsscash
88     chmod 0644 /etc/group.nsscash
89
90 Configure the `nsscash` configuration file `nsscash.toml`, see below.
91
92 Then start `nsscash`:
93
94     nsscash fetch /path/to/config/nsscash.toml
95
96 This will fetch the configured files and update the local caches. The files
97 are atomically overwritten (via temporary file, sync, and rename).
98
99 Verify the users/groups are available, e.g. with `getent`. If everything
100 works, remember to reboot the host as changes to `nsswitch.conf` don't affect
101 running processes!
102
103 Now configure `nsscash` to run regularly, for example via cron or a systemd
104 timer.
105
106 To monitor `nsscash` for errors one can use the last modification time of the
107 state file (see below). It's written on each successful run and not modified
108 if an error occurs.
109
110 === CONFIGURATION
111
112 Nsscash is configured through a simple configuration file written in TOML. A
113 typical configuration looks like this:
114
115     statepath = "/var/lib/nsscash/state.json"
116
117     [[file]]
118     type = "passwd"
119     url = "https://example.org/passwd"
120     path = "/etc/passwd.nsscash"
121
122     [[file]]
123     type = "group"
124     url = "https://example.org/group"
125     path = "/etc/group.nsscash"
126
127     # Optional, but useful to deploy files which are not supported by the
128     # nsscash NSS module, but by libc's "files" NSS module. nsscash takes care
129     # of the atomic replacement and updates; an "netgroup: files" entry in
130     # "/etc/nsswitch.conf" makes the netgroups available.
131     [[file]]
132     type = "plain"
133     url = "https://example.org/netgroup"
134     path = "/etc/netgroup"
135
136 The following global keys are available:
137
138 - `statepath`: Path to a JSON file which stores the last modification time and
139   hash of each file; automatically updated by `nsscash`. Used to fetch data
140   only when something has changed to reduce the required traffic, via
141   `If-Modified-Since`. When the hash of a file has changed the download is
142   forced.
143
144 Each `file` block describes a single file to download/write. The following
145 keys are available:
146
147 - `type`: Type of this file; can be either `passwd` (for files in
148   `/etc/passwd` format), `group` (for files in `/etc/group` format), or
149   `plain` (arbitrary format). Only `passwd` and `group` files are supported by
150   the nsscash NSS module. But, as explained above, `plain` can be used to
151   distribute arbitrary files. The type is required as the `.nsscash` files are
152   pre processed for faster lookups and simpler C code which requires a known
153   format.
154
155 - `url`: URL to fetch the file from; HTTP and HTTPS are supported
156
157 - `ca`: Path to a custom CA in PEM format. Restricts HTTPS requests to accept
158   only certificates signed by this CA. Defaults to the system's certificate
159   store when omitted. (optional)
160
161 - `username`/`password`: Username and password sent via HTTP Basic-Auth to the
162   webserver. The configuration file must not be readable by other users when
163   this is used. (optional)
164
165 - `path`: Path to store the retrieved file
166
167
168 == AUTHORS
169
170 Written by Simon Ruderich <simon@ruderich.org>.
171
172
173 == LICENSE
174
175 This program is licensed under AGPL version 3 or later.
176
177 Copyright (C) 2019  Simon Ruderich
178
179 This program is free software: you can redistribute it and/or modify
180 it under the terms of the GNU Affero General Public License as published by
181 the Free Software Foundation, either version 3 of the License, or
182 (at your option) any later version.
183
184 This program is distributed in the hope that it will be useful,
185 but WITHOUT ANY WARRANTY; without even the implied warranty of
186 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
187 GNU Affero General Public License for more details.
188
189 You should have received a copy of the GNU Affero General Public License
190 along with this program.  If not, see <https://www.gnu.org/licenses/>.