Whamcloud - gitweb
LU-3289 gss: Add option for loading keys during mount 01/17601/16
authorJeremy Filizetti <jeremy.filizetti@gmail.com>
Mon, 14 Dec 2015 05:19:56 +0000 (00:19 -0500)
committerOleg Drokin <oleg.drokin@intel.com>
Mon, 13 Jun 2016 17:16:32 +0000 (17:16 +0000)
This adds functionality for loading GSS shared keys using
mount.lustre (mount) command.  The --skpath option has been
added which supports a directory or file of keys to load.
The context from which the mount occurs is used to determine
which type of key to load (MGS, MDT/OST, or client).

Signed-off-by: Jeremy Filizetti <jeremy.filizetti@gmail.com>
Change-Id: I4ffbfb9ea76d32ed69f94da93f82e90e161cb99d
Reviewed-on: http://review.whamcloud.com/17601
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Jenkins
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
lustre/doc/mount.lustre.8
lustre/utils/Makefile.am
lustre/utils/mount_lustre.c
lustre/utils/mount_utils.c
lustre/utils/mount_utils.h

index c020ae2..db88cd6 100644 (file)
@@ -105,6 +105,13 @@ Enable FID to path translation by regular users.
 .BI nouser_fid2path
 Disable FID to path translation by regular users.  Root and process with
 CAP_DAC_READ_SEARCH can still perform FID to path translation.
 .BI nouser_fid2path
 Disable FID to path translation by regular users.  Root and process with
 CAP_DAC_READ_SEARCH can still perform FID to path translation.
+.TP
+.BI skpath= file|directory
+Path to a file or directory with the keyfile(s) to load for this mount command.
+Keys are inserted into the KEY_SPEC_SESSION_KEYRING keyring with a description
+containing "lustre:" and a suffix which depends on whether the context of the
+mount command is for an MGS, MDT/OST, or client.
+This option is only available when built with --enable-gss.
 .PP
 In addition to the standard mount options and backing disk type
 (e.g. ext3) options listed in
 .PP
 In addition to the standard mount options and backing disk type
 (e.g. ext3) options listed in
index 9fea34e..87b4861 100644 (file)
@@ -19,6 +19,11 @@ if UTILS
 
 if GSS
 SUBDIRS = gss
 
 if GSS
 SUBDIRS = gss
+GSSSRC = gss/sk_utils.c gss/sk_utils.h gss/err_util.c gss/err_util.h
+GSSLIB = -lcrypto -lssl -lkeyutils -lm
+else
+GSSSRC =
+GSSLIB =
 endif
 
 # mount only finds helpers in /sbin
 endif
 
 # mount only finds helpers in /sbin
@@ -137,19 +142,19 @@ mount_osd_ldiskfs_la_LDFLAGS  := -shared -export-dynamic -module -avoid-version
 mount_osd_ldiskfs_la_LIBADD   := $(SELINUX)
 endif # LDISKFS_ENABLED
 
 mount_osd_ldiskfs_la_LIBADD   := $(SELINUX)
 endif # LDISKFS_ENABLED
 
-mount_lustre_SOURCES = mount_lustre.c mount_utils.c mount_utils.h
+mount_lustre_SOURCES = mount_lustre.c mount_utils.c mount_utils.h $(GSSSRC)
 mount_lustre_CPPFLAGS := ${MNTMODCFLAGS}
 mount_lustre_LDFLAGS  := ${MNTMODLDFLAGS}
 mount_lustre_CPPFLAGS := ${MNTMODCFLAGS}
 mount_lustre_LDFLAGS  := ${MNTMODLDFLAGS}
-mount_lustre_LDADD    := $(LIBPTLCTL) $(SELINUX) $(LDLIBMOUNT)
+mount_lustre_LDADD    := $(LIBPTLCTL) $(SELINUX) $(LDLIBMOUNT) $(GSSLIB)
 mount_lustre_DEPENDENCIES := $(LIBPTLCTL)
 
 mount_lustre_DEPENDENCIES := $(LIBPTLCTL)
 
-mkfs_lustre_SOURCES = mkfs_lustre.c mount_utils.c mount_utils.h
+mkfs_lustre_SOURCES = mkfs_lustre.c mount_utils.c mount_utils.h $(GSSSRC)
 mkfs_lustre_CPPFLAGS := -UTUNEFS ${MNTMODCFLAGS}
 mkfs_lustre_LDFLAGS  := ${MNTMODLDFLAGS}
 mkfs_lustre_CPPFLAGS := -UTUNEFS ${MNTMODCFLAGS}
 mkfs_lustre_LDFLAGS  := ${MNTMODLDFLAGS}
-mkfs_lustre_LDADD    := $(LIBPTLCTL) $(LDLIBMOUNT)
+mkfs_lustre_LDADD    := $(LIBPTLCTL) $(LDLIBMOUNT) $(GSSLIB)
 mkfs_lustre_DEPENDENCIES := $(LIBPTLCTL)
 
 mkfs_lustre_DEPENDENCIES := $(LIBPTLCTL)
 
-tunefs_lustre_SOURCES = mkfs_lustre.c mount_utils.c mount_utils.h
+tunefs_lustre_SOURCES = mkfs_lustre.c mount_utils.c mount_utils.h $(GSSSRC)
 tunefs_lustre_CPPFLAGS := -DTUNEFS ${MNTMODCFLAGS}
 tunefs_lustre_LDFLAGS  := ${MNTMODLDFLAGS}
 tunefs_lustre_LDADD    := $(mkfs_lustre_LDADD)
 tunefs_lustre_CPPFLAGS := -DTUNEFS ${MNTMODCFLAGS}
 tunefs_lustre_LDFLAGS  := ${MNTMODLDFLAGS}
 tunefs_lustre_LDADD    := $(mkfs_lustre_LDADD)
index b247327..7ed9fff 100644 (file)
@@ -114,6 +114,10 @@ void usage(FILE *out)
                "\t\tskip_lfsck: NOT auto resume the paused/crashed LFSCK\n"
                "\t\texclude=<ostname>[:<ostname>] : colon-separated list of "
                "inactive OSTs (e.g. lustre-OST0001)\n"
                "\t\tskip_lfsck: NOT auto resume the paused/crashed LFSCK\n"
                "\t\texclude=<ostname>[:<ostname>] : colon-separated list of "
                "inactive OSTs (e.g. lustre-OST0001)\n"
+#ifdef HAVE_GSS
+               "\t\tskpath=<file|directory>: Path to a file or directory of"
+               "key configuration files to load into the kernel keyring\n"
+#endif
                "\t\tretry=<num>: number of times mount is retried by client\n"
                "\t\tmd_stripe_cache_size=<num>: set the raid stripe cache "
                "size for the underlying raid if present\n");
                "\t\tretry=<num>: number of times mount is retried by client\n"
                "\t\tmd_stripe_cache_size=<num>: set the raid stripe cache "
                "size for the underlying raid if present\n");
@@ -277,6 +281,17 @@ int parse_options(struct mount_opts *mop, char *orig_options, int *flagp)
                        /* XXX special check for 'force' option */
                        ++mop->mo_force;
                        printf("force: %d\n", mop->mo_force);
                        /* XXX special check for 'force' option */
                        ++mop->mo_force;
                        printf("force: %d\n", mop->mo_force);
+#ifdef HAVE_GSS
+               } else if (val && strncmp(opt, "skpath=", 7) == 0) {
+                       if (strlen(val) + 1 >= sizeof(mop->mo_skpath)) {
+                               fprintf(stderr,
+                                       "%s: shared key path too long\n",
+                                       progname);
+                               free(options);
+                               return -1;
+                       }
+                       strncpy(mop->mo_skpath, val + 1, strlen(val + 1));
+#endif
                } else if (parse_one_option(opt, flagp) == 0) {
                        /* pass this on as an option */
                        append_option(options, opt);
                } else if (parse_one_option(opt, flagp) == 0) {
                        /* pass this on as an option */
                        append_option(options, opt);
@@ -629,6 +644,7 @@ int main(int argc, char *const argv[])
        struct mount_opts mop;
        char *options;
        int i, rc, flags;
        struct mount_opts mop;
        char *options;
        int i, rc, flags;
+       bool client;
 
        progname = strrchr(argv[0], '/');
        progname = progname ? progname + 1 : argv[0];
 
        progname = strrchr(argv[0], '/');
        progname = progname ? progname + 1 : argv[0];
@@ -687,7 +703,8 @@ int main(int argc, char *const argv[])
                return rc;
        }
 
                return rc;
        }
 
-       if (strstr(mop.mo_usource, ":/") == NULL) {
+       client = (strstr(mop.mo_usource, ":/") != NULL);
+       if (!client) {
                rc = osd_init();
                if (rc)
                        return rc;
                rc = osd_init();
                if (rc)
                        return rc;
@@ -706,14 +723,26 @@ int main(int argc, char *const argv[])
                printf("mounting device %s at %s, flags=%#x options=%s\n",
                       mop.mo_source, mop.mo_target, flags, options);
 
                printf("mounting device %s at %s, flags=%#x options=%s\n",
                       mop.mo_source, mop.mo_target, flags, options);
 
-       if (strstr(mop.mo_usource, ":/") == NULL &&
-           osd_tune_lustre(mop.mo_source, &mop)) {
+       if (!client && osd_tune_lustre(mop.mo_source, &mop)) {
                if (verbose)
                        fprintf(stderr, "%s: unable to set tunables for %s"
                                        " (may cause reduced IO performance)\n",
                                        argv[0], mop.mo_source);
        }
 
                if (verbose)
                        fprintf(stderr, "%s: unable to set tunables for %s"
                                        " (may cause reduced IO performance)\n",
                                        argv[0], mop.mo_source);
        }
 
+#ifdef HAVE_GSS
+       if (mop.mo_skpath[0] != '\0') {
+               /* Treat shared key failures as fatal */
+               rc = load_shared_keys(&mop);
+               if (rc) {
+                       fprintf(stderr,
+                               "%s: Error loading shared keys: %s\n",
+                               progname, strerror(rc));
+                       return rc;
+               }
+       }
+#endif
+
        if (!mop.mo_fake) {
                /* flags and target get to lustre_get_sb(), but not
                 * lustre_fill_super().  Lustre ignores the flags, but mount
        if (!mop.mo_fake) {
                /* flags and target get to lustre_get_sb(), but not
                 * lustre_fill_super().  Lustre ignores the flags, but mount
@@ -833,7 +862,7 @@ int main(int argc, char *const argv[])
        /* mo_usource should be freed, but we can rely on the kernel */
        free(mop.mo_source);
 
        /* mo_usource should be freed, but we can rely on the kernel */
        free(mop.mo_source);
 
-       if (strstr(mop.mo_usource, ":/") == NULL)
+       if (!client)
                osd_fini();
 
        return rc;
                osd_fini();
 
        return rc;
index 8287d34..cf4dca3 100644 (file)
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <linux/loop.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <linux/loop.h>
+#include <sys/types.h>
+#include <dirent.h>
 #include <dlfcn.h>
 
 #include <dlfcn.h>
 
+#ifdef HAVE_GSS
+#include <keyutils.h>
+#include <lustre/utils/gss/sk_utils.h>
+#endif
+
 #include "mount_utils.h"
 
 extern char *progname;
 #include "mount_utils.h"
 
 extern char *progname;
@@ -873,3 +880,89 @@ int file_create(char *path, __u64 size)
 
        return 0;
 }
 
        return 0;
 }
+
+#ifdef HAVE_GSS
+int load_shared_keys(struct mount_opts *mop)
+{
+       DIR *dir;
+       struct dirent *dentry;
+       struct stat sbuf;
+       char fullpath[PATH_MAX];
+       char *path = mop->mo_skpath;
+       int type = 0;
+       int rc;
+
+       if (IS_SERVER(&mop->mo_ldd)) {
+               if (IS_MGS(&mop->mo_ldd))
+                       type |= SK_TYPE_MGS;
+               if (IS_MDT(&mop->mo_ldd) || IS_OST(&mop->mo_ldd))
+                       type |= SK_TYPE_SERVER | SK_TYPE_CLIENT;
+       } else {
+               type |= SK_TYPE_CLIENT;
+       }
+
+       /* init logging */
+       sk_init_logging(NULL, 1, 1);
+
+       rc = stat(path, &sbuf);
+       if (rc < 0) {
+               fprintf(stderr, "stat() failed for key %s: %s\n", path,
+                       strerror(errno));
+               return -errno;
+       }
+
+       /* Load individual keys or a directory of them */
+       if (S_ISREG(sbuf.st_mode)) {
+               return sk_load_keyfile(path, type);
+       } else if (!S_ISDIR(sbuf.st_mode)) {
+               fprintf(stderr, "Invalid shared key path: %s\n", path);
+               return -ENOKEY;
+       }
+
+       dir = opendir(path);
+       if (dir == NULL) {
+               fprintf(stderr, "Unable to open shared key directory: %s\n",
+                       path);
+               return -ENOENT;
+       }
+
+       /* Loop through the files in the directory attempting to load them.
+        * Any issue with loading the keyfile is treated as an error although
+        * the loop continues until all files have been attempted.  This will
+        * allow all errors be reported at once rather then requiring
+        * incremental corrections to fix each one and try again. */
+       while ((dentry = readdir(dir)) != NULL) {
+               if (strcmp(".", dentry->d_name) == 0 ||
+                   strcmp("..", dentry->d_name) == 0)
+                       continue;
+
+               rc = snprintf(fullpath, PATH_MAX, "%s/%s", path,
+                             dentry->d_name);
+               if (rc >= PATH_MAX) {
+                       fprintf(stderr, "Path too long for %s/%s\n",
+                               path, dentry->d_name);
+                       rc = -ENAMETOOLONG;
+                       continue;
+               }
+
+               rc = stat(fullpath, &sbuf);
+               if (rc < 0) {
+                       fprintf(stderr, "Unable to stat %s: %s\n", fullpath,
+                               strerror(errno));
+                       rc = -errno;
+                       continue;
+               }
+
+               if (!S_ISREG(sbuf.st_mode))
+                       continue;
+
+               rc = sk_load_keyfile(fullpath, type);
+               if (rc) {
+                       fprintf(stderr, "Failed to load key %s\n", fullpath);
+               }
+       }
+       closedir(dir);
+
+       return rc;
+}
+#endif
index ae238eb..7fd9b34 100644 (file)
@@ -100,6 +100,9 @@ struct mount_opts {
        char    *mo_usource;            /* user-specified mount device */
        char    *mo_source;             /* our mount device name */
        char     mo_target[PATH_MAX];   /* mount directory */
        char    *mo_usource;            /* user-specified mount device */
        char    *mo_source;             /* our mount device name */
        char     mo_target[PATH_MAX];   /* mount directory */
+#ifdef HAVE_GSS
+       char     mo_skpath[PATH_MAX];   /* shared key file/directory */
+#endif
        int      mo_nomtab;
        int      mo_fake;
        int      mo_force;
        int      mo_nomtab;
        int      mo_fake;
        int      mo_force;
@@ -119,6 +122,10 @@ int get_mountdata(char *, struct lustre_disk_data *);
 #define IS_OST(data)   ((data)->ldd_flags & LDD_F_SV_TYPE_OST)
 #undef IS_MGS
 #define IS_MGS(data)  ((data)->ldd_flags & LDD_F_SV_TYPE_MGS)
 #define IS_OST(data)   ((data)->ldd_flags & LDD_F_SV_TYPE_OST)
 #undef IS_MGS
 #define IS_MGS(data)  ((data)->ldd_flags & LDD_F_SV_TYPE_MGS)
+#undef IS_SERVER
+#define IS_SERVER(data) ((data)->ldd_flags & (LDD_F_SV_TYPE_MGS | \
+                         LDD_F_SV_TYPE_MDT | LDD_F_SV_TYPE_OST))
+
 
 /* mkfs/mount helper functions */
 void fatal(void);
 
 /* mkfs/mount helper functions */
 void fatal(void);
@@ -176,5 +183,5 @@ struct module_backfs_ops {
 
 struct module_backfs_ops *load_backfs_module(enum ldd_mount_type mount_type);
 void unload_backfs_ops(struct module_backfs_ops *ops);
 
 struct module_backfs_ops *load_backfs_module(enum ldd_mount_type mount_type);
 void unload_backfs_ops(struct module_backfs_ops *ops);
-
+int load_shared_keys(struct mount_opts *mop);
 #endif
 #endif