Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libflux/message: add message cred helpers #2670

Merged
merged 13 commits into from
Jan 26, 2020

Conversation

garlick
Copy link
Member

@garlick garlick commented Jan 23, 2020

In the course of adding more job manager services, I found myself repeating the authorization check for 1) is the requestor the instance owner? 2) If no, is the requestor the owner of the job being manipulated? I also noted that one such instance in the job manager didn't have tests, and that not all implementations are consistent with regard to whether FLUX_ROLE_USER is required in addition to a userid match, and whether a match on FLUX_USERID_UNKNOWN is allowed.

It's a little bit verbose to make this check, and although the authorization code is simple, repeating it all over the place seems like a bad idea, so I added the following helpers in message.h:

/* Combined rolemask, userid access for convenience
 */
struct flux_msg_cred {
    uint32_t userid;
    uint32_t rolemask;
};
int flux_msg_get_cred (const flux_msg_t *msg, struct flux_msg_cred *cred);
int flux_msg_set_cred (flux_msg_t *msg, struct flux_msg_cred cred);

/* Simple authorization for service access:
 * If cred rolemask includes OWNER, grant (return 0).
 * If cred rolemask includes USER and userid matches 'userid',
 * and userid is not FLUX_USERID_UNKNOWN, grant (return 0).
 * Otherwise deny (return -1, errno = EPERM).
 */
int flux_msg_cred_authorize (struct flux_msg_cred cred, uint32_t userid);

/* Convenience functions that calls
 * flux_msg_get_cred() + flux_msg_cred_authorize().
 */
int flux_msg_authorize (const flux_msg_t *msg, uint32_t userid);

Adding this (and its tests) was simple. Unfortunately updating all the places where it could be employed touched a lot of code. We'll see from the coverage how well tested it all is.

@grondo
Copy link
Contributor

grondo commented Jan 23, 2020

Great idea! 👍

@grondo
Copy link
Contributor

grondo commented Jan 23, 2020

Restarted builder that failed with

ERROR: t1008-kvs-eventlog.t - exited with status 137 (terminated by signal 9?)

@grondo
Copy link
Contributor

grondo commented Jan 24, 2020

Trying this:

@Mergifyio rebase

@mergify
Copy link
Contributor

mergify bot commented Jan 24, 2020

Command rebase: success

Branch has been successfully rebased

Hey, I reacted but my real name is @Mergifyio

@grondo
Copy link
Contributor

grondo commented Jan 24, 2020

Had mergify rebase on current master so we can see if codecov.io reports this time.

@garlick
Copy link
Member Author

garlick commented Jan 24, 2020

Thanks for that!

@grondo
Copy link
Contributor

grondo commented Jan 24, 2020

This looks great!

If I had any comments it would be that the credential struct flux_msg_cred doesn't seem to be only applicable to messages, so it possibly could have been struct flux_user_cred or just struct flux_cred, and also somehow I thought flux_msg_authorize() would be more utilized than it ended up being (I think it was only used in one module?)

However, these comments shouldn't prevent this PR from being merged as-is.

@garlick
Copy link
Member Author

garlick commented Jan 26, 2020

If I had any comments it would be that the credential struct flux_msg_cred doesn't seem to be only applicable to messages, so it possibly could have been struct flux_user_cred or just struct flux_cred

Despite some contrary examples in the flux-core internals in the broker, connectors and "message routers", I felt like the primary external usage would be validating requests in user-written services, so the new functions felt like they ought to be there next to the individual rolemask/userid message accessors. I think you could successfully argue the credential belongs in its own security interface also. I just didn't go there.

and also somehow I thought flux_msg_authorize() would be more utilized than it ended up being (I think it was only used in one module?)

Yeah, me too. I could have been more aggressive in refactoring code that used the individual accessors, but I didn't want to get too invasive here.

Copy link
Contributor

@grondo grondo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then, LGTM!

Problem: accessors for message creds do not protect against
NULL pointer arguments.

Add checks that return EINVAL when arguments are NULL,
before they are dereferneced.
Problem: boiler plate for checking request message authorization involves
defining rolemask and userid individually, fetching them from the request
with two accessors, and then implementing logic that is identical for
most services.  It is simple, but there is a high consequence of error.

To reduce size of boiler plate and reduce chance of mistakes:
- add 'struct flux_msg_cred' to contain rolemask, userid
- add flux_msg_get_cred(), flux_msg_set_cred() accessors
  that operate on the cred
- add flux_msg_authorize() and flux_msg_cred_authorize()
  to authorize an action if the (message) cred userid matches
  a supplied one, or the message cred rolemask includes OWNER.

Add unit tests.
Problem: librouter defines a struct identical to flux_msg_cred
in its private API.

Switch to the public struct definition in librouter and its
internal users.
Also, the unit test alluded to in kill.h was missing, and
was simple, so added that here.
@mergify mergify bot merged commit 40e4807 into flux-framework:master Jan 26, 2020
@codecov-io
Copy link

Codecov Report

Merging #2670 into master will decrease coverage by 0.08%.
The diff coverage is 94.11%.

@@            Coverage Diff             @@
##           master    #2670      +/-   ##
==========================================
- Coverage   81.27%   81.19%   -0.09%     
==========================================
  Files         247      246       -1     
  Lines       38263    38113     -150     
==========================================
- Hits        31100    30946     -154     
- Misses       7163     7167       +4
Impacted Files Coverage Δ
src/cmd/builtin/relay.c 76.92% <ø> (ø) ⬆️
src/cmd/builtin/proxy.c 76.27% <0%> (ø) ⬆️
src/modules/connector-local/local.c 78.26% <0%> (ø) ⬆️
src/modules/job-manager/raise.c 78.37% <100%> (-3.44%) ⬇️
src/modules/kvs-watch/kvs-watch.c 78.57% <100%> (-0.23%) ⬇️
src/modules/kvs/kvsroot.c 70.94% <100%> (-0.73%) ⬇️
src/broker/module.c 75.18% <100%> (-0.12%) ⬇️
src/modules/job-ingest/job-ingest.c 76.24% <100%> (ø) ⬆️
src/modules/job-info/allow.c 84% <100%> (-1.72%) ⬇️
src/modules/kvs/lookup.c 81.2% <100%> (-0.04%) ⬇️
... and 20 more

@garlick garlick deleted the msg_cred branch January 27, 2020 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants