diff --git a/acs/abac_views.py b/acs/abac_views.py index 14611c5..72a3feb 100644 --- a/acs/abac_views.py +++ b/acs/abac_views.py @@ -32,6 +32,17 @@ from django.http import HttpResponseRedirect from django.conf import settings from django.db import transaction +from attribute_aggregator.models import AttributeSource, AttributeData +from attribute_aggregator.xacml_constants import * +from attribute_aggregator.core import get_all_attribute_definitions, \ + get_all_sources, get_attribute_type_of_definition, \ + convert_from_string +from attribute_aggregator.mapping import ATTRIBUTE_MAPPING + +from acs.abac.core import remove_rule +from acs.abac.logic import is_proposition +from acs.abac.models import AbacRule, AssertionData, AssertionDefinition, \ + PredicateRequired, PredicateRole, PredicateComparison from core import is_policy_action_creator, is_policy_object_creator, \ is_policy_user_administrator, is_in_policy, is_valid_regex, \ @@ -60,24 +71,14 @@ from decorators import prevent_access_to_normal_users,\ prevent_access_to_not_self_administrators_or_normal_users, \ check_authorized_for_abac +from views import check_object_or_view, check_action_or_activity, \ + return_add_any + from utils_views import get_policy_from_session, \ get_who_from_one_post_field, \ get_what_from_one_post_field, \ get_how_from_one_post_field -from views import check_object_or_view, check_action_or_activity, \ - return_add_any - -from acs.abac.models import * - -from acs.abac.core import get_all_attribute_definitions, get_all_sources, \ - get_attribute_definition_by_name, \ - remove_rule - -from acs.abac.logic import is_proposition - -from acs.xacml.constants import * - logger = logging.getLogger('acs') @@ -225,12 +226,12 @@ def add_abac_permission(request): ''' - Predicate choice: + Predicate required: - select definition and require single-valued - select source ''' if 'select_attribute_definition' in request.POST \ - and 'attribute_definition_id' in request.POST: + and 'attribute_definition' in request.POST: if not 'working_predicate' in request.session: messages.add_message(request, messages.ERROR, _('No working predicate')) @@ -241,21 +242,17 @@ def add_abac_permission(request): PREDICATE_REQUIRED: messages.add_message(request, messages.ERROR, _('Working predicate is not a required attribute')) + elif not request.POST['attribute_definition'] in ATTRIBUTE_MAPPING: + messages.add_message(request, messages.ERROR, + _('Unknown attribute definition')) else: - try: - ad = AttributeDefinition.objects.get(id=request.POST['attribute_definition_id']) working_predicate = request.session['working_predicate'] request.session.pop('working_predicate') - working_predicate['definition_id'] \ - = request.POST['attribute_definition_id'] working_predicate['definition_name'] \ - = ad.attribute_name + = request.POST['attribute_definition'] if 'singlevalued' in request.POST: working_predicate['singlevalued'] = 'singlevalued' request.session['working_predicate'] = working_predicate - except: - messages.add_message(request, messages.ERROR, - _('Attribute definition not found')) return return_add_abac_permission_form(request) if 'select_source' in request.POST \ @@ -272,7 +269,8 @@ def add_abac_permission(request): _('Working predicate is not a required attribute')) else: try: - s = Source.objects.get(id=request.POST['source_id']) + s = AttributeSource.objects.get(\ + id=request.POST['source_id']) working_predicate = request.session['working_predicate'] if 'sources_selected' in working_predicate: if 'singlevalued' in working_predicate: @@ -473,12 +471,11 @@ def add_abac_permission(request): working_predicate['working_operand']['type'] = 'value' # Definition type is the same as operand one working_predicate['working_operand']['definition_name'] = working_predicate['operand1_defined']['definition_name'] - working_predicate['working_operand']['definition_id'] = working_predicate['operand1_defined']['definition_id'] request.session['working_predicate'] = working_predicate return return_add_abac_permission_form(request) if 'select_attribute_definition_operand' in request.POST \ - and 'attribute_definition_id' in request.POST: + and 'attribute_definition' in request.POST: if not 'working_predicate' in request.session: messages.add_message(request, messages.ERROR, _('No working predicate')) @@ -497,23 +494,22 @@ def add_abac_permission(request): or not 'type' in request.session['working_predicate']['working_operand']: messages.add_message(request, messages.ERROR, _('There is no valid operand definition in progress')) - else: - try: - ad = AttributeDefinition.objects.get(id=request.POST['attribute_definition_id']) - if ad.attribute_type != ACS_COMP_TYPE[request.session['working_predicate']['type']]: - messages.add_message(request, messages.ERROR, - _('The attribute type does not match the comparison type')) - return return_add_abac_permission_form(request) - working_predicate = request.session['working_predicate'] - request.session.pop('working_predicate') - working_predicate['working_operand']['definition_id'] \ - = request.POST['attribute_definition_id'] - working_predicate['working_operand']['definition_name'] \ - = ad.attribute_name - request.session['working_predicate'] = working_predicate - except Exception, e: + elif not request.POST['attribute_definition'] in ATTRIBUTE_MAPPING: messages.add_message(request, messages.ERROR, - _('Attribute definition not found (%s)') %str(e)) + _('Unknown attribute definition')) + else: + definition = request.POST['attribute_definition'] + if get_attribute_type_of_definition(definition) \ + != ACS_COMP_TYPE[\ + request.session['working_predicate']['type']]: + messages.add_message(request, messages.ERROR, + _('The attribute type does not match the comparison type')) + return return_add_abac_permission_form(request) + working_predicate = request.session['working_predicate'] + request.session.pop('working_predicate') + working_predicate['working_operand']['definition_name'] \ + = definition + request.session['working_predicate'] = working_predicate return return_add_abac_permission_form(request) if 'select_source_operand' in request.POST \ @@ -536,13 +532,13 @@ def add_abac_permission(request): or not 'type' in request.session['working_predicate']['working_operand']: messages.add_message(request, messages.ERROR, _('There is no valid operand definition in progress')) - elif not 'definition_id' in request.session['working_predicate']['working_operand'] \ - or not 'definition_name' in request.session['working_predicate']['working_operand']: + elif not 'definition_name' in request.session['working_predicate']['working_operand']: messages.add_message(request, messages.ERROR, _('Missing definition of the working operand')) else: try: - s = Source.objects.get(id=request.POST['source_operand_id']) + s = AttributeSource.objects.get(\ + id=request.POST['source_operand_id']) working_predicate = request.session['working_predicate'] if 'sources_selected' in working_predicate['working_operand']: if not 'operand1_defined' in request.session['working_predicate'] and 'operandone_singlevalued' in working_predicate: @@ -589,8 +585,7 @@ def add_abac_permission(request): or not 'type' in request.session['working_predicate']['working_operand']: messages.add_message(request, messages.ERROR, _('There is no valid operand definition in progress')) - elif not 'definition_id' in request.session['working_predicate']['working_operand'] \ - or not 'definition_name' in request.session['working_predicate']['working_operand']: + elif not 'definition_name' in request.session['working_predicate']['working_operand']: messages.add_message(request, messages.ERROR, _('Missing definition of the working operand')) else: @@ -635,8 +630,7 @@ def add_abac_permission(request): or not 'type' in request.session['working_predicate']['working_operand']: messages.add_message(request, messages.ERROR, _('There is no valid operand definition in progress')) - elif not 'definition_id' in request.session['working_predicate']['working_operand'] \ - or not 'definition_name' in request.session['working_predicate']['working_operand']: + elif not 'definition_name' in request.session['working_predicate']['working_operand']: messages.add_message(request, messages.ERROR, _('Missing definition of the working operand')) elif not 'values_selected' in request.session['working_predicate']['working_operand'] \ @@ -690,6 +684,8 @@ def add_abac_permission(request): else: if 'rule' in request.session: request.session.pop('rule') + messages.add_message(request, messages.INFO, + _('The logical expression is well-formed')) request.session['rule'] = request.POST['rule_string'] return return_add_abac_permission_form(request) @@ -757,10 +753,10 @@ def add_abac_permission(request): request.session.pop('predicates') if 'rule' in request.session: request.session.pop('rule') + message += str(p) messages.add_message(request, messages.INFO, message) - policy = get_policy_from_session(request) - return HttpResponseRedirect('mod_policy?id=' + str(policy.id)) + return HttpResponseRedirect('add_permission_any') messages.add_message(request, messages.ERROR, _('Unknown action')) @@ -777,7 +773,7 @@ def check_data_and_create_permission(request, who, what, how): rule = AbacRule() rule.save() except: - raise Exception('unable to initalize rule') + raise Exception('Unable to initialize rule') p_ids1 = {} p_ids2 = {} p_id = 1 @@ -786,34 +782,40 @@ def check_data_and_create_permission(request, who, what, how): raise Exception('Missing type of predicate %s' %str(p_id)) pred = None if predicate['type'] == PREDICATE_REQUIRED: - if not 'definition_name' in predicate \ - or not 'definition_id' in predicate: - raise Exception('Missing definition of predicate %s' %str(p_id)) + if not 'definition_name' in predicate: + raise Exception('Missing definition of predicate %s' \ + % str(p_id)) if not 'sources_selected' in predicate: - raise Exception('Missing sources for predicate %s' %str(p_id)) - d = get_attribute_definition_by_name(predicate['definition_name']) - if not d: - raise Exception('Definition unknown for predicate %s' %str(p_id)) + raise Exception('Missing sources for predicate %s' \ + % str(p_id)) ad = None try: - ad = AssertionDefinition(attribute_definition=d) + ad = AssertionDefinition(\ + definition=predicate['definition_name']) ad.save() except: - raise Exception('Unable to create assertion for predicate %s' %str(p_id)) + raise Exception(\ + 'Unable to create assertion for predicate %s' \ + % str(p_id)) for s_id, s_name in predicate['sources_selected']: - ss = None + source = None try: - ss = Source.objects.get(id=s_id) + source = AttributeSource.objects.get(id=s_id) except: - raise Exception('Unable to find source (%s, %s) for predicate %s' % (s_id, s_name, str(p_id))) + raise Exception(\ + 'Unable to find source (%s, %s) for predicate %s' \ + % (s_id, s_name, str(p_id))) try: - AttachedSource(assertion=ad, source=ss).save() + ad.add_source(source) except: - raise Exception('Unable to attach source %s to predicate %s' % (ss, str(p_id))) + raise Exception(\ + 'Unable to add source %s to predicate %s' \ + % (source, str(p_id))) single_value = False if 'singlevalued' in predicate: single_value = True - pred = PredicateRequired(definition=ad, rule=rule, single_value=single_value) + pred = PredicateRequired(assertion_definition=ad, + single_value=single_value, rule=rule) elif predicate['type'] == PREDICATE_ROLE: if not 'role' in predicate: raise Exception('Missing role of predicate %s' %str(p_id)) @@ -830,35 +832,40 @@ def check_data_and_create_permission(request, who, what, how): 'DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2', 'DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2', 'DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2'): - raise Exception('Missing suitable option for multivalues treatment') + raise Exception(\ + 'Missing suitable option for multivalues treatment') if 'operandone_singlevalued' in predicate \ and 'operandtwo_singlevalued' in predicate \ - and predicate['multivalues_step_two'] != 'NO_MULTIVALUES': - raise Exception('Unacceptable option for multivalues treatment') + and predicate['multivalues_step_two'] \ + != 'NO_MULTIVALUES': + raise Exception(\ + 'Unacceptable option for multivalues treatment') if not 'operand1_defined' in predicate: - raise Exception('Missing operand1 for predicate %s' %str(p_id)) + raise Exception('Missing operand1 for predicate %s' \ + % str(p_id)) if not 'type' in predicate['operand1_defined']: - raise Exception('Missing type of operand1 for predicate %s' %str(p_id)) - if not 'definition_name' in predicate['operand1_defined'] \ - or not 'definition_id' in predicate['operand1_defined']: - raise Exception('Missing definition of operand1 of predicate %s' %str(p_id)) + raise Exception('Missing type of operand1 for predicate \ + %s' % str(p_id)) + if not 'definition_name' in predicate['operand1_defined']: + raise Exception('Missing definition of operand1 of \ + predicate %s' %str(p_id)) if not 'operand2_defined' in predicate: - raise Exception('Missing operand2 for predicate %s' %str(p_id)) + raise Exception('Missing operand2 for predicate %s' \ + % str(p_id)) if not 'type' in predicate['operand2_defined']: - raise Exception('Missing type of operand2 for predicate %s' %str(p_id)) - if not 'definition_name' in predicate['operand2_defined'] \ - or not 'definition_id' in predicate['operand2_defined']: - raise Exception('Missing definition of operand2 of predicate %s' %str(p_id)) + raise Exception('Missing type of operand2 for predicate \ + %s' % str(p_id)) + if not 'definition_name' in predicate['operand2_defined']: + raise Exception('Missing definition of operand2 of \ + predicate %s' % str(p_id)) - d1 = get_attribute_definition_by_name(predicate['operand1_defined']['definition_name']) - if not d1: - raise Exception('Definition unknown of operand1 of predicate %s' %str(p_id)) - d2 = get_attribute_definition_by_name(predicate['operand2_defined']['definition_name']) - if not d2: - raise Exception('Definition unknown of operand2 of predicate %s' %str(p_id)) - if d1.attribute_type != d2.attribute_type: - raise Exception('Data types of the two operands of predicate %s differ' %str(p_id)) + d1 = predicate['operand1_defined']['definition_name'] + d2 = predicate['operand2_defined']['definition_name'] + if get_attribute_type_of_definition(d1) \ + != get_attribute_type_of_definition(d2): + raise Exception('Data types of the two operands of \ + predicate %s differ' %str(p_id)) a1 = handle_operand(predicate, p_id, 'operand1', d1) a2 = handle_operand(predicate, p_id, 'operand2', d2) @@ -939,115 +946,68 @@ def check_data_and_create_permission(request, who, what, how): p.save() except Exception, err: raise Exception('Fail to save permission with error: %s' %err) - logger.info('add_permission: Permission added: %s' %str(p)) + logger.info(\ + 'check_data_and_create_permission: Permission added: %s' %str(p)) except Exception, err: + logger.info(\ + 'check_data_and_create_permission: \ + Rollback transaction because of %s.' % err) transaction.rollback() return (None, _('Failed to create permission due to %s') % str(err)) else: + logger.info(\ + 'check_data_and_create_permission: Commit transaction.') transaction.commit() - return (p, _('Successful permission creation')) + return (p, _('Successful creation of permission')) def handle_operand(predicate, p_id, name, d): a = None if predicate[name + '_defined']['type'] == "definition": if not 'sources_selected' in predicate[name + '_defined']: - raise Exception('Missing sources of %s of predicate %s' % (name, str(p_id))) + raise Exception('Missing sources of %s of predicate %s' \ + % (name, str(p_id))) try: - a = AssertionDefinition(attribute_definition=d) + a = AssertionDefinition(definition=d) a.save() except: - raise Exception('Unable to create assertion of %s of predicate %s' % (name, str(p_id))) + raise Exception(\ + 'Unable to create assertion of %s of predicate %s' \ + % (name, str(p_id))) for s_id, s_name in predicate[name + '_defined']['sources_selected']: - ss = None + source = None try: - ss = Source.objects.get(id=s_id) + source = AttributeSource.objects.get(id=s_id) except: - raise Exception('Unable to find source (%s, %s) of %s of predicate %s' % (s_id, s_name, name, str(p_id))) + raise Exception(\ + 'Unable to find source (%s, %s) of %s of predicate %s' \ + % (s_id, s_name, name, str(p_id))) try: - AttachedSource(assertion=a, source=ss).save() + a.add_source(source) except: - raise Exception('Unable to attach source %s of %s of predicate %s' % (ss, name, str(p_id))) + raise Exception(\ + 'Unable to attach source %s of %s of predicate %s' \ + % (source, name, str(p_id))) else: if not 'values_selected' in predicate[name + '_defined']: - raise Exception('Missing values of %s of predicate %s' % (name, str(p_id))) - try: - data = AttributeData(definition=d) - data.save() - except: - raise Exception('Unable to create data of %s of predicate %s' % (name, str(p_id))) + raise Exception('Missing values of %s of predicate %s' \ + % (name, str(p_id))) for value in predicate[name + '_defined']['values_selected']: - if d.attribute_type == ACS_XACML_DATATYPE_STRING: - try: - StringM(data=data, value=value).save() - except Exception, err: - raise Exception('Unable to set string %s i.e. %s of %s of predicate %s, err %s' % (value, d.attribute_type, name, str(p_id), str(err))) - elif d.attribute_type == ACS_XACML_DATATYPE_INTEGER: - try: - v = int(value) - IntegerM(data=data, value=v).save() - except Exception, err: - raise Exception('Unable to convert string %s to %s of %s of predicate %s, err %s' % (value, d.attribute_type, name, str(p_id), str(err))) - elif d.attribute_type == ACS_XACML_DATATYPE_DOUBLE: - try: - v = float(value) - DoubleM(data=data, value=v).save() - except: - raise Exception('Unable to convert string %s to %s of %s of predicate %s' % (value, d.attribute_type, name, str(p_id))) - elif d.attribute_type == ACS_XACML_DATATYPE_BOOLEAN: - try: - v = False - if value in ('True', 'true', 'Vrai', 'vrai'): - v = True - BooleanM(data=data, value=v).save() - except: - raise Exception('Unable to convert string %s to %s of %s of predicate %s' % (value, d.attribute_type, name, str(p_id))) - elif d.attribute_type == ACS_XACML_DATATYPE_TIME: - try: - v = time.strptime(value,"%h:%m:%s") #12:15:00 - TimeM(data=data, value=v).save() - except: - raise Exception('Unable to convert string %s to %s of %s of predicate %s' % (value, d.attribute_type, name, str(p_id))) - elif d.attribute_type == ACS_XACML_DATATYPE_DATE: - try: - v = time.strptime(value,"%d/%b/%Y") #28/01/1982 - DateM(data=data, value=v).save() - except: - raise Exception('Unable to convert string %s to %s of %s of predicate %s' % (value, d.attribute_type, name, str(p_id))) - elif d.attribute_type == ACS_XACML_DATATYPE_DATETIME: - try: - v = time.strptime(value,"%d/%b/%Y-%h:%m:%s") #28/01/1982-12:15:00 - DateTimeM(data=data, value=v).save() - except: - raise Exception('Unable to convert string %s to %s of %s of predicate %s' % (value, d.attribute_type, name, str(p_id))) - elif d.attribute_type == ACS_XACML_DATATYPE_RFC822NAME: - try: - v = None - r = re.compile('[a-zA-Z0-9+_\-\.]+@[0-9a-zA-Z][.-0-9a-zA-Z]*.[a-zA-Z]+') # email - if r.search(value): - v = value - else: - raise Exception('Unable to convert string %s to %s of %s of predicate %s' % (value, d.attribute_type, name, str(p_id))) - Rfc822NameM(data=data, value=v).save() - except: - raise Exception('Unable to convert string %s to %s of %s of predicate %s' % (value, d.attribute_type, name, str(p_id))) - elif d.attribute_type == ACS_XACML_DATATYPE_IPADDRESS: - try: - v = None - r = re.compile('(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})') # x.x.x.x - if r.search(value): - v = value - else: - raise Exception('Unable to convert string %s to %s of %s of predicate %s' % (value, d.attribute_type, name, str(p_id))) - IpAddressM(data=data, value=v).save() - except: - raise Exception('Unable to convert string %s to %s of %s of predicate %s' % (value, d.attribute_type, name, str(p_id))) + if not convert_from_string(d, value): + raise Exception('The value %s cannot be converted into the \ + type of the definition %s for predicate %s' \ + % (value, d, str(p_id))) + data = AttributeData(definition=d, + values=predicate[name + '_defined']['values_selected']) try: - a = AssertionData(attribute_data=data) + a = AssertionData() a.save() + a.set_attribute_data(data) except: - raise Exception('Unable to create assertion of %s of predicate %s' % (name, str(p_id))) + raise Exception(\ + 'Unable to create assertion data of predicate %s' \ + % str(p_id)) return a @@ -1058,10 +1018,13 @@ def return_add_abac_permission_form(request, template_name='add_abac_permission. policy = get_policy_from_session(request) tpl_p['multivalues'] = [] + if 'working_predicate' in request.session \ and 'type' in request.session['working_predicate'] \ - and request.session['working_predicate']['type'] \ - in (XACML_COMPARISON_EQUALITY, ACS_XACML_COMPARISON): + and (request.session['working_predicate']['type'] \ + in XACML_COMPARISON_EQUALITY \ + or request.session['working_predicate']['type'] \ + in ACS_XACML_COMPARISON): if 'multivalues_step_one' in request.session['working_predicate'] \ and request.session['working_predicate']['type'] \ @@ -1107,8 +1070,11 @@ def return_add_abac_permission_form(request, template_name='add_abac_permission. tpl_p['roles'] = \ filter_list_in_namespace(tpl_p['roles'], policy.namespace) else: - tpl_p['attribute_definitions'] = \ - AttributeDefinition.objects.filter(attribute_type=ACS_COMP_TYPE[request.session['working_predicate']['type']]) + tpl_p['attribute_definitions'] = [definition \ + for definition in get_all_attribute_definitions() \ + if get_attribute_type_of_definition(definition) \ + == ACS_COMP_TYPE[\ + request.session['working_predicate']['type']]] tpl_p['sources'] = get_all_sources() else: @@ -1199,11 +1165,9 @@ def list_abac_permissions(request): @check_authorized_for_abac def del_abac_permission(request): policy = get_policy_from_session(request) - administration = Action.objects.get(name='administration') back = '/list_abac_permissions' if request.method == 'POST': p = None - delegateds = [] if 'back_url' in request.POST and request.POST['back_url']: back = request.POST['back_url'] if 'Cancel' in request.POST: diff --git a/acs/acs_administration_views.py b/acs/acs_administration_views.py index 323c76b..83192d8 100644 --- a/acs/acs_administration_views.py +++ b/acs/acs_administration_views.py @@ -47,6 +47,7 @@ from utils_views import get_policy_from_session, \ get_who_from_one_post_field, \ get_what_admin_from_one_post_field + logger = logging.getLogger('acs') login_url = settings.LOGIN_URL diff --git a/acs/alias_mgmt_views.py b/acs/alias_mgmt_views.py index c122067..3261ff2 100644 --- a/acs/alias_mgmt_views.py +++ b/acs/alias_mgmt_views.py @@ -29,6 +29,9 @@ from django.http import HttpResponseRedirect from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.conf import settings +from attribute_aggregator.models import AttributeSource, UserAliasInSource +from attribute_aggregator.core import set_user_alias_in_source + from core import get_alias_in_policy, \ is_policy_user_administrator, \ is_user_administrator, \ @@ -39,14 +42,13 @@ from core import get_alias_in_policy, \ from models import UserAlias, Namespace, Policy -from abac.models import Source, LdapSource - from decorators import prevent_access_to_not_user_administrators, \ check_policy_in_session, \ check_authorized_on_users_and_roles from utils_views import get_policy_from_session + logger = logging.getLogger('acs') login_url = settings.LOGIN_URL @@ -282,7 +284,7 @@ def list_aliases(request, pk=None): sources = None try: - sources = LdapSource.objects.all() + sources = AttributeSource.objects.all() except Exception, err: logger.error('list_aliases: An error occurred looking for \ sources: %s' % err) @@ -316,20 +318,12 @@ def list_aliases(request, pk=None): ''' aliases_sources = [] for source in sources: - if not source.get_source_instance().is_auth_backend: - ns = None - try: - ns = Namespace.objects.get(name=source.name) - except Exception, err: - logger.error('list_aliases: An error occurred \ - looking for the namespace of %s: %s\ - sources: %s' % (source.name, err)) - else: - try: - u = UserAlias.objects.get(user=user, namespace=ns) - aliases_sources.append((ns, u)) - except: - aliases_sources.append((ns, None)) + try: + aliases_sources.append((source, + UserAliasInSource.objects.get(user=user, + source=source))) + except: + aliases_sources.append((source, None)) back_url = '/list_aliases?id=%s' %pk tpl_parameters = {'namespaces_not_in': namespaces_not_in, @@ -452,7 +446,7 @@ def set_user_in_source(request): '''The admin must have admin right on this user''' if request.method == 'POST': if not 'alias' in request.POST or not 'user_id' in request.POST \ - or not 'namespace_id' in request.POST: + or not 'source_id' in request.POST: logger.error('set_user_in_namespace_from_home: \ missing data from %s' %request.user) messages.add_message(request, messages.ERROR, _('Invalid action')) @@ -467,49 +461,29 @@ def set_user_in_source(request): HttpResponseRedirect('/list_users_for_aliases') backurl = '/list_aliases?id=' + request.POST['user_id'] - ns = None + source = None try: - ns = Namespace.objects.get(id=request.POST['namespace_id']) + source = AttributeSource.objects.get(id=request.POST['source_id']) except: logger.error('set_user_in_source: \ - unknown namespace with id %s' %request.POST['namespace_id']) + unknown source with id %s' %request.POST['source_id']) messages.add_message(request, messages.ERROR, _('Unkown namespace')) return HttpResponseRedirect(backurl) '''Create alias''' - try: - a = UserAlias.objects.get(user=user, namespace=ns) - logger.error('set_user_in_source: the user %s \ - already has the alias %s in this namespace' %(user, a)) - messages.add_message(request, messages.ERROR, - _('The user already has the alias %s in this namespace') %a) - return HttpResponseRedirect(backurl) - except ObjectDoesNotExist: - pass - except MultipleObjectsReturned: - logger.critical('set_user_in_source: \ - the user has mulitple aliases in this namespace') - messages.add_message(request, messages.ERROR, - _('The user already has multiple aliases in this namespace')) - return HttpResponseRedirect(backurl) - if not 'alias' in request.POST or not request.POST['alias']: - alias = user.username + name = user.username else: - alias = request.POST['alias'] - - ua = None - try: - ua = UserAlias(alias=alias, user=user, namespace=ns) - ua.save() - except: + name = request.POST['alias'] + ua = set_user_alias_in_source(user, source, name, force_change=True) + if not ua: messages.add_message(request, messages.ERROR, - _('Unable to add %s for %s in %s') %(alias, user, ns)) + _('Unable to add %s for %s in %s') %(name, user, source)) return HttpResponseRedirect(backurl) messages.add_message(request, messages.INFO, - _('User %s added in %s') %(ua, ns)) + _('User %s added in %s') %(ua, source)) return HttpResponseRedirect(backurl) messages.add_message(request, messages.ERROR, _('Unknown action')) diff --git a/acs/core.py b/acs/core.py index 7b33f19..c252477 100644 --- a/acs/core.py +++ b/acs/core.py @@ -28,7 +28,7 @@ from django.db import transaction from models import UserAlias, Role, AcsObject, View, Action, Activity, \ Namespace, AcsPermission, AcsAbacPermission, Policy -from signals import attributes_call +#from signals import attributes_call from abac.models import * @@ -733,12 +733,14 @@ def is_authorized_by_names_with_abac(requestor_name, who_name, what_name, Attribute loading in profile object ''' - from abac.core import load_profile_by_dic, load_or_create_user_profile +# from abac.core import load_profile_by_dic, load_or_create_user_profile + from attribute_aggregator.core import load_or_create_user_profile if who.user: profile = load_or_create_user_profile(user=who.user) else: - profile = load_or_create_user_profile(user=None) +# profile = load_or_create_user_profile(user=None) + profile = load_or_create_user_profile() if not profile: logger.critical('is_authorized_by_names_with_abac: \ Error to create or load profile for %s' % who) @@ -747,7 +749,11 @@ def is_authorized_by_names_with_abac(requestor_name, who_name, what_name, % profile) if attributes: - load_profile_by_dic(profile, attributes) + logger.debug('is_authorized_by_names_with_abac: \ + load attributes %s in parameters' \ + % attributes) +# load_profile_by_dic(profile, attributes) + profile.load_by_dic(attributes) ''' The requester is who, that means that the user is logged on @@ -762,23 +768,36 @@ def is_authorized_by_names_with_abac(requestor_name, who_name, what_name, if (not requestor and not who) \ or (requestor and who and requestor == who): if request and getattr(request, 'session', None) and 'attributes' in request.session: - load_profile_by_dic(profile, request.session['attributes']) +# load_profile_by_dic(profile, request.session['attributes']) + logger.debug('is_authorized_by_names_with_abac: \ + load attributes %s in parameters' \ + % request.session['attributes']) + profile.load_by_dic(request.session['attributes']) - if who and not no_attribute_signal: - if not who.user: - attributes_provided = attributes_call.send(sender=None, - request=request, user=who) - else: - attributes_provided = attributes_call.send(sender=None, - request=request, user=who.user) - logger.info('is_authorized_by_names_with_abac: signal attributes_call sent') +# if who and not no_attribute_signal: +# if not who.user: +# attributes_provided = attributes_call.send(sender=None, +# request=request, user=who) +# else: +# attributes_provided = attributes_call.send(sender=None, +# request=request, user=who.user) +# logger.info('is_authorized_by_names_with_abac: signal attributes_call sent') + +# attributes = {} +# for attrs in attributes_provided: +# logger.info('is_authorized_by_names_with_abac: attributes_call connected to function %s' % \ +# attrs[0].__name__) +# logger.info('is_authorized_by_names_with_abac: attributes provided are %s' %str(attrs[1])) +# load_profile_by_dic(profile, attrs[1]) + + ''' + Attribute profile filled by the signal only works with a User instance + ''' + if who.user and not no_attribute_signal: + logger.debug('is_authorized_by_names_with_abac: \ + load attributes in bulk for %s' % who.user) + profile.load_greedy() - attributes = {} - for attrs in attributes_provided: - logger.info('is_authorized_by_names_with_abac: attributes_call connected to function %s' % \ - attrs[0].__name__) - logger.info('is_authorized_by_names_with_abac: attributes provided are %s' %str(attrs[1])) - load_profile_by_dic(profile, attrs[1]) logger.debug('is_authorized_by_names_with_abac: The profile is %s' % profile) @@ -890,6 +909,7 @@ def is_authorized_by_names_with_abac(requestor_name, who_name, what_name, content_type_how__pk=t_how.id, object_id_how=how.id)) + if not permissions: logger.debug('is_authorized_by_names_with_abac: Access denied - no permission found') return (False, None, 0) diff --git a/acs/deletion_view.py b/acs/deletion_view.py index d2579ff..2e7c61b 100644 --- a/acs/deletion_view.py +++ b/acs/deletion_view.py @@ -30,6 +30,8 @@ from django.utils.translation import ugettext as _ from django.template import RequestContext from django.contrib.contenttypes.models import ContentType +from attribute_aggregator.models import AttributeSource, UserAliasInSource + from core import isAuthorizedRBAC2, \ set_default_alias, is_user_administrator, \ is_policy_root_administrator, is_policy_user_administrator, \ @@ -44,12 +46,13 @@ 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 abac.models import 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 @@ -158,6 +161,23 @@ def del_any(request): ContentType.objects.get_for_model(administration).id, object_id_how=administration.id)) + elif type_entity == 'alias_in_source': + try: + item = UserAliasInSource.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''' + back_url = root_url + if 'back_url' in request.POST: + back_url = request.POST['back_url'] + if not is_user_administrator(request.user): + messages.add_message(request, messages.ERROR, + _('You are not authorized to delete the user alias %s') %item) + return HttpResponseRedirect(back_url) + + elif type_entity == 'role': if not policy: messages.add_message(request, messages.ERROR, @@ -400,49 +420,30 @@ def del_any(request): _('You are not authorized to delete a source of attributes')) return list_any(request, type_entity) try: - item = Source.objects.get(id=pk) + item = AttributeSource.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 + source. + + Not for now. Need a fine-grained deletion, for instance + some premission should not deleted if it based on a list of + source. Only the source in the list should be deleted, not the + permission. + + TODO: A better solution should be in the deletion interface of + permissions so look for permission containing a specified + element, then to delete all the objects selected. ''' - 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 + source. + + TODO: No. Implement a cleaning interface for profiles. ''' else: @@ -501,6 +502,10 @@ def del_any(request): for it in p_admin: collateral_damages.append(it) + ''' + TODO: We should ask also ask if the user only wants to delete the + item and not the permissions. + ''' if not 'consent' in request.POST: tpl_parameters = {'item': item, 'type_entity': type_entity, diff --git a/acs/forms.py b/acs/forms.py index b3732bf..704029a 100644 --- a/acs/forms.py +++ b/acs/forms.py @@ -26,7 +26,8 @@ from registration.forms import RegistrationForm from models import Action, Activity, AcsObject, Role, View, Namespace -from abac.models import Source, LdapSource +from attribute_aggregator.models import AttributeSource, LdapSource + logger = logging.getLogger('acs') @@ -375,7 +376,7 @@ class AddSourceForm(forms.ModelForm): numbers and @/./+/-/_ characters.")}) class Meta: - model = Source + model = AttributeSource fields = ("name",) def save(self, commit=True): diff --git a/acs/main_views.py b/acs/main_views.py index 8704a03..cbcb289 100644 --- a/acs/main_views.py +++ b/acs/main_views.py @@ -53,7 +53,8 @@ from decorators import prevent_access_to_not_root_administrators from models import Policy -from abac.models import Source +from attribute_aggregator.models import AttributeSource + logger = logging.getLogger('acs') @@ -163,10 +164,10 @@ def index(request): 'list_users': "Modify or delete a user", 'add_abac_source': "Add a generic source of attributes", 'add_abac_ldap_source': "Add a LDAP source of attributes"} - sources = Source.objects.all() + sources = AttributeSource.objects.all() if sources: list_power_services['Generic user management']\ - ['list_abac_sources'] = 'Modify a source of attributes' + ['list_abac_sources'] = 'Modify or delete a source of attributes' if policies or sources: list_user_mgmt_services['list_users_for_aliases'] = \ 'Manage user aliases or \ diff --git a/acs/models.py b/acs/models.py index c9fa4a7..840bc2e 100644 --- a/acs/models.py +++ b/acs/models.py @@ -17,6 +17,7 @@ along with this program. If not, see . ''' + from django.db import models from django.contrib.auth.models import User from django.utils.translation import ugettext as _ @@ -26,6 +27,7 @@ from django.contrib.contenttypes import generic from abac.models import AbacRule + class Namespace(models.Model): '''Namespace Allow objects of same name @@ -174,9 +176,12 @@ class View(models.Model): class AcsPermission(models.Model): - content_type_who = models.ForeignKey(ContentType, related_name = "who_rbac") - content_type_what = models.ForeignKey(ContentType, related_name = "what_rbac") - content_type_how = models.ForeignKey(ContentType, related_name = "how_rbac") + content_type_who = models.ForeignKey(ContentType, + related_name = "who_rbac") + content_type_what = models.ForeignKey(ContentType, + related_name = "what_rbac") + content_type_how = models.ForeignKey(ContentType, + related_name = "how_rbac") object_id_who = models.PositiveIntegerField() object_id_what = models.PositiveIntegerField() object_id_how = models.PositiveIntegerField() @@ -189,8 +194,8 @@ class AcsPermission(models.Model): ''' If set it means that the permission is obtained by delegation ''' - permission_source = models.ForeignKey('AcsPermission', blank=True, null=True, - related_name = 'source_permission') + permission_source = models.ForeignKey('AcsPermission', + blank=True, null=True, related_name = 'source_permission') ''' Means that a permission can be delegated Also that a permission delegated can be delegated @@ -260,9 +265,10 @@ class AcsAbacPermission(models.Model): Who is only a User When a request is treated: - If who is a role. If there is a matching RBAC rule, the decision is True. - If there is an ABAC rule set on anybody with a unique predicate role on - that role, the decission is True. + If who is a role. If there is a matching RBAC rule, the decision is + True. + If there is an ABAC rule set on anybody with a unique predicate role + on that role, the decission is True. Else a new rule is returned made of permissions set on anybody. Axiom: @@ -276,9 +282,12 @@ class AcsAbacPermission(models.Model): Should depreciate AcsPermission and RBAC only processing. ''' - who = models.ForeignKey(UserAlias, 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") + who = models.ForeignKey(UserAlias, 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_what = models.PositiveIntegerField() object_id_how = models.PositiveIntegerField() what = generic.GenericForeignKey(ct_field='content_type_what', @@ -311,7 +320,6 @@ class AcsAbacPermission(models.Model): def save(self, *args, **kwargs): p = None - t_who = None 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''' diff --git a/acs/templates/add_abac_permission.html b/acs/templates/add_abac_permission.html index 670886a..7609689 100644 --- a/acs/templates/add_abac_permission.html +++ b/acs/templates/add_abac_permission.html @@ -71,9 +71,9 @@

{% trans "Choose an attribute definition:" %} - {% for attr_definition in attribute_definitions %} - + {% endfor %}

@@ -182,12 +182,12 @@ {% if working_predicate.operand1_defined.type == "definition" %} {% trans " from" %}( {% for s_id, s_name in working_predicate.operand1_defined.sources_selected %} - {{ s_name }}, + {{ s_name }}, {% endfor %})

{% else %} {% trans "of values" %}( {% for value in working_predicate.operand1_defined.values_selected %} - {{ value }}, + {{ value }}, {% endfor %})

{% endif %} {% endif %} @@ -197,12 +197,12 @@

{% trans "Operand two is attribute" %} {{ working_predicate.operand2_defined.definition_name }} {% trans " from" %}( {% for s_id, s_name in working_predicate.operand2_defined.sources_selected %} - {{ s_name }}, + {{ s_name }}, {% endfor %})

{% else %}

{% trans "Compared with values" %}( {% for value in working_predicate.operand2_defined.values_selected %} - {{ value }}, + {{ value }}, {% endfor %})

{% endif %} {% endif %} @@ -231,9 +231,9 @@

{% trans "Choose an attribute as operand two of the comparison:" %} {% endif %} - {% for attr_definition in attribute_definitions %} - + {% endfor %} @@ -369,7 +369,7 @@ {% if predicate.singlevalued %}{% trans "The attribute must be single-valued." %}{% endif %} {% trans "It is expected from" %}( {% for s_id, s_name in predicate.sources_selected %} - {{ s_name }}, + {{ s_name }}, {% endfor %}) {% else %} @@ -403,24 +403,24 @@ {% if predicate.operand1_defined.type == "definition" %} {% trans " from" %}( {% for s_id, s_name in predicate.operand1_defined.sources_selected %} - {{ s_name }}, + {{ s_name }}, {% endfor %})

{% else %} {% trans "of values" %}( {% for value in predicate.operand1_defined.values_selected %} - {{ value }}, + {{ value }}, {% endfor %})

{% endif %} {% if predicate.operand2_defined.type == "definition" %}

{% trans "Operand two is attribute" %} {{ predicate.operand2_defined.definition_name }} {% trans " from" %}( {% for s_id, s_name in predicate.operand2_defined.sources_selected %} - {{ s_name }}, + {{ s_name }}, {% endfor %})

{% else %}

{% trans "Compared with values" %}( {% for value in predicate.operand2_defined.values_selected %} - {{ value }}, + {{ value }}, {% endfor %})

{% endif %} {% endif %} @@ -529,7 +529,7 @@

{% endblock %} diff --git a/acs/templates/list_aliases_and_add.html b/acs/templates/list_aliases_and_add.html index f28e1d7..8ff4447 100644 --- a/acs/templates/list_aliases_and_add.html +++ b/acs/templates/list_aliases_and_add.html @@ -67,22 +67,22 @@ {% if aliases_sources %}

{% trans "Manage aliases in sources" %}