fully passwordless nfs through kerberos
The short answer is that the current NFS Kerberos authentication mechanism (RPCSEC_GSS) does not support this. The principal that's making the call is the one who gets access. So if you don't want users to manually get tickets, then you'll need to have the host automatically get tickets for them.
In the future, the newer RPCSEC_GSSv3 protocol might have options for allowing hosts to impersonate arbitrary users, but it hasn't yet been finished nor implemented.
If you want to allow hosts to impersonate any UID, then you don't need Kerberos at all – switch back to the sec=sys
security mode that was used "in the old days". In this mode, the host literally gets to specify a symbolic identifier of the user. (Permission checks still happen, of course.)
In the end, there is no functional difference between allowing a host to impersonate any user via Kerberos (authenticated using the host's /etc/krb5.keytab), versus allowing a host to impersonate any user via basic UID claim (authenticated using the host's IPsec or WireGuard private key or) – and the latter will give you much higher performance than GSSAPI can achieve.
Within Kerberos, when using existing tools only (without outright implementing some kind of host-level authentication for RPC), the closest thing you have is constrained delegation with protocol transition (S4U2Self + S4U2Proxy), where a service is allowed to get tickets to specific other services in the name of a user. It is commonly used in Active Directory environments but is also supported by MIT Kerberos KDCs (and probably Heimdal KDCs – the code is there, thanks to Samba, but I do not know how to enable it on Heimdal).
To enable this in a MIT Kerberos KDC you will need to use the LDAP backend; the file-based HDB backend doesn't support storing the additional fields.
-
Set the
ok_to_auth_as_delegate
principal flag on the client's host principal (can be done through kadmin, or by ORing0x200000
into thekrbTicketFlags
LDAP attribute).kadmin.local modprinc +ok_to_auth_as_delegate host/foo.example.com
-
Set the client principal's
krbAllowedToDelegateTo
LDAP attribute to a list of NFS service principals that it may create the fake tickets for. (One service per value.)ldapmodify <<EOF dn: krbPrincipalName=host/[email protected],cn=EXAMPLE.COM,ou=Kerberos,o=Example add: krbAllowedToDelegateTo krbAllowedToDelegateTo: nfs/fs1.example.com - EOF
-
Test whether S4U features work, as root:
# Acquire host credentials using system keytab host_cc=FILE:/tmp/krb5cc_host kinit -c $host_cc -k klist -c $host_cc # Acquire NFS tickets on behalf of the user using S4U2Proxy kvno -c $host_cc -I $user_name -P nfs/fs1.example.com klist -c $host_cc # Do the same, but put the tickets in that user's cache # so that rpc.gssd would be able to find them user_cc=FILE:/tmp/krb5cc_$(id -u $user) kvno -c $host_cc -I $user -P nfs/fs1.example.com --out-cache $user_cc chown $user: $user_cc
-
Install gss-proxy on the client, and edit its included
nfs-client.conf
to use S4U2Proxy instead of individual client keytabs:[service/nfs-client] mechs = krb5 cred_store = keytab:/etc/krb5.keytab cred_store = ccache:FILE:/var/lib/gssproxy/clients/krb5cc_%U impersonate = yes allow_any_uid = yes trusted = yes euid = 0
This example is based on https://github.com/gssapi/gssproxy/blob/main/docs/NFS.md#user-impersonation-via-constrained-delegation.
-
Configure the client's rpc.gssd daemon to use gss-proxy by adding
GSS_USE_PROXY=1
to the environment:# systemctl edit rpc-gssd [Service] Environment=GSS_USE_PROXY=1 # systemctl restart rpc-gssd
If Kerberos is used exclusively for NFS, and if each host only needs a limited set of users, then the host can store client keytabs (which hold the password-derived keys) for those users. This is roughly equivalent to storing the users' passwords, as the keytab allows