[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:
parent
8b5d3ece1e
commit
b1a1825c1d
314
acs/abac/core.py
314
acs/abac/core.py
|
@ -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
|
||||
|
||||
|
||||
|
|
Reference in New Issue