Skip to content

Commit 4e58d4c

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Move default policy target"
2 parents b6a7642 + 06c0fd4 commit 4e58d4c

File tree

4 files changed

+22
-14
lines changed

4 files changed

+22
-14
lines changed

nova/context.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,8 @@ def can(self, action, target=None, fatal=True):
228228
:param action: string representing the action to be checked.
229229
:param target: dictionary representing the object of the action
230230
for object creation this should be a dictionary representing the
231-
location of the object e.g. ``{'project_id': context.project_id}``.
232-
If None, then this default target will be considered:
233-
{'project_id': self.project_id, 'user_id': self.user_id}
231+
location of the object
232+
e.g. ``{'project_id': instance.project_id}``.
234233
:param fatal: if False, will return False when an exception.Forbidden
235234
occurs.
236235
@@ -240,19 +239,13 @@ def can(self, action, target=None, fatal=True):
240239
:return: returns a non-False value (not necessarily "True") if
241240
authorized and False if not authorized and fatal is False.
242241
"""
243-
if target is None:
244-
target = self.default_target()
245-
246242
try:
247243
return policy.authorize(self, action, target)
248244
except exception.Forbidden:
249245
if fatal:
250246
raise
251247
return False
252248

253-
def default_target(self):
254-
return {'project_id': self.project_id, 'user_id': self.user_id}
255-
256249
def to_policy_values(self):
257250
policy = super(RequestContext, self).to_policy_values()
258251
policy['is_admin'] = self.is_admin

nova/policy.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def set_rules(rules, overwrite=True, use_conf=False):
122122
_ENFORCER.set_rules(rules, overwrite, use_conf)
123123

124124

125-
def authorize(context, action, target, do_raise=True, exc=None):
125+
def authorize(context, action, target=None, do_raise=True, exc=None):
126126
"""Verifies that the action is valid on the target in this context.
127127
128128
:param context: nova context
@@ -133,7 +133,9 @@ def authorize(context, action, target, do_raise=True, exc=None):
133133
``volume:attach_volume``
134134
:param target: dictionary representing the object of the action
135135
for object creation this should be a dictionary representing the
136-
location of the object e.g. ``{'project_id': context.project_id}``
136+
location of the object e.g. ``{'project_id': instance.project_id}``
137+
If None, then this default target will be considered:
138+
{'project_id': self.project_id, 'user_id': self.user_id}
137139
:param do_raise: if True (the default), raises PolicyNotAuthorized;
138140
if False, returns False
139141
:param exc: Class of the exception to raise if the check fails.
@@ -154,6 +156,12 @@ def authorize(context, action, target, do_raise=True, exc=None):
154156
credentials = context.to_policy_values()
155157
if not exc:
156158
exc = exception.PolicyNotAuthorized
159+
160+
# Legacy fallback for emtpy target from context.can()
161+
# should be removed once we improve testing and scope checks
162+
if target is None:
163+
target = default_target(context)
164+
157165
try:
158166
result = _ENFORCER.authorize(action, target, credentials,
159167
do_raise=do_raise, exc=exc, action=action)
@@ -168,6 +176,10 @@ def authorize(context, action, target, do_raise=True, exc=None):
168176
return result
169177

170178

179+
def default_target(context):
180+
return {'project_id': context.project_id, 'user_id': context.user_id}
181+
182+
171183
def check_is_admin(context):
172184
"""Whether or not roles contains 'admin' role according to policy setting.
173185
@@ -176,7 +188,7 @@ def check_is_admin(context):
176188
init()
177189
# the target is user-self
178190
credentials = context.to_policy_values()
179-
target = context.default_target()
191+
target = default_target(context)
180192
return _ENFORCER.authorize('context_is_admin', target, credentials)
181193

182194

nova/tests/unit/test_context.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,7 @@ def test_can(self, mock_authorize):
216216

217217
self.assertTrue(result)
218218
mock_authorize.assert_called_once_with(
219-
ctxt, mock.sentinel.rule,
220-
{'project_id': ctxt.project_id, 'user_id': ctxt.user_id})
219+
ctxt, mock.sentinel.rule, None)
221220

222221
@mock.patch.object(context.policy, 'authorize')
223222
def test_can_fatal(self, mock_authorize):

nova/tests/unit/test_policy.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ def test_templatized_authorization(self):
134134
target_not_mine = {'project_id': 'another'}
135135
action = "example:my_file"
136136
policy.authorize(self.context, action, target_mine)
137+
# check we fallback to context.project_id
138+
# TODO(johngarbutt): longer term we need to remove this and make
139+
# the target a required param.
140+
policy.authorize(self.context, action)
137141
self.assertRaises(exception.PolicyNotAuthorized, policy.authorize,
138142
self.context, action, target_not_mine)
139143

0 commit comments

Comments
 (0)