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