565 lines
24 KiB
Python
565 lines
24 KiB
Python
'''
|
|
VERIDIC - Towards a centralized access control system
|
|
|
|
Copyright (C) 2011 Mikael Ates
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
'''
|
|
|
|
|
|
import logging
|
|
|
|
from django.http import HttpResponseRedirect
|
|
from django.shortcuts import render_to_response
|
|
from django.contrib import messages
|
|
from django.conf import settings
|
|
from django.contrib.auth.models import User
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.utils.translation import ugettext as _
|
|
from django.template import RequestContext
|
|
from django.contrib.contenttypes.models import ContentType
|
|
|
|
from core import isAuthorizedRBAC2, \
|
|
set_default_alias, is_user_administrator, \
|
|
is_policy_root_administrator, is_policy_user_administrator, \
|
|
check_permission, return_all_derived_delegated_permissions
|
|
|
|
from views import list_any
|
|
|
|
from alias_mgmt_views import list_aliases
|
|
|
|
from utils_views import get_policy_from_session
|
|
|
|
from models import UserAlias, Role, AcsObject, View, Action, Activity, \
|
|
Namespace, AcsPermission, Policy, AcsAbacPermission
|
|
|
|
from abac.models import Source, PredicateRequired, PredicateComparison
|
|
|
|
from acs.abac.core import remove_rule
|
|
|
|
from decorators import prevent_access_to_normal_users
|
|
|
|
logger = logging.getLogger('acs')
|
|
|
|
login_url = settings.LOGIN_URL
|
|
root_url = settings.ROOT_URL
|
|
|
|
|
|
@csrf_exempt
|
|
@prevent_access_to_normal_users
|
|
def del_any(request):
|
|
backlink = root_url
|
|
if request.method == 'POST':
|
|
logger.debug('del_any: POST')
|
|
if 'Cancel' in request.POST:
|
|
messages.add_message(request, messages.INFO,
|
|
_('Operation canceled'))
|
|
if 'type_entity' in request.POST:
|
|
return list_any(request, request.POST['type_entity'])
|
|
elif 'back_url' in request.POST:
|
|
return HttpResponseRedirect(request.POST['back_url'])
|
|
else:
|
|
return HttpResponseRedirect(root_url)
|
|
if not 'Delete' in request.POST:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unknown action requested'))
|
|
return HttpResponseRedirect(root_url)
|
|
if not 'id' in request.POST or not 'type_entity' in request.POST:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return HttpResponseRedirect(root_url)
|
|
|
|
|
|
type_entity = request.POST['type_entity']
|
|
pk = request.POST['id']
|
|
item = None
|
|
p = []
|
|
p_admin = []
|
|
administration = Action.objects.get(name='administration')
|
|
admin_deletion=[]
|
|
policy = get_policy_from_session(request)
|
|
default_ns = Namespace.objects.get(name='Default')
|
|
|
|
if type_entity == 'user':
|
|
try:
|
|
item = User.objects.get(id=pk)
|
|
except:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return list_any(request, type_entity)
|
|
|
|
'''
|
|
Check authorization to delete this item
|
|
The special user administrator role is needed because here we
|
|
manage users even if they are not declared in ACS (empowered)
|
|
'''
|
|
if not is_user_administrator(request.user):
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete the user %s') %item)
|
|
return list_any(request, type_entity)
|
|
'''
|
|
Even if users can administrate themselves,
|
|
we do not want hem to delete themselves
|
|
'''
|
|
if request.user.id == item.id:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete yourself Mister or Miss \
|
|
%s') %item)
|
|
return list_any(request, type_entity)
|
|
|
|
elif type_entity == 'alias':
|
|
try:
|
|
item = UserAlias.objects.get(id=pk)
|
|
except:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return list_aliases(request)
|
|
'''Check authorization to delete this item'''
|
|
policy = None
|
|
try:
|
|
policy = Policy.objects.get(namespace=item.namespace)
|
|
except:
|
|
pass
|
|
back_url = root_url
|
|
if 'back_url' in request.POST:
|
|
back_url = request.POST['back_url']
|
|
if item.namespace.id == default_ns.id:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Default user alias cannot be deleted'))
|
|
return HttpResponseRedirect(back_url)
|
|
if not is_policy_user_administrator(request.user, policy):
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete the user alias %s') %item)
|
|
return HttpResponseRedirect(back_url)
|
|
'''
|
|
The permissions that should be removed, only aliases not in
|
|
default, so no admin permission with this alias as who
|
|
'''
|
|
p = list(AcsPermission.objects.\
|
|
filter(content_type_who__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_who=item.id))
|
|
'''This alias may be what of an administration permission'''
|
|
p_admin = list(AcsPermission.objects.\
|
|
filter(content_type_what__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_what=item.id, content_type_how__pk=\
|
|
ContentType.objects.get_for_model(administration).id,
|
|
object_id_how=administration.id))
|
|
|
|
elif type_entity == 'role':
|
|
if not policy:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Missing policy'))
|
|
return list_any(request, type_entity)
|
|
try:
|
|
item = Role.objects.get(id=pk)
|
|
except:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return list_any(request, type_entity)
|
|
if item in policy.admin_roles.all():
|
|
messages.add_message(request, messages.ERROR,
|
|
_('%s is an administration role and cannot be deleted here')
|
|
%item)
|
|
return list_any(request, type_entity)
|
|
'''Check authorization to delete this item'''
|
|
p = isAuthorizedRBAC2(set_default_alias(request.user), item,
|
|
administration)
|
|
if not p:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete the role %s') %item)
|
|
return list_any(request, type_entity)
|
|
'''
|
|
The permissions that should be removed, only not admin role,
|
|
so no admin permission with this alias as who
|
|
'''
|
|
p = list(AcsPermission.objects.\
|
|
filter(content_type_who__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_who=item.id))
|
|
'''This alias may be what of an administration permission'''
|
|
p_admin = list(AcsPermission.objects.\
|
|
filter(content_type_what__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_what=item.id, content_type_how__pk=\
|
|
ContentType.objects.get_for_model(administration).id,
|
|
object_id_how=administration.id))
|
|
|
|
elif type_entity == 'admin_role':
|
|
if not policy:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Missing policy'))
|
|
return list_any(request, type_entity)
|
|
try:
|
|
item = Role.objects.get(id=pk)
|
|
except:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return list_any(request, type_entity)
|
|
if not item in policy.admin_roles.all():
|
|
messages.add_message(request, messages.ERROR,
|
|
_('%s is not an administration role') %item)
|
|
return list_any(request, type_entity)
|
|
'''Check authorization to delete this item'''
|
|
if not is_policy_root_administrator(request.user, policy):
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete the role %s') %item)
|
|
return list_any(request, type_entity)
|
|
'''The permissions that should be removed'''
|
|
p = list(AcsPermission.objects.\
|
|
filter(content_type_who__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_who=item.id, content_type_how__pk=\
|
|
ContentType.objects.get_for_model(administration).id,
|
|
object_id_how=administration.id))
|
|
'''
|
|
No administration permission with an administration role as what
|
|
'''
|
|
|
|
elif type_entity == 'object':
|
|
if not policy:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Missing policy'))
|
|
return list_any(request, type_entity)
|
|
try:
|
|
item = AcsObject.objects.get(id=pk)
|
|
except:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return list_any(request, type_entity)
|
|
'''Check authorization to delete this item'''
|
|
p = isAuthorizedRBAC2(set_default_alias(request.user), item,
|
|
administration)
|
|
if not p:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete the object %s') %item)
|
|
return list_any(request, type_entity)
|
|
'''
|
|
The permissions that should be removed, object of a normal
|
|
permission and objects of administration permission
|
|
'''
|
|
p = list(AcsPermission.objects.\
|
|
filter(content_type_what__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_what=item.id))
|
|
for it in p:
|
|
if it.how.id == administration.id:
|
|
p_admin.append(it)
|
|
p.remove(it)
|
|
|
|
elif type_entity == 'view':
|
|
if not policy:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Missing policy'))
|
|
return list_any(request, type_entity)
|
|
try:
|
|
item = View.objects.get(id=pk)
|
|
except:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return list_any(request, type_entity)
|
|
if item in policy.admin_views.all():
|
|
messages.add_message(request, messages.ERROR,
|
|
_('%s is an administration view and cannot be deleted here')
|
|
%item)
|
|
return list_any(request, type_entity)
|
|
'''Check authorization to delete this item'''
|
|
p = isAuthorizedRBAC2(set_default_alias(request.user), item,
|
|
administration)
|
|
if not p:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete the view %s') %item)
|
|
return list_any(request, type_entity)
|
|
'''
|
|
The permissions that should be removed, view of a normal
|
|
permission and objects of administration permission
|
|
'''
|
|
p = list(AcsPermission.objects.\
|
|
filter(content_type_what__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_what=item.id))
|
|
for it in p:
|
|
if it.how.id == administration.id:
|
|
p_admin.append(it)
|
|
p.remove(it)
|
|
|
|
elif type_entity == 'admin_view':
|
|
if not policy:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Missing policy'))
|
|
return list_any(request, type_entity)
|
|
try:
|
|
item = View.objects.get(id=pk)
|
|
except:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return list_any(request, type_entity)
|
|
if not item in policy.admin_views.all():
|
|
messages.add_message(request, messages.ERROR,
|
|
_('%s is not an administration role') %item)
|
|
return list_any(request, type_entity)
|
|
'''Check authorization to delete this item'''
|
|
if not is_policy_root_administrator(request.user, policy):
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete the role %s') %item)
|
|
return list_any(request, type_entity)
|
|
'''
|
|
The permissions that should be removed, only administration
|
|
permission on admin views
|
|
'''
|
|
p_admin = list(AcsPermission.objects.\
|
|
filter(content_type_what__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_what=item.id, content_type_how__pk=\
|
|
ContentType.objects.get_for_model(administration).id,
|
|
object_id_how=administration.id))
|
|
|
|
elif type_entity == 'action':
|
|
if not policy:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Missing policy'))
|
|
return list_any(request, type_entity)
|
|
try:
|
|
item = Action.objects.get(id=pk)
|
|
except:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return list_any(request, type_entity)
|
|
if item.namespace.id == default_ns.id:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Default action cannot be deleted'))
|
|
return list_any(request, type_entity)
|
|
'''Check authorization to delete this item'''
|
|
p = isAuthorizedRBAC2(set_default_alias(request.user), item,
|
|
administration)
|
|
if not p:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete the action %s') %item)
|
|
return list_any(request, type_entity)
|
|
'''The permissions that should be removed'''
|
|
p = list(AcsPermission.objects.\
|
|
filter(content_type_how__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_how=item.id))
|
|
p_admin = list(AcsPermission.objects.\
|
|
filter(content_type_what__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_what=item.id, content_type_how__pk=\
|
|
ContentType.objects.get_for_model(administration).id,
|
|
object_id_how=administration.id))
|
|
|
|
elif type_entity == 'activity':
|
|
if not policy:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Missing policy'))
|
|
return list_any(request, type_entity)
|
|
try:
|
|
item = Activity.objects.get(id=pk)
|
|
except:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return list_any(request, type_entity)
|
|
if item.namespace.id == default_ns.id:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Default activity cannot be deleted'))
|
|
return list_any(request, type_entity)
|
|
'''Check authorization to delete this item'''
|
|
p = isAuthorizedRBAC2(set_default_alias(request.user), item,
|
|
administration)
|
|
if not p:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete the activity %s') %item)
|
|
return list_any(request, type_entity)
|
|
'''The permissions that should be removed'''
|
|
p = list(AcsPermission.objects.\
|
|
filter(content_type_how__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_how=item.id))
|
|
p_admin = list(AcsPermission.objects.\
|
|
filter(content_type_what__pk=\
|
|
ContentType.objects.get_for_model(item).id,
|
|
object_id_what=item.id, content_type_how__pk=\
|
|
ContentType.objects.get_for_model(administration).id,
|
|
object_id_how=administration.id))
|
|
|
|
elif type_entity == 'source':
|
|
if not is_user_administrator(request.user):
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to delete a source of attributes'))
|
|
return list_any(request, type_entity)
|
|
try:
|
|
item = Source.objects.get(id=pk)
|
|
except:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the source'))
|
|
return list_any(request, type_entity)
|
|
'''
|
|
Grab all ABAC permissions that have a predicate with that
|
|
source
|
|
'''
|
|
ats = item.attachedsource_set.all()
|
|
preds_req = []
|
|
for at in ats:
|
|
tmp = \
|
|
PredicateRequired.objects.filter(definition=at.assertion)
|
|
for t in tmp:
|
|
if t not in preds_req:
|
|
preds_req.append(t)
|
|
preds_cmp = []
|
|
for at in ats:
|
|
tmp = \
|
|
PredicateComparison.objects.filter(operand1=at.assertion)
|
|
for t in tmp:
|
|
if t not in preds_cmp:
|
|
preds_cmp.append(t)
|
|
tmp = \
|
|
PredicateComparison.objects.filter(operand2=at.assertion)
|
|
for t in tmp:
|
|
if t not in preds_cmp:
|
|
preds_cmp.append(t)
|
|
p = []
|
|
for it in preds_req:
|
|
tmp = AcsAbacPermission.objects.filter(rule=it.rule)
|
|
for t in tmp:
|
|
if t not in p:
|
|
p.append(t)
|
|
for it in preds_cmp:
|
|
tmp = AcsAbacPermission.objects.filter(rule=it.rule)
|
|
for t in tmp:
|
|
if t not in p:
|
|
p.append(t)
|
|
'''
|
|
Here we should remove assertionData of profile on such a
|
|
source
|
|
'''
|
|
|
|
else:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to find the object'))
|
|
return list_any(request, type_entity)
|
|
|
|
collateral_damages = []
|
|
denied = []
|
|
'''The permissions that should be removed'''
|
|
if p_admin and not is_policy_root_administrator(request.user, policy):
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to perform this deletion because \
|
|
you have not the administration right to delete the \
|
|
following administration permissions that should be removed \
|
|
if this object is removed:'))
|
|
for it in p_admin:
|
|
messages.add_message(request, messages.ERROR,
|
|
'%s' %it)
|
|
return list_any(request, type_entity)
|
|
for it in p:
|
|
collateral_damages.append(it)
|
|
'''
|
|
We check here that the user has the permission to delete the
|
|
permissions that should be removed if the object is removed
|
|
'''
|
|
if type_entity != 'source':
|
|
if not check_permission(request.user, policy, it):
|
|
if not it in denied:
|
|
denied.append(it)
|
|
else:
|
|
delegateds = return_all_derived_delegated_permissions(it)
|
|
if len(delegateds) > 1:
|
|
logger.debug('del_permission: delegated permissions \
|
|
%s' % delegateds)
|
|
for i in delegateds:
|
|
if not i in collateral_damages:
|
|
collateral_damages.append(i)
|
|
else:
|
|
logger.debug('del_permission: no delegated \
|
|
permissions')
|
|
if not it in collateral_damages:
|
|
collateral_damages.append(it)
|
|
|
|
if denied:
|
|
messages.add_message(request, messages.ERROR,
|
|
_('You are not authorized to perform this deletion because \
|
|
you have not the rights to delete the following permissions \
|
|
that should be removed if this object is removed:'))
|
|
for it in denied:
|
|
messages.add_message(request, messages.ERROR,
|
|
'%s' %it)
|
|
return list_any(request, type_entity)
|
|
|
|
if p_admin:
|
|
for it in p_admin:
|
|
collateral_damages.append(it)
|
|
|
|
if not 'consent' in request.POST:
|
|
tpl_parameters = {'item': item,
|
|
'type_entity': type_entity,
|
|
'admin_deletion': admin_deletion,
|
|
'collateral_damages': collateral_damages}
|
|
if 'back_url' in request.POST:
|
|
tpl_parameters['back_url'] = request.POST['back_url']
|
|
return render_to_response('deletion_confirmation.html',
|
|
tpl_parameters, context_instance=RequestContext(request))
|
|
|
|
'''Here we remove the permissions by hand'''
|
|
for it in collateral_damages:
|
|
try:
|
|
if type_entity == 'source':
|
|
remove_rule(it.rule)
|
|
it.delete()
|
|
messages.add_message(request, messages.INFO,
|
|
_('Object %s successfully deleted') %it)
|
|
except:
|
|
logger.error('del_any_final: \
|
|
Unable to delete the object: %s' %it)
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to delete the the object: %s') %it)
|
|
|
|
try:
|
|
if type_entity == 'user':
|
|
for u in UserAlias.objects.filter(user=item):
|
|
logger.debug('del_any_final: User %s will be \
|
|
deleted - deletion of alias: %s' % (item, u))
|
|
u.delete()
|
|
elif type_entity == 'source':
|
|
try:
|
|
ns = Namespace.objects.get(name=item.name)
|
|
for u in UserAlias.objects.filter(namespace=ns):
|
|
logger.debug('del_any_final: Source %s will be \
|
|
deleted - deletion of alias: %s' % (item, u))
|
|
u.delete()
|
|
logger.debug('del_any_final: Source %s will be \
|
|
deleted - deletion of namespace: %s' % (item, ns))
|
|
ns.delete()
|
|
except Exception, err:
|
|
logger.error('del_any_final: \
|
|
Error removing a source due to: %s' % err)
|
|
pass
|
|
item.delete()
|
|
except:
|
|
logger.error('del_any_final: \
|
|
Unable to delete the object: %s' %item)
|
|
messages.add_message(request, messages.ERROR,
|
|
_('Unable to delete the the object: %s') %item)
|
|
return list_any(request, type_entity)
|
|
|
|
messages.add_message(request, messages.INFO,
|
|
_('Object %s successfully deleted') %item)
|
|
|
|
if 'back_url' in request.POST:
|
|
return HttpResponseRedirect(request.POST['back_url'])
|
|
|
|
return list_any(request, type_entity)
|
|
|
|
return HttpResponseRedirect(backlink)
|