2022-02-06 02:19:13

by Benjamin Coddington

[permalink] [raw]
Subject: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

The nfs4id program will either create a new UUID from a random source or
derive it from /etc/machine-id, else it returns a UUID that has already
been written to /etc/nfs4-id. This small, lightweight tool is suitable for
execution by systemd-udev in rules to populate the nfs4 client uniquifier.

Signed-off-by: Benjamin Coddington <[email protected]>
---
.gitignore | 1 +
configure.ac | 4 +
tools/Makefile.am | 1 +
tools/nfs4id/Makefile.am | 8 ++
tools/nfs4id/nfs4id.c | 184 +++++++++++++++++++++++++++++++++++++++
tools/nfs4id/nfs4id.man | 29 ++++++
6 files changed, 227 insertions(+)
create mode 100644 tools/nfs4id/Makefile.am
create mode 100644 tools/nfs4id/nfs4id.c
create mode 100644 tools/nfs4id/nfs4id.man

diff --git a/.gitignore b/.gitignore
index c89d1cd2583d..a37964148dd8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,7 @@ utils/statd/statd
tools/locktest/testlk
tools/getiversion/getiversion
tools/nfsconf/nfsconf
+tools/nfs4id/nfs4id
support/export/mount.h
support/export/mount_clnt.c
support/export/mount_xdr.c
diff --git a/configure.ac b/configure.ac
index 50e9b321dcf3..93d0a902cfd8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -355,6 +355,9 @@ if test "$enable_nfsv4" = yes; then
dnl check for the keyutils libraries and headers
AC_KEYUTILS

+ dnl check for the libuuid library and headers
+ AC_LIBUUID
+
dnl Check for sqlite3
AC_SQLITE3_VERS

@@ -740,6 +743,7 @@ AC_CONFIG_FILES([
tools/nfsdclnts/Makefile
tools/nfsconf/Makefile
tools/nfsdclddb/Makefile
+ tools/nfs4id/Makefile
utils/Makefile
utils/blkmapd/Makefile
utils/nfsdcld/Makefile
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 9b4b0803db39..cc658f69bb32 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -7,6 +7,7 @@ OPTDIRS += rpcgen
endif

OPTDIRS += nfsconf
+OPTDIRS += nfs4id

if CONFIG_NFSDCLD
OPTDIRS += nfsdclddb
diff --git a/tools/nfs4id/Makefile.am b/tools/nfs4id/Makefile.am
new file mode 100644
index 000000000000..d1e60a35a510
--- /dev/null
+++ b/tools/nfs4id/Makefile.am
@@ -0,0 +1,8 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS = nfs4id.man
+
+bin_PROGRAMS = nfs4id
+
+nfs4id_SOURCES = nfs4id.c
+nfs4id_LDADD = $(LIBUUID)
diff --git a/tools/nfs4id/nfs4id.c b/tools/nfs4id/nfs4id.c
new file mode 100644
index 000000000000..dbb807ae21f3
--- /dev/null
+++ b/tools/nfs4id/nfs4id.c
@@ -0,0 +1,184 @@
+/*
+ * nfs4id.c -- create and persist uniquifiers for nfs4 clients
+ *
+ * Copyright (C) 2022 Red Hat, Benjamin Coddington <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <uuid/uuid.h>
+
+#define NFS4IDFILE "/etc/nfs4-id"
+
+UUID_DEFINE(nfs4_clientid_uuid_template,
+ 0xa2, 0x25, 0x68, 0xb2, 0x7a, 0x5f, 0x49, 0x90,
+ 0x8f, 0x98, 0xc5, 0xf0, 0x67, 0x78, 0xcc, 0xf1);
+
+static char *prog;
+static char *source = NULL;
+static char nfs4_id[64];
+static int force = 0;
+
+static void usage(void)
+{
+ fprintf(stderr, "usage: %s [-f|--force] [machine]\n", prog);
+}
+
+static void fatal(const char *fmt, ...)
+{
+ int err = errno;
+ va_list args;
+ char fatal_msg[256] = "fatal: ";
+
+ va_start(args, fmt);
+ vsnprintf(&fatal_msg[7], 255, fmt, args);
+ if (err)
+ fprintf(stderr, "%s: %s\n", fatal_msg, strerror(err));
+ else
+ fprintf(stderr, "%s\n", fatal_msg);
+ exit(-1);
+}
+
+static int read_nfs4_id(void)
+{
+ int fd;
+
+ fd = open(NFS4IDFILE, O_RDONLY);
+ if (fd < 0)
+ return fd;
+ read(fd, nfs4_id, 64);
+ close(fd);
+ return 0;
+}
+
+static void write_nfs4_id(void)
+{
+ int fd;
+
+ fd = open(NFS4IDFILE, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (fd < 0)
+ fatal("could not write id to " NFS4IDFILE);
+ write(fd, nfs4_id, 37);
+}
+
+static void print_nfs4_id(void)
+{
+ fprintf(stdout, "%s", nfs4_id);
+}
+
+static void check_or_make_id(void)
+{
+ int ret;
+ uuid_t nfs4id_uuid;
+
+ ret = read_nfs4_id();
+ if (ret != 0) {
+ if (errno != ENOENT )
+ fatal("reading file " NFS4IDFILE);
+ uuid_generate_random(nfs4id_uuid);
+ uuid_unparse(nfs4id_uuid, nfs4_id);
+ nfs4_id[36] = '\n';
+ nfs4_id[37] = '\0';
+ write_nfs4_id();
+ }
+ print_nfs4_id();
+}
+
+static void check_or_make_id_from_machine(void)
+{
+ int fd, ret;
+ char machineid[32];
+ uuid_t nfs4id_uuid;
+
+ ret = read_nfs4_id();
+ if (ret != 0) {
+ if (errno != ENOENT )
+ fatal("reading file " NFS4IDFILE);
+
+ fd = open("/etc/machine-id", O_RDONLY);
+ if (fd < 0)
+ fatal("unable to read /etc/machine-id");
+
+ read(fd, machineid, 32);
+ close(fd);
+
+ uuid_generate_sha1(nfs4id_uuid, nfs4_clientid_uuid_template, machineid, 32);
+ uuid_unparse(nfs4id_uuid, nfs4_id);
+ nfs4_id[36] = '\n';
+ nfs4_id[37] = '\0';
+ write_nfs4_id();
+ }
+ print_nfs4_id();
+}
+
+int main(int argc, char **argv)
+{
+ prog = argv[0];
+
+ while (1) {
+ int opt;
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"force", no_argument, 0, 'f' },
+ {0, 0, 0, 0 }
+ };
+
+ errno = 0;
+ opt = getopt_long(argc, argv, ":f", long_options, &option_index);
+ if (opt == -1)
+ break;
+
+ switch (opt) {
+ case 'f':
+ force = 1;
+ break;
+ case '?':
+ usage();
+ fatal("unexpected arg \"%s\"", argv[optind - 1]);
+ break;
+ }
+ }
+
+ argc -= optind;
+
+ if (argc > 1) {
+ usage();
+ fatal("Too many arguments");
+ }
+
+ if (argc)
+ source = argv[optind++];
+
+ if (force)
+ unlink(NFS4IDFILE);
+
+ if (!source)
+ check_or_make_id();
+ else if (strcmp(source, "machine") == 0)
+ check_or_make_id_from_machine();
+ else {
+ usage();
+ fatal("unrecognized source %s\n", source);
+ }
+}
diff --git a/tools/nfs4id/nfs4id.man b/tools/nfs4id/nfs4id.man
new file mode 100644
index 000000000000..358f836468a2
--- /dev/null
+++ b/tools/nfs4id/nfs4id.man
@@ -0,0 +1,29 @@
+.\"
+.\" nfs4id(8)
+.\"
+.TH nfs4id 8 "3 Feb 2022"
+.SH NAME
+nfs4id \- Generate or return nfs4 client id uniqueifiers
+.SH SYNOPSIS
+.B nfs4id [ -f | --force ] [<source>]
+
+.SH DESCRIPTION
+The
+.B nfs4id
+command provides a simple utility to help NFS Version 4 clients use unique
+and persistent client id values. The command checks for the existence of a
+file /etc/nfs4-id and returns the first 64 chars read from that file. If
+the file is not found, a UUID is generated from the specified source and
+written to the file and returned.
+.SH OPTIONS
+.TP
+.BR \-f, \-\-force
+Overwrite the existing /etc/nfs4-id with a UUID generated from <source>.
+.SH Sources
+If <source> is not specified, nfs4id will generate a new random UUID.
+
+If <source> is "machine", nfs4id will generate a deterministic UUID value
+derived from a sha1 hash of the contents of /etc/machine-id and a static
+key.
+.SH SEE ALSO
+.BR machine-id (5)
--
2.31.1



2022-02-07 19:10:24

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 4 Feb 2022, at 10:17, Chuck Lever III wrote:

> Hi Ben-
>
>> On Feb 4, 2022, at 7:56 AM, Benjamin Coddington <[email protected]>
>> wrote:
>>
>> The nfs4id program will either create a new UUID from a random source
>> or
>> derive it from /etc/machine-id, else it returns a UUID that has
>> already
>> been written to /etc/nfs4-id. This small, lightweight tool is
>> suitable for
>> execution by systemd-udev in rules to populate the nfs4 client
>> uniquifier.
>
> Glad to see some progress here!
>
> Regarding the generation of these uniquifiers:
>
> If you have a UUID generation mechanism, why bother with machine-id at
> all?

We'd like to deterministically tie our clients to /etc/machine-id for a
number
of reasons:

- it condenses the work of "uniquifying" a machine to a single point
in
the distro.

- the machine-id has a number of ways to handle cases where machines
are
PXE-booted, cloned, or used as "golden images" for cloud containers
(See
machine-id(5)).

- the machine-id has good documentation and awareness (See sd-id128(3)
and
friends)

> As noted in bugzilla@redhat 1801326, these uniquifiers will appear in
> the
> clear on open networks (and we all know open network deployments are
> common
> for NFS). I don't believe that TLS or GSS Kerberos will be available
> to
> protect every deployment from a network MitM from sniffing these
> values and
> attempting to make some hay with them. In particular, any deployment
> of a
> system before we have in-transit NFS encryption implemented will be
> vulnerable.

Yes.

> Some young punk from Tatooine could drop a bomb down our reactor
> shaft,
> and then where would we be?

This little tool isn't attempting to solve any of those problems.

> Regarding the storage of these uniquifiers:
>
> As discussed in earlier threads, we believe that storing multiple
> unique-ids
> in one file, especially without locking to prevent tearing of data in
> the
> file, is problematic. Now, it might be that the objection to this was
> based
> on storing these in a file that can simultaneously be edited by humans
> (ie, /etc/nfs.conf). But I would prefer to see a separate file used
> for
> each uniquifier / network namespace.

This tool isn't trying to store uniquifiers for multiple namespaces, or
describe how it ought to be used in relation to namespaces. It only
attempts to create a fairly persistent unique value that can be
generated
and consumed from a udev rule.

I think the problem of how to create uniquifiers for every net namespace
might easily be solved by bind-mounding /etc/nfs4-id into the
namespace-specific filesystem, or a number of other ways. That would be
an
interesting new topic. New sources could be added to this tool in the
future that are namespace-aware.

Thanks for the look at this!

Ben


2022-02-08 14:35:36

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 7 Feb 2022, at 22:14, NeilBrown wrote:

> On Sat, 05 Feb 2022, Chuck Lever III wrote:
>>
>> The problem is that a network namespace (to which the persistent
>> uniquifier is attached) and an FS namespace (in which the persistent
>> uniquifier is stored) are created and managed independently.
>
> Not necessarily .... at least: network namespaces do have visibility in
> the filesystem and you can have files that associate with a specific
> network namespace - without depending on FS namespaces.
>
> "man ip-netns" tells us that when a tool (e.g. mount.nfs) is
> network-namespace aware, it should first look in /etc/netns/NAME/
> before looking in /etc/ for any config file.
> The tool can determine "NAME" by running "ip netns identify", but there
> is bound to library code to achieve the same effect.
> You stat /proc/self/ns/net, then readdir /run/netns and stat everything
> in there until you find something that matches /proc/self/ns/net
>
> If a container management system wants to put /etc/ elsewhere, it can
> doubtlessly install a symlink in /etc/netns/NAME, and as this is an
> established standard, it seems likely that they already do.
>
> So: enhance nfs-utils config code to (optionally) look in
> /etc/netns/NAME first (or maybe last if they are to override) , and
> store the identity in /etc/{netns/NAME/}nfs.conf.d/identity.conf
>
> Whatever tool creates the identity, writes it to
> /etc/netns/NAME/nfs.conf.d/identity.conf
>
> While we are at it, we should get exportfs to look there too, and
> establish some convention so /var/lib/nfs can use a different path in
> different network namespaces.

Thanks! This is extremely helpful.

I can modify nfs4id to check if it has been invoked within a network
namespace, then then check and store uuids in /etc/netns/NAME first.

Ben


2022-02-09 02:47:34

by Steve Dickson

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers



On 2/8/22 11:21 AM, Chuck Lever III wrote:
>
>
>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <[email protected]> wrote:
>>
>> Hello,
>>
>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>> The nfs4id program will either create a new UUID from a random source or
>>> derive it from /etc/machine-id, else it returns a UUID that has already
>>> been written to /etc/nfs4-id. This small, lightweight tool is suitable for
>>> execution by systemd-udev in rules to populate the nfs4 client uniquifier.
>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>> ---
>>> .gitignore | 1 +
>>> configure.ac | 4 +
>>> tools/Makefile.am | 1 +
>>> tools/nfs4id/Makefile.am | 8 ++
>>> tools/nfs4id/nfs4id.c | 184 +++++++++++++++++++++++++++++++++++++++
>>> tools/nfs4id/nfs4id.man | 29 ++++++
>>> 6 files changed, 227 insertions(+)
>>> create mode 100644 tools/nfs4id/Makefile.am
>>> create mode 100644 tools/nfs4id/nfs4id.c
>>> create mode 100644 tools/nfs4id/nfs4id.man
>> Just a nit... naming convention... In the past
>> we never put the protocol version in the name.
>> Do a ls tools and utils directory and you
>> see what I mean....
>>
>> Would it be a problem to change the name from
>> nfs4id to nfsid?
>
> nfs4id is pretty generic, too.
>
> Can we go with nfs-client-id ?
I'm never been big with putting '-'
in command names... nfscltid would
be better IMHO... if we actually
need the 'clt' in the name.

steved.

>
>
>> steved.
>>
>>> diff --git a/.gitignore b/.gitignore
>>> index c89d1cd2583d..a37964148dd8 100644
>>> --- a/.gitignore
>>> +++ b/.gitignore
>>> @@ -61,6 +61,7 @@ utils/statd/statd
>>> tools/locktest/testlk
>>> tools/getiversion/getiversion
>>> tools/nfsconf/nfsconf
>>> +tools/nfs4id/nfs4id
>>> support/export/mount.h
>>> support/export/mount_clnt.c
>>> support/export/mount_xdr.c
>>> diff --git a/configure.ac b/configure.ac
>>> index 50e9b321dcf3..93d0a902cfd8 100644
>>> --- a/configure.ac
>>> +++ b/configure.ac
>>> @@ -355,6 +355,9 @@ if test "$enable_nfsv4" = yes; then
>>> dnl check for the keyutils libraries and headers
>>> AC_KEYUTILS
>>> + dnl check for the libuuid library and headers
>>> + AC_LIBUUID
>>> +
>>> dnl Check for sqlite3
>>> AC_SQLITE3_VERS
>>> @@ -740,6 +743,7 @@ AC_CONFIG_FILES([
>>> tools/nfsdclnts/Makefile
>>> tools/nfsconf/Makefile
>>> tools/nfsdclddb/Makefile
>>> + tools/nfs4id/Makefile
>>> utils/Makefile
>>> utils/blkmapd/Makefile
>>> utils/nfsdcld/Makefile
>>> diff --git a/tools/Makefile.am b/tools/Makefile.am
>>> index 9b4b0803db39..cc658f69bb32 100644
>>> --- a/tools/Makefile.am
>>> +++ b/tools/Makefile.am
>>> @@ -7,6 +7,7 @@ OPTDIRS += rpcgen
>>> endif
>>> OPTDIRS += nfsconf
>>> +OPTDIRS += nfs4id
>>> if CONFIG_NFSDCLD
>>> OPTDIRS += nfsdclddb
>>> diff --git a/tools/nfs4id/Makefile.am b/tools/nfs4id/Makefile.am
>>> new file mode 100644
>>> index 000000000000..d1e60a35a510
>>> --- /dev/null
>>> +++ b/tools/nfs4id/Makefile.am
>>> @@ -0,0 +1,8 @@
>>> +## Process this file with automake to produce Makefile.in
>>> +
>>> +man8_MANS = nfs4id.man
>>> +
>>> +bin_PROGRAMS = nfs4id
>>> +
>>> +nfs4id_SOURCES = nfs4id.c
>>> +nfs4id_LDADD = $(LIBUUID)
>>> diff --git a/tools/nfs4id/nfs4id.c b/tools/nfs4id/nfs4id.c
>>> new file mode 100644
>>> index 000000000000..dbb807ae21f3
>>> --- /dev/null
>>> +++ b/tools/nfs4id/nfs4id.c
>>> @@ -0,0 +1,184 @@
>>> +/*
>>> + * nfs4id.c -- create and persist uniquifiers for nfs4 clients
>>> + *
>>> + * Copyright (C) 2022 Red Hat, Benjamin Coddington <[email protected]>
>>> + *
>>> + * This program is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU General Public License
>>> + * as published by the Free Software Foundation; either version 2
>>> + * of the License, or (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program; if not, write to the Free Software
>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
>>> + * Boston, MA 02110-1301, USA.
>>> + */
>>> +
>>> +#include <stdio.h>
>>> +#include <stdarg.h>
>>> +#include <getopt.h>
>>> +#include <string.h>
>>> +#include <errno.h>
>>> +#include <stdlib.h>
>>> +#include <fcntl.h>
>>> +#include <unistd.h>
>>> +#include <uuid/uuid.h>
>>> +
>>> +#define NFS4IDFILE "/etc/nfs4-id"
>>> +
>>> +UUID_DEFINE(nfs4_clientid_uuid_template,
>>> + 0xa2, 0x25, 0x68, 0xb2, 0x7a, 0x5f, 0x49, 0x90,
>>> + 0x8f, 0x98, 0xc5, 0xf0, 0x67, 0x78, 0xcc, 0xf1);
>>> +
>>> +static char *prog;
>>> +static char *source = NULL;
>>> +static char nfs4_id[64];
>>> +static int force = 0;
>>> +
>>> +static void usage(void)
>>> +{
>>> + fprintf(stderr, "usage: %s [-f|--force] [machine]\n", prog);
>>> +}
>>> +
>>> +static void fatal(const char *fmt, ...)
>>> +{
>>> + int err = errno;
>>> + va_list args;
>>> + char fatal_msg[256] = "fatal: ";
>>> +
>>> + va_start(args, fmt);
>>> + vsnprintf(&fatal_msg[7], 255, fmt, args);
>>> + if (err)
>>> + fprintf(stderr, "%s: %s\n", fatal_msg, strerror(err));
>>> + else
>>> + fprintf(stderr, "%s\n", fatal_msg);
>>> + exit(-1);
>>> +}
>>> +
>>> +static int read_nfs4_id(void)
>>> +{
>>> + int fd;
>>> +
>>> + fd = open(NFS4IDFILE, O_RDONLY);
>>> + if (fd < 0)
>>> + return fd;
>>> + read(fd, nfs4_id, 64);
>>> + close(fd);
>>> + return 0;
>>> +}
>>> +
>>> +static void write_nfs4_id(void)
>>> +{
>>> + int fd;
>>> +
>>> + fd = open(NFS4IDFILE, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
>>> + if (fd < 0)
>>> + fatal("could not write id to " NFS4IDFILE);
>>> + write(fd, nfs4_id, 37);
>>> +}
>>> +
>>> +static void print_nfs4_id(void)
>>> +{
>>> + fprintf(stdout, "%s", nfs4_id);
>>> +}
>>> +
>>> +static void check_or_make_id(void)
>>> +{
>>> + int ret;
>>> + uuid_t nfs4id_uuid;
>>> +
>>> + ret = read_nfs4_id();
>>> + if (ret != 0) {
>>> + if (errno != ENOENT )
>>> + fatal("reading file " NFS4IDFILE);
>>> + uuid_generate_random(nfs4id_uuid);
>>> + uuid_unparse(nfs4id_uuid, nfs4_id);
>>> + nfs4_id[36] = '\n';
>>> + nfs4_id[37] = '\0';
>>> + write_nfs4_id();
>>> + }
>>> + print_nfs4_id();
>>> +}
>>> +
>>> +static void check_or_make_id_from_machine(void)
>>> +{
>>> + int fd, ret;
>>> + char machineid[32];
>>> + uuid_t nfs4id_uuid;
>>> +
>>> + ret = read_nfs4_id();
>>> + if (ret != 0) {
>>> + if (errno != ENOENT )
>>> + fatal("reading file " NFS4IDFILE);
>>> +
>>> + fd = open("/etc/machine-id", O_RDONLY);
>>> + if (fd < 0)
>>> + fatal("unable to read /etc/machine-id");
>>> +
>>> + read(fd, machineid, 32);
>>> + close(fd);
>>> +
>>> + uuid_generate_sha1(nfs4id_uuid, nfs4_clientid_uuid_template, machineid, 32);
>>> + uuid_unparse(nfs4id_uuid, nfs4_id);
>>> + nfs4_id[36] = '\n';
>>> + nfs4_id[37] = '\0';
>>> + write_nfs4_id();
>>> + }
>>> + print_nfs4_id();
>>> +}
>>> +
>>> +int main(int argc, char **argv)
>>> +{
>>> + prog = argv[0];
>>> +
>>> + while (1) {
>>> + int opt;
>>> + int option_index = 0;
>>> + static struct option long_options[] = {
>>> + {"force", no_argument, 0, 'f' },
>>> + {0, 0, 0, 0 }
>>> + };
>>> +
>>> + errno = 0;
>>> + opt = getopt_long(argc, argv, ":f", long_options, &option_index);
>>> + if (opt == -1)
>>> + break;
>>> +
>>> + switch (opt) {
>>> + case 'f':
>>> + force = 1;
>>> + break;
>>> + case '?':
>>> + usage();
>>> + fatal("unexpected arg \"%s\"", argv[optind - 1]);
>>> + break;
>>> + }
>>> + }
>>> +
>>> + argc -= optind;
>>> +
>>> + if (argc > 1) {
>>> + usage();
>>> + fatal("Too many arguments");
>>> + }
>>> +
>>> + if (argc)
>>> + source = argv[optind++];
>>> +
>>> + if (force)
>>> + unlink(NFS4IDFILE);
>>> +
>>> + if (!source)
>>> + check_or_make_id();
>>> + else if (strcmp(source, "machine") == 0)
>>> + check_or_make_id_from_machine();
>>> + else {
>>> + usage();
>>> + fatal("unrecognized source %s\n", source);
>>> + }
>>> +}
>>> diff --git a/tools/nfs4id/nfs4id.man b/tools/nfs4id/nfs4id.man
>>> new file mode 100644
>>> index 000000000000..358f836468a2
>>> --- /dev/null
>>> +++ b/tools/nfs4id/nfs4id.man
>>> @@ -0,0 +1,29 @@
>>> +.\"
>>> +.\" nfs4id(8)
>>> +.\"
>>> +.TH nfs4id 8 "3 Feb 2022"
>>> +.SH NAME
>>> +nfs4id \- Generate or return nfs4 client id uniqueifiers
>>> +.SH SYNOPSIS
>>> +.B nfs4id [ -f | --force ] [<source>]
>>> +
>>> +.SH DESCRIPTION
>>> +The
>>> +.B nfs4id
>>> +command provides a simple utility to help NFS Version 4 clients use unique
>>> +and persistent client id values. The command checks for the existence of a
>>> +file /etc/nfs4-id and returns the first 64 chars read from that file. If
>>> +the file is not found, a UUID is generated from the specified source and
>>> +written to the file and returned.
>>> +.SH OPTIONS
>>> +.TP
>>> +.BR \-f, \-\-force
>>> +Overwrite the existing /etc/nfs4-id with a UUID generated from <source>.
>>> +.SH Sources
>>> +If <source> is not specified, nfs4id will generate a new random UUID.
>>> +
>>> +If <source> is "machine", nfs4id will generate a deterministic UUID value
>>> +derived from a sha1 hash of the contents of /etc/machine-id and a static
>>> +key.
>>> +.SH SEE ALSO
>>> +.BR machine-id (5)
>
> --
> Chuck Lever
>
>
>


2022-02-09 05:46:25

by Steve Dickson

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

Hey!

On 2/8/22 3:00 PM, Benjamin Coddington wrote:
> On 8 Feb 2022, at 14:52, Steve Dickson wrote:
>
>> On 2/8/22 11:22 AM, Benjamin Coddington wrote:
>>> On 8 Feb 2022, at 11:04, Steve Dickson wrote:
>>>
>>>> Hello,
>>>>
>>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>>> The nfs4id program will either create a new UUID from a random
>>>>> source or
>>>>> derive it from /etc/machine-id, else it returns a UUID that has
>>>>> already
>>>>> been written to /etc/nfs4-id.  This small, lightweight tool is
>>>>> suitable for
>>>>> execution by systemd-udev in rules to populate the nfs4 client
>>>>> uniquifier.
>>>>>
>>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>>> ---
>>>>>   .gitignore               |   1 +
>>>>>   configure.ac             |   4 +
>>>>>   tools/Makefile.am        |   1 +
>>>>>   tools/nfs4id/Makefile.am |   8 ++
>>>>>   tools/nfs4id/nfs4id.c    | 184
>>>>> +++++++++++++++++++++++++++++++++++++++
>>>>>   tools/nfs4id/nfs4id.man  |  29 ++++++
>>>>>   6 files changed, 227 insertions(+)
>>>>>   create mode 100644 tools/nfs4id/Makefile.am
>>>>>   create mode 100644 tools/nfs4id/nfs4id.c
>>>>>   create mode 100644 tools/nfs4id/nfs4id.man
>>>> Just a nit... naming convention... In the past
>>>> we never put the protocol version in the name.
>>>> Do a ls tools and utils directory and you
>>>> see what I mean....
>>>>
>>>> Would it be a problem to change the name from
>>>> nfs4id to nfsid?
>>>
>>> Not at all..
>> Good...
>
> I didn't orginally do that because I thought it might be confusing for some
> folks who want `nfsid` to display their kerberos identity.  There's a BZ
> open for that!
>
> Do you think that's a problem?  I feel like it's a problem.
>
>>> and I think there's a lot of room for naming discussions about
>>> the file to store the id too:
>>>
>>> Trond sent /etc/nfs4_uuid
>>> Neil suggests /etc/netns/NAME/nfs.conf.d/identity.conf
>>> Ben sent /etc/nfs4-id (to match /etc/machine-id)
>> Question... is it kosher to be writing /etc which is
>> generally on the root filesystem?
>
> Sure, why not?
In general, writes to /etc are only happen when packages
are installed and removed... any real time writes go
to /var or /run (which is not persistent).

>
>> By far Neil suggestion is the most intriguing... but
>> on the containers I'm looking at there no /etc/netns
>> directory.
>
> Not yet -- you can create it.
"you" meaning who? the nfs-utils install or network
namespace env? Or is it, when /etc/netns exists
there is a network namespace and we should use
that dir?

>
>> I had to install the iproute package to do the
>> "ip netns identify" which returns NULL...
>> also adds yet another dependency on nfs-utils.
>
> We don't need the dependency..this little binary is just a helper for a
> udev
> rule.  Trond already wrote his version of this.  :)  This one's just trying
> to be a little lighter (whoa, we don't need all of bash!).
Fair enough.

>
>> So if "ip netns identify" does return NULL what directory
>> path should be used?
>
> I think thats out of scope..  if udevd is running in a container, and has a
> rule that uses this tool, then the container either is likely to have
> already customized its /etc.  Or perhaps we can make the udev rule
> namespace
> aware (I need to look into what's available to udev's rule environment when
> it runs in a namespace).
With all do respect... that is a lot of hand waving :-)
I'll wait to see what comes you come up with.

>
>> I'm all for making things container friendly but I'm
>> also a fan of keeping things simple... So
>> how about /etc/nfs.conf.d/identity.conf or
>> /etc/nfs.conf.d/nfsid.conf?
>
> Really, because its not a configuration.  Its value persistence, and we
> /really/
> don't want people configuring it.
Good point... and I got it... I was just trying to used
the parsing code we already have in place.

>
>>>
>>> Maybe the tool wants an option to specify the file?
>> This is probably not a bad idea... It is a common practice
>
> OK, I'll do that.
Thanks!

steved.

>
> Ben
>


2022-02-09 06:33:47

by Chuck Lever III

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers



> On Feb 8, 2022, at 2:29 PM, Steve Dickson <[email protected]> wrote:
>
>
>
> On 2/8/22 11:21 AM, Chuck Lever III wrote:
>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <[email protected]> wrote:
>>>
>>> Hello,
>>>
>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>> The nfs4id program will either create a new UUID from a random source or
>>>> derive it from /etc/machine-id, else it returns a UUID that has already
>>>> been written to /etc/nfs4-id. This small, lightweight tool is suitable for
>>>> execution by systemd-udev in rules to populate the nfs4 client uniquifier.
>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>> ---
>>>> .gitignore | 1 +
>>>> configure.ac | 4 +
>>>> tools/Makefile.am | 1 +
>>>> tools/nfs4id/Makefile.am | 8 ++
>>>> tools/nfs4id/nfs4id.c | 184 +++++++++++++++++++++++++++++++++++++++
>>>> tools/nfs4id/nfs4id.man | 29 ++++++
>>>> 6 files changed, 227 insertions(+)
>>>> create mode 100644 tools/nfs4id/Makefile.am
>>>> create mode 100644 tools/nfs4id/nfs4id.c
>>>> create mode 100644 tools/nfs4id/nfs4id.man
>>> Just a nit... naming convention... In the past
>>> we never put the protocol version in the name.
>>> Do a ls tools and utils directory and you
>>> see what I mean....
>>>
>>> Would it be a problem to change the name from
>>> nfs4id to nfsid?
>> nfs4id is pretty generic, too.
>> Can we go with nfs-client-id ?
> I'm never been big with putting '-'
> in command names... nfscltid would
> be better IMHO... if we actually
> need the 'clt' in the name.

We have nfsidmap already. IMO we need some distinction
with user ID mapping tools... and some day we might
want to manage server IDs too (see EXCHANGE_ID).

nfsclientid then?


> steved.
>
>>> steved.
>>>
>>>> diff --git a/.gitignore b/.gitignore
>>>> index c89d1cd2583d..a37964148dd8 100644
>>>> --- a/.gitignore
>>>> +++ b/.gitignore
>>>> @@ -61,6 +61,7 @@ utils/statd/statd
>>>> tools/locktest/testlk
>>>> tools/getiversion/getiversion
>>>> tools/nfsconf/nfsconf
>>>> +tools/nfs4id/nfs4id
>>>> support/export/mount.h
>>>> support/export/mount_clnt.c
>>>> support/export/mount_xdr.c
>>>> diff --git a/configure.ac b/configure.ac
>>>> index 50e9b321dcf3..93d0a902cfd8 100644
>>>> --- a/configure.ac
>>>> +++ b/configure.ac
>>>> @@ -355,6 +355,9 @@ if test "$enable_nfsv4" = yes; then
>>>> dnl check for the keyutils libraries and headers
>>>> AC_KEYUTILS
>>>> + dnl check for the libuuid library and headers
>>>> + AC_LIBUUID
>>>> +
>>>> dnl Check for sqlite3
>>>> AC_SQLITE3_VERS
>>>> @@ -740,6 +743,7 @@ AC_CONFIG_FILES([
>>>> tools/nfsdclnts/Makefile
>>>> tools/nfsconf/Makefile
>>>> tools/nfsdclddb/Makefile
>>>> + tools/nfs4id/Makefile
>>>> utils/Makefile
>>>> utils/blkmapd/Makefile
>>>> utils/nfsdcld/Makefile
>>>> diff --git a/tools/Makefile.am b/tools/Makefile.am
>>>> index 9b4b0803db39..cc658f69bb32 100644
>>>> --- a/tools/Makefile.am
>>>> +++ b/tools/Makefile.am
>>>> @@ -7,6 +7,7 @@ OPTDIRS += rpcgen
>>>> endif
>>>> OPTDIRS += nfsconf
>>>> +OPTDIRS += nfs4id
>>>> if CONFIG_NFSDCLD
>>>> OPTDIRS += nfsdclddb
>>>> diff --git a/tools/nfs4id/Makefile.am b/tools/nfs4id/Makefile.am
>>>> new file mode 100644
>>>> index 000000000000..d1e60a35a510
>>>> --- /dev/null
>>>> +++ b/tools/nfs4id/Makefile.am
>>>> @@ -0,0 +1,8 @@
>>>> +## Process this file with automake to produce Makefile.in
>>>> +
>>>> +man8_MANS = nfs4id.man
>>>> +
>>>> +bin_PROGRAMS = nfs4id
>>>> +
>>>> +nfs4id_SOURCES = nfs4id.c
>>>> +nfs4id_LDADD = $(LIBUUID)
>>>> diff --git a/tools/nfs4id/nfs4id.c b/tools/nfs4id/nfs4id.c
>>>> new file mode 100644
>>>> index 000000000000..dbb807ae21f3
>>>> --- /dev/null
>>>> +++ b/tools/nfs4id/nfs4id.c
>>>> @@ -0,0 +1,184 @@
>>>> +/*
>>>> + * nfs4id.c -- create and persist uniquifiers for nfs4 clients
>>>> + *
>>>> + * Copyright (C) 2022 Red Hat, Benjamin Coddington <[email protected]>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU General Public License
>>>> + * as published by the Free Software Foundation; either version 2
>>>> + * of the License, or (at your option) any later version.
>>>> + *
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>>> + * GNU General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU General Public License
>>>> + * along with this program; if not, write to the Free Software
>>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
>>>> + * Boston, MA 02110-1301, USA.
>>>> + */
>>>> +
>>>> +#include <stdio.h>
>>>> +#include <stdarg.h>
>>>> +#include <getopt.h>
>>>> +#include <string.h>
>>>> +#include <errno.h>
>>>> +#include <stdlib.h>
>>>> +#include <fcntl.h>
>>>> +#include <unistd.h>
>>>> +#include <uuid/uuid.h>
>>>> +
>>>> +#define NFS4IDFILE "/etc/nfs4-id"
>>>> +
>>>> +UUID_DEFINE(nfs4_clientid_uuid_template,
>>>> + 0xa2, 0x25, 0x68, 0xb2, 0x7a, 0x5f, 0x49, 0x90,
>>>> + 0x8f, 0x98, 0xc5, 0xf0, 0x67, 0x78, 0xcc, 0xf1);
>>>> +
>>>> +static char *prog;
>>>> +static char *source = NULL;
>>>> +static char nfs4_id[64];
>>>> +static int force = 0;
>>>> +
>>>> +static void usage(void)
>>>> +{
>>>> + fprintf(stderr, "usage: %s [-f|--force] [machine]\n", prog);
>>>> +}
>>>> +
>>>> +static void fatal(const char *fmt, ...)
>>>> +{
>>>> + int err = errno;
>>>> + va_list args;
>>>> + char fatal_msg[256] = "fatal: ";
>>>> +
>>>> + va_start(args, fmt);
>>>> + vsnprintf(&fatal_msg[7], 255, fmt, args);
>>>> + if (err)
>>>> + fprintf(stderr, "%s: %s\n", fatal_msg, strerror(err));
>>>> + else
>>>> + fprintf(stderr, "%s\n", fatal_msg);
>>>> + exit(-1);
>>>> +}
>>>> +
>>>> +static int read_nfs4_id(void)
>>>> +{
>>>> + int fd;
>>>> +
>>>> + fd = open(NFS4IDFILE, O_RDONLY);
>>>> + if (fd < 0)
>>>> + return fd;
>>>> + read(fd, nfs4_id, 64);
>>>> + close(fd);
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static void write_nfs4_id(void)
>>>> +{
>>>> + int fd;
>>>> +
>>>> + fd = open(NFS4IDFILE, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
>>>> + if (fd < 0)
>>>> + fatal("could not write id to " NFS4IDFILE);
>>>> + write(fd, nfs4_id, 37);
>>>> +}
>>>> +
>>>> +static void print_nfs4_id(void)
>>>> +{
>>>> + fprintf(stdout, "%s", nfs4_id);
>>>> +}
>>>> +
>>>> +static void check_or_make_id(void)
>>>> +{
>>>> + int ret;
>>>> + uuid_t nfs4id_uuid;
>>>> +
>>>> + ret = read_nfs4_id();
>>>> + if (ret != 0) {
>>>> + if (errno != ENOENT )
>>>> + fatal("reading file " NFS4IDFILE);
>>>> + uuid_generate_random(nfs4id_uuid);
>>>> + uuid_unparse(nfs4id_uuid, nfs4_id);
>>>> + nfs4_id[36] = '\n';
>>>> + nfs4_id[37] = '\0';
>>>> + write_nfs4_id();
>>>> + }
>>>> + print_nfs4_id();
>>>> +}
>>>> +
>>>> +static void check_or_make_id_from_machine(void)
>>>> +{
>>>> + int fd, ret;
>>>> + char machineid[32];
>>>> + uuid_t nfs4id_uuid;
>>>> +
>>>> + ret = read_nfs4_id();
>>>> + if (ret != 0) {
>>>> + if (errno != ENOENT )
>>>> + fatal("reading file " NFS4IDFILE);
>>>> +
>>>> + fd = open("/etc/machine-id", O_RDONLY);
>>>> + if (fd < 0)
>>>> + fatal("unable to read /etc/machine-id");
>>>> +
>>>> + read(fd, machineid, 32);
>>>> + close(fd);
>>>> +
>>>> + uuid_generate_sha1(nfs4id_uuid, nfs4_clientid_uuid_template, machineid, 32);
>>>> + uuid_unparse(nfs4id_uuid, nfs4_id);
>>>> + nfs4_id[36] = '\n';
>>>> + nfs4_id[37] = '\0';
>>>> + write_nfs4_id();
>>>> + }
>>>> + print_nfs4_id();
>>>> +}
>>>> +
>>>> +int main(int argc, char **argv)
>>>> +{
>>>> + prog = argv[0];
>>>> +
>>>> + while (1) {
>>>> + int opt;
>>>> + int option_index = 0;
>>>> + static struct option long_options[] = {
>>>> + {"force", no_argument, 0, 'f' },
>>>> + {0, 0, 0, 0 }
>>>> + };
>>>> +
>>>> + errno = 0;
>>>> + opt = getopt_long(argc, argv, ":f", long_options, &option_index);
>>>> + if (opt == -1)
>>>> + break;
>>>> +
>>>> + switch (opt) {
>>>> + case 'f':
>>>> + force = 1;
>>>> + break;
>>>> + case '?':
>>>> + usage();
>>>> + fatal("unexpected arg \"%s\"", argv[optind - 1]);
>>>> + break;
>>>> + }
>>>> + }
>>>> +
>>>> + argc -= optind;
>>>> +
>>>> + if (argc > 1) {
>>>> + usage();
>>>> + fatal("Too many arguments");
>>>> + }
>>>> +
>>>> + if (argc)
>>>> + source = argv[optind++];
>>>> +
>>>> + if (force)
>>>> + unlink(NFS4IDFILE);
>>>> +
>>>> + if (!source)
>>>> + check_or_make_id();
>>>> + else if (strcmp(source, "machine") == 0)
>>>> + check_or_make_id_from_machine();
>>>> + else {
>>>> + usage();
>>>> + fatal("unrecognized source %s\n", source);
>>>> + }
>>>> +}
>>>> diff --git a/tools/nfs4id/nfs4id.man b/tools/nfs4id/nfs4id.man
>>>> new file mode 100644
>>>> index 000000000000..358f836468a2
>>>> --- /dev/null
>>>> +++ b/tools/nfs4id/nfs4id.man
>>>> @@ -0,0 +1,29 @@
>>>> +.\"
>>>> +.\" nfs4id(8)
>>>> +.\"
>>>> +.TH nfs4id 8 "3 Feb 2022"
>>>> +.SH NAME
>>>> +nfs4id \- Generate or return nfs4 client id uniqueifiers
>>>> +.SH SYNOPSIS
>>>> +.B nfs4id [ -f | --force ] [<source>]
>>>> +
>>>> +.SH DESCRIPTION
>>>> +The
>>>> +.B nfs4id
>>>> +command provides a simple utility to help NFS Version 4 clients use unique
>>>> +and persistent client id values. The command checks for the existence of a
>>>> +file /etc/nfs4-id and returns the first 64 chars read from that file. If
>>>> +the file is not found, a UUID is generated from the specified source and
>>>> +written to the file and returned.
>>>> +.SH OPTIONS
>>>> +.TP
>>>> +.BR \-f, \-\-force
>>>> +Overwrite the existing /etc/nfs4-id with a UUID generated from <source>.
>>>> +.SH Sources
>>>> +If <source> is not specified, nfs4id will generate a new random UUID.
>>>> +
>>>> +If <source> is "machine", nfs4id will generate a deterministic UUID value
>>>> +derived from a sha1 hash of the contents of /etc/machine-id and a static
>>>> +key.
>>>> +.SH SEE ALSO
>>>> +.BR machine-id (5)
>> --
>> Chuck Lever
>

--
Chuck Lever




2022-02-09 06:55:56

by Chuck Lever III

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers



> On Feb 8, 2022, at 11:04 AM, Steve Dickson <[email protected]> wrote:
>
> Hello,
>
> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>> The nfs4id program will either create a new UUID from a random source or
>> derive it from /etc/machine-id, else it returns a UUID that has already
>> been written to /etc/nfs4-id. This small, lightweight tool is suitable for
>> execution by systemd-udev in rules to populate the nfs4 client uniquifier.
>> Signed-off-by: Benjamin Coddington <[email protected]>
>> ---
>> .gitignore | 1 +
>> configure.ac | 4 +
>> tools/Makefile.am | 1 +
>> tools/nfs4id/Makefile.am | 8 ++
>> tools/nfs4id/nfs4id.c | 184 +++++++++++++++++++++++++++++++++++++++
>> tools/nfs4id/nfs4id.man | 29 ++++++
>> 6 files changed, 227 insertions(+)
>> create mode 100644 tools/nfs4id/Makefile.am
>> create mode 100644 tools/nfs4id/nfs4id.c
>> create mode 100644 tools/nfs4id/nfs4id.man
> Just a nit... naming convention... In the past
> we never put the protocol version in the name.
> Do a ls tools and utils directory and you
> see what I mean....
>
> Would it be a problem to change the name from
> nfs4id to nfsid?

nfs4id is pretty generic, too.

Can we go with nfs-client-id ?


> steved.
>
>> diff --git a/.gitignore b/.gitignore
>> index c89d1cd2583d..a37964148dd8 100644
>> --- a/.gitignore
>> +++ b/.gitignore
>> @@ -61,6 +61,7 @@ utils/statd/statd
>> tools/locktest/testlk
>> tools/getiversion/getiversion
>> tools/nfsconf/nfsconf
>> +tools/nfs4id/nfs4id
>> support/export/mount.h
>> support/export/mount_clnt.c
>> support/export/mount_xdr.c
>> diff --git a/configure.ac b/configure.ac
>> index 50e9b321dcf3..93d0a902cfd8 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -355,6 +355,9 @@ if test "$enable_nfsv4" = yes; then
>> dnl check for the keyutils libraries and headers
>> AC_KEYUTILS
>> + dnl check for the libuuid library and headers
>> + AC_LIBUUID
>> +
>> dnl Check for sqlite3
>> AC_SQLITE3_VERS
>> @@ -740,6 +743,7 @@ AC_CONFIG_FILES([
>> tools/nfsdclnts/Makefile
>> tools/nfsconf/Makefile
>> tools/nfsdclddb/Makefile
>> + tools/nfs4id/Makefile
>> utils/Makefile
>> utils/blkmapd/Makefile
>> utils/nfsdcld/Makefile
>> diff --git a/tools/Makefile.am b/tools/Makefile.am
>> index 9b4b0803db39..cc658f69bb32 100644
>> --- a/tools/Makefile.am
>> +++ b/tools/Makefile.am
>> @@ -7,6 +7,7 @@ OPTDIRS += rpcgen
>> endif
>> OPTDIRS += nfsconf
>> +OPTDIRS += nfs4id
>> if CONFIG_NFSDCLD
>> OPTDIRS += nfsdclddb
>> diff --git a/tools/nfs4id/Makefile.am b/tools/nfs4id/Makefile.am
>> new file mode 100644
>> index 000000000000..d1e60a35a510
>> --- /dev/null
>> +++ b/tools/nfs4id/Makefile.am
>> @@ -0,0 +1,8 @@
>> +## Process this file with automake to produce Makefile.in
>> +
>> +man8_MANS = nfs4id.man
>> +
>> +bin_PROGRAMS = nfs4id
>> +
>> +nfs4id_SOURCES = nfs4id.c
>> +nfs4id_LDADD = $(LIBUUID)
>> diff --git a/tools/nfs4id/nfs4id.c b/tools/nfs4id/nfs4id.c
>> new file mode 100644
>> index 000000000000..dbb807ae21f3
>> --- /dev/null
>> +++ b/tools/nfs4id/nfs4id.c
>> @@ -0,0 +1,184 @@
>> +/*
>> + * nfs4id.c -- create and persist uniquifiers for nfs4 clients
>> + *
>> + * Copyright (C) 2022 Red Hat, Benjamin Coddington <[email protected]>
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version 2
>> + * of the License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
>> + * Boston, MA 02110-1301, USA.
>> + */
>> +
>> +#include <stdio.h>
>> +#include <stdarg.h>
>> +#include <getopt.h>
>> +#include <string.h>
>> +#include <errno.h>
>> +#include <stdlib.h>
>> +#include <fcntl.h>
>> +#include <unistd.h>
>> +#include <uuid/uuid.h>
>> +
>> +#define NFS4IDFILE "/etc/nfs4-id"
>> +
>> +UUID_DEFINE(nfs4_clientid_uuid_template,
>> + 0xa2, 0x25, 0x68, 0xb2, 0x7a, 0x5f, 0x49, 0x90,
>> + 0x8f, 0x98, 0xc5, 0xf0, 0x67, 0x78, 0xcc, 0xf1);
>> +
>> +static char *prog;
>> +static char *source = NULL;
>> +static char nfs4_id[64];
>> +static int force = 0;
>> +
>> +static void usage(void)
>> +{
>> + fprintf(stderr, "usage: %s [-f|--force] [machine]\n", prog);
>> +}
>> +
>> +static void fatal(const char *fmt, ...)
>> +{
>> + int err = errno;
>> + va_list args;
>> + char fatal_msg[256] = "fatal: ";
>> +
>> + va_start(args, fmt);
>> + vsnprintf(&fatal_msg[7], 255, fmt, args);
>> + if (err)
>> + fprintf(stderr, "%s: %s\n", fatal_msg, strerror(err));
>> + else
>> + fprintf(stderr, "%s\n", fatal_msg);
>> + exit(-1);
>> +}
>> +
>> +static int read_nfs4_id(void)
>> +{
>> + int fd;
>> +
>> + fd = open(NFS4IDFILE, O_RDONLY);
>> + if (fd < 0)
>> + return fd;
>> + read(fd, nfs4_id, 64);
>> + close(fd);
>> + return 0;
>> +}
>> +
>> +static void write_nfs4_id(void)
>> +{
>> + int fd;
>> +
>> + fd = open(NFS4IDFILE, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
>> + if (fd < 0)
>> + fatal("could not write id to " NFS4IDFILE);
>> + write(fd, nfs4_id, 37);
>> +}
>> +
>> +static void print_nfs4_id(void)
>> +{
>> + fprintf(stdout, "%s", nfs4_id);
>> +}
>> +
>> +static void check_or_make_id(void)
>> +{
>> + int ret;
>> + uuid_t nfs4id_uuid;
>> +
>> + ret = read_nfs4_id();
>> + if (ret != 0) {
>> + if (errno != ENOENT )
>> + fatal("reading file " NFS4IDFILE);
>> + uuid_generate_random(nfs4id_uuid);
>> + uuid_unparse(nfs4id_uuid, nfs4_id);
>> + nfs4_id[36] = '\n';
>> + nfs4_id[37] = '\0';
>> + write_nfs4_id();
>> + }
>> + print_nfs4_id();
>> +}
>> +
>> +static void check_or_make_id_from_machine(void)
>> +{
>> + int fd, ret;
>> + char machineid[32];
>> + uuid_t nfs4id_uuid;
>> +
>> + ret = read_nfs4_id();
>> + if (ret != 0) {
>> + if (errno != ENOENT )
>> + fatal("reading file " NFS4IDFILE);
>> +
>> + fd = open("/etc/machine-id", O_RDONLY);
>> + if (fd < 0)
>> + fatal("unable to read /etc/machine-id");
>> +
>> + read(fd, machineid, 32);
>> + close(fd);
>> +
>> + uuid_generate_sha1(nfs4id_uuid, nfs4_clientid_uuid_template, machineid, 32);
>> + uuid_unparse(nfs4id_uuid, nfs4_id);
>> + nfs4_id[36] = '\n';
>> + nfs4_id[37] = '\0';
>> + write_nfs4_id();
>> + }
>> + print_nfs4_id();
>> +}
>> +
>> +int main(int argc, char **argv)
>> +{
>> + prog = argv[0];
>> +
>> + while (1) {
>> + int opt;
>> + int option_index = 0;
>> + static struct option long_options[] = {
>> + {"force", no_argument, 0, 'f' },
>> + {0, 0, 0, 0 }
>> + };
>> +
>> + errno = 0;
>> + opt = getopt_long(argc, argv, ":f", long_options, &option_index);
>> + if (opt == -1)
>> + break;
>> +
>> + switch (opt) {
>> + case 'f':
>> + force = 1;
>> + break;
>> + case '?':
>> + usage();
>> + fatal("unexpected arg \"%s\"", argv[optind - 1]);
>> + break;
>> + }
>> + }
>> +
>> + argc -= optind;
>> +
>> + if (argc > 1) {
>> + usage();
>> + fatal("Too many arguments");
>> + }
>> +
>> + if (argc)
>> + source = argv[optind++];
>> +
>> + if (force)
>> + unlink(NFS4IDFILE);
>> +
>> + if (!source)
>> + check_or_make_id();
>> + else if (strcmp(source, "machine") == 0)
>> + check_or_make_id_from_machine();
>> + else {
>> + usage();
>> + fatal("unrecognized source %s\n", source);
>> + }
>> +}
>> diff --git a/tools/nfs4id/nfs4id.man b/tools/nfs4id/nfs4id.man
>> new file mode 100644
>> index 000000000000..358f836468a2
>> --- /dev/null
>> +++ b/tools/nfs4id/nfs4id.man
>> @@ -0,0 +1,29 @@
>> +.\"
>> +.\" nfs4id(8)
>> +.\"
>> +.TH nfs4id 8 "3 Feb 2022"
>> +.SH NAME
>> +nfs4id \- Generate or return nfs4 client id uniqueifiers
>> +.SH SYNOPSIS
>> +.B nfs4id [ -f | --force ] [<source>]
>> +
>> +.SH DESCRIPTION
>> +The
>> +.B nfs4id
>> +command provides a simple utility to help NFS Version 4 clients use unique
>> +and persistent client id values. The command checks for the existence of a
>> +file /etc/nfs4-id and returns the first 64 chars read from that file. If
>> +the file is not found, a UUID is generated from the specified source and
>> +written to the file and returned.
>> +.SH OPTIONS
>> +.TP
>> +.BR \-f, \-\-force
>> +Overwrite the existing /etc/nfs4-id with a UUID generated from <source>.
>> +.SH Sources
>> +If <source> is not specified, nfs4id will generate a new random UUID.
>> +
>> +If <source> is "machine", nfs4id will generate a deterministic UUID value
>> +derived from a sha1 hash of the contents of /etc/machine-id and a static
>> +key.
>> +.SH SEE ALSO
>> +.BR machine-id (5)

--
Chuck Lever




2022-02-09 07:11:42

by Steve Dickson

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers



On 2/8/22 11:22 AM, Benjamin Coddington wrote:
> On 8 Feb 2022, at 11:04, Steve Dickson wrote:
>
>> Hello,
>>
>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>> The nfs4id program will either create a new UUID from a random source or
>>> derive it from /etc/machine-id, else it returns a UUID that has already
>>> been written to /etc/nfs4-id.  This small, lightweight tool is
>>> suitable for
>>> execution by systemd-udev in rules to populate the nfs4 client
>>> uniquifier.
>>>
>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>> ---
>>>   .gitignore               |   1 +
>>>   configure.ac             |   4 +
>>>   tools/Makefile.am        |   1 +
>>>   tools/nfs4id/Makefile.am |   8 ++
>>>   tools/nfs4id/nfs4id.c    | 184 +++++++++++++++++++++++++++++++++++++++
>>>   tools/nfs4id/nfs4id.man  |  29 ++++++
>>>   6 files changed, 227 insertions(+)
>>>   create mode 100644 tools/nfs4id/Makefile.am
>>>   create mode 100644 tools/nfs4id/nfs4id.c
>>>   create mode 100644 tools/nfs4id/nfs4id.man
>> Just a nit... naming convention... In the past
>> we never put the protocol version in the name.
>> Do a ls tools and utils directory and you
>> see what I mean....
>>
>> Would it be a problem to change the name from
>> nfs4id to nfsid?
>
> Not at all..
Good...

> and I think there's a lot of room for naming discussions about
> the file to store the id too:
>
> Trond sent /etc/nfs4_uuid
> Neil suggests /etc/netns/NAME/nfs.conf.d/identity.conf
> Ben sent /etc/nfs4-id (to match /etc/machine-id)
Question... is it kosher to be writing /etc which is
generally on the root filesystem?

By far Neil suggestion is the most intriguing... but
on the containers I'm looking at there no /etc/netns
directory.

I had to install the iproute package to do the
"ip netns identify" which returns NULL...
also adds yet another dependency on nfs-utils.

So if "ip netns identify" does return NULL what directory
path should be used?

I'm all for making things container friendly but I'm
also a fan of keeping things simple... So
how about /etc/nfs.conf.d/identity.conf or
/etc/nfs.conf.d/nfsid.conf?

>
> Maybe the tool wants an option to specify the file?
This is probably not a bad idea... It is a common practice

steved.

>
> Ben
>


2022-02-09 07:41:51

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 8 Feb 2022, at 11:04, Steve Dickson wrote:

> Hello,
>
> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>> The nfs4id program will either create a new UUID from a random source
>> or
>> derive it from /etc/machine-id, else it returns a UUID that has
>> already
>> been written to /etc/nfs4-id. This small, lightweight tool is
>> suitable for
>> execution by systemd-udev in rules to populate the nfs4 client
>> uniquifier.
>>
>> Signed-off-by: Benjamin Coddington <[email protected]>
>> ---
>> .gitignore | 1 +
>> configure.ac | 4 +
>> tools/Makefile.am | 1 +
>> tools/nfs4id/Makefile.am | 8 ++
>> tools/nfs4id/nfs4id.c | 184
>> +++++++++++++++++++++++++++++++++++++++
>> tools/nfs4id/nfs4id.man | 29 ++++++
>> 6 files changed, 227 insertions(+)
>> create mode 100644 tools/nfs4id/Makefile.am
>> create mode 100644 tools/nfs4id/nfs4id.c
>> create mode 100644 tools/nfs4id/nfs4id.man
> Just a nit... naming convention... In the past
> we never put the protocol version in the name.
> Do a ls tools and utils directory and you
> see what I mean....
>
> Would it be a problem to change the name from
> nfs4id to nfsid?

Not at all.. and I think there's a lot of room for naming discussions
about
the file to store the id too:

Trond sent /etc/nfs4_uuid
Neil suggests /etc/netns/NAME/nfs.conf.d/identity.conf
Ben sent /etc/nfs4-id (to match /etc/machine-id)

Maybe the tool wants an option to specify the file?

Ben


2022-02-09 07:42:51

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 8 Feb 2022, at 14:52, Steve Dickson wrote:

> On 2/8/22 11:22 AM, Benjamin Coddington wrote:
>> On 8 Feb 2022, at 11:04, Steve Dickson wrote:
>>
>>> Hello,
>>>
>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>> The nfs4id program will either create a new UUID from a random
>>>> source or
>>>> derive it from /etc/machine-id, else it returns a UUID that has
>>>> already
>>>> been written to /etc/nfs4-id.  This small, lightweight tool is
>>>> suitable for
>>>> execution by systemd-udev in rules to populate the nfs4 client
>>>> uniquifier.
>>>>
>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>> ---
>>>>   .gitignore               |   1 +
>>>>   configure.ac             |   4 +
>>>>   tools/Makefile.am        |   1 +
>>>>   tools/nfs4id/Makefile.am |   8 ++
>>>>   tools/nfs4id/nfs4id.c    | 184
>>>> +++++++++++++++++++++++++++++++++++++++
>>>>   tools/nfs4id/nfs4id.man  |  29 ++++++
>>>>   6 files changed, 227 insertions(+)
>>>>   create mode 100644 tools/nfs4id/Makefile.am
>>>>   create mode 100644 tools/nfs4id/nfs4id.c
>>>>   create mode 100644 tools/nfs4id/nfs4id.man
>>> Just a nit... naming convention... In the past
>>> we never put the protocol version in the name.
>>> Do a ls tools and utils directory and you
>>> see what I mean....
>>>
>>> Would it be a problem to change the name from
>>> nfs4id to nfsid?
>>
>> Not at all..
> Good...

I didn't orginally do that because I thought it might be confusing for
some
folks who want `nfsid` to display their kerberos identity. There's a BZ
open for that!

Do you think that's a problem? I feel like it's a problem.

>> and I think there's a lot of room for naming discussions about
>> the file to store the id too:
>>
>> Trond sent /etc/nfs4_uuid
>> Neil suggests /etc/netns/NAME/nfs.conf.d/identity.conf
>> Ben sent /etc/nfs4-id (to match /etc/machine-id)
> Question... is it kosher to be writing /etc which is
> generally on the root filesystem?

Sure, why not?

> By far Neil suggestion is the most intriguing... but
> on the containers I'm looking at there no /etc/netns
> directory.

Not yet -- you can create it.

> I had to install the iproute package to do the
> "ip netns identify" which returns NULL...
> also adds yet another dependency on nfs-utils.

We don't need the dependency..this little binary is just a helper for a
udev
rule. Trond already wrote his version of this. :) This one's just
trying
to be a little lighter (whoa, we don't need all of bash!).

> So if "ip netns identify" does return NULL what directory
> path should be used?

I think thats out of scope.. if udevd is running in a container, and
has a
rule that uses this tool, then the container either is likely to have
already customized its /etc. Or perhaps we can make the udev rule
namespace
aware (I need to look into what's available to udev's rule environment
when
it runs in a namespace).

> I'm all for making things container friendly but I'm
> also a fan of keeping things simple... So
> how about /etc/nfs.conf.d/identity.conf or
> /etc/nfs.conf.d/nfsid.conf?

Really, because its not a configuration. Its value persistence, and we
/really/
don't want people configuring it.

>>
>> Maybe the tool wants an option to specify the file?
> This is probably not a bad idea... It is a common practice

OK, I'll do that.

Ben


2022-02-09 07:44:05

by Steve Dickson

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

Hello,

On 2/4/22 7:56 AM, Benjamin Coddington wrote:
> The nfs4id program will either create a new UUID from a random source or
> derive it from /etc/machine-id, else it returns a UUID that has already
> been written to /etc/nfs4-id. This small, lightweight tool is suitable for
> execution by systemd-udev in rules to populate the nfs4 client uniquifier.
>
> Signed-off-by: Benjamin Coddington <[email protected]>
> ---
> .gitignore | 1 +
> configure.ac | 4 +
> tools/Makefile.am | 1 +
> tools/nfs4id/Makefile.am | 8 ++
> tools/nfs4id/nfs4id.c | 184 +++++++++++++++++++++++++++++++++++++++
> tools/nfs4id/nfs4id.man | 29 ++++++
> 6 files changed, 227 insertions(+)
> create mode 100644 tools/nfs4id/Makefile.am
> create mode 100644 tools/nfs4id/nfs4id.c
> create mode 100644 tools/nfs4id/nfs4id.man
Just a nit... naming convention... In the past
we never put the protocol version in the name.
Do a ls tools and utils directory and you
see what I mean....

Would it be a problem to change the name from
nfs4id to nfsid?

steved.

>
> diff --git a/.gitignore b/.gitignore
> index c89d1cd2583d..a37964148dd8 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -61,6 +61,7 @@ utils/statd/statd
> tools/locktest/testlk
> tools/getiversion/getiversion
> tools/nfsconf/nfsconf
> +tools/nfs4id/nfs4id
> support/export/mount.h
> support/export/mount_clnt.c
> support/export/mount_xdr.c
> diff --git a/configure.ac b/configure.ac
> index 50e9b321dcf3..93d0a902cfd8 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -355,6 +355,9 @@ if test "$enable_nfsv4" = yes; then
> dnl check for the keyutils libraries and headers
> AC_KEYUTILS
>
> + dnl check for the libuuid library and headers
> + AC_LIBUUID
> +
> dnl Check for sqlite3
> AC_SQLITE3_VERS
>
> @@ -740,6 +743,7 @@ AC_CONFIG_FILES([
> tools/nfsdclnts/Makefile
> tools/nfsconf/Makefile
> tools/nfsdclddb/Makefile
> + tools/nfs4id/Makefile
> utils/Makefile
> utils/blkmapd/Makefile
> utils/nfsdcld/Makefile
> diff --git a/tools/Makefile.am b/tools/Makefile.am
> index 9b4b0803db39..cc658f69bb32 100644
> --- a/tools/Makefile.am
> +++ b/tools/Makefile.am
> @@ -7,6 +7,7 @@ OPTDIRS += rpcgen
> endif
>
> OPTDIRS += nfsconf
> +OPTDIRS += nfs4id
>
> if CONFIG_NFSDCLD
> OPTDIRS += nfsdclddb
> diff --git a/tools/nfs4id/Makefile.am b/tools/nfs4id/Makefile.am
> new file mode 100644
> index 000000000000..d1e60a35a510
> --- /dev/null
> +++ b/tools/nfs4id/Makefile.am
> @@ -0,0 +1,8 @@
> +## Process this file with automake to produce Makefile.in
> +
> +man8_MANS = nfs4id.man
> +
> +bin_PROGRAMS = nfs4id
> +
> +nfs4id_SOURCES = nfs4id.c
> +nfs4id_LDADD = $(LIBUUID)
> diff --git a/tools/nfs4id/nfs4id.c b/tools/nfs4id/nfs4id.c
> new file mode 100644
> index 000000000000..dbb807ae21f3
> --- /dev/null
> +++ b/tools/nfs4id/nfs4id.c
> @@ -0,0 +1,184 @@
> +/*
> + * nfs4id.c -- create and persist uniquifiers for nfs4 clients
> + *
> + * Copyright (C) 2022 Red Hat, Benjamin Coddington <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
> + * Boston, MA 02110-1301, USA.
> + */
> +
> +#include <stdio.h>
> +#include <stdarg.h>
> +#include <getopt.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <uuid/uuid.h>
> +
> +#define NFS4IDFILE "/etc/nfs4-id"
> +
> +UUID_DEFINE(nfs4_clientid_uuid_template,
> + 0xa2, 0x25, 0x68, 0xb2, 0x7a, 0x5f, 0x49, 0x90,
> + 0x8f, 0x98, 0xc5, 0xf0, 0x67, 0x78, 0xcc, 0xf1);
> +
> +static char *prog;
> +static char *source = NULL;
> +static char nfs4_id[64];
> +static int force = 0;
> +
> +static void usage(void)
> +{
> + fprintf(stderr, "usage: %s [-f|--force] [machine]\n", prog);
> +}
> +
> +static void fatal(const char *fmt, ...)
> +{
> + int err = errno;
> + va_list args;
> + char fatal_msg[256] = "fatal: ";
> +
> + va_start(args, fmt);
> + vsnprintf(&fatal_msg[7], 255, fmt, args);
> + if (err)
> + fprintf(stderr, "%s: %s\n", fatal_msg, strerror(err));
> + else
> + fprintf(stderr, "%s\n", fatal_msg);
> + exit(-1);
> +}
> +
> +static int read_nfs4_id(void)
> +{
> + int fd;
> +
> + fd = open(NFS4IDFILE, O_RDONLY);
> + if (fd < 0)
> + return fd;
> + read(fd, nfs4_id, 64);
> + close(fd);
> + return 0;
> +}
> +
> +static void write_nfs4_id(void)
> +{
> + int fd;
> +
> + fd = open(NFS4IDFILE, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
> + if (fd < 0)
> + fatal("could not write id to " NFS4IDFILE);
> + write(fd, nfs4_id, 37);
> +}
> +
> +static void print_nfs4_id(void)
> +{
> + fprintf(stdout, "%s", nfs4_id);
> +}
> +
> +static void check_or_make_id(void)
> +{
> + int ret;
> + uuid_t nfs4id_uuid;
> +
> + ret = read_nfs4_id();
> + if (ret != 0) {
> + if (errno != ENOENT )
> + fatal("reading file " NFS4IDFILE);
> + uuid_generate_random(nfs4id_uuid);
> + uuid_unparse(nfs4id_uuid, nfs4_id);
> + nfs4_id[36] = '\n';
> + nfs4_id[37] = '\0';
> + write_nfs4_id();
> + }
> + print_nfs4_id();
> +}
> +
> +static void check_or_make_id_from_machine(void)
> +{
> + int fd, ret;
> + char machineid[32];
> + uuid_t nfs4id_uuid;
> +
> + ret = read_nfs4_id();
> + if (ret != 0) {
> + if (errno != ENOENT )
> + fatal("reading file " NFS4IDFILE);
> +
> + fd = open("/etc/machine-id", O_RDONLY);
> + if (fd < 0)
> + fatal("unable to read /etc/machine-id");
> +
> + read(fd, machineid, 32);
> + close(fd);
> +
> + uuid_generate_sha1(nfs4id_uuid, nfs4_clientid_uuid_template, machineid, 32);
> + uuid_unparse(nfs4id_uuid, nfs4_id);
> + nfs4_id[36] = '\n';
> + nfs4_id[37] = '\0';
> + write_nfs4_id();
> + }
> + print_nfs4_id();
> +}
> +
> +int main(int argc, char **argv)
> +{
> + prog = argv[0];
> +
> + while (1) {
> + int opt;
> + int option_index = 0;
> + static struct option long_options[] = {
> + {"force", no_argument, 0, 'f' },
> + {0, 0, 0, 0 }
> + };
> +
> + errno = 0;
> + opt = getopt_long(argc, argv, ":f", long_options, &option_index);
> + if (opt == -1)
> + break;
> +
> + switch (opt) {
> + case 'f':
> + force = 1;
> + break;
> + case '?':
> + usage();
> + fatal("unexpected arg \"%s\"", argv[optind - 1]);
> + break;
> + }
> + }
> +
> + argc -= optind;
> +
> + if (argc > 1) {
> + usage();
> + fatal("Too many arguments");
> + }
> +
> + if (argc)
> + source = argv[optind++];
> +
> + if (force)
> + unlink(NFS4IDFILE);
> +
> + if (!source)
> + check_or_make_id();
> + else if (strcmp(source, "machine") == 0)
> + check_or_make_id_from_machine();
> + else {
> + usage();
> + fatal("unrecognized source %s\n", source);
> + }
> +}
> diff --git a/tools/nfs4id/nfs4id.man b/tools/nfs4id/nfs4id.man
> new file mode 100644
> index 000000000000..358f836468a2
> --- /dev/null
> +++ b/tools/nfs4id/nfs4id.man
> @@ -0,0 +1,29 @@
> +.\"
> +.\" nfs4id(8)
> +.\"
> +.TH nfs4id 8 "3 Feb 2022"
> +.SH NAME
> +nfs4id \- Generate or return nfs4 client id uniqueifiers
> +.SH SYNOPSIS
> +.B nfs4id [ -f | --force ] [<source>]
> +
> +.SH DESCRIPTION
> +The
> +.B nfs4id
> +command provides a simple utility to help NFS Version 4 clients use unique
> +and persistent client id values. The command checks for the existence of a
> +file /etc/nfs4-id and returns the first 64 chars read from that file. If
> +the file is not found, a UUID is generated from the specified source and
> +written to the file and returned.
> +.SH OPTIONS
> +.TP
> +.BR \-f, \-\-force
> +Overwrite the existing /etc/nfs4-id with a UUID generated from <source>.
> +.SH Sources
> +If <source> is not specified, nfs4id will generate a new random UUID.
> +
> +If <source> is "machine", nfs4id will generate a deterministic UUID value
> +derived from a sha1 hash of the contents of /etc/machine-id and a static
> +key.
> +.SH SEE ALSO
> +.BR machine-id (5)


2022-02-09 09:38:32

by Steve Dickson

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers



On 2/8/22 4:18 PM, Chuck Lever III wrote:
>
>
>> On Feb 8, 2022, at 2:29 PM, Steve Dickson <[email protected]> wrote:
>>
>>
>>
>> On 2/8/22 11:21 AM, Chuck Lever III wrote:
>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <[email protected]> wrote:
>>>>
>>>> Hello,
>>>>
>>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>>> The nfs4id program will either create a new UUID from a random source or
>>>>> derive it from /etc/machine-id, else it returns a UUID that has already
>>>>> been written to /etc/nfs4-id. This small, lightweight tool is suitable for
>>>>> execution by systemd-udev in rules to populate the nfs4 client uniquifier.
>>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>>> ---
>>>>> .gitignore | 1 +
>>>>> configure.ac | 4 +
>>>>> tools/Makefile.am | 1 +
>>>>> tools/nfs4id/Makefile.am | 8 ++
>>>>> tools/nfs4id/nfs4id.c | 184 +++++++++++++++++++++++++++++++++++++++
>>>>> tools/nfs4id/nfs4id.man | 29 ++++++
>>>>> 6 files changed, 227 insertions(+)
>>>>> create mode 100644 tools/nfs4id/Makefile.am
>>>>> create mode 100644 tools/nfs4id/nfs4id.c
>>>>> create mode 100644 tools/nfs4id/nfs4id.man
>>>> Just a nit... naming convention... In the past
>>>> we never put the protocol version in the name.
>>>> Do a ls tools and utils directory and you
>>>> see what I mean....
>>>>
>>>> Would it be a problem to change the name from
>>>> nfs4id to nfsid?
>>> nfs4id is pretty generic, too.
>>> Can we go with nfs-client-id ?
>> I'm never been big with putting '-'
>> in command names... nfscltid would
>> be better IMHO... if we actually
>> need the 'clt' in the name.
>
> We have nfsidmap already. IMO we need some distinction
> with user ID mapping tools... and some day we might
> want to manage server IDs too (see EXCHANGE_ID).
Hmm... So we could not use the same tool to do
both the server and client, via flags?

>
> nfsclientid then?
You like to type more than I do... You always have... :-)

But like I started the conversation... the naming is
a nit... but I would like to see one tool to set the
ids for both the server and client... how about
nfsid -s and nfsid -c

steved.
>
>
>> steved.
>>
>>>> steved.
>>>>
>>>>> diff --git a/.gitignore b/.gitignore
>>>>> index c89d1cd2583d..a37964148dd8 100644
>>>>> --- a/.gitignore
>>>>> +++ b/.gitignore
>>>>> @@ -61,6 +61,7 @@ utils/statd/statd
>>>>> tools/locktest/testlk
>>>>> tools/getiversion/getiversion
>>>>> tools/nfsconf/nfsconf
>>>>> +tools/nfs4id/nfs4id
>>>>> support/export/mount.h
>>>>> support/export/mount_clnt.c
>>>>> support/export/mount_xdr.c
>>>>> diff --git a/configure.ac b/configure.ac
>>>>> index 50e9b321dcf3..93d0a902cfd8 100644
>>>>> --- a/configure.ac
>>>>> +++ b/configure.ac
>>>>> @@ -355,6 +355,9 @@ if test "$enable_nfsv4" = yes; then
>>>>> dnl check for the keyutils libraries and headers
>>>>> AC_KEYUTILS
>>>>> + dnl check for the libuuid library and headers
>>>>> + AC_LIBUUID
>>>>> +
>>>>> dnl Check for sqlite3
>>>>> AC_SQLITE3_VERS
>>>>> @@ -740,6 +743,7 @@ AC_CONFIG_FILES([
>>>>> tools/nfsdclnts/Makefile
>>>>> tools/nfsconf/Makefile
>>>>> tools/nfsdclddb/Makefile
>>>>> + tools/nfs4id/Makefile
>>>>> utils/Makefile
>>>>> utils/blkmapd/Makefile
>>>>> utils/nfsdcld/Makefile
>>>>> diff --git a/tools/Makefile.am b/tools/Makefile.am
>>>>> index 9b4b0803db39..cc658f69bb32 100644
>>>>> --- a/tools/Makefile.am
>>>>> +++ b/tools/Makefile.am
>>>>> @@ -7,6 +7,7 @@ OPTDIRS += rpcgen
>>>>> endif
>>>>> OPTDIRS += nfsconf
>>>>> +OPTDIRS += nfs4id
>>>>> if CONFIG_NFSDCLD
>>>>> OPTDIRS += nfsdclddb
>>>>> diff --git a/tools/nfs4id/Makefile.am b/tools/nfs4id/Makefile.am
>>>>> new file mode 100644
>>>>> index 000000000000..d1e60a35a510
>>>>> --- /dev/null
>>>>> +++ b/tools/nfs4id/Makefile.am
>>>>> @@ -0,0 +1,8 @@
>>>>> +## Process this file with automake to produce Makefile.in
>>>>> +
>>>>> +man8_MANS = nfs4id.man
>>>>> +
>>>>> +bin_PROGRAMS = nfs4id
>>>>> +
>>>>> +nfs4id_SOURCES = nfs4id.c
>>>>> +nfs4id_LDADD = $(LIBUUID)
>>>>> diff --git a/tools/nfs4id/nfs4id.c b/tools/nfs4id/nfs4id.c
>>>>> new file mode 100644
>>>>> index 000000000000..dbb807ae21f3
>>>>> --- /dev/null
>>>>> +++ b/tools/nfs4id/nfs4id.c
>>>>> @@ -0,0 +1,184 @@
>>>>> +/*
>>>>> + * nfs4id.c -- create and persist uniquifiers for nfs4 clients
>>>>> + *
>>>>> + * Copyright (C) 2022 Red Hat, Benjamin Coddington <[email protected]>
>>>>> + *
>>>>> + * This program is free software; you can redistribute it and/or
>>>>> + * modify it under the terms of the GNU General Public License
>>>>> + * as published by the Free Software Foundation; either version 2
>>>>> + * of the License, or (at your option) any later version.
>>>>> + *
>>>>> + * This program is distributed in the hope that it will be useful,
>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>>>> + * GNU General Public License for more details.
>>>>> + *
>>>>> + * You should have received a copy of the GNU General Public License
>>>>> + * along with this program; if not, write to the Free Software
>>>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
>>>>> + * Boston, MA 02110-1301, USA.
>>>>> + */
>>>>> +
>>>>> +#include <stdio.h>
>>>>> +#include <stdarg.h>
>>>>> +#include <getopt.h>
>>>>> +#include <string.h>
>>>>> +#include <errno.h>
>>>>> +#include <stdlib.h>
>>>>> +#include <fcntl.h>
>>>>> +#include <unistd.h>
>>>>> +#include <uuid/uuid.h>
>>>>> +
>>>>> +#define NFS4IDFILE "/etc/nfs4-id"
>>>>> +
>>>>> +UUID_DEFINE(nfs4_clientid_uuid_template,
>>>>> + 0xa2, 0x25, 0x68, 0xb2, 0x7a, 0x5f, 0x49, 0x90,
>>>>> + 0x8f, 0x98, 0xc5, 0xf0, 0x67, 0x78, 0xcc, 0xf1);
>>>>> +
>>>>> +static char *prog;
>>>>> +static char *source = NULL;
>>>>> +static char nfs4_id[64];
>>>>> +static int force = 0;
>>>>> +
>>>>> +static void usage(void)
>>>>> +{
>>>>> + fprintf(stderr, "usage: %s [-f|--force] [machine]\n", prog);
>>>>> +}
>>>>> +
>>>>> +static void fatal(const char *fmt, ...)
>>>>> +{
>>>>> + int err = errno;
>>>>> + va_list args;
>>>>> + char fatal_msg[256] = "fatal: ";
>>>>> +
>>>>> + va_start(args, fmt);
>>>>> + vsnprintf(&fatal_msg[7], 255, fmt, args);
>>>>> + if (err)
>>>>> + fprintf(stderr, "%s: %s\n", fatal_msg, strerror(err));
>>>>> + else
>>>>> + fprintf(stderr, "%s\n", fatal_msg);
>>>>> + exit(-1);
>>>>> +}
>>>>> +
>>>>> +static int read_nfs4_id(void)
>>>>> +{
>>>>> + int fd;
>>>>> +
>>>>> + fd = open(NFS4IDFILE, O_RDONLY);
>>>>> + if (fd < 0)
>>>>> + return fd;
>>>>> + read(fd, nfs4_id, 64);
>>>>> + close(fd);
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>>> +static void write_nfs4_id(void)
>>>>> +{
>>>>> + int fd;
>>>>> +
>>>>> + fd = open(NFS4IDFILE, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
>>>>> + if (fd < 0)
>>>>> + fatal("could not write id to " NFS4IDFILE);
>>>>> + write(fd, nfs4_id, 37);
>>>>> +}
>>>>> +
>>>>> +static void print_nfs4_id(void)
>>>>> +{
>>>>> + fprintf(stdout, "%s", nfs4_id);
>>>>> +}
>>>>> +
>>>>> +static void check_or_make_id(void)
>>>>> +{
>>>>> + int ret;
>>>>> + uuid_t nfs4id_uuid;
>>>>> +
>>>>> + ret = read_nfs4_id();
>>>>> + if (ret != 0) {
>>>>> + if (errno != ENOENT )
>>>>> + fatal("reading file " NFS4IDFILE);
>>>>> + uuid_generate_random(nfs4id_uuid);
>>>>> + uuid_unparse(nfs4id_uuid, nfs4_id);
>>>>> + nfs4_id[36] = '\n';
>>>>> + nfs4_id[37] = '\0';
>>>>> + write_nfs4_id();
>>>>> + }
>>>>> + print_nfs4_id();
>>>>> +}
>>>>> +
>>>>> +static void check_or_make_id_from_machine(void)
>>>>> +{
>>>>> + int fd, ret;
>>>>> + char machineid[32];
>>>>> + uuid_t nfs4id_uuid;
>>>>> +
>>>>> + ret = read_nfs4_id();
>>>>> + if (ret != 0) {
>>>>> + if (errno != ENOENT )
>>>>> + fatal("reading file " NFS4IDFILE);
>>>>> +
>>>>> + fd = open("/etc/machine-id", O_RDONLY);
>>>>> + if (fd < 0)
>>>>> + fatal("unable to read /etc/machine-id");
>>>>> +
>>>>> + read(fd, machineid, 32);
>>>>> + close(fd);
>>>>> +
>>>>> + uuid_generate_sha1(nfs4id_uuid, nfs4_clientid_uuid_template, machineid, 32);
>>>>> + uuid_unparse(nfs4id_uuid, nfs4_id);
>>>>> + nfs4_id[36] = '\n';
>>>>> + nfs4_id[37] = '\0';
>>>>> + write_nfs4_id();
>>>>> + }
>>>>> + print_nfs4_id();
>>>>> +}
>>>>> +
>>>>> +int main(int argc, char **argv)
>>>>> +{
>>>>> + prog = argv[0];
>>>>> +
>>>>> + while (1) {
>>>>> + int opt;
>>>>> + int option_index = 0;
>>>>> + static struct option long_options[] = {
>>>>> + {"force", no_argument, 0, 'f' },
>>>>> + {0, 0, 0, 0 }
>>>>> + };
>>>>> +
>>>>> + errno = 0;
>>>>> + opt = getopt_long(argc, argv, ":f", long_options, &option_index);
>>>>> + if (opt == -1)
>>>>> + break;
>>>>> +
>>>>> + switch (opt) {
>>>>> + case 'f':
>>>>> + force = 1;
>>>>> + break;
>>>>> + case '?':
>>>>> + usage();
>>>>> + fatal("unexpected arg \"%s\"", argv[optind - 1]);
>>>>> + break;
>>>>> + }
>>>>> + }
>>>>> +
>>>>> + argc -= optind;
>>>>> +
>>>>> + if (argc > 1) {
>>>>> + usage();
>>>>> + fatal("Too many arguments");
>>>>> + }
>>>>> +
>>>>> + if (argc)
>>>>> + source = argv[optind++];
>>>>> +
>>>>> + if (force)
>>>>> + unlink(NFS4IDFILE);
>>>>> +
>>>>> + if (!source)
>>>>> + check_or_make_id();
>>>>> + else if (strcmp(source, "machine") == 0)
>>>>> + check_or_make_id_from_machine();
>>>>> + else {
>>>>> + usage();
>>>>> + fatal("unrecognized source %s\n", source);
>>>>> + }
>>>>> +}
>>>>> diff --git a/tools/nfs4id/nfs4id.man b/tools/nfs4id/nfs4id.man
>>>>> new file mode 100644
>>>>> index 000000000000..358f836468a2
>>>>> --- /dev/null
>>>>> +++ b/tools/nfs4id/nfs4id.man
>>>>> @@ -0,0 +1,29 @@
>>>>> +.\"
>>>>> +.\" nfs4id(8)
>>>>> +.\"
>>>>> +.TH nfs4id 8 "3 Feb 2022"
>>>>> +.SH NAME
>>>>> +nfs4id \- Generate or return nfs4 client id uniqueifiers
>>>>> +.SH SYNOPSIS
>>>>> +.B nfs4id [ -f | --force ] [<source>]
>>>>> +
>>>>> +.SH DESCRIPTION
>>>>> +The
>>>>> +.B nfs4id
>>>>> +command provides a simple utility to help NFS Version 4 clients use unique
>>>>> +and persistent client id values. The command checks for the existence of a
>>>>> +file /etc/nfs4-id and returns the first 64 chars read from that file. If
>>>>> +the file is not found, a UUID is generated from the specified source and
>>>>> +written to the file and returned.
>>>>> +.SH OPTIONS
>>>>> +.TP
>>>>> +.BR \-f, \-\-force
>>>>> +Overwrite the existing /etc/nfs4-id with a UUID generated from <source>.
>>>>> +.SH Sources
>>>>> +If <source> is not specified, nfs4id will generate a new random UUID.
>>>>> +
>>>>> +If <source> is "machine", nfs4id will generate a deterministic UUID value
>>>>> +derived from a sha1 hash of the contents of /etc/machine-id and a static
>>>>> +key.
>>>>> +.SH SEE ALSO
>>>>> +.BR machine-id (5)
>>> --
>>> Chuck Lever
>>
>
> --
> Chuck Lever
>
>
>


2022-02-09 11:51:15

by NeilBrown

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On Sat, 05 Feb 2022, Chuck Lever III wrote:
>
> The problem is that a network namespace (to which the persistent
> uniquifier is attached) and an FS namespace (in which the persistent
> uniquifier is stored) are created and managed independently.

Not necessarily .... at least: network namespaces do have visibility in
the filesystem and you can have files that associate with a specific
network namespace - without depending on FS namespaces.

"man ip-netns" tells us that when a tool (e.g. mount.nfs) is
network-namespace aware, it should first look in /etc/netns/NAME/
before looking in /etc/ for any config file.
The tool can determine "NAME" by running "ip netns identify", but there
is bound to library code to achieve the same effect.
You stat /proc/self/ns/net, then readdir /run/netns and stat everything
in there until you find something that matches /proc/self/ns/net

If a container management system wants to put /etc/ elsewhere, it can
doubtlessly install a symlink in /etc/netns/NAME, and as this is an
established standard, it seems likely that they already do.

So: enhance nfs-utils config code to (optionally) look in
/etc/netns/NAME first (or maybe last if they are to override) , and
store the identity in /etc/{netns/NAME/}nfs.conf.d/identity.conf

Whatever tool creates the identity, writes it to
/etc/netns/NAME/nfs.conf.d/identity.conf

While we are at it, we should get exportfs to look there too, and
establish some convention so /var/lib/nfs can use a different path in
different network namespaces.

Thanks,
NeilBrown


>
> We need to agree on how NFSv4 clients in containers are to be
> supported before the proposed tool can be evaluated fully.
>
>
> --
> Chuck Lever
>
>
>
>

2022-02-09 16:08:53

by Steve Dickson

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers



On 2/9/22 8:55 AM, Benjamin Coddington wrote:
> On 8 Feb 2022, at 17:30, Steve Dickson wrote:
>
>> Hey!
>>
>> On 2/8/22 3:00 PM, Benjamin Coddington wrote:
>>> On 8 Feb 2022, at 14:52, Steve Dickson wrote:
>>>
>>>> On 2/8/22 11:22 AM, Benjamin Coddington wrote:
>>>>> On 8 Feb 2022, at 11:04, Steve Dickson wrote:
>>>>>
>>>>>> Hello,
>>>>>>
>>>>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>>>>> The nfs4id program will either create a new UUID from a random
>>>>>>> source or
>>>>>>> derive it from /etc/machine-id, else it returns a UUID that has
>>>>>>> already
>>>>>>> been written to /etc/nfs4-id.  This small, lightweight tool is
>>>>>>> suitable for
>>>>>>> execution by systemd-udev in rules to populate the nfs4 client
>>>>>>> uniquifier.
>>>>>>>
>>>>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>>>>> ---
>>>>>>>   .gitignore               |   1 +
>>>>>>>   configure.ac             |   4 +
>>>>>>>   tools/Makefile.am        |   1 +
>>>>>>>   tools/nfs4id/Makefile.am |   8 ++
>>>>>>>   tools/nfs4id/nfs4id.c    | 184
>>>>>>> +++++++++++++++++++++++++++++++++++++++
>>>>>>>   tools/nfs4id/nfs4id.man  |  29 ++++++
>>>>>>>   6 files changed, 227 insertions(+)
>>>>>>>   create mode 100644 tools/nfs4id/Makefile.am
>>>>>>>   create mode 100644 tools/nfs4id/nfs4id.c
>>>>>>>   create mode 100644 tools/nfs4id/nfs4id.man
>>>>>> Just a nit... naming convention... In the past
>>>>>> we never put the protocol version in the name.
>>>>>> Do a ls tools and utils directory and you
>>>>>> see what I mean....
>>>>>>
>>>>>> Would it be a problem to change the name from
>>>>>> nfs4id to nfsid?
>>>>>
>>>>> Not at all..
>>>> Good...
>>>
>>> I didn't orginally do that because I thought it might be confusing
>>> for some
>>> folks who want `nfsid` to display their kerberos identity.  There's a BZ
>>> open for that!
>>>
>>> Do you think that's a problem?  I feel like it's a problem.
>>>
>>>>> and I think there's a lot of room for naming discussions about
>>>>> the file to store the id too:
>>>>>
>>>>> Trond sent /etc/nfs4_uuid
>>>>> Neil suggests /etc/netns/NAME/nfs.conf.d/identity.conf
>>>>> Ben sent /etc/nfs4-id (to match /etc/machine-id)
>>>> Question... is it kosher to be writing /etc which is
>>>> generally on the root filesystem?
>>>
>>> Sure, why not?
>> In general, writes to /etc are only happen when packages
>> are installed and removed... any real time writes go
>> to /var or /run (which is not persistent).
>
> I use `passwd` and `usermod`, which write to etc.  I can think of other
> examples.  For me, /etc is fair game.
>
> There's three of us that think /etc is a good place.  You're the maintainer
> though, tell us what's acceptable.  If we add an -f option to specify the
> file, I'd like there to be a sane default if -f is absent.
/etc is fine...

steved,

>
>>>> By far Neil suggestion is the most intriguing... but
>>>> on the containers I'm looking at there no /etc/netns
>>>> directory.
>>>
>>> Not yet -- you can create it.
>> "you" meaning who? the nfs-utils install or network
>> namespace env? Or is it, when /etc/netns exists
>> there is a network namespace and we should use
>> that dir?
>
> Anyone that wants to create network namespace specific configuration can
> create /etc/netns/NAME, and the iproute2 tools will bind-mount
> configuration
> from there over /etc/ when doing `ip netns exec`.
>
> Ben
>


2022-02-09 18:43:20

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 8 Feb 2022, at 17:30, Steve Dickson wrote:

> Hey!
>
> On 2/8/22 3:00 PM, Benjamin Coddington wrote:
>> On 8 Feb 2022, at 14:52, Steve Dickson wrote:
>>
>>> On 2/8/22 11:22 AM, Benjamin Coddington wrote:
>>>> On 8 Feb 2022, at 11:04, Steve Dickson wrote:
>>>>
>>>>> Hello,
>>>>>
>>>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>>>> The nfs4id program will either create a new UUID from a random
>>>>>> source or
>>>>>> derive it from /etc/machine-id, else it returns a UUID that has
>>>>>> already
>>>>>> been written to /etc/nfs4-id.  This small, lightweight tool is
>>>>>> suitable for
>>>>>> execution by systemd-udev in rules to populate the nfs4 client
>>>>>> uniquifier.
>>>>>>
>>>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>>>> ---
>>>>>>   .gitignore               |   1 +
>>>>>>   configure.ac             |   4 +
>>>>>>   tools/Makefile.am        |   1 +
>>>>>>   tools/nfs4id/Makefile.am |   8 ++
>>>>>>   tools/nfs4id/nfs4id.c    | 184
>>>>>> +++++++++++++++++++++++++++++++++++++++
>>>>>>   tools/nfs4id/nfs4id.man  |  29 ++++++
>>>>>>   6 files changed, 227 insertions(+)
>>>>>>   create mode 100644 tools/nfs4id/Makefile.am
>>>>>>   create mode 100644 tools/nfs4id/nfs4id.c
>>>>>>   create mode 100644 tools/nfs4id/nfs4id.man
>>>>> Just a nit... naming convention... In the past
>>>>> we never put the protocol version in the name.
>>>>> Do a ls tools and utils directory and you
>>>>> see what I mean....
>>>>>
>>>>> Would it be a problem to change the name from
>>>>> nfs4id to nfsid?
>>>>
>>>> Not at all..
>>> Good...
>>
>> I didn't orginally do that because I thought it might be confusing
>> for some
>> folks who want `nfsid` to display their kerberos identity.  There's
>> a BZ
>> open for that!
>>
>> Do you think that's a problem?  I feel like it's a problem.
>>
>>>> and I think there's a lot of room for naming discussions about
>>>> the file to store the id too:
>>>>
>>>> Trond sent /etc/nfs4_uuid
>>>> Neil suggests /etc/netns/NAME/nfs.conf.d/identity.conf
>>>> Ben sent /etc/nfs4-id (to match /etc/machine-id)
>>> Question... is it kosher to be writing /etc which is
>>> generally on the root filesystem?
>>
>> Sure, why not?
> In general, writes to /etc are only happen when packages
> are installed and removed... any real time writes go
> to /var or /run (which is not persistent).

I use `passwd` and `usermod`, which write to etc. I can think of other
examples. For me, /etc is fair game.

There's three of us that think /etc is a good place. You're the
maintainer
though, tell us what's acceptable. If we add an -f option to specify
the
file, I'd like there to be a sane default if -f is absent.

>>> By far Neil suggestion is the most intriguing... but
>>> on the containers I'm looking at there no /etc/netns
>>> directory.
>>
>> Not yet -- you can create it.
> "you" meaning who? the nfs-utils install or network
> namespace env? Or is it, when /etc/netns exists
> there is a network namespace and we should use
> that dir?

Anyone that wants to create network namespace specific configuration can
create /etc/netns/NAME, and the iproute2 tools will bind-mount
configuration
from there over /etc/ when doing `ip netns exec`.

Ben


2022-02-09 23:20:57

by Trond Myklebust

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On Thu, 2022-02-10 at 08:21 +1100, NeilBrown wrote:
> On Wed, 09 Feb 2022, Steve Dickson wrote:
> >
> > On 2/8/22 11:22 AM, Benjamin Coddington wrote:
> > > On 8 Feb 2022, at 11:04, Steve Dickson wrote:
> > >
> > > > Hello,
> > > >
> > > > On 2/4/22 7:56 AM, Benjamin Coddington wrote:
> > > > > The nfs4id program will either create a new UUID from a
> > > > > random source or
> > > > > derive it from /etc/machine-id, else it returns a UUID that
> > > > > has already
> > > > > been written to /etc/nfs4-id.  This small, lightweight tool
> > > > > is
> > > > > suitable for
> > > > > execution by systemd-udev in rules to populate the nfs4
> > > > > client
> > > > > uniquifier.
> > > > >
> > > > > Signed-off-by: Benjamin Coddington <[email protected]>
> > > > > ---
> > > > >   .gitignore               |   1 +
> > > > >   configure.ac             |   4 +
> > > > >   tools/Makefile.am        |   1 +
> > > > >   tools/nfs4id/Makefile.am |   8 ++
> > > > >   tools/nfs4id/nfs4id.c    | 184
> > > > > +++++++++++++++++++++++++++++++++++++++
> > > > >   tools/nfs4id/nfs4id.man  |  29 ++++++
> > > > >   6 files changed, 227 insertions(+)
> > > > >   create mode 100644 tools/nfs4id/Makefile.am
> > > > >   create mode 100644 tools/nfs4id/nfs4id.c
> > > > >   create mode 100644 tools/nfs4id/nfs4id.man
> > > > Just a nit... naming convention... In the past
> > > > we never put the protocol version in the name.
> > > > Do a ls tools and utils directory and you
> > > > see what I mean....
> > > >
> > > > Would it be a problem to change the name from
> > > > nfs4id to nfsid?
> > >
> > > Not at all..
> > Good...
> >
> > > and I think there's a lot of room for naming discussions about
> > > the file to store the id too:
> > >
> > > Trond sent /etc/nfs4_uuid
> > > Neil suggests /etc/netns/NAME/nfs.conf.d/identity.conf
> > > Ben sent /etc/nfs4-id (to match /etc/machine-id)
> > Question... is it kosher to be writing /etc which is
> > generally on the root filesystem?
> >
> > By far Neil suggestion is the most intriguing... but
> > on the containers I'm looking at there no /etc/netns
> > directory.
> >
> > I had to install the iproute package to do the
> > "ip netns identify" which returns NULL...
> > also adds yet another dependency on nfs-utils.
> >
> > So if "ip netns identify" does return NULL what directory
> > path should be used?
>
> I'm not sure if this has been explicitly answered or not, so just in
> case...
>   if "ip netns/identify" report NAME, then use /etc/netns/NAME/foo
>   if it fails or report nothing, use /etc/foo
>
> I think this is required whether we use nfs4-id, nfs-id, nfs-
> identity,
> nfs.conf.d/identity.conf or any other file in /etc.
>

Who uses this tool, and for what? This isn't anything that the standard
container orchestration managers use.

I'm running docker right now:

NR_09-21:41:07 host ~ $ ls /etc/net*
/etc/netconfig /etc/networks
NR_09-21:41:47 hosts ~ $ docker exec -it f7debc079f4e bash
[root@f7debc079f4e /]# ls /etc/net*
/etc/netconfig /etc/networks
[root@f7debc079f4e /]# ip netns identify

[root@f7debc079f4e /]#

As you can see, neither the host nor the container have anything in
/etc/netns, and 'ip netns identify' is drawing a blank in both.

--
Trond Myklebust
Linux NFS client maintainer, Hammerspace
[email protected]


2022-02-09 23:38:18

by NeilBrown

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On Wed, 09 Feb 2022, Steve Dickson wrote:
>
> On 2/8/22 11:22 AM, Benjamin Coddington wrote:
> > On 8 Feb 2022, at 11:04, Steve Dickson wrote:
> >
> >> Hello,
> >>
> >> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
> >>> The nfs4id program will either create a new UUID from a random source or
> >>> derive it from /etc/machine-id, else it returns a UUID that has already
> >>> been written to /etc/nfs4-id.  This small, lightweight tool is
> >>> suitable for
> >>> execution by systemd-udev in rules to populate the nfs4 client
> >>> uniquifier.
> >>>
> >>> Signed-off-by: Benjamin Coddington <[email protected]>
> >>> ---
> >>>   .gitignore               |   1 +
> >>>   configure.ac             |   4 +
> >>>   tools/Makefile.am        |   1 +
> >>>   tools/nfs4id/Makefile.am |   8 ++
> >>>   tools/nfs4id/nfs4id.c    | 184 +++++++++++++++++++++++++++++++++++++++
> >>>   tools/nfs4id/nfs4id.man  |  29 ++++++
> >>>   6 files changed, 227 insertions(+)
> >>>   create mode 100644 tools/nfs4id/Makefile.am
> >>>   create mode 100644 tools/nfs4id/nfs4id.c
> >>>   create mode 100644 tools/nfs4id/nfs4id.man
> >> Just a nit... naming convention... In the past
> >> we never put the protocol version in the name.
> >> Do a ls tools and utils directory and you
> >> see what I mean....
> >>
> >> Would it be a problem to change the name from
> >> nfs4id to nfsid?
> >
> > Not at all..
> Good...
>
> > and I think there's a lot of room for naming discussions about
> > the file to store the id too:
> >
> > Trond sent /etc/nfs4_uuid
> > Neil suggests /etc/netns/NAME/nfs.conf.d/identity.conf
> > Ben sent /etc/nfs4-id (to match /etc/machine-id)
> Question... is it kosher to be writing /etc which is
> generally on the root filesystem?
>
> By far Neil suggestion is the most intriguing... but
> on the containers I'm looking at there no /etc/netns
> directory.
>
> I had to install the iproute package to do the
> "ip netns identify" which returns NULL...
> also adds yet another dependency on nfs-utils.
>
> So if "ip netns identify" does return NULL what directory
> path should be used?

I'm not sure if this has been explicitly answered or not, so just in
case...
if "ip netns/identify" report NAME, then use /etc/netns/NAME/foo
if it fails or report nothing, use /etc/foo

I think this is required whether we use nfs4-id, nfs-id, nfs-identity,
nfs.conf.d/identity.conf or any other file in /etc.

NeilBrown

2022-02-10 02:36:10

by NeilBrown

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On Thu, 10 Feb 2022, Trond Myklebust wrote:
> On Thu, 2022-02-10 at 08:21 +1100, NeilBrown wrote:
> >
> > I'm not sure if this has been explicitly answered or not, so just in
> > case...
> >   if "ip netns/identify" report NAME, then use /etc/netns/NAME/foo
> >   if it fails or report nothing, use /etc/foo
> >
> > I think this is required whether we use nfs4-id, nfs-id, nfs-
> > identity,
> > nfs.conf.d/identity.conf or any other file in /etc.
> >
>
> Who uses this tool, and for what? This isn't anything that the standard
> container orchestration managers use.

At a guess, I'd say it would be used by anyone who just wants to set up
a separate network namespace, not necessarily a full "container".

>
> I'm running docker right now:
>
> NR_09-21:41:07 host ~ $ ls /etc/net*
> /etc/netconfig /etc/networks
> NR_09-21:41:47 hosts ~ $ docker exec -it f7debc079f4e bash
> [root@f7debc079f4e /]# ls /etc/net*
> /etc/netconfig /etc/networks
> [root@f7debc079f4e /]# ip netns identify
>
> [root@f7debc079f4e /]#
>
> As you can see, neither the host nor the container have anything in
> /etc/netns, and 'ip netns identify' is drawing a blank in both.
>

One of the original reasons given to reject the idea of using
/etc/nfs.conf{,.d} was that is wasn't "container aware".
I tried to find out what this might mean and discovered "ip netnfs" and
its man page which says:

For applications that are aware of network namespaces, the convention
is to look for global network configuration files first in
/etc/netns/NAME/ then in /etc/. For example, if you want a different
version of /etc/resolv.conf for a network namespace used to isolate
your vpn you would name it /etc/netns/myvpn/resolv.conf.

Obviously containers don't *have* to follow this model. I guess there
is a difference between being "container aware" and being "network
namespace aware".

Presumably a full container manager (e.g. docker) would set everything up
so that tools don't *need* to be container aware. When you run docker,
do you get a separate /etc/ from the one outside of docker? If you
create /etc/nfs-client-identifier inside the docker container, does it
remain private to that container? Does it persist with the container?

Possibly NFS tools don't need to check in /etc/netnfs/NAME as they could
simply be run with "ip netns exec NAME tool args" which would set up
/etc. This is fine for reading config files, but doesn't necessarily
work correctly for creating config files.

Possibly the goal of having an NFS tool which automatically creates and
persists a client identifier for the current container is not practical.
Maybe we just document what any container-creation platform must do for
NFS, and let them all implement that however seems best. With the new
random-identity-at-namespace-creation patch the cost of not doing
anything is localised to the container

Maybe we should just provide a tool
nfs-set-client-identity NAME
The container setup code provides some "NAME" for the container which it
is responsible for keeping persistent, and we just write it to
/sys/fs/nfs/net/nfs_client/idenfier, possibly after hashing or whatever.

NeilBrown

2022-02-10 13:39:34

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 9 Feb 2022, at 18:58, NeilBrown wrote:

> On Thu, 10 Feb 2022, Trond Myklebust wrote:
>> On Thu, 2022-02-10 at 08:21 +1100, NeilBrown wrote:
>>>
>>> I'm not sure if this has been explicitly answered or not, so just in
>>> case...
>>>   if "ip netns/identify" report NAME, then use /etc/netns/NAME/foo
>>>   if it fails or report nothing, use /etc/foo
>>>
>>> I think this is required whether we use nfs4-id, nfs-id, nfs-
>>> identity,
>>> nfs.conf.d/identity.conf or any other file in /etc.
>>>
>>
>> Who uses this tool, and for what? This isn't anything that the standard
>> container orchestration managers use.
>
> At a guess, I'd say it would be used by anyone who just wants to set up
> a separate network namespace, not necessarily a full "container".
>
>>
>> I'm running docker right now:
>>
>> NR_09-21:41:07 host ~ $ ls /etc/net*
>> /etc/netconfig /etc/networks
>> NR_09-21:41:47 hosts ~ $ docker exec -it f7debc079f4e bash
>> [root@f7debc079f4e /]# ls /etc/net*
>> /etc/netconfig /etc/networks
>> [root@f7debc079f4e /]# ip netns identify
>>
>> [root@f7debc079f4e /]#
>>
>> As you can see, neither the host nor the container have anything in
>> /etc/netns, and 'ip netns identify' is drawing a blank in both.
>>
>
> One of the original reasons given to reject the idea of using
> /etc/nfs.conf{,.d} was that is wasn't "container aware".
> I tried to find out what this might mean and discovered "ip netnfs" and
> its man page which says:
>
> For applications that are aware of network namespaces, the convention
> is to look for global network configuration files first in
> /etc/netns/NAME/ then in /etc/. For example, if you want a different
> version of /etc/resolv.conf for a network namespace used to isolate
> your vpn you would name it /etc/netns/myvpn/resolv.conf.
>
> Obviously containers don't *have* to follow this model. I guess there
> is a difference between being "container aware" and being "network
> namespace aware".
>
> Presumably a full container manager (e.g. docker) would set everything up
> so that tools don't *need* to be container aware. When you run docker,
> do you get a separate /etc/ from the one outside of docker? If you
> create /etc/nfs-client-identifier inside the docker container, does it
> remain private to that container? Does it persist with the container?
>
> Possibly NFS tools don't need to check in /etc/netnfs/NAME as they could
> simply be run with "ip netns exec NAME tool args" which would set up
> /etc. This is fine for reading config files, but doesn't necessarily
> work correctly for creating config files.
>
> Possibly the goal of having an NFS tool which automatically creates and
> persists a client identifier for the current container is not practical.
> Maybe we just document what any container-creation platform must do for
> NFS, and let them all implement that however seems best. With the new
> random-identity-at-namespace-creation patch the cost of not doing
> anything is localised to the container

Yes, I think this is the right approach, since all the containers do it
differently.

If there's a simple way to generate and persist a uuid (a small tool to do
so), and a udev rule to move that value to the kernel, that should be
sufficient for a container to use as well as our common case with the host.
When (if?) container folks want persistent ids, We can simply say: the way
to have persistent ids is to run udev in your container with a rule just
like the one on the host.

I can't imagine a container that needs to be persistent for NFS not having
its own /etc, but if it doesn't (say only /var is writeable) the udev rule
can be modififed to send an argument to the tool to change where it stores
the id. Another way of generating a stable uniquifier might be to just
simply specify a static value in the udev rule itself, or containers might
just come up with their own methods.

On our distro, we want to seed the client id from /etc/machine-id.

> Maybe we should just provide a tool
> nfs-set-client-identity NAME
> The container setup code provides some "NAME" for the container which it
> is responsible for keeping persistent, and we just write it to
> /sys/fs/nfs/net/nfs_client/idenfier, possibly after hashing or whatever.

Yes, but even better than having the tool do the writing is to have udev do
it, because udev makes the problem of when and who will execute this tool go
away, and the entire process is configurable for anyone that needs to change
any part of it or use their own methods of generating/storing ids.

Ben


2022-02-10 14:48:44

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 8 Feb 2022, at 17:39, Steve Dickson wrote:

> On 2/8/22 4:18 PM, Chuck Lever III wrote:
>>
>>
>>> On Feb 8, 2022, at 2:29 PM, Steve Dickson <[email protected]> wrote:
>>>
>>>
>>>
>>> On 2/8/22 11:21 AM, Chuck Lever III wrote:
>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <[email protected]>
>>>>> wrote:
>>>>>
>>>>> Hello,
>>>>>
>>>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>>>> The nfs4id program will either create a new UUID from a random
>>>>>> source or
>>>>>> derive it from /etc/machine-id, else it returns a UUID that has
>>>>>> already
>>>>>> been written to /etc/nfs4-id. This small, lightweight tool is
>>>>>> suitable for
>>>>>> execution by systemd-udev in rules to populate the nfs4 client
>>>>>> uniquifier.
>>>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>>>> ---
>>>>>> .gitignore | 1 +
>>>>>> configure.ac | 4 +
>>>>>> tools/Makefile.am | 1 +
>>>>>> tools/nfs4id/Makefile.am | 8 ++
>>>>>> tools/nfs4id/nfs4id.c | 184
>>>>>> +++++++++++++++++++++++++++++++++++++++
>>>>>> tools/nfs4id/nfs4id.man | 29 ++++++
>>>>>> 6 files changed, 227 insertions(+)
>>>>>> create mode 100644 tools/nfs4id/Makefile.am
>>>>>> create mode 100644 tools/nfs4id/nfs4id.c
>>>>>> create mode 100644 tools/nfs4id/nfs4id.man
>>>>> Just a nit... naming convention... In the past
>>>>> we never put the protocol version in the name.
>>>>> Do a ls tools and utils directory and you
>>>>> see what I mean....
>>>>>
>>>>> Would it be a problem to change the name from
>>>>> nfs4id to nfsid?
>>>> nfs4id is pretty generic, too.
>>>> Can we go with nfs-client-id ?
>>> I'm never been big with putting '-'
>>> in command names... nfscltid would
>>> be better IMHO... if we actually
>>> need the 'clt' in the name.
>>
>> We have nfsidmap already. IMO we need some distinction
>> with user ID mapping tools... and some day we might
>> want to manage server IDs too (see EXCHANGE_ID).
> Hmm... So we could not use the same tool to do
> both the server and client, via flags?
>
>>
>> nfsclientid then?
> You like to type more than I do... You always have... :-)
>
> But like I started the conversation... the naming is
> a nit... but I would like to see one tool to set the
> ids for both the server and client... how about
> nfsid -s and nfsid -c

The tricky thing here is that this little binary isn't going to set
anything, and we probably never want people to run it from the command
line.

A 'nfsid -s' and 'nfsid -c' seem to want to do much more. I feel they
are
out of scope for the problem I'm trying to solve: I need something that
will generate a unique value, and persist it, suitable for execution in
a
udevd rule.

Perhaps we can stop worrying so much about the name of this as I don't
think
it should be a first-class nfs-utils command, rather just a helper for
udev.

And maybe the name can reflect that - "nfsuuid" ?

Ben


2022-02-10 16:43:44

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 10 Feb 2022, at 10:21, Chuck Lever III wrote:

>> On Feb 10, 2022, at 8:28 AM, Benjamin Coddington
>> <[email protected]> wrote:
>>
>> On 8 Feb 2022, at 17:39, Steve Dickson wrote:
>>
>>> On 2/8/22 4:18 PM, Chuck Lever III wrote:
>>>>
>>>>
>>>>> On Feb 8, 2022, at 2:29 PM, Steve Dickson <[email protected]>
>>>>> wrote:
>>>>>
>>>>>
>>>>>
>>>>> On 2/8/22 11:21 AM, Chuck Lever III wrote:
>>>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <[email protected]>
>>>>>>> wrote:
>>>>>>>
>>>>>>> Hello,
>>>>>>>
>>>>>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>>>>>> The nfs4id program will either create a new UUID from a random
>>>>>>>> source or
>>>>>>>> derive it from /etc/machine-id, else it returns a UUID that has
>>>>>>>> already
>>>>>>>> been written to /etc/nfs4-id. This small, lightweight tool is
>>>>>>>> suitable for
>>>>>>>> execution by systemd-udev in rules to populate the nfs4 client
>>>>>>>> uniquifier.
>>>>>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>>>>>> ---
>>>>>>>> .gitignore | 1 +
>>>>>>>> configure.ac | 4 +
>>>>>>>> tools/Makefile.am | 1 +
>>>>>>>> tools/nfs4id/Makefile.am | 8 ++
>>>>>>>> tools/nfs4id/nfs4id.c | 184
>>>>>>>> +++++++++++++++++++++++++++++++++++++++
>>>>>>>> tools/nfs4id/nfs4id.man | 29 ++++++
>>>>>>>> 6 files changed, 227 insertions(+)
>>>>>>>> create mode 100644 tools/nfs4id/Makefile.am
>>>>>>>> create mode 100644 tools/nfs4id/nfs4id.c
>>>>>>>> create mode 100644 tools/nfs4id/nfs4id.man
>>>>>>> Just a nit... naming convention... In the past
>>>>>>> we never put the protocol version in the name.
>>>>>>> Do a ls tools and utils directory and you
>>>>>>> see what I mean....
>>>>>>>
>>>>>>> Would it be a problem to change the name from
>>>>>>> nfs4id to nfsid?
>>>>>> nfs4id is pretty generic, too.
>>>>>> Can we go with nfs-client-id ?
>>>>> I'm never been big with putting '-'
>>>>> in command names... nfscltid would
>>>>> be better IMHO... if we actually
>>>>> need the 'clt' in the name.
>>>>
>>>> We have nfsidmap already. IMO we need some distinction
>>>> with user ID mapping tools... and some day we might
>>>> want to manage server IDs too (see EXCHANGE_ID).
>>> Hmm... So we could not use the same tool to do
>>> both the server and client, via flags?
>>>
>>>>
>>>> nfsclientid then?
>>> You like to type more than I do... You always have... :-)
>>>
>>> But like I started the conversation... the naming is
>>> a nit... but I would like to see one tool to set the
>>> ids for both the server and client... how about
>>> nfsid -s and nfsid -c
>>
>> The tricky thing here is that this little binary isn't going to set
>> anything, and we probably never want people to run it from the
>> command line.
>>
>> A 'nfsid -s' and 'nfsid -c' seem to want to do much more. I feel
>> they are
>> out of scope for the problem I'm trying to solve: I need something
>> that
>> will generate a unique value, and persist it, suitable for execution
>> in a
>> udevd rule.
>>
>> Perhaps we can stop worrying so much about the name of this as I
>> don't think
>> it should be a first-class nfs-utils command, rather just a helper
>> for udev.
>>
>> And maybe the name can reflect that - "nfsuuid" ?
>
> The client ID can be an arbitrary string, so I think not.

I feel like we might all be missing the fact that this tool doesn't
create
client IDs. The tool only creates uuids, and returns what may have
already
been set by something somewhere else. It's not supposed to ever get
typed
out or run by people. Any other suggestions? Here's where we are:

nfs4id - no: we dislike the number 4
nfsuuid - no: it doesn't have to be a uuid
nfsid - no: too ambiguous
nfscltid - no: also too ambiguous
nfsclientid - no: too much typing

Since I've already re-written it, I'm going to send it again as nfsuuid
-
and let's bikeshed on it again over there, and see if we can make
suggestions that might make everyone happy.

Ben


2022-02-10 17:02:04

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 10 Feb 2022, at 11:25, Chuck Lever III wrote:

>> On Feb 10, 2022, at 10:47 AM, Benjamin Coddington
>> <[email protected]> wrote:
>>
>> On 10 Feb 2022, at 10:21, Chuck Lever III wrote:
>>
>>>> On Feb 10, 2022, at 8:28 AM, Benjamin Coddington
>>>> <[email protected]> wrote:
>>>>
>>>> On 8 Feb 2022, at 17:39, Steve Dickson wrote:
>>>>
>>>>> On 2/8/22 4:18 PM, Chuck Lever III wrote:
>>>>>>
>>>>>>
>>>>>>> On Feb 8, 2022, at 2:29 PM, Steve Dickson <[email protected]>
>>>>>>> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 2/8/22 11:21 AM, Chuck Lever III wrote:
>>>>>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <[email protected]>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> Hello,
>>>>>>>>>
>>>>>>>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>>>>>>>> The nfs4id program will either create a new UUID from a
>>>>>>>>>> random source or
>>>>>>>>>> derive it from /etc/machine-id, else it returns a UUID that
>>>>>>>>>> has already
>>>>>>>>>> been written to /etc/nfs4-id. This small, lightweight tool
>>>>>>>>>> is suitable for
>>>>>>>>>> execution by systemd-udev in rules to populate the nfs4
>>>>>>>>>> client uniquifier.
>>>>>>>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>>>>>>>> ---
>>>>>>>>>> .gitignore | 1 +
>>>>>>>>>> configure.ac | 4 +
>>>>>>>>>> tools/Makefile.am | 1 +
>>>>>>>>>> tools/nfs4id/Makefile.am | 8 ++
>>>>>>>>>> tools/nfs4id/nfs4id.c | 184
>>>>>>>>>> +++++++++++++++++++++++++++++++++++++++
>>>>>>>>>> tools/nfs4id/nfs4id.man | 29 ++++++
>>>>>>>>>> 6 files changed, 227 insertions(+)
>>>>>>>>>> create mode 100644 tools/nfs4id/Makefile.am
>>>>>>>>>> create mode 100644 tools/nfs4id/nfs4id.c
>>>>>>>>>> create mode 100644 tools/nfs4id/nfs4id.man
>>>>>>>>> Just a nit... naming convention... In the past
>>>>>>>>> we never put the protocol version in the name.
>>>>>>>>> Do a ls tools and utils directory and you
>>>>>>>>> see what I mean....
>>>>>>>>>
>>>>>>>>> Would it be a problem to change the name from
>>>>>>>>> nfs4id to nfsid?
>>>>>>>> nfs4id is pretty generic, too.
>>>>>>>> Can we go with nfs-client-id ?
>>>>>>> I'm never been big with putting '-'
>>>>>>> in command names... nfscltid would
>>>>>>> be better IMHO... if we actually
>>>>>>> need the 'clt' in the name.
>>>>>>
>>>>>> We have nfsidmap already. IMO we need some distinction
>>>>>> with user ID mapping tools... and some day we might
>>>>>> want to manage server IDs too (see EXCHANGE_ID).
>>>>> Hmm... So we could not use the same tool to do
>>>>> both the server and client, via flags?
>>>>>
>>>>>>
>>>>>> nfsclientid then?
>>>>> You like to type more than I do... You always have... :-)
>>>>>
>>>>> But like I started the conversation... the naming is
>>>>> a nit... but I would like to see one tool to set the
>>>>> ids for both the server and client... how about
>>>>> nfsid -s and nfsid -c
>>>>
>>>> The tricky thing here is that this little binary isn't going to set
>>>> anything, and we probably never want people to run it from the
>>>> command line.
>>>>
>>>> A 'nfsid -s' and 'nfsid -c' seem to want to do much more. I feel
>>>> they are
>>>> out of scope for the problem I'm trying to solve: I need something
>>>> that
>>>> will generate a unique value, and persist it, suitable for
>>>> execution in a
>>>> udevd rule.
>>>>
>>>> Perhaps we can stop worrying so much about the name of this as I
>>>> don't think
>>>> it should be a first-class nfs-utils command, rather just a helper
>>>> for udev.
>>>>
>>>> And maybe the name can reflect that - "nfsuuid" ?
>>>
>>> The client ID can be an arbitrary string, so I think not.
>>
>> I feel like we might all be missing the fact that this tool doesn't
>> create
>> client IDs. The tool only creates uuids, and returns what may have
>> already
>> been set by something somewhere else. It's not supposed to ever get
>> typed
>> out or run by people. Any other suggestions?
>
> nfsgetclientid
> nfsgenclientid

But it doesn't generate client ids either.. the client id is the
uniquifier
and the nodename and conditionally the address. I feel thats even more
misleading.

> Since you asked above for other suggestions, I responded here.
> I'll try really hard not to respond again in this thread :)

:) I got sucked into this thread again too.

Ben


2022-02-10 17:30:55

by Chuck Lever III

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers



> On Feb 10, 2022, at 8:28 AM, Benjamin Coddington <[email protected]> wrote:
>
> On 8 Feb 2022, at 17:39, Steve Dickson wrote:
>
>> On 2/8/22 4:18 PM, Chuck Lever III wrote:
>>>
>>>
>>>> On Feb 8, 2022, at 2:29 PM, Steve Dickson <[email protected]> wrote:
>>>>
>>>>
>>>>
>>>> On 2/8/22 11:21 AM, Chuck Lever III wrote:
>>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <[email protected]> wrote:
>>>>>>
>>>>>> Hello,
>>>>>>
>>>>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>>>>> The nfs4id program will either create a new UUID from a random source or
>>>>>>> derive it from /etc/machine-id, else it returns a UUID that has already
>>>>>>> been written to /etc/nfs4-id. This small, lightweight tool is suitable for
>>>>>>> execution by systemd-udev in rules to populate the nfs4 client uniquifier.
>>>>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>>>>> ---
>>>>>>> .gitignore | 1 +
>>>>>>> configure.ac | 4 +
>>>>>>> tools/Makefile.am | 1 +
>>>>>>> tools/nfs4id/Makefile.am | 8 ++
>>>>>>> tools/nfs4id/nfs4id.c | 184 +++++++++++++++++++++++++++++++++++++++
>>>>>>> tools/nfs4id/nfs4id.man | 29 ++++++
>>>>>>> 6 files changed, 227 insertions(+)
>>>>>>> create mode 100644 tools/nfs4id/Makefile.am
>>>>>>> create mode 100644 tools/nfs4id/nfs4id.c
>>>>>>> create mode 100644 tools/nfs4id/nfs4id.man
>>>>>> Just a nit... naming convention... In the past
>>>>>> we never put the protocol version in the name.
>>>>>> Do a ls tools and utils directory and you
>>>>>> see what I mean....
>>>>>>
>>>>>> Would it be a problem to change the name from
>>>>>> nfs4id to nfsid?
>>>>> nfs4id is pretty generic, too.
>>>>> Can we go with nfs-client-id ?
>>>> I'm never been big with putting '-'
>>>> in command names... nfscltid would
>>>> be better IMHO... if we actually
>>>> need the 'clt' in the name.
>>>
>>> We have nfsidmap already. IMO we need some distinction
>>> with user ID mapping tools... and some day we might
>>> want to manage server IDs too (see EXCHANGE_ID).
>> Hmm... So we could not use the same tool to do
>> both the server and client, via flags?
>>
>>>
>>> nfsclientid then?
>> You like to type more than I do... You always have... :-)
>>
>> But like I started the conversation... the naming is
>> a nit... but I would like to see one tool to set the
>> ids for both the server and client... how about
>> nfsid -s and nfsid -c
>
> The tricky thing here is that this little binary isn't going to set
> anything, and we probably never want people to run it from the command line.
>
> A 'nfsid -s' and 'nfsid -c' seem to want to do much more. I feel they are
> out of scope for the problem I'm trying to solve: I need something that
> will generate a unique value, and persist it, suitable for execution in a
> udevd rule.
>
> Perhaps we can stop worrying so much about the name of this as I don't think
> it should be a first-class nfs-utils command, rather just a helper for udev.
>
> And maybe the name can reflect that - "nfsuuid" ?

The client ID can be an arbitrary string, so I think not.



--
Chuck Lever




2022-02-10 22:33:27

by Chuck Lever III

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers



> On Feb 10, 2022, at 10:47 AM, Benjamin Coddington <[email protected]> wrote:
>
> On 10 Feb 2022, at 10:21, Chuck Lever III wrote:
>
>>> On Feb 10, 2022, at 8:28 AM, Benjamin Coddington <[email protected]> wrote:
>>>
>>> On 8 Feb 2022, at 17:39, Steve Dickson wrote:
>>>
>>>> On 2/8/22 4:18 PM, Chuck Lever III wrote:
>>>>>
>>>>>
>>>>>> On Feb 8, 2022, at 2:29 PM, Steve Dickson <[email protected]> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 2/8/22 11:21 AM, Chuck Lever III wrote:
>>>>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <[email protected]> wrote:
>>>>>>>>
>>>>>>>> Hello,
>>>>>>>>
>>>>>>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>>>>>>> The nfs4id program will either create a new UUID from a random source or
>>>>>>>>> derive it from /etc/machine-id, else it returns a UUID that has already
>>>>>>>>> been written to /etc/nfs4-id. This small, lightweight tool is suitable for
>>>>>>>>> execution by systemd-udev in rules to populate the nfs4 client uniquifier.
>>>>>>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>>>>>>> ---
>>>>>>>>> .gitignore | 1 +
>>>>>>>>> configure.ac | 4 +
>>>>>>>>> tools/Makefile.am | 1 +
>>>>>>>>> tools/nfs4id/Makefile.am | 8 ++
>>>>>>>>> tools/nfs4id/nfs4id.c | 184 +++++++++++++++++++++++++++++++++++++++
>>>>>>>>> tools/nfs4id/nfs4id.man | 29 ++++++
>>>>>>>>> 6 files changed, 227 insertions(+)
>>>>>>>>> create mode 100644 tools/nfs4id/Makefile.am
>>>>>>>>> create mode 100644 tools/nfs4id/nfs4id.c
>>>>>>>>> create mode 100644 tools/nfs4id/nfs4id.man
>>>>>>>> Just a nit... naming convention... In the past
>>>>>>>> we never put the protocol version in the name.
>>>>>>>> Do a ls tools and utils directory and you
>>>>>>>> see what I mean....
>>>>>>>>
>>>>>>>> Would it be a problem to change the name from
>>>>>>>> nfs4id to nfsid?
>>>>>>> nfs4id is pretty generic, too.
>>>>>>> Can we go with nfs-client-id ?
>>>>>> I'm never been big with putting '-'
>>>>>> in command names... nfscltid would
>>>>>> be better IMHO... if we actually
>>>>>> need the 'clt' in the name.
>>>>>
>>>>> We have nfsidmap already. IMO we need some distinction
>>>>> with user ID mapping tools... and some day we might
>>>>> want to manage server IDs too (see EXCHANGE_ID).
>>>> Hmm... So we could not use the same tool to do
>>>> both the server and client, via flags?
>>>>
>>>>>
>>>>> nfsclientid then?
>>>> You like to type more than I do... You always have... :-)
>>>>
>>>> But like I started the conversation... the naming is
>>>> a nit... but I would like to see one tool to set the
>>>> ids for both the server and client... how about
>>>> nfsid -s and nfsid -c
>>>
>>> The tricky thing here is that this little binary isn't going to set
>>> anything, and we probably never want people to run it from the command line.
>>>
>>> A 'nfsid -s' and 'nfsid -c' seem to want to do much more. I feel they are
>>> out of scope for the problem I'm trying to solve: I need something that
>>> will generate a unique value, and persist it, suitable for execution in a
>>> udevd rule.
>>>
>>> Perhaps we can stop worrying so much about the name of this as I don't think
>>> it should be a first-class nfs-utils command, rather just a helper for udev.
>>>
>>> And maybe the name can reflect that - "nfsuuid" ?
>>
>> The client ID can be an arbitrary string, so I think not.
>
> I feel like we might all be missing the fact that this tool doesn't create
> client IDs. The tool only creates uuids, and returns what may have already
> been set by something somewhere else. It's not supposed to ever get typed
> out or run by people. Any other suggestions?

nfsgetclientid
nfsgenclientid


> Here's where we are:
>
> nfs4id - no: we dislike the number 4
> nfsuuid - no: it doesn't have to be a uuid
> nfsid - no: too ambiguous
> nfscltid - no: also too ambiguous
> nfsclientid - no: too much typing

Since this is not a tool that is meant to be run by humans, I'm
not sure why "too much typing" is a reasonable objection. I think
we need a name that, when a human reads it in the udev rule,
immediately reflects the purpose of the tool. The tool's name
is documentation.


> Since I've already re-written it, I'm going to send it again as nfsuuid -
> and let's bikeshed on it again over there, and see if we can make
> suggestions that might make everyone happy.

Since you asked above for other suggestions, I responded here.
I'll try really hard not to respond again in this thread :-)


--
Chuck Lever




2022-02-11 07:07:34

by NeilBrown

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On Thu, 10 Feb 2022, Benjamin Coddington wrote:
>
> Yes, but even better than having the tool do the writing is to have udev do
> it, because udev makes the problem of when and who will execute this tool go
> away, and the entire process is configurable for anyone that needs to change
> any part of it or use their own methods of generating/storing ids.

I really don't understand the focus on udev.

Something, somewhere, deliberately creates the new network namespace.
It then deliberately configures that namespace - creating a virtual
device maybe, adding an IP address, setting a default route or whatever.
None of that is done by udev rules (is it)?
Setting the NFS identity is just another part of configuring the new
network namespace.

udev is great when we don't know exactly when an event will happen, but
we want to respond when it does.
That doesn't match the case of creating a new network namespace. Some
code deliberately creates it and is perfectly positioned to then
configure it.

udev is async. How certain can we be that the udev event will be fully
handled before the first mount attempt?

NeilBrown

2022-02-11 11:18:52

by Steve Dickson

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers



On 2/10/22 8:28 AM, Benjamin Coddington wrote:
> On 8 Feb 2022, at 17:39, Steve Dickson wrote:
>
>> On 2/8/22 4:18 PM, Chuck Lever III wrote:
>>>
>>>
>>>> On Feb 8, 2022, at 2:29 PM, Steve Dickson <[email protected]> wrote:
>>>>
>>>>
>>>>
>>>> On 2/8/22 11:21 AM, Chuck Lever III wrote:
>>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <[email protected]> wrote:
>>>>>>
>>>>>> Hello,
>>>>>>
>>>>>> On 2/4/22 7:56 AM, Benjamin Coddington wrote:
>>>>>>> The nfs4id program will either create a new UUID from a random
>>>>>>> source or
>>>>>>> derive it from /etc/machine-id, else it returns a UUID that has
>>>>>>> already
>>>>>>> been written to /etc/nfs4-id.  This small, lightweight tool is
>>>>>>> suitable for
>>>>>>> execution by systemd-udev in rules to populate the nfs4 client
>>>>>>> uniquifier.
>>>>>>> Signed-off-by: Benjamin Coddington <[email protected]>
>>>>>>> ---
>>>>>>>   .gitignore               |   1 +
>>>>>>>   configure.ac             |   4 +
>>>>>>>   tools/Makefile.am        |   1 +
>>>>>>>   tools/nfs4id/Makefile.am |   8 ++
>>>>>>>   tools/nfs4id/nfs4id.c    | 184
>>>>>>> +++++++++++++++++++++++++++++++++++++++
>>>>>>>   tools/nfs4id/nfs4id.man  |  29 ++++++
>>>>>>>   6 files changed, 227 insertions(+)
>>>>>>>   create mode 100644 tools/nfs4id/Makefile.am
>>>>>>>   create mode 100644 tools/nfs4id/nfs4id.c
>>>>>>>   create mode 100644 tools/nfs4id/nfs4id.man
>>>>>> Just a nit... naming convention... In the past
>>>>>> we never put the protocol version in the name.
>>>>>> Do a ls tools and utils directory and you
>>>>>> see what I mean....
>>>>>>
>>>>>> Would it be a problem to change the name from
>>>>>> nfs4id to nfsid?
>>>>> nfs4id is pretty generic, too.
>>>>> Can we go with nfs-client-id ?
>>>> I'm never been big with putting '-'
>>>> in command names... nfscltid would
>>>> be better IMHO... if we actually
>>>> need the 'clt' in the name.
>>>
>>> We have nfsidmap already. IMO we need some distinction
>>> with user ID mapping tools... and some day we might
>>> want to manage server IDs too (see EXCHANGE_ID).
>> Hmm... So we could not use the same tool to do
>> both the server and client, via flags?
>>
>>>
>>> nfsclientid then?
>> You like to type more than I do... You always have... :-)
>>
>> But like I started the conversation... the naming is
>> a nit... but I would like to see one tool to set the
>> ids for both the server and client... how about
>> nfsid -s and nfsid -c
>
> The tricky thing here is that this little binary isn't going to set
> anything, and we probably never want people to run it from the command
> line.
>
> A 'nfsid -s' and 'nfsid -c' seem to want to do much more.  I feel they are
> out of scope for the problem I'm trying to solve:  I need something that
> will generate a unique value, and persist it, suitable for execution in a
> udevd rule.
>
> Perhaps we can stop worrying so much about the name of this as I don't
> think
> it should be a first-class nfs-utils command, rather just a helper for
> udev.
>
> And maybe the name can reflect that - "nfsuuid" ?
I can live with this....

steved


>
> Ben
>


2022-02-11 16:25:42

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 10 Feb 2022, at 17:54, NeilBrown wrote:

> On Thu, 10 Feb 2022, Benjamin Coddington wrote:
>>
>> Yes, but even better than having the tool do the writing is to have
>> udev do
>> it, because udev makes the problem of when and who will execute this
>> tool go
>> away, and the entire process is configurable for anyone that needs to
>> change
>> any part of it or use their own methods of generating/storing ids.
>
> I really don't understand the focus on udev.
>
> Something, somewhere, deliberately creates the new network namespace.
> It then deliberately configures that namespace - creating a virtual
> device maybe, adding an IP address, setting a default route or
> whatever.
> None of that is done by udev rules (is it)?
> Setting the NFS identity is just another part of configuring the new
> network namespace.
>
> udev is great when we don't know exactly when an event will happen,
> but
> we want to respond when it does.
> That doesn't match the case of creating a new network namespace. Some
> code deliberately creates it and is perfectly positioned to then
> configure it.

I think there's so many ways to create a new network namespace that we
can't
reasonably be expected to try to insert out problem into all of them.
Handling the event from the kernel allows us to make a best-effort
default
attempt.

> udev is async. How certain can we be that the udev event will be
> fully
> handled before the first mount attempt?

Good point. We can't at all be certain.

We can start over completely from here..

We can have mount.nfs /also/ try to configure the id.. this is more
robust.

We can have mount.nfs do a round of udev settle..

Are there other options?

Ben

2022-02-14 09:59:14

by NeilBrown

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On Sat, 12 Feb 2022, Benjamin Coddington wrote:
> On 10 Feb 2022, at 17:54, NeilBrown wrote:
>
> > On Thu, 10 Feb 2022, Benjamin Coddington wrote:
> >>
> >> Yes, but even better than having the tool do the writing is to have
> >> udev do
> >> it, because udev makes the problem of when and who will execute this
> >> tool go
> >> away, and the entire process is configurable for anyone that needs to
> >> change
> >> any part of it or use their own methods of generating/storing ids.
> >
> > I really don't understand the focus on udev.
> >
> > Something, somewhere, deliberately creates the new network namespace.
> > It then deliberately configures that namespace - creating a virtual
> > device maybe, adding an IP address, setting a default route or
> > whatever.
> > None of that is done by udev rules (is it)?
> > Setting the NFS identity is just another part of configuring the new
> > network namespace.
> >
> > udev is great when we don't know exactly when an event will happen,
> > but
> > we want to respond when it does.
> > That doesn't match the case of creating a new network namespace. Some
> > code deliberately creates it and is perfectly positioned to then
> > configure it.
>
> I think there's so many ways to create a new network namespace that we
> can't
> reasonably be expected to try to insert out problem into all of them.

I 100% agree. Similarly there are lots of init systems and we don't try
to provide configuration for each one to ensure - e.g. - that sm-notify
is run at the correct time.
But we *do* provide configuration for one - systemd. This is partly
because it is widely used, but largely because the distro that I
personally help maintain uses it. So I added those systemd/* files.
(and then others helped improve them).

> Handling the event from the kernel allows us to make a best-effort
> default attempt.

That "best" effort is not actually very good.

Might I suggest that we take a similar approach to the systemd config.
You choose whatever container system is important to you are the moment,
determine how best to integrate the required support with that system,
make sure the tool works well for that case, provide any config files
that might be generally useful for anyone using that container system,
and in the documentation for the tool explain generally when it must run
and why, and give an example for the system that you know.

If someone else uses a different container system, they are free to
create a solution based on your example, and welcome to submit patches -
either to nfs-utils or to that container system.

Obviously you make the tool reasonably general without over-engineering,
but don't try to solve problems that you don't even know really exist.
I would suggest the tool be passed one of:
- a unique string
- a file containing a unique string
- a file in which a randomly generated unique string may be stored if
it doesn't already contain one
- (maybe) nothing, in which case a new random identity is generate each
time. This could be useful for older kernels.

>
> > udev is async. How certain can we be that the udev event will be
> > fully
> > handled before the first mount attempt?
>
> Good point. We can't at all be certain.
>
> We can start over completely from here..
>
> We can have mount.nfs /also/ try to configure the id.. this is more
> robust.

If mount.nfs is going to do it, then the "also" is pointless. There
would be no point in any other code doing it. However I'm no longer as
keen on mount.nfs as I was.

>
> We can have mount.nfs do a round of udev settle..

My experience with "udev settle" with md does not make me want to depend
on it. It has it's place and does useful things, but not always quite
what I want.

>
> Are there other options?

Document the requirement and make it "someone elses problem".
Your kernel patch to provide a random default mean a lack of
configuration will only hurt the container which lacks it - which nicely
localises the problem.

Thanks,
NeilBrown

2022-02-14 17:51:33

by Benjamin Coddington

[permalink] [raw]
Subject: Re: [nfs-utils PATCH] nfs4id: a tool to create and persist nfs4 client uniquifiers

On 13 Feb 2022, at 18:24, NeilBrown wrote:
> Document the requirement and make it "someone elses problem".
> Your kernel patch to provide a random default mean a lack of
> configuration will only hurt the container which lacks it - which nicely
> localises the problem.

I thought of another approach which was to have either mount.nfs or the
kernel emit a warning if a client is not uniquified.

Ben