Author: tmckay
Date: 2012-07-12 15:06:02 +0000 (Thu, 12 Jul 2012)
New Revision: 5429
Modified:
trunk/cumin/python/cumin/grid/job.py
trunk/cumin/python/cumin/grid/submission.py
trunk/cumin/python/cumin/objectframe.py
trunk/wooly/python/wooly/__init__.py
trunk/wooly/python/wooly/server.py
Log:
Tweaks to role enforcement.
BZ837047
Modified: trunk/cumin/python/cumin/grid/job.py
===================================================================
--- trunk/cumin/python/cumin/grid/job.py 2012-07-10 13:21:25 UTC (rev 5428)
+++ trunk/cumin/python/cumin/grid/job.py 2012-07-12 15:06:02 UTC (rev 5429)
@@ -25,20 +25,21 @@
log = logging.getLogger("cumin.job")
class JobFrame(ObjectFrame):
- def __init__(self, app, name, submission):
+ def __init__(self, app, name, submission, check_viewable=False):
cls = app.model.com_redhat_grid.Submission
super(JobFrame, self).__init__(app, name, cls)
self.view = JobView(app, "view", self.object)
self.replace_child(self.view)
+ self.do_check_viewable = check_viewable
# view or edit
- self.ads = JobAdModes(app, "ads")
+ self.ads = JobAdModes(app, "ads", check_viewable)
self.view.add_tab(self.ads)
- self.view.add_tab(JobOutput(app, "output"))
+ self.view.add_tab(JobOutput(app, "output", check_viewable))
self.job_id = Parameter(app, "job_id")
self.add_parameter(self.job_id)
@@ -98,18 +99,60 @@
return branch.marshal()
def not_viewable_redirect(self):
+ # The object held by this frame is actually a submission,
+ # so a redirect from a higher level should use this message
return (self.parent,
- "Logged in user does not own the specified job")
+ "Logged in user does not own the specified submission")
+ def do_process(self, session):
+ super(JobFrame, self).do_process(session)
+
+ # Make sure that the job belongs to the designated submission.
+ id = self.id.get(session)
+ submission, js, sched = self.get_trifecta(session, id)
+ summaries = self.app.model.get_submission_job_summaries(submission,
+ sched.Name)
+ okay = False
+ frame = None
+ message = ""
+ if summaries.data is None:
+ # Well, someone is requesting a particular job but we have no
+ # data yet so we don't know if it is legit or not. Redirect
+ # to the parent frame, but without a notice. Normally data should
+ # be present because the trail through Cumin goes to the submission
+ # job list first, with a link to a particular job.
+ frame = self.parent
+ else:
+ job_id = self.job_id.get(session)
+ for summary in summaries.data:
+ if str(summary["ClusterId"]) + "." + \
+ str(summary["ProcId"]) == job_id:
+ okay = True
+ break
+
+ if not okay:
+ frame = self.parent
+ message = "The specified job is not part "\
+ "of the specified submission"
+
+ # If the check failed and there is not yet a redirect
+ # value, set the redirect. Add the notice in either case.
+ if not self.get_redirect(session) and frame:
+ self.set_redirect(session, frame, message)
+ elif message:
+ session.add_notice(Notice(message))
+
class JobAdModes(ModeSet):
- def __init__(self, app, name):
+ def __init__(self, app, name, check_viewable):
super(JobAdModes, self).__init__(app, name)
self.viewer = JobAdsViewer(app, "viewer")
self.add_mode(self.viewer)
+ self.viewer.do_check_viewable = check_viewable
self.editor = JobAdsEditor(app, "editor")
self.add_mode(self.editor)
+ self.editor.do_check_viewable = check_viewable
def render_title(self, session):
return "Attributes"
@@ -444,7 +487,7 @@
if not self.errors.get(session) and \
self.app.authorizator.is_enforcing():
# Check here to make sure the logged in user owns
- # the job or is an admin
+ # the submission or is an admin
login = session.client_session.attributes["login_session"]
if "admin" not in login.group:
user = login.user.name
@@ -456,8 +499,7 @@
f = FormError("The logged in user does not "\
"own this submission.")
self.errors.add(session, f)
-
-
+
class JobAdsSet(PropertySet):
types = {0: "expression",
1: "integer",
@@ -473,19 +515,38 @@
self.qmf_error = Attribute(app, "qmf_error")
self.add_attribute(self.qmf_error)
+ self.do_check_viewable = False
+
+ def get_job_ad(self, session):
+ id = self.frame.id.get(session)
+ submission, job_server, sched = self.frame.get_trifecta(session, id)
+ job_id = self.frame.job_id.get(session)
+ results = self.app.remote.get_job_ad(job_server, job_id,
+ sched.Name, submission,
+ default={'JobAd': {}})
+ return results
+
+ def check_job_owner(self, session, ad):
+ error = None
+ if not session.client_session.check_owner(ad['Owner']):
+ class InventError:
+ def __init__(self, msg):
+ self.args = [msg]
+ error = InventError("Logged in user does not own the specified
job")
+ return error
+
def do_get_items(self, session):
ad_list = self.items.get(session)
error = self.qmf_error.get(session)
-
if not ad_list and not error:
ad_list = list()
- id = self.frame.id.get(session)
- submission, job_server, sched = self.frame.get_trifecta(session, id)
- job_id = self.frame.job_id.get(session)
- results = self.app.remote.get_job_ad(job_server, job_id,
- sched.Name, submission,
- default={'JobAd': {}})
- error = results.error
+ results = self.get_job_ad(session)
+ error = None
+ if results.error:
+ error = results.error
+ elif self.do_check_viewable:
+ error = self.check_job_owner(session, results.data['JobAd'])
+
self.qmf_error.set(session, error)
ads = results.data['JobAd']
cls = self.app.model.job_meta_data
@@ -637,7 +698,8 @@
# check for qmf error
_, error = self.parent.do_get_items(session)
if error:
- msg = len(error.args) > 0 and error.args[0] or ""
+ msg = (hasattr(error, "args") and \
+ len(error.args) > 0 and error.args[0]) or ""
if not msg:
# probably a timeout exception
msg = "Unable to get Job information at this time"
@@ -693,6 +755,8 @@
else:
return super(JobAdsViewer, self).do_render(session)
+ self.do_check_viewable = False
+
def render_edit_button(self, session):
_, error = self.do_get_items(session)
render = True
@@ -822,6 +886,9 @@
orig=ads[x]["orig"]) for x in ads]
items, error = super(JobAdsEditor, self).do_get_items(session)
+ if error:
+ items = []
+
for item in items:
item["path"] = self.ads.path
return items, error
@@ -844,6 +911,21 @@
def has_double_quotes(value):
return value[:1] == "\"" and value[-1:] ==
"\""
+ # Check to see if the job is owned by the logged in user.
+ # At this point, the only way to do this check is request
+ # the job ad again. Maybe not efficient.
+ if self.do_check_viewable:
+ results = self.get_job_ad(session)
+ if results.error:
+ error = results.error
+ else:
+ error = self.check_job_owner(session,
+ results.data['JobAd'])
+ if error:
+ self.qmf_error.set(session, error)
+ self.process_cancel(session)
+ return
+
ads = self.ads.get(session)
just_ads = dict()
@@ -965,7 +1047,7 @@
return file and "loading..." or self.err_msg
class JobOutput(JobAdsSet, Form):
- def __init__(self, app, name):
+ def __init__(self, app, name, check_viewable):
super(JobOutput, self).__init__(app, name)
self.which_file = self.FileSwitch(app, "file")
@@ -980,6 +1062,8 @@
self.output = OutputFile(app, "job_output", self.which_file,
self.first_last)
self.add_child(self.output)
+ self.do_check_viewable = check_viewable
+
def render_title(self, session):
return "Output"
@@ -1004,6 +1088,11 @@
iwd = None
ads, error = self.do_get_items(session)
+ if error:
+ msg = (hasattr(error, "args") and \
+ len(error.args) > 0 and error.args[0]) or ""
+ self.set_redirect(session, self.frame.parent, msg)
+
for ad in ads:
if ad['name'] == "Out":
out_file = ad['value']
Modified: trunk/cumin/python/cumin/grid/submission.py
===================================================================
--- trunk/cumin/python/cumin/grid/submission.py 2012-07-10 13:21:25 UTC (rev 5428)
+++ trunk/cumin/python/cumin/grid/submission.py 2012-07-12 15:06:02 UTC (rev 5429)
@@ -34,13 +34,9 @@
# processing pass.
self.do_check_viewable = check_viewable
- self.job = JobFrame(app, "job", self.object)
+ self.job = JobFrame(app, "job", self.object, check_viewable)
self.add_mode(self.job)
- # Ditto. This will check whether the selected job
- # is viewable by the logged in user.
- self.job.do_check_viewable = check_viewable
-
jobs = JobSelector(app, "jobs", self.object)
self.view.add_tab(jobs)
Modified: trunk/cumin/python/cumin/objectframe.py
===================================================================
--- trunk/cumin/python/cumin/objectframe.py 2012-07-10 13:21:25 UTC (rev 5428)
+++ trunk/cumin/python/cumin/objectframe.py 2012-07-12 15:06:02 UTC (rev 5429)
@@ -62,24 +62,18 @@
return (self.parent,
"Logged in user does not own a specified object")
+ def check_owner(self, obj, session):
+ return not hasattr(obj, "Owner") or \
+ session.client_session.check_owner(obj.Owner)
+
def check_viewable(self, obj, session):
- login = session.client_session.attributes["login_session"]
- user = login.user.name
- okay = not hasattr(obj, "Owner") or obj.Owner == user
- if okay:
- frame = None
- message = None
- else:
- frame, message = self.not_viewable_redirect()
- return okay, frame, message
+ frame = None
+ message = None
+ okay = self.check_owner(obj, session)
+ if not okay:
+ frame, message = self.not_viewable_redirect()
+ return okay, frame, message
- def set_redirect(self, session, frame, message):
- nsession = session.branch()
- frame.view.show(nsession)
- url = nsession.marshal()
- self.page.redirect.set(session, url)
- session.add_notice(Notice(message))
-
def do_process(self, session):
# XXX don't process if this frame is invisible
Modified: trunk/wooly/python/wooly/__init__.py
===================================================================
--- trunk/wooly/python/wooly/__init__.py 2012-07-10 13:21:25 UTC (rev 5428)
+++ trunk/wooly/python/wooly/__init__.py 2012-07-12 15:06:02 UTC (rev 5429)
@@ -396,6 +396,17 @@
def render_error_msg(self, session, *args):
return "There is no content to display"
+ def set_redirect(self, session, frame, message):
+ nsession = session.branch()
+ frame.view.show(nsession)
+ url = nsession.marshal()
+ self.page.redirect.set(session, url)
+ if message:
+ session.add_notice(Notice(message))
+
+ def get_redirect(self, session):
+ return self.page.redirect.get(session)
+
class Frame(Widget):
def show(self, session):
super(Frame, self).show(session)
Modified: trunk/wooly/python/wooly/server.py
===================================================================
--- trunk/wooly/python/wooly/server.py 2012-07-10 13:21:25 UTC (rev 5428)
+++ trunk/wooly/python/wooly/server.py 2012-07-12 15:06:02 UTC (rev 5429)
@@ -267,6 +267,10 @@
self.attributes = dict()
+ def check_owner(self, owner):
+ user = self.attributes["login_session"].user.name
+ return owner == user
+
def __repr__(self):
args = (self.__class__.__name__, self.id, self.created)
return "%s(%s,%s)" % args