[abac] An ABAC permission can be set for a user, a role, or anybody.
An ABAC permission can now be set on a user, a role or anybody. For a decision request about a user or a role, it works the same way has regular RBAC permissions execpt that moreover the ABAC rule must be satisfied. For permissions on anyone, it means that ACS is combined with a system able to maintain sessions without authentication. The owner of such a session must be able to bring (certified) attributes. It can then be granted the permissions that have ABAC rules that are satisfied.
This commit is contained in:
parent
6ec65d84a3
commit
83fc3d5a36
|
@ -623,6 +623,17 @@ def add_abac_permission(request):
|
|||
messages.add_message(request, messages.ERROR,
|
||||
_('No object for How provided'))
|
||||
return return_add_abac_permission_form(request)
|
||||
who = None
|
||||
if 'who_matches' in request.POST \
|
||||
and request.POST['who_matches'] != '_':
|
||||
try:
|
||||
who = get_who_from_one_post_field(request, 'who_matches')
|
||||
except Exception, err:
|
||||
logger.error('add_permission: \
|
||||
Fail to find who due to %s' % err)
|
||||
messages.add_message(request, messages.ERROR,
|
||||
_('Fail to find who due to %s') % err)
|
||||
return return_add_abac_permission_form(request)
|
||||
try:
|
||||
what = get_what_from_one_post_field(request, 'what_matches')
|
||||
how = get_how_from_one_post_field(request, 'how_matches')
|
||||
|
@ -636,7 +647,8 @@ def add_abac_permission(request):
|
|||
or not check_action_or_activity(request, how):
|
||||
return return_add_abac_permission_form(request)
|
||||
|
||||
p, message = check_data_and_create_permission(request, what, how)
|
||||
p, message = \
|
||||
check_data_and_create_permission(request, who, what, how)
|
||||
|
||||
if not p:
|
||||
messages.add_message(request, messages.ERROR,
|
||||
|
@ -661,7 +673,7 @@ def add_abac_permission(request):
|
|||
|
||||
|
||||
@transaction.commit_manually
|
||||
def check_data_and_create_permission(request, what, how):
|
||||
def check_data_and_create_permission(request, who, what, how):
|
||||
p = None
|
||||
try:
|
||||
rule = None
|
||||
|
@ -793,7 +805,10 @@ def check_data_and_create_permission(request, what, how):
|
|||
rule.expression = expression
|
||||
rule.save()
|
||||
|
||||
p = AcsAbacPermission(what=what, how=how, rule=rule)
|
||||
if who:
|
||||
p = AcsAbacPermission(who=who, what=what, how=how, rule=rule)
|
||||
else:
|
||||
p = AcsAbacPermission(what=what, how=how, rule=rule)
|
||||
if not p:
|
||||
raise Exception('Fail to create permission')
|
||||
try:
|
||||
|
@ -974,6 +989,21 @@ def return_add_abac_permission_form(request, template_name='add_abac_permission.
|
|||
if 'rule' in request.session:
|
||||
tpl_p['rule'] = request.session['rule']
|
||||
|
||||
tpl_p['who_to_display'] = \
|
||||
return_list_users_authorized_for_admin(
|
||||
set_default_alias(request.user)) + \
|
||||
return_list_roles_authorized_for_admin(
|
||||
set_default_alias(request.user))
|
||||
tpl_p['who_to_display'] = \
|
||||
filter_list_in_namespace(tpl_p['who_to_display'], policy.namespace)
|
||||
if is_policy_user_administrator(request.user, policy):
|
||||
for a in UserAlias.objects.filter(namespace=policy.namespace):
|
||||
if not a in tpl_p['who_to_display']:
|
||||
tpl_p['who_to_display'].append(a)
|
||||
for a in Role.objects.filter(namespace=policy.namespace):
|
||||
if not a in tpl_p['who_to_display']:
|
||||
tpl_p['who_to_display'].append(a)
|
||||
|
||||
tpl_p['what_to_display'] = \
|
||||
return_list_objects_authorized_for_admin(
|
||||
set_default_alias(request.user)) + \
|
||||
|
@ -1076,8 +1106,6 @@ def del_abac_permission(request):
|
|||
|
||||
logger.debug('del_abac_permission: deletion of %s' % p)
|
||||
|
||||
# Todo: remove all data associated: predicates, values, rule, etc
|
||||
|
||||
p.delete()
|
||||
|
||||
messages.add_message(request, messages.INFO,
|
||||
|
|
|
@ -255,10 +255,14 @@ class AcsPermission(models.Model):
|
|||
|
||||
|
||||
class AcsAbacPermission(models.Model):
|
||||
content_type_who = models.ForeignKey(ContentType, related_name = "who_abac", blank=True, null=True)
|
||||
content_type_what = models.ForeignKey(ContentType, related_name = "what_abac")
|
||||
content_type_how = models.ForeignKey(ContentType, related_name = "how_abac")
|
||||
object_id_who = models.PositiveIntegerField(blank=True, null=True)
|
||||
object_id_what = models.PositiveIntegerField()
|
||||
object_id_how = models.PositiveIntegerField()
|
||||
who = generic.GenericForeignKey(ct_field='content_type_who',
|
||||
fk_field='object_id_who')
|
||||
what = generic.GenericForeignKey(ct_field='content_type_what',
|
||||
fk_field='object_id_what')
|
||||
how = generic.GenericForeignKey(ct_field='content_type_how',
|
||||
|
@ -277,24 +281,44 @@ class AcsAbacPermission(models.Model):
|
|||
"content_type_how", "object_id_how"))
|
||||
|
||||
def __unicode__(self):
|
||||
s = _('Permission on %s to perform %s if "%s"') \
|
||||
%(self.what, self.how.name, self.rule)
|
||||
if self.who:
|
||||
s = _('Permission of %s on %s to perform %s if "%s"') \
|
||||
% (self.who, self.what, self.how.name, self.rule)
|
||||
else:
|
||||
s = _('Permission of anyone on %s to perform %s if "%s"') \
|
||||
% (self.what, self.how.name, self.rule)
|
||||
if self.expiration_date:
|
||||
s += _(' (expires on %s)' %self.expiration_date)
|
||||
return s
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
p = None
|
||||
t_who = None
|
||||
if self.who:
|
||||
if not isinstance(self.who, (UserAlias, Role)):
|
||||
raise Exception('What is %s, not a User or a Role') \
|
||||
%ContentType.objects.get_for_model(self.what)
|
||||
t_who = ContentType.objects.get_for_model(self.who)
|
||||
t_what = ContentType.objects.get_for_model(self.what)
|
||||
t_how = ContentType.objects.get_for_model(self.how)
|
||||
'''We check here the unicity, not redundant with unique_together'''
|
||||
try:
|
||||
p = AcsAbacPermission.objects.get(rule=self.rule,
|
||||
content_type_what__pk=t_what.id,
|
||||
object_id_what=self.what.id,
|
||||
content_type_how__pk=t_how.id,
|
||||
object_id_how=self.how.id,
|
||||
)
|
||||
if self.who:
|
||||
p = AcsAbacPermission.objects.get(rule=self.rule,
|
||||
content_type_who__pk=t_who.id,
|
||||
object_id_who=self.who.id,
|
||||
content_type_what__pk=t_what.id,
|
||||
object_id_what=self.what.id,
|
||||
content_type_how__pk=t_how.id,
|
||||
object_id_how=self.how.id,
|
||||
)
|
||||
else:
|
||||
p = AcsAbacPermission.objects.get(rule=self.rule,
|
||||
content_type_what__pk=t_what.id,
|
||||
object_id_what=self.what.id,
|
||||
content_type_how__pk=t_how.id,
|
||||
object_id_how=self.how.id,
|
||||
)
|
||||
except MultipleObjectsReturned:
|
||||
raise Exception('This should never happen')
|
||||
except ObjectDoesNotExist:
|
||||
|
@ -304,6 +328,9 @@ class AcsAbacPermission(models.Model):
|
|||
if not isinstance(self.how, (Action, Activity)):
|
||||
raise Exception('How is %s, not an Action or an Activity') \
|
||||
%ContentType.objects.get_for_model(self.how)
|
||||
if self.who:
|
||||
self.content_type_who = ContentType.objects.get_for_model(self.who)
|
||||
self.object_id_who = self.who.id
|
||||
self.content_type_what = ContentType.objects.get_for_model(self.what)
|
||||
self.object_id_what = self.what.id
|
||||
self.content_type_how = ContentType.objects.get_for_model(self.how)
|
||||
|
|
|
@ -429,6 +429,23 @@
|
|||
{% if what_to_display and how_to_display %}
|
||||
|
||||
<form method="post" action="">
|
||||
{% if who_to_display %}
|
||||
<p>
|
||||
<h3>{% trans "Who" %}</h3>
|
||||
<p>{% trans "You can set an ABAC rule on a user a role or anybody. If you indicate 'Anybody' in the following list, it means that there exist mechanisms to make a user able to present (certified) attributes to the system. If you indicate a role, take that it does not conflict with a role in the rule that the user should not have, for instance due to heritage and a 'not' statement." %}
|
||||
</p>
|
||||
<select name="who_matches" id="id_who_matches">
|
||||
<option value="_">-- {% trans "Anybody" %} --</option>
|
||||
{% for it in who_to_display %}
|
||||
{% if it|klass == "UserAlias" %}
|
||||
<option value="{{ it.id }}_{{ it|klass }}">{{ it.alias }}</option>
|
||||
{% else %}
|
||||
<option value="{{ it.id }}_{{ it|klass }}">{{ it.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
<h3>{% trans "What" %}</h3>
|
||||
<select name="what_matches" id="id_what_matches">
|
||||
|
@ -447,7 +464,7 @@
|
|||
</p>
|
||||
<p>
|
||||
<br style="clear: both;"/>
|
||||
<input type="submit" name="add_permission" value="{% trans "Add" %}"/>
|
||||
<input type="submit" name="add_permission" value="{% trans "Add permission" %}"/>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
|
@ -461,12 +478,13 @@
|
|||
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
<br style="clear: both;"/>
|
||||
<form method="post" action="">
|
||||
<input type="submit" name="cancel_all" value="{% trans "Cancel Rule" %}"/>
|
||||
<input type="submit" name="cancel_all" value="{% trans "Cancel permission creation" %}"/>
|
||||
</form>
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
<p><a href="{{ backlink }}">{% trans "Back" %}</a></p>
|
||||
|
|
Reference in New Issue