From 3a09b7c02c64700686512dae20c0b1bbaa8a4779 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Fri, 12 Oct 2018 11:10:30 -0700 Subject: [PATCH] libjob: add FLUX_JOB_PRE_SIGNED flag Problem: users of flux_job_submit() must know whether flux-core was built --with-flux-security or not. Add a FLUX_JOB_PRE_SIGNED flag that allows jobspec to be signed before submission, but change the default so flux_job_submit() signs the jobspec internally. If built --with-flux-security, configure a security context using default config file path and cache it in the flux_t handle. Each time flux_job_submit() is called, the context is reused, and the jobspec is signed with the default mechanism. If built without --with-flux-security, sign using the "sign_none" class. Update flux-job to use the FLUX_JOB_PRE_SIGNED flag if built --with-flux-security. Fixes #1715 --- src/cmd/flux-job.c | 3 +- src/common/Makefile.am | 2 +- src/common/libjob/Makefile.am | 5 +-- src/common/libjob/job.c | 57 ++++++++++++++++++++++++++++++++--- src/common/libjob/job.h | 10 +++--- 5 files changed, 64 insertions(+), 13 deletions(-) diff --git a/src/cmd/flux-job.c b/src/cmd/flux-job.c index 49c827e8e635..8ab9436a5217 100644 --- a/src/cmd/flux-job.c +++ b/src/cmd/flux-job.c @@ -267,7 +267,8 @@ void submitbench_check (flux_reactor_t *r, flux_watcher_t *w, log_err_exit ("flux_sign_wrap: %s", flux_security_last_error (ctx->sec)); } - if (!(f = flux_job_submit (ctx->h, ctx->J, ctx->priority, ctx->flags))) + if (!(f = flux_job_submit (ctx->h, ctx->J, ctx->priority, ctx->flags + | FLUX_JOB_PRE_SIGNED))) log_err_exit ("flux_job_submit"); #else char *cpy = strndup (ctx->jobspec, ctx->jobspecsz); diff --git a/src/common/Makefile.am b/src/common/Makefile.am index d83d71cb6940..e7a826e1046d 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -38,7 +38,7 @@ libflux_internal_la_LIBADD = \ $(builddir)/libcompat/libcompat.la \ $(builddir)/libtomlc99/libtomlc99.la \ $(LIBMUNGE) $(JANSSON_LIBS) $(ZMQ_LIBS) $(LIBPTHREAD) $(LIBUTIL) \ - $(LIBDL) $(LIBRT) + $(LIBDL) $(LIBRT) $(FLUX_SECURITY_LIBS) libflux_internal_la_LDFLAGS = $(san_ld_zdef_flag) lib_LTLIBRARIES = libflux-core.la libflux-optparse.la libflux-idset.la diff --git a/src/common/libjob/Makefile.am b/src/common/libjob/Makefile.am index fe481769a547..6353c4e940e6 100644 --- a/src/common/libjob/Makefile.am +++ b/src/common/libjob/Makefile.am @@ -7,7 +7,7 @@ AM_LDFLAGS = \ AM_CPPFLAGS = \ -I$(top_srcdir) -I$(top_srcdir)/src/include \ - $(ZMQ_CFLAGS) $(JANSSON_CFLAGS) + $(ZMQ_CFLAGS) $(JANSSON_CFLAGS) $(FLUX_SECURITY_CFLAGS) noinst_LTLIBRARIES = libjob.la fluxcoreinclude_HEADERS = job.h @@ -33,7 +33,8 @@ test_ldadd = \ $(top_builddir)/src/common/libflux/libflux.la \ $(top_builddir)/src/common/libflux-internal.la \ $(top_builddir)/src/common/libtap/libtap.la \ - $(ZMQ_LIBS) $(JANSSON_LIBS) $(LIBPTHREAD) $(LIBRT) $(LIBDL) $(LIBMUNGE) + $(ZMQ_LIBS) $(JANSSON_LIBS) $(LIBPTHREAD) $(LIBRT) \ + $(FLUX_SECURITY_LIBS) $(LIBDL) $(LIBMUNGE) test_cppflags = \ $(AM_CPPFLAGS) \ diff --git a/src/common/libjob/job.c b/src/common/libjob/job.c index 1eadb4316eb1..69996e840f3c 100644 --- a/src/common/libjob/job.c +++ b/src/common/libjob/job.c @@ -25,28 +25,75 @@ #if HAVE_CONFIG_H #include "config.h" #endif - +#include +#include #include - +#if HAVE_FLUX_SECURITY +#include +#endif #include "job.h" +#include "sign_none.h" +#if HAVE_FLUX_SECURITY +static flux_security_t *get_security_ctx (flux_t *h) +{ + const char *auxkey = "flux::job_security_ctx"; + flux_security_t *sec = flux_aux_get (h, auxkey); + if (!sec) { + if (!(sec = flux_security_create (0))) + goto error; + if (flux_security_configure (sec, NULL) < 0) + goto error; + flux_aux_set (h, auxkey, sec, (flux_free_f)flux_security_destroy); + } + return sec; +error: + flux_security_destroy (sec); + return NULL; +} +#endif -flux_future_t *flux_job_submit (flux_t *h, const char *J, int priority, +flux_future_t *flux_job_submit (flux_t *h, const char *jobspec, int priority, int flags) { flux_future_t *f; + const char *J; + char *s = NULL; + int saved_errno; - if (!h || !J) { + if (!h || !jobspec) { errno = EINVAL; return NULL; } + if (!(flags & FLUX_JOB_PRE_SIGNED)) { +#if HAVE_FLUX_SECURITY + flux_security_t *sec = get_security_ctx (h); + if (!sec) + goto error; + if (!(J = flux_sign_wrap (sec, jobspec, strlen (jobspec), NULL, 0))) + goto error; +#else + if (!(s = sign_none_wrap (jobspec, strlen (jobspec), geteuid ()))) + goto error; + J = s; +#endif + } + else { + J = jobspec; + flags &= ~FLUX_JOB_PRE_SIGNED; // client only flag + } if (!(f = flux_rpc_pack (h, "job-ingest.submit", FLUX_NODEID_ANY, 0, "{s:s s:i s:i}", "J", J, "priority", priority, "flags", flags))) - return NULL; + goto error; return f; +error: + saved_errno = errno; + free (s); + errno = saved_errno; + return NULL; } int flux_job_submit_get_id (flux_future_t *f, flux_jobid_t *jobid) diff --git a/src/common/libjob/job.h b/src/common/libjob/job.h index 091e26d0575d..439cd2a0f80f 100644 --- a/src/common/libjob/job.h +++ b/src/common/libjob/job.h @@ -9,6 +9,10 @@ extern "C" { #endif +enum job_submit_flags { + FLUX_JOB_PRE_SIGNED = 1, // 'jobspec' is already signed +}; + enum job_priority { FLUX_JOB_PRIORITY_MIN = 0, FLUX_JOB_PRIORITY_DEFAULT = 16, @@ -18,12 +22,10 @@ enum job_priority { typedef uint64_t flux_jobid_t; /* Submit a job to the system. - * J should be RFC 14 jobspec signed by flux_sign_wrap(), provided - * flux was built --with-flux-security. If not, then J should be bare jobspec. - * Currently the 'flags' parameter must be set to 0. + * 'jobspec' should be RFC 14 jobspec. * The system assigns a jobid and returns it in the response. */ -flux_future_t *flux_job_submit (flux_t *h, const char *J, +flux_future_t *flux_job_submit (flux_t *h, const char *jobspec, int priority, int flags); /* Parse jobid from response to flux_job_submit() request.