[abac] Modify core functions to handle more precise multi-valued attributes

The following options for dealing with multivalued attributes in comparison are now supported:

        All:
            NO_MULTIVALUES
                Both operand are single valued attributes

        Equality:
            EQUAL_ONE_VALUE
                At least one value of the values of OP1 is equal to one value of the values of OP2
            EQUAL_OP1_SUBSET_OP2
                The values of OP1 is is a subset of the values of OP2
            EQUAL_EXACT_MATCH
                Equal set of values

        Diff strict:
            DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2
                ACS_XACML_COMPARISON_INTEGER_LT
                    All values of OP1 must be less than the highest value of OP2
                ACS_XACML_COMPARISON_INTEGER_GRT
                    All values of OP1 must be greater than the highest value of OP2
            DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2
                ACS_XACML_COMPARISON_INTEGER_LT
                    All values of OP1 must be less than the smallest value of OP2
                ACS_XACML_COMPARISON_INTEGER_GRT
                    All values of OP1 must be greater than the smallest value of OP2
            DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2
                ACS_XACML_COMPARISON_INTEGER_LT
                    At least one value of OP1 must be less than the highest value of OP2
                ACS_XACML_COMPARISON_INTEGER_GRT
                    At least one value of OP1 must be greater than the highest value of OP2
            DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2
                ACS_XACML_COMPARISON_INTEGER_LT
                    At least one value of OP1 must be less than the smallest value of OP2
                ACS_XACML_COMPARISON_INTEGER_GRT
                    At least one value of OP1 must be greater than the smallest value of OP2

        Diff or equal:
            Same as for strict and equality is treated as follows:
            DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2
                ACS_XACML_COMPARISON_INTEGER_LT_OE
                    All values of OP1 must be less than or equal to the highest value of OP2
                ACS_XACML_COMPARISON_INTEGER_GRT_OE
                    All values of OP1 must be greater than or equal to the highest value of OP2
            DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2
                ACS_XACML_COMPARISON_INTEGER_LT_OE
                    All values of OP1 must be less than or equal to the smallest value of OP2
                ACS_XACML_COMPARISON_INTEGER_GRT_OE
                    All values of OP1 must be greater than or equal to the smallest value of OP2
            DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2
                ACS_XACML_COMPARISON_INTEGER_LT_OE
                    At least one value of OP1 must be less than or equal to the highest value of OP2
                ACS_XACML_COMPARISON_INTEGER_GRT_OE
                    At least one value of OP1 must be greater than or equal to the highest value of OP2
            DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2
                ACS_XACML_COMPARISON_INTEGER_LT_OE
                    At least one value of OP1 must be less than or equal to the smallest value of OP2
                ACS_XACML_COMPARISON_INTEGER_GRT_OE
                    At least one value of OP1 must be greater than or equal to the smallest value of OP2

        To deal with richer comparison and equality of multivalued attributes, a 'or' statement should be used
This commit is contained in:
Mikaël Ates 2011-08-23 17:05:14 +02:00
parent 8b5d3ece1e
commit b1a1825c1d
1 changed files with 237 additions and 77 deletions

View File

@ -113,17 +113,68 @@ def check_predicate_comparison(predicate, profile):
'''
A predicate contains an option indicating if an attribute must be single valued.
Since considered has an enforcement, a check includes the test that attribute has a single value if required,
else that a multivalue option not NO_MULTIVALUES must be set.
All:
NO_MULTIVALUES,
NO_MULTIVALUES
Both operand are single valued attributes
Equality:
EQUAL_ONE_VALUE, EQUAL_OP1_SUBSET_OP2,
EQUAL_EXACT_MATCH,
EQUAL_ONE_VALUE
At least one value of the values of OP1 is equal to one value of the values of OP2
EQUAL_OP1_SUBSET_OP2
The values of OP1 is is a subset of the values of OP2
EQUAL_EXACT_MATCH
Equal set of values
Diff strict:
DIFF_ONE_VALUE, DIFF_ALL_VALUES,
DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2
ACS_XACML_COMPARISON_INTEGER_LT
All values of OP1 must be less than the highest value of OP2
ACS_XACML_COMPARISON_INTEGER_GRT
All values of OP1 must be greater than the highest value of OP2
DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2
ACS_XACML_COMPARISON_INTEGER_LT
All values of OP1 must be less than the smallest value of OP2
ACS_XACML_COMPARISON_INTEGER_GRT
All values of OP1 must be greater than the smallest value of OP2
DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2
ACS_XACML_COMPARISON_INTEGER_LT
At least one value of OP1 must be less than the highest value of OP2
ACS_XACML_COMPARISON_INTEGER_GRT
At least one value of OP1 must be greater than the highest value of OP2
DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2
ACS_XACML_COMPARISON_INTEGER_LT
At least one value of OP1 must be less than the smallest value of OP2
ACS_XACML_COMPARISON_INTEGER_GRT
At least one value of OP1 must be greater than the smallest value of OP2
Diff or equal:
DE_ONE_VALUE_ONE_VALUE, DE_ONE_VALUE_OP1_SUBSET_OP2,
DE_ONE_VALUE_EXACT_MATCH, DE_ALL_VALUES_ONE_VALUE,
DE_ALL_VALUES_OP1_SUBSET_OP2, DE_ALL_VALUES_EXACT_MATCH
Same as for strict and equality is treated as follows:
DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2
ACS_XACML_COMPARISON_INTEGER_LT_OE
All values of OP1 must be less than or equal to the highest value of OP2
ACS_XACML_COMPARISON_INTEGER_GRT_OE
All values of OP1 must be greater than or equal to the highest value of OP2
DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2
ACS_XACML_COMPARISON_INTEGER_LT_OE
All values of OP1 must be less than or equal to the smallest value of OP2
ACS_XACML_COMPARISON_INTEGER_GRT_OE
All values of OP1 must be greater than or equal to the smallest value of OP2
DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2
ACS_XACML_COMPARISON_INTEGER_LT_OE
At least one value of OP1 must be less than or equal to the highest value of OP2
ACS_XACML_COMPARISON_INTEGER_GRT_OE
At least one value of OP1 must be greater than or equal to the highest value of OP2
DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2
ACS_XACML_COMPARISON_INTEGER_LT_OE
At least one value of OP1 must be less than or equal to the smallest value of OP2
ACS_XACML_COMPARISON_INTEGER_GRT_OE
At least one value of OP1 must be greater than or equal to the smallest value of OP2
To deal with richer comparison and equality of multivalued attributes, a 'or' statement should be used
'''
@ -159,91 +210,171 @@ def compare_two_data(predicate, data1, data2):
data2_values = IpAddressM.objects.filter(data=data2)
if not data1_values or not data2_values:
logger.debug("compare_two_data: \
Return False because no values was found for predicate %s" \
% predicate)
return False
if predicate.operand1_single_value and len(data1_values) > 1:
logger.debug("compare_two_data: \
Return False because a single value is required for operand one \
and multiple were found %s for predicate %s" \
% ([x.value for x in data1_values], predicate))
return False
if predicate.operand2_single_value and len(data2_values) > 1:
logger.debug("compare_two_data: \
Return False because a single value is required for operand two \
and multiple were found %s for predicate %s" \
% ([x.value for x in data2_values], predicate))
return False
if not(predicate.operand1_single_value \
and predicate.operand2_single_value) \
and ((predicate.comparison_type in XACML_COMPARISON_EQUALITY \
and not predicate.multivalues in \
('EQUAL_ONE_VALUE',
'EQUAL_OP1_SUBSET_OP2',
'EQUAL_EXACT_MATCH')) \
or (predicate.comparison_type in ACS_XACML_COMPARISON \
and not predicate.multivalues in \
('DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2',
'DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2',
'DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2',
'DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2'))):
logger.debug("compare_two_data: \
Return False because multivalued attributes are accepted and no \
suitable management option has been selected for predicate %s" \
% str(predicate))
return False
logger.debug("compare_two_data: \
Evaluation of predicate %s" \
% str(predicate))
if predicate.comparison_type in XACML_COMPARISON_EQUALITY:
return test_equality_of_values(data1_values, data2_values,
data1.definition.attribute_type,
predicate.comparison_type,
predicate.multivalues)
elif predicate.comparison_type in ACS_XACML_COMPARISON:
return test_diff_of_values(data1_values, data2_values,
return test_diff_of_multivalues(data1_values, data2_values,
data1.definition.attribute_type,
predicate.comparison_type,
predicate.multivalues)
return False
def test_diff_of_values(data1_values, data2_values, data_type, comparison_type,
test_type='NO_MULTIVALUES'):
if test_type == 'NO_MULTIVALUES':
if test_diff_two_values(data1_values[0], data2_values[0], comparison_type):
return True
elif comparison_type in ACS_XACML_COMPARISON_GRT \
or comparison_type in ACS_XACML_COMPARISON_LT:
if test_diff_of_multivalues(data1_values, data2_values, data_type, comparison_type,
test_type):
return True
elif comparison_type in ACS_XACML_COMPARISON_GRT_OE \
or comparison_type in ACS_XACML_COMPARISON_LT_OE:
if test_type == 'DE_ONE_VALUE_ONE_VALUE':
if test_diff_of_multivalues(data1_values, data2_values, data_type, comparison_type,
test_type='DIFF_ONE_VALUE'):
return True
elif test_equality_of_values(data1_values, data2_values, data_type, comparison_type,
test_type='EQUAL_ONE_VALUE'):
return True
elif test_type == 'DE_ONE_VALUE_OP1_SUBSET_OP2':
if test_diff_of_multivalues(data1_values, data2_values, data_type, comparison_type,
test_type='DIFF_ONE_VALUE'):
return True
elif test_equality_of_values(data1_values, data2_values, data_type, comparison_type,
test_type='EQUAL_OP1_SUBSET_OP2'):
return True
elif test_type == 'DE_ONE_VALUE_EXACT_MATCH':
if test_diff_of_multivalues(data1_values, data2_values, data_type, comparison_type,
test_type='DIFF_ONE_VALUE'):
return True
elif test_equality_of_values(data1_values, data2_values, data_type, comparison_type,
test_type='EQUAL_EXACT_MATCH'):
return True
elif test_type == 'DE_ALL_VALUES_ONE_VALUE':
if test_diff_of_multivalues(data1_values, data2_values, data_type, comparison_type,
test_type='DIFF_ALL_VALUES'):
return True
elif test_equality_of_values(data1_values, data2_values, data_type, comparison_type,
test_type='EQUAL_ONE_VALUE'):
return True
elif test_type == 'DE_ALL_VALUES_OP1_SUBSET_OP2':
if test_diff_of_multivalues(data1_values, data2_values, data_type, comparison_type,
test_type='DIFF_ALL_VALUES'):
return True
elif test_equality_of_values(data1_values, data2_values, data_type, comparison_type,
test_type='EQUAL_OP1_SUBSET_OP2'):
return True
elif test_type == 'DE_ALL_VALUES_EXACT_MATCH':
if test_diff_of_multivalues(data1_values, data2_values, data_type, comparison_type,
test_type='DIFF_ALL_VALUES'):
return True
elif test_equality_of_values(data1_values, data2_values, data_type, comparison_type,
test_type='EQUAL_EXACT_MATCH'):
return True
logger.debug("compare_two_data: \
Return False because of unknown comparison type \
for predicate %s" \
% predicate)
return False
def test_diff_of_multivalues(data1_values, data2_values, data_type, comparison_type,
test_type='NO_MULTIVALUES'):
if test_type == 'DIFF_ONE_VALUE':
if test_type == 'NO_MULTIVALUES':
logger.debug("test_diff_of_multivalues: \
No multivalues, test %s and %s" \
% (data1_values[0].value, data2_values[0].value))
if test_diff_two_values(data1_values[0].value, data2_values[0].value, comparison_type):
logger.debug("test_diff_of_multivalues: True")
return True
else:
logger.debug("test_diff_of_multivalues: False")
return False
# BOTTOM LIMIT with LT and UPPER LIMIT with GTR
# OP1a <= OP1b <= OP2a <= OP2b
# OP1b >= OP1a >= OP2b >= OP2a
# With ALL and LT, no value of OP1 must be superior to the bottom limit of OP2
# With ALL and GRT, no value of OP1 must be less than the upper limit of OP2
elif (test_type == 'DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2' \
and comparison_type in ACS_XACML_COMPARISON_LT + \
ACS_XACML_COMPARISON_LT_OE) \
or (test_type == 'DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2' \
and comparison_type in ACS_XACML_COMPARISON_GRT + \
ACS_XACML_COMPARISON_GRT_OE):
for v1 in data1_values:
for v2 in data2_values:
if not test_diff_two_values(v1.value, v2.value, comparison_type):
logger.debug("test_diff_of_multivalues: \
DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2 (LT) or \
DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2 (GRT) - \
predicate not satisfied")
return False
return True
# UPPER LIMIT with LT and BOTTOM LIMIT with GTR
# OP2a <= OP1a <= OP1b <= OP2b
# OP2b >= OP1b >= OP2a >= OP2a
# With ALL and LT, no value of OP1 must be superior to the upper limit of OP2
# With ALL and GRT, no value of OP1 must be less than the bottom limit of OP2
elif (test_type == 'DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2' \
and comparison_type in ACS_XACML_COMPARISON_GRT + \
ACS_XACML_COMPARISON_GRT_OE) \
or (test_type == 'DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2' \
and comparison_type in ACS_XACML_COMPARISON_LT + \
ACS_XACML_COMPARISON_LT_OE):
for v2 in data2_values:
found = True
for v1 in data1_values:
if not test_diff_two_values(v1.value, v2.value, comparison_type):
found = False
if found:
return True
logger.debug("test_diff_of_multivalues: \
DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2 (GRT) or \
DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2 (LT) - \
predicate not satisfied")
return False
# BOTTOM LIMIT with LT and UPPER LIMIT with GTR
# OP1a <= OP2a <= OP1b <= OP2b
# OP1b >= OP2b >= OP2a >= OP2a
# With ONE and LT, some values of OP1 may be superior to the bottom limit of OP2
# With ONE and GRT, some values of OP1 must be less than the upper limit of OP2
elif (test_type == 'DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2' \
and comparison_type in ACS_XACML_COMPARISON_LT + \
ACS_XACML_COMPARISON_LT_OE) \
or (test_type == 'DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2' \
and comparison_type in ACS_XACML_COMPARISON_GRT + \
ACS_XACML_COMPARISON_GRT_OE):
for v1 in data1_values:
found = True
for v2 in data2_values:
if not test_diff_two_values(v1.value, v2.value, comparison_type):
found = False
if found:
return True
logger.debug("test_diff_of_multivalues: \
DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2 (LT) or \
DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2 (GRT) - \
predicate not satisfied")
return False
# UPPER LIMIT with LT and BOTTOM LIMIT with GTR
# OP1a <= OP2a <= OP1b <= OP2b
# OP1b >= OP2b >= OP2a >= OP2a
# With ONE and LT, some values of OP1 may be superior to the upper limit of OP2
# With ONE and GRT, some values of OP1 must be less than the bottom limit of OP2
elif (test_type == 'DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2' \
and comparison_type in ACS_XACML_COMPARISON_LT + \
ACS_XACML_COMPARISON_LT_OE) \
or (test_type == 'DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2' \
and comparison_type in ACS_XACML_COMPARISON_GRT + \
ACS_XACML_COMPARISON_GRT_OE):
for v1 in data1_values:
for v2 in data2_values:
if test_diff_two_values(v1.value, v2.value, comparison_type):
return True
elif test_type == 'DIFF_ALL_VALUES':
for v1 in data1_values:
for v2 in data2_values:
if not test_diff_two_values(v1.value, v2.value, comparison_type):
return False
return True
logger.debug("test_diff_of_multivalues: \
DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2 (GRT) or \
DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2 (LT) - \
predicate not satisfied")
return False
logger.debug("test_diff_of_multivalues: \
Unknown multivalue option, \
predicate not satisfied")
return False
@ -320,15 +451,44 @@ def check_predicate_required(predicate, profile):
'''
Look in profile all attributedata with that attribute type
Then check the source and return True on the first acceptable source
A single value attribute is checked per sources
Declaring multiple source is a OR between sources.
So the single-valued is checked per source.
If it is expected to check a unique value with multiple sources
it is required to use multiple required predicates and NOT operators
'''
logger.debug("check_predicate_any: beginning...")
logger.debug("check_predicate_required: check %s" % predicate)
definition = predicate.definition.attribute_definition
sources = AttachedSource.objects.filter(assertion=predicate.definition)
for source in sources:
ads = AssertionData.objects.filter(profile=profile, source=source.source)
for ad in ads:
if ad.attribute_data.definition.id == definition.id:
return True
if not predicate.single_value:
logger.debug("check_predicate_required: single value not required")
for source in sources:
ads = AssertionData.objects.filter(profile=profile, source=source.source)
for ad in ads:
if ad.attribute_data.definition.id == definition.id:
logger.debug("check_predicate_required: satisfied")
return True
else:
logger.debug("check_predicate_required: single value required")
found = False
for source in sources:
ads = AssertionData.objects.filter(profile=profile, source=source.source)
c = 0
for ad in ads:
if ad.attribute_data.definition.id == definition.id:
c = c + 1
if c > 1:
logger.debug("check_predicate_required: multiple values found \
- not satisfied")
return False
elif c == 1:
found = True
if found:
return True
logger.debug("check_predicate_required: At least one source with a \
unique value found")
return False