It’s a new service introduced by systemd v245 (released March 6th 2020) which can take the role of getpwnam(3) and related calls.
userdbctl --output=json Output
{
"userName" : "root",
"uid" : 0,
"gid" : 0,
"homeDirectory" : "/root",
"shell" : "/bin/zsh",
"privileged" : {
"hashedPassword" : [
"$6$wKUquM/L7HzvV5eI$dhexy2iU1efxnYe6k0rm4qT8D1TOgAVtYYyjC5wZeClK.ETeCfPCn0xmwZKK/l8MtzJhtSPTsWEopILQXbA.40"
]
},
"passwordChangeNow" : false,
"lastPasswordChangeUSec" : 1588377600000000,
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "nobody",
"uid" : 65534,
"gid" : 65534,
"realName" : "Nobody",
"homeDirectory" : "/",
"shell" : "/bin/nologin",
"passwordChangeNow" : false,
"lastPasswordChangeUSec" : 1588377600000000,
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "systemd-network",
"uid" : 983,
"gid" : 983,
"realName" : "systemd Network Management",
"homeDirectory" : "/",
"shell" : "/bin/nologin",
"passwordChangeNow" : false,
"lastPasswordChangeUSec" : 1588377600000000,
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "systemd-resolve",
"uid" : 982,
"gid" : 982,
"realName" : "systemd Resolver",
"homeDirectory" : "/",
"shell" : "/bin/nologin",
"passwordChangeNow" : false,
"lastPasswordChangeUSec" : 1588377600000000,
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "systemd-timesync",
"uid" : 981,
"gid" : 981,
"realName" : "systemd Time Synchronization",
"homeDirectory" : "/",
"shell" : "/bin/nologin",
"passwordChangeNow" : false,
"lastPasswordChangeUSec" : 1588377600000000,
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "systemd-coredump",
"uid" : 980,
"gid" : 980,
"realName" : "systemd Core Dumper",
"homeDirectory" : "/",
"shell" : "/bin/nologin",
"passwordChangeNow" : false,
"lastPasswordChangeUSec" : 1588377600000000,
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "systemd-network",
"uid" : 101,
"gid" : 101,
"realName" : "network",
"homeDirectory" : "/run/systemd/netif",
"shell" : "/bin/false",
"passwordChangeNow" : false,
"lastPasswordChangeUSec" : 1588377600000000,
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "systemd-resolve",
"uid" : 105,
"gid" : 105,
"realName" : "resolve",
"homeDirectory" : "/run/systemd/resolve",
"shell" : "/bin/false",
"passwordChangeNow" : false,
"lastPasswordChangeUSec" : 1588377600000000,
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "sshd",
"uid" : 102,
"gid" : 102,
"homeDirectory" : "/",
"shell" : "/bin/false",
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "messagebus",
"uid" : 106,
"gid" : 106,
"homeDirectory" : "/var/run/dbus",
"shell" : "/bin/false",
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "lightdm",
"uid" : 979,
"gid" : 979,
"realName" : "Light Display Manager",
"homeDirectory" : "/var/lib/lightdm",
"shell" : "/bin/nologin",
"passwordChangeNow" : false,
"lastPasswordChangeUSec" : 1588377600000000,
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
{
"userName" : "polkitd",
"uid" : 978,
"gid" : 978,
"realName" : "PolicyKit Daemon",
"homeDirectory" : "/etc/polkit-1",
"shell" : "/bin/nologin",
"passwordChangeNow" : false,
"lastPasswordChangeUSec" : 1588377600000000,
"status" : {
"12f5c9abd57d4914abe2d5cb4958378b" : {
"service" : "io.systemd.NameServiceSwitch"
}
}
}
I recently learnt about systemd’s “User/Group Record Lookup API via Varlink”.
It’s a new service introduced by systemd v245 (released March 6th 2020) which can take the role of getpwnam(3) and related calls.
We could consider this as an option for
os/user, which currently integrates with Name Service Switch (NSS) only when cgo is available. In non-cgo environments, we could try queryingsystemd-userdbd.service(8)before falling back to the current behavior of parsing/etc/passwd.There are two possible ways to query the service:
Parsing
userdbctl --output=json. The upside is that userdbctl itself queries NSS if systemd-userdbd is not working. The downside is that we are relying on an external process. I’m not sure how this is regarded in the standard library, and whether overhead of os/user is of concern?If we wanted to avoid the process overhead, we could integrate with systemd-userdbd directly. I implemented a <100-line proof of concept which prints just the user name. The User/Group Record Lookup API uses a subset of varlink, which boils down to sending and receiving 0-terminated JSON messages over a Unix socket.
Appendix:
userdbctl --output=jsonOutput{ "userName" : "root", "uid" : 0, "gid" : 0, "homeDirectory" : "/root", "shell" : "/bin/zsh", "privileged" : { "hashedPassword" : [ "$6$wKUquM/L7HzvV5eI$dhexy2iU1efxnYe6k0rm4qT8D1TOgAVtYYyjC5wZeClK.ETeCfPCn0xmwZKK/l8MtzJhtSPTsWEopILQXbA.40" ] }, "passwordChangeNow" : false, "lastPasswordChangeUSec" : 1588377600000000, "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "nobody", "uid" : 65534, "gid" : 65534, "realName" : "Nobody", "homeDirectory" : "/", "shell" : "/bin/nologin", "passwordChangeNow" : false, "lastPasswordChangeUSec" : 1588377600000000, "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "systemd-network", "uid" : 983, "gid" : 983, "realName" : "systemd Network Management", "homeDirectory" : "/", "shell" : "/bin/nologin", "passwordChangeNow" : false, "lastPasswordChangeUSec" : 1588377600000000, "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "systemd-resolve", "uid" : 982, "gid" : 982, "realName" : "systemd Resolver", "homeDirectory" : "/", "shell" : "/bin/nologin", "passwordChangeNow" : false, "lastPasswordChangeUSec" : 1588377600000000, "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "systemd-timesync", "uid" : 981, "gid" : 981, "realName" : "systemd Time Synchronization", "homeDirectory" : "/", "shell" : "/bin/nologin", "passwordChangeNow" : false, "lastPasswordChangeUSec" : 1588377600000000, "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "systemd-coredump", "uid" : 980, "gid" : 980, "realName" : "systemd Core Dumper", "homeDirectory" : "/", "shell" : "/bin/nologin", "passwordChangeNow" : false, "lastPasswordChangeUSec" : 1588377600000000, "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "systemd-network", "uid" : 101, "gid" : 101, "realName" : "network", "homeDirectory" : "/run/systemd/netif", "shell" : "/bin/false", "passwordChangeNow" : false, "lastPasswordChangeUSec" : 1588377600000000, "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "systemd-resolve", "uid" : 105, "gid" : 105, "realName" : "resolve", "homeDirectory" : "/run/systemd/resolve", "shell" : "/bin/false", "passwordChangeNow" : false, "lastPasswordChangeUSec" : 1588377600000000, "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "sshd", "uid" : 102, "gid" : 102, "homeDirectory" : "/", "shell" : "/bin/false", "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "messagebus", "uid" : 106, "gid" : 106, "homeDirectory" : "/var/run/dbus", "shell" : "/bin/false", "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "lightdm", "uid" : 979, "gid" : 979, "realName" : "Light Display Manager", "homeDirectory" : "/var/lib/lightdm", "shell" : "/bin/nologin", "passwordChangeNow" : false, "lastPasswordChangeUSec" : 1588377600000000, "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } } { "userName" : "polkitd", "uid" : 978, "gid" : 978, "realName" : "PolicyKit Daemon", "homeDirectory" : "/etc/polkit-1", "shell" : "/bin/nologin", "passwordChangeNow" : false, "lastPasswordChangeUSec" : 1588377600000000, "status" : { "12f5c9abd57d4914abe2d5cb4958378b" : { "service" : "io.systemd.NameServiceSwitch" } } }