On Do, 24.11.22 00:58, Dominik George (nik@xxxxxxxxxxxxx) wrote: > Hi, > > for some time now, I have been investigating how to best make a > desktop system talk to a web API (HTTP, REST) for user management, so > NSS and PAM make HTTP requests to an API to verify authentication > (using OIDC) and to retrieve NIS information (using REST endpoints). > > One of the approaches I am evaluating involves systemd-userdbd, > because it seems to be designed with extensibility with modular > service implementations in mind. That would make a lot of sense to me. > Right now, I have a few questions concerning its architecture and use: > > * Why was Varlink chosen over D-Bus, given that most other parts of > systemd seem to talk D-Bus? Three reasons: 1. We want this to work in early boot, i.e. before dbus-daemon is up 2. dbus-daemon policies involve user names, thus dbus-daemon must be able to resolve them, and this deadlocks if dbus-daemon is used as transport for the resolution requests dbus-daemon itself makes. 3. D-Bus is suitable for transmitting control data only. It puts limits on queued messages, and thus is not suitable to transfer bulk data. This means it's kinda unsuitable for doing things like a dump of a user database, which might have millions of entries. If we'd ignore that fact, then whenever the user would try to dump the user databsae userdbd would be forcibly kicked off the bus, under the assumption it tried to flood the bus. Every single one of the three is a killer really. using varlink avoids that mess, it requires no broker, is efficient for transferring bulk data, and works from any context. (There are other reasons: for example we want user records to be json objects, and it's just a lot nicer if json is passed around over a json-based IPC then nesting it inside of dbus marshalling. But hese are "softer" reasons, so I'll spare you the rest) > * How does protection of privileged fields work? In a different > approach (using my own gRPC-based protocol), I used peer > credentials on the UNIX socket for authorisation, but it seems this > should break with userdbd when going through the > multipelxer. However, I see "Warning: lacking rights to acquire > privileged fields of user record of 'testnik', output incomplete." > when I try to inspect another user as an unprivileged user. How > does userdbd determine that? See: https://systemd.io/USER_RECORD/ Basically, a user record consist of multiple sections (i.e. json fields contain subobjects), one is called "privileged": this contains everything traditionally found in /etc/shadow basically, and everything else pretty much that should only be visible to privileged users and the user itself. Any IPC service is supposed to strip "privileged" from user records it sends or passes on, and report that in the "incomplete" boolean return parameter – unless it can know for sure (via SO_PEERCRED or so) that whoever it is talking to is the user itself or is privileged. See this for details on the IPC API: https://systemd.io/USER_GROUP_API/ > * userdbd only helps for user information, i.e. for providing data to > NSS through a decoupled interface. I would need to do the same for > PAM, but intil now, I could not find an existing standard for > verifying credentials. Was that just not done yet, or is there a > design decision that userdbd should not offer methods for > authentication? I see that systemd-homed implements its own API > through D-Bus… Yeah, you have to deal with PAM yourself (unless you add classic hashed UNIX passwords in the "privileged" section of your use records – in that case pam_unix will just use that). One of these days people should revisit PAM and redesign it around IPC, but today is not that day I fear. > * Ultimately, I would like to retrieve and store an OAuth token on > user login. It would somehow be a good fit for the "secret" section > of the User Record, but the fields allowed in it seem to be > static. Are there any ideas around here where such a token could be > stored during the user session? Kernel keyring for the user? It's where kerberos stuff is stored, and is probably the best place. The API is a bit convoluted, but this has been done before. Lennart -- Lennart Poettering, Berlin