Message ID | c2e8b7c06352d3cad3454de096024fff80e638af.1643979161.git.bcodding@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [nfs-utils] nfs4id: a tool to create and persist nfs4 client uniquifiers | expand |
Hi Ben- > On Feb 4, 2022, at 7:56 AM, Benjamin Coddington <bcodding@redhat.com> 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? 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. Some young punk from Tatooine could drop a bomb down our reactor shaft, and then where would we be? 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. > Signed-off-by: Benjamin Coddington <bcodding@redhat.com> > --- > .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 <bcodding@redhat.com> > + * > + * 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 > -- Chuck Lever
On 4 Feb 2022, at 10:17, Chuck Lever III wrote: > Hi Ben- > >> On Feb 4, 2022, at 7:56 AM, Benjamin Coddington <bcodding@redhat.com> >> 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
> On Feb 4, 2022, at 10:49 AM, Benjamin Coddington <bcodding@redhat.com> wrote: > > On 4 Feb 2022, at 10:17, Chuck Lever III wrote: > >> 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. I don't think that's a new topic at all. This mechanism needs to deal with containers properly from day one. That's why we are using a udev rule for this purpose in the first place instead of something more obvious. 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. We need to agree on how NFSv4 clients in containers are to be supported before the proposed tool can be evaluated fully. -- Chuck Lever
On 4 Feb 2022, at 13:45, Chuck Lever III wrote: >> On Feb 4, 2022, at 10:49 AM, Benjamin Coddington >> <bcodding@redhat.com> wrote: >> >> On 4 Feb 2022, at 10:17, Chuck Lever III wrote: >> >>> 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. > > I don't think that's a new topic at all. This mechanism needs to > deal with containers properly from day one. That's why we are > using a udev rule for this purpose in the first place instead of > something more obvious. This isn't a mechanism to deal with containers, its a small helper utility that we'd like to use to solve an existing, non-container problem in a way that's future-proof for containers. > 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. > > We need to agree on how NFSv4 clients in containers are to be > supported before the proposed tool can be evaluated fully. I disagree. This tool is immediately useful when I have multiple NAT-ed NFS clients with the same hostnames and they end up with identical NFS client identifiers. That's the problem this little utility helps to solve, and that's the real-world issue we've been asked to fix. I don't think we have to solve all the problems at once, and I think this is headed in the right direction. I can commit to working on the namespace part.. but there's a number of things that aren't clear to me there: - is udev namespace-aware? - can we get udev rules to trigger for a namespace (my simple tests show that my "root" system-udevd doesnt see the creation or entry of processes into a new network namespace) Maybe we need to run udevd in every network namespace? - can uniquifiers be network-namespace uniquified by just using information available within a udev rule, or do we really need this utility to be namespace aware? There's a bunch of stuff to discuss and figure out (unless someone else already has), maybe we can start a new thread? Ben
> On Feb 4, 2022, at 2:44 PM, Benjamin Coddington <bcodding@redhat.com> wrote: > > On 4 Feb 2022, at 13:45, Chuck Lever III wrote: > >>> On Feb 4, 2022, at 10:49 AM, Benjamin Coddington <bcodding@redhat.com> wrote: >>> >>> On 4 Feb 2022, at 10:17, Chuck Lever III wrote: >>> >>>> 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. >> >> I don't think that's a new topic at all. This mechanism needs to >> deal with containers properly from day one. That's why we are >> using a udev rule for this purpose in the first place instead of >> something more obvious. > > This isn't a mechanism to deal with containers, its a small helper utility > that we'd like to use to solve an existing, non-container problem in a way > that's future-proof for containers. I understand that it doesn't support containers. I also understand that the uniquifier issue is a nagging and ongoing problem that needs to be rectified as soon as possible. I'm not pushing back on this without (good) reason, and I will try to be as helpful as I can to move this forward. I don't believe the solution to this problem is complete unless it deals with containers. I fear that the simpler non-container solution will be merged and then we will all put our pencils down and never deal properly with NFSv4 in containers. Or, that we will get farther down the road and discover that the simple solution has painted us into a corner, and significant visible changes will be necessary to get proper container support. (This viewpoint is based on watching other subsystems attempt to go from single instance to container support). I'd like to have some confidence that neither of those things will happen, and I don't think it will take a lot more effort to see that this is a proper and complete solution. To be absolutely clear, I want to see this issue resolved, but without adding more long-term to-dos or other issues hanging over our heads. >> 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. >> >> We need to agree on how NFSv4 clients in containers are to be >> supported before the proposed tool can be evaluated fully. > > I disagree. This tool is immediately useful when I have multiple NAT-ed NFS > clients with the same hostnames and they end up with identical NFS client > identifiers. That's the problem this little utility helps to solve, and > that's the real-world issue we've been asked to fix. The real-world problem is linked to the container issue whether Red Hat likes it or not. Upstream we have to think about the larger issues. Again, I do understand the narrower scope of your bugzilla / enhancement request. Yes, your proposal addresses the narrowly defined issue, but I'm concerned that it will introduce long- term problems. > I don't think we have to solve all the problems at once, and I think this is > headed in the right direction. This is the best solution I've seen so far, but it needs a little more design thinking IMHO. Like earlier proposals, there is still a possibility that significant and visible changes will be necessary to convert from single instance systems to containers. I'd really really like to avoid that, and I believe our users would also appreciate it. > I can commit to working on the namespace part.. I very much appreciate your effort. > but there's a number of things that aren't clear to me there: > > - is udev namespace-aware? I thought that it was. That was supposed to be the reason Trond went with a udev rule mechanism. The rule is supposed to fire when each network namespace is created. > - can we get udev rules to trigger for a namespace (my simple tests show > that my "root" system-udevd doesnt see the creation or entry of processes > into a new network namespace) Maybe we need to run udevd in every > network namespace? > > - can uniquifiers be network-namespace uniquified by just using information > available within a udev rule, or do we really need this utility to be > namespace aware? I thought that was how this mechanism was supposed to work. I believe Trond even posted an example rule at some point in the past. > There's a bunch of stuff to discuss and figure out (unless someone else > already has), maybe we can start a new thread? Since neither of us is 100% certain, can you find a container or udev expert inside of Red Hat who can give some guidance? -- Chuck Lever
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 > > > >
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
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 <bcodding@redhat.com> > --- > .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 <bcodding@redhat.com> > + * > + * 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)
> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@redhat.com> 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 <bcodding@redhat.com> >> --- >> .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 <bcodding@redhat.com> >> + * >> + * 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
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 <bcodding@redhat.com> >> --- >> .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
On 2/8/22 11:21 AM, Chuck Lever III wrote: > > >> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@redhat.com> 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 <bcodding@redhat.com> >>> --- >>> .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 <bcodding@redhat.com> >>> + * >>> + * 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 > > >
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 <bcodding@redhat.com> >>> --- >>> .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 >
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 <bcodding@redhat.com> >>>> --- >>>> .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
> On Feb 8, 2022, at 2:29 PM, Steve Dickson <steved@redhat.com> wrote: > > > > On 2/8/22 11:21 AM, Chuck Lever III wrote: >>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@redhat.com> 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 <bcodding@redhat.com> >>>> --- >>>> .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 <bcodding@redhat.com> >>>> + * >>>> + * 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
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 <bcodding@redhat.com> >>>>> --- >>>>> .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 >
On 2/8/22 4:18 PM, Chuck Lever III wrote: > > >> On Feb 8, 2022, at 2:29 PM, Steve Dickson <steved@redhat.com> wrote: >> >> >> >> On 2/8/22 11:21 AM, Chuck Lever III wrote: >>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@redhat.com> 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 <bcodding@redhat.com> >>>>> --- >>>>> .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 <bcodding@redhat.com> >>>>> + * >>>>> + * 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 > > >
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 <bcodding@redhat.com> >>>>>> --- >>>>>> .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
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 <bcodding@redhat.com> >>>>>>> --- >>>>>>> .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 >
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 <bcodding@redhat.com> > >>> --- > >>> .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
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 <bcodding@redhat.com> > > > > > --- > > > > > .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.
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
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
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 <steved@redhat.com> wrote: >>> >>> >>> >>> On 2/8/22 11:21 AM, Chuck Lever III wrote: >>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@redhat.com> >>>>> 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 <bcodding@redhat.com> >>>>>> --- >>>>>> .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
> On Feb 10, 2022, at 8:28 AM, Benjamin Coddington <bcodding@redhat.com> 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 <steved@redhat.com> wrote: >>>> >>>> >>>> >>>> On 2/8/22 11:21 AM, Chuck Lever III wrote: >>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@redhat.com> 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 <bcodding@redhat.com> >>>>>>> --- >>>>>>> .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
On 10 Feb 2022, at 10:21, Chuck Lever III wrote: >> On Feb 10, 2022, at 8:28 AM, Benjamin Coddington >> <bcodding@redhat.com> 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 <steved@redhat.com> >>>>> wrote: >>>>> >>>>> >>>>> >>>>> On 2/8/22 11:21 AM, Chuck Lever III wrote: >>>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@redhat.com> >>>>>>> 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 <bcodding@redhat.com> >>>>>>>> --- >>>>>>>> .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
> On Feb 10, 2022, at 10:47 AM, Benjamin Coddington <bcodding@redhat.com> wrote: > > On 10 Feb 2022, at 10:21, Chuck Lever III wrote: > >>> On Feb 10, 2022, at 8:28 AM, Benjamin Coddington <bcodding@redhat.com> 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 <steved@redhat.com> wrote: >>>>>> >>>>>> >>>>>> >>>>>> On 2/8/22 11:21 AM, Chuck Lever III wrote: >>>>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@redhat.com> 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 <bcodding@redhat.com> >>>>>>>>> --- >>>>>>>>> .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
On 10 Feb 2022, at 11:25, Chuck Lever III wrote: >> On Feb 10, 2022, at 10:47 AM, Benjamin Coddington >> <bcodding@redhat.com> wrote: >> >> On 10 Feb 2022, at 10:21, Chuck Lever III wrote: >> >>>> On Feb 10, 2022, at 8:28 AM, Benjamin Coddington >>>> <bcodding@redhat.com> 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 <steved@redhat.com> >>>>>>> wrote: >>>>>>> >>>>>>> >>>>>>> >>>>>>> On 2/8/22 11:21 AM, Chuck Lever III wrote: >>>>>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@redhat.com> >>>>>>>>> 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 <bcodding@redhat.com> >>>>>>>>>> --- >>>>>>>>>> .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
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 <steved@redhat.com> wrote: >>>> >>>> >>>> >>>> On 2/8/22 11:21 AM, Chuck Lever III wrote: >>>>>> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@redhat.com> 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 <bcodding@redhat.com> >>>>>>> --- >>>>>>> .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 >
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
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
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
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
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 <bcodding@redhat.com> + * + * 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)
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 <bcodding@redhat.com> --- .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