[core] Mainly, a core function for decisions based on ABAC permissions.
1- A core function for decisions based on ABAC permissions. 2- Core functions to add and modify policy objects checking administration rights A core function for decisions based on ABAC permissions ------------------------------------------------------- * Preface 1- Reminder on aliases Requester is the user accessing ACS. The username is equal to the alias in default. Who is the subject of the request, it is described by the alias in a policy. Requester == who means that default_alias(requester) == default_alias(who) 2- difference between ABAC and RBAC permissions An RBAC permission set with who is a role means that at the evaluation, the access is granted if who is that role, a subject (a user or a role) has that role (directly or by hierarchy) With an ABAC rule, a request with a role as subject can never be granted, but can only serve to obtain a new rule with that role has subject or other permissions with roles as who included in that role Note that an ABAC rule with who that is a role is strictly equivalent to a rule on anybody with in the ABAC rule a PredicateRole at the root with a AND statement with the rest of the logical expression. Then an ABAC permission set with who is a role is not a way to authorize a role (only possible with classic RABC rules) but a way to indicate that they are candidate permissions for users that have that role. In fact it is not very useful to ask if a role may have an access. It does not make to say "does the role/function can access what/how?". The right way to ask the question is "User lambda that eventually I don't but who has the role/function X can access what/how?". Then with ABAC rule we do not handle when the request is about a role. It explains why we have removed the possibility to set an ABAC rule on a role as who. - When who is None/Anybody and the rule is only a predicate of having a role, it is a classic RBAC permission. - Idem with a rule on attributes, a classic ABAC rule. - We can mix both. It is a way to give a logical expression on roles. - Who is a user and no rule, classic IBAC rule. - Who is a user and a rule, this user can have an access if the rule is satisfied * Requester != who Requester != None Who != None A requester different from who request the policy to know if who can do how on what. The requester must be authorized in that policy for administration on who, what and how. RBAC permissions are checked. Then ABAC permissions are checked. Attributes can be retreived from different sources. who has a default alias that is the username that is mapped with the user identifiers wihtin the different identity repositories (sources) configured. A signal is send to make external functions provide attributes. This is the preferred way the attributes should be provided from sources. An option allows to say to not send this signal no_attribute_signal = True, at False by default. Attributes can also be given in parameters of the functions. A validity period may be provided per attribute or per source. When it is the case, these attributes are cached to be reused in other session. These are stored is a special source called cached_attributes. This function always tries to load attributes from this source. Attributes are provided with dictionnaries as follows: data = [] attr = {} attr['name'] = 'certificate_type' attr['namespace'] = 'ACS-ABAC' attr['values'] = ('eID',) data.append(attr) attr = {} attr['name'] = \ 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth' attr['namespace'] = \ 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims' attr['values'] = ('22', ) data.append(attr) dic = {} dic[source_name] = data *All attributes are loaded in an object profile used for the evaluation.* If the access is granted, the function return un tuple containing 'True', the permission that allowed the positive answer and error code at 0. If the access is denied, the function return un tuple containing 'False', the ABAC rule necessary to grant the access and error code at 0. Obtaining a new ABAC rule can only be done with ABAC permissions. The rule returned can be build from any ABAC permission that is on what to do how. The process of building a new rule is ressource consuming, this process can be desactivated with the option no_rule_returned = True, at False by default. 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. * Requester != who Requester == None Who != None Unauthorized access to request the policy on somebody is not authorized. This request is rejected with an error code * Requester != who Requester != None Who == None This is supported to only to make a requester authorized for administration on what and how to obtain a rule that anybody may satisfy to do how on what. This is not compatible with no_rule_returned = True * Requester == who != None This mode means that the user is currently using an application coupled with ACS. This application and ACS share the user session. Checking administration rights does not have sense here. Except this, this functions the same way as the first case. However, attributes are also check in the session: request.session['attributes'] An option allows to say to not check attributes in the session no_session_attributes = True, at False by default. This mode also always try to load attributes from the cached_attributes source The rule returned can only contain predicates of ABAC rules set on anybody or on who or on a role that who has. Differently from when requester != who and the requester is checked for administration, new rule can not be set from any ABAC permission matching what and how. Indeed, since the administration rights are not check, the access to the policy is given on ABAC permissions that have as subject anybody, the requester or a role that the requester has. * Requester == who == None This mode means that the user is currently using an application coupled with ACS. This application and ACS share the user session. Checking administration rights does not have sense here neither. The requester/subject being 'anonymous', identity attributes can't be retreived from sources. Contextual attributes (time for instance) but it is not supported yet. Signals may be used for contextual attributes. Attributes in parameters and in the session can be used. Example of scenario: - The user is redirected on an IdP proxy with an access request from a SP. - The user is not able to authenticate against the proxy. - The proxy asks the policy in that mode with no attributes, a new rule from permissions set on anybody are returned. - The attributes can only come from external sources and be brought by the user, i.e. certificates. - The proxy make the user provide certificates to from the ABAC rule. - Then the proxy parse the certificates and builds a dictionnary. The proxy may also try to authenticate the user from certificates. if yes, previously provided certificates may be loaded from cached_attributes. - Either the dictionnary is put in the session, or given in parameter of this function. - The policy is requested. - If the access is not granted, a new rule is returned. - If the access is granted, before responding to the SP, the proxy may create an account giving authentication credentials to the user or using one of the certificates as an authentication credential. - Then the proxy associates the living-more-than-a-session certified attributes to this profile. The proxy is in charge to add by itself add attributes in the cached_attributes source. - Next time, the user will be able to authenticate and benefit from the cached_attributes source
This commit is contained in:
parent
62c722654b
commit
bda42675e0
908
acs/core.py
908
acs/core.py
|
@ -28,6 +28,9 @@ from django.db import transaction
|
|||
|
||||
from models import UserAlias, Role, AcsObject, View, Action, Activity, \
|
||||
Namespace, AcsPermission, AcsAbacPermission, Policy
|
||||
from signals import attributes_call
|
||||
|
||||
from abac.models import *
|
||||
|
||||
logger = logging.getLogger('acs')
|
||||
|
||||
|
@ -163,8 +166,8 @@ def isAuthorizedRBAC1(who, what, how):
|
|||
return None
|
||||
|
||||
'''Limit the number of activities to check'''
|
||||
limit = 0
|
||||
if not settings.ACTIVITY_GRAPH_LIMIT:
|
||||
limit = 0
|
||||
logger.warning('isAuthorizedRBAC1: Not Limit to research')
|
||||
else:
|
||||
limit = settings.ACTIVITY_GRAPH_LIMIT
|
||||
|
@ -233,8 +236,8 @@ def isAuthorizedRBAC2(who, what, how):
|
|||
return None
|
||||
|
||||
'''Limit the number of views to check'''
|
||||
limit = 0
|
||||
if not settings.VIEW_GRAPH_LIMIT:
|
||||
limit = 0
|
||||
logger.warning('isAuthorizedRBAC2: Not Limit to research')
|
||||
else:
|
||||
limit = settings.VIEW_GRAPH_LIMIT
|
||||
|
@ -255,7 +258,7 @@ def isAuthorizedRBAC2(who, what, how):
|
|||
|
||||
tmp = []
|
||||
for view in v:
|
||||
# Append the list of roles already checked
|
||||
# Append the list of views already checked
|
||||
control.append(view)
|
||||
for it in View.objects.filter(views__id=view.id):
|
||||
if it not in control:
|
||||
|
@ -266,6 +269,607 @@ def isAuthorizedRBAC2(who, what, how):
|
|||
return None
|
||||
|
||||
|
||||
'''
|
||||
RBAC and ABAC policies requesting.
|
||||
|
||||
* Output
|
||||
|
||||
The function returns a tuple (decision, rule/permission, error code)
|
||||
- decision is a boolean
|
||||
- rule/permission is new rule computed when decision is False, else it is
|
||||
the persmission that permitted that the decision be True
|
||||
- See error codes below
|
||||
|
||||
* @parameters
|
||||
|
||||
By default @who is a User instance, @what is an Object instance and @how
|
||||
is an Action instance.
|
||||
Deprecated (cf bellow): Use @role=True if @who is a Role instance
|
||||
Use @view=True if @what is a View instance
|
||||
Use @activity=True if @how is a Activity instance
|
||||
|
||||
@who, @what and @how are the name attribute of instances
|
||||
|
||||
@namespace is the name of a namespace instance
|
||||
|
||||
@no_rule_returned is False by default. The process of building a new
|
||||
rule is ressource consuming. This process can be desactivated with
|
||||
option no_rule_returned = True
|
||||
|
||||
@no_attribute_signal is False by default. Use to not send the signal to
|
||||
obtain attributes.
|
||||
|
||||
* Error codes:
|
||||
0 : No error
|
||||
-1 : requester must be provided to request the policy on somebody
|
||||
-2 : what not found
|
||||
-3 : how not found
|
||||
-4 : namespace not found
|
||||
-5 : error processing request
|
||||
-6 : requester not found
|
||||
-7 : requester not authorized on who
|
||||
-8 : requester not authorized on what
|
||||
-9 : requester not authorized on how
|
||||
|
||||
* Preface
|
||||
|
||||
1- Reminder on aliases
|
||||
|
||||
Requester is the user accessing ACS. The username is equal to the alias in
|
||||
default.
|
||||
|
||||
Who is the subject of the request, it is described by the alias in a
|
||||
policy.
|
||||
|
||||
Requester == who means that default_alias(requester) == default_alias(who)
|
||||
|
||||
2- difference between ABAC and RBAC permissions
|
||||
|
||||
An RBAC permission set with who is a role means that at the evaluation,
|
||||
the access is granted if who is that role, a subject (a user or a role)
|
||||
has that role (directly or by hierarchy)
|
||||
|
||||
With an ABAC rule, a request with a role as subject can never be granted,
|
||||
but can only serve to obtain a new rule with that role has subject or
|
||||
other permissions with roles as who included in that role
|
||||
Note that an ABAC rule with who that is a role is strictly equivalent to
|
||||
a rule on anybody with in the ABAC rule a PredicateRole at the root with
|
||||
a AND statement with the rest of the logical expression.
|
||||
Then an ABAC permission set with who is a role is not a way to authorize a
|
||||
role (only possible with classic RABC rules) but a way to indicate that
|
||||
they are candidate permissions for users that have that role.
|
||||
|
||||
In fact it is not very useful to ask if a role may have an access.
|
||||
It does not make to say "does the role/function can access what/how?".
|
||||
The right way to ask the question is "User lambda that eventually I don't
|
||||
but who has the role/function X can access what/how?".
|
||||
Then with ABAC rule we do not handle when the request is about a role.
|
||||
It explains why we have removed the possibility to set an ABAC rule on a
|
||||
role as who.
|
||||
|
||||
- When who is None/Anybody and the rule is only a predicate of having a
|
||||
role, it is a classic RBAC permission.
|
||||
- Idem with a rule on attributes, a classic ABAC rule.
|
||||
- We can mix both. It is a way to give a logical expression on roles.
|
||||
- Who is a user and no rule, classic IBAC rule.
|
||||
- Who is a user and a rule, this user can have an access if the rule is
|
||||
satisfied
|
||||
|
||||
* Requester != who
|
||||
Requester != None
|
||||
Who != None
|
||||
|
||||
A requester different from who request the policy to know if who can do
|
||||
how on what.
|
||||
|
||||
The requester must be authorized in that policy for administration on who,
|
||||
what and how.
|
||||
|
||||
RBAC permissions are checked. Then ABAC permissions are checked.
|
||||
|
||||
Attributes can be retreived from different sources. who has a default
|
||||
alias that is the username that is mapped with the user identifiers wihtin
|
||||
the different identity repositories (sources) configured.
|
||||
|
||||
A signal is send to make external functions provide attributes.
|
||||
This is the preferred way the attributes should be provided from sources.
|
||||
An option allows to say to not send this signal
|
||||
no_attribute_signal = True, at False by default.
|
||||
|
||||
Attributes can also be given in parameters of the functions.
|
||||
|
||||
A validity period may be provided per attribute or per source. When it is
|
||||
the case, these attributes are cached to be reused in other session.
|
||||
These are stored is a special source called cached_attributes.
|
||||
This function always tries to load attributes from this source.
|
||||
|
||||
Attributes are provided with dictionnaries as follows:
|
||||
|
||||
data = []
|
||||
|
||||
attr = {}
|
||||
attr['name'] = 'certificate_type'
|
||||
attr['namespace'] = 'ACS-ABAC'
|
||||
attr['values'] = ('eID',)
|
||||
|
||||
data.append(attr)
|
||||
|
||||
attr = {}
|
||||
attr['name'] = \
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth'
|
||||
attr['namespace'] = \
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims'
|
||||
attr['values'] = ('22', )
|
||||
|
||||
data.append(attr)
|
||||
|
||||
dic = {}
|
||||
dic[source_name] = data
|
||||
|
||||
*All attributes are loaded in an object profile used for the evaluation.*
|
||||
|
||||
If the access is granted, the function return un tuple containing 'True',
|
||||
the permission that allowed the positive answer and error code at 0.
|
||||
If the access is denied, the function return un tuple containing 'False',
|
||||
the ABAC rule necessary to grant the access and error code at 0.
|
||||
|
||||
Obtaining a new ABAC rule can only be done with ABAC permissions.
|
||||
|
||||
The rule returned can be build from any ABAC permission that is on what to
|
||||
do how.
|
||||
|
||||
The process of building a new rule is ressource consuming, this process
|
||||
can be desactivated with the option no_rule_returned = True, at False by
|
||||
default.
|
||||
|
||||
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.
|
||||
|
||||
* Requester != who
|
||||
Requester == None
|
||||
Who != None
|
||||
|
||||
Unauthorized access to request the policy on somebody is not authorized.
|
||||
This request is rejected with an error code
|
||||
|
||||
* Requester != who
|
||||
Requester != None
|
||||
Who == None
|
||||
|
||||
This is supported to only to make a requester authorized for
|
||||
administration on what and how to obtain a rule that anybody may satisfy
|
||||
to do how on what.
|
||||
|
||||
This is not compatible with no_rule_returned = True
|
||||
|
||||
* Requester == who != None
|
||||
|
||||
This mode means that the user is currently using an application coupled
|
||||
with ACS. This application and ACS share the user session.
|
||||
|
||||
Checking administration rights does not have sense here.
|
||||
|
||||
Except this, this functions the same way as the first case.
|
||||
|
||||
However, attributes are also check in the session:
|
||||
request.session['attributes']
|
||||
|
||||
An option allows to say to not check attributes in the session
|
||||
no_session_attributes = True, at False by default.
|
||||
|
||||
This mode also always try to load attributes from the cached_attributes
|
||||
source
|
||||
|
||||
The rule returned can only contain predicates of ABAC rules set on
|
||||
anybody or on who or on a role that who has.
|
||||
Differently from when requester != who and the requester is checked for
|
||||
administration, new rule can not be set from any ABAC permission matching
|
||||
what and how. Indeed, since the administration rights are not check, the
|
||||
access to the policy is given on ABAC permissions that have as subject
|
||||
anybody, the requester or a role that the requester has.
|
||||
|
||||
* Requester == who == None
|
||||
|
||||
This mode means that the user is currently using an application coupled
|
||||
with ACS. This application and ACS share the user session.
|
||||
|
||||
Checking administration rights does not have sense here neither.
|
||||
|
||||
The requester/subject being 'anonymous', identity attributes can't be
|
||||
retreived from sources.
|
||||
Contextual attributes (time for instance) but it is not supported yet.
|
||||
|
||||
Signals may be used for contextual attributes.
|
||||
Attributes in parameters and in the session can be used.
|
||||
|
||||
Example of scenario:
|
||||
- The user is redirected on an IdP proxy with an access request from a SP.
|
||||
- The user is not able to authenticate against the proxy.
|
||||
- The proxy asks the policy in that mode with no attributes, a new rule from
|
||||
permissions set on anybody are returned.
|
||||
- The attributes can only come from external sources and be brought by
|
||||
the user, i.e. certificates.
|
||||
- The proxy make the user provide certificates to from the ABAC rule.
|
||||
- Then the proxy parse the certificates and builds a dictionnary. The proxy
|
||||
may also try to authenticate the user from certificates. if yes,
|
||||
previously provided certificates may be loaded from cached_attributes.
|
||||
- Either the dictionnary is put in the session, or given in parameter of
|
||||
this function.
|
||||
- The policy is requested.
|
||||
- If the access is not granted, a new rule is returned.
|
||||
- If the access is granted, before responding to the SP, the proxy may
|
||||
create an account giving authentication credentials to the user or using
|
||||
one of the certificates as an authentication credential.
|
||||
- Then the proxy associates the living-more-than-a-session certified
|
||||
attributes to this profile. The proxy is in charge to add by itself add
|
||||
attributes in the cached_attributes source.
|
||||
- Next time, the user will be able to authenticate and benefit from the
|
||||
cached_attributes source
|
||||
'''
|
||||
|
||||
def is_authorized_by_names_with_abac(requestor_name, who_name, what_name,
|
||||
how_name, namespace_name,
|
||||
view=False, activity=False, request=None, attributes={},
|
||||
no_rule_returned=False,
|
||||
no_attribute_signal=False):
|
||||
'''
|
||||
Check for an RBAC permission
|
||||
'''
|
||||
|
||||
if not what_name or not how_name or not namespace_name:
|
||||
logger.error('is_authorized_by_names_with_abac: \
|
||||
a parameters is missing')
|
||||
return (False, None, -1)
|
||||
|
||||
ns = None
|
||||
try:
|
||||
ns = Namespace.objects.get(name=namespace_name)
|
||||
except ObjectDoesNotExist:
|
||||
logger.error('is_authorized_by_names_with_abac: \
|
||||
unable to find the namespace object')
|
||||
return (False, None, -4)
|
||||
except MultipleObjectsReturned:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Multiple namespaces with name %s' %namespace_name)
|
||||
return (False, None, -5)
|
||||
except Exception, err:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Namespace %s - Error due to %s' % (namespace_name, err))
|
||||
return (False, None, -5)
|
||||
policy = get_policy_from_namespace(ns)
|
||||
if not policy:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Not policy found for %s' % ns)
|
||||
return (False, None, -5)
|
||||
|
||||
|
||||
what = None
|
||||
if view:
|
||||
try:
|
||||
what = View.objects.get(name=what_name, namespace=ns)
|
||||
except ObjectDoesNotExist:
|
||||
logger.error('is_authorized_by_names_with_abac: \
|
||||
unable to find the view object')
|
||||
return (False, None, -2)
|
||||
except MultipleObjectsReturned:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Multiple views with name %s' %what_name)
|
||||
return (False, None, -5)
|
||||
except Exception, err:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
View %s - Error due to %s' % (what_name, err))
|
||||
return (False, None, -5)
|
||||
else:
|
||||
try:
|
||||
what = AcsObject.objects.get(name=what_name, namespace=ns)
|
||||
except ObjectDoesNotExist:
|
||||
logger.error('is_authorized_by_names_with_abac: \
|
||||
unable to find the object object')
|
||||
return (False, None, -2)
|
||||
except MultipleObjectsReturned:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Multiple objects with name %s' %what_name)
|
||||
return (False, None, -5)
|
||||
except Exception, err:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
UserAlias %s - Error due to %s' % (what_name, err))
|
||||
return (False, None, -5)
|
||||
how = None
|
||||
if activity:
|
||||
try:
|
||||
how = Activity.objects.get(name=how_name, namespace=ns)
|
||||
except ObjectDoesNotExist:
|
||||
logger.error('is_authorized_by_names_with_abac: \
|
||||
unable to find the activity object')
|
||||
return (False, None, -3)
|
||||
except MultipleObjectsReturned:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Multiple activities with name %s' %how_name)
|
||||
return (False, None, -5)
|
||||
except Exception, err:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Activity %s - Error due to %s' % (how_name, err))
|
||||
return (False, None, -5)
|
||||
else:
|
||||
try:
|
||||
how = Action.objects.get(name=how_name, namespace=ns)
|
||||
except ObjectDoesNotExist:
|
||||
logger.error('is_authorized_by_names_with_abac: \
|
||||
unable to find the action object')
|
||||
return (False, None, -3)
|
||||
except MultipleObjectsReturned:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Multiple actions with name %s' %how_name)
|
||||
return (False, None, -5)
|
||||
except Exception, err:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Action %s - Error due to %s' % (how_name, err))
|
||||
return (False, None, -5)
|
||||
|
||||
requestor = None
|
||||
if requestor_name:
|
||||
try:
|
||||
requestor = User.objects.get(username=requestor_name)
|
||||
if not set_default_alias(requestor):
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
unable to handle default alias of %s' % requestor)
|
||||
return (False, None, -6)
|
||||
except ObjectDoesNotExist:
|
||||
logger.error('is_authorized_by_names_with_abac: \
|
||||
the requestor with name %s does not exists' % requestor_name)
|
||||
return (False, None, -6)
|
||||
except MultipleObjectsReturned:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Multiple user with name %s' % requestor_name)
|
||||
return (False, None, -5)
|
||||
except Exception, err:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
User %s - Error due to %s' % (requestor_name, err))
|
||||
return (False, None, -5)
|
||||
|
||||
who = None
|
||||
if who_name:
|
||||
who = None
|
||||
try:
|
||||
who = UserAlias.objects.get(alias=who_name, namespace=ns)
|
||||
except ObjectDoesNotExist:
|
||||
logger.error('is_authorized_by_names_with_abac: \
|
||||
the user with name %s does not exists' % who_name)
|
||||
return (False, None, -7)
|
||||
except MultipleObjectsReturned:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
Multiple users with name %s' %who)
|
||||
return (False, None, -5)
|
||||
except Exception, err:
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
UserAlias %s - Error due to %s' % (who, err))
|
||||
return (False, None, -5)
|
||||
|
||||
if not requestor and who:
|
||||
logger.error('is_authorized_by_names_with_abac: \
|
||||
requestor is unknwon and who %s is provided' % who)
|
||||
return (False, None, -8)
|
||||
|
||||
'''
|
||||
The requester is different from who that means that the requester must
|
||||
be authorized on the parameters of its request
|
||||
'''
|
||||
if requestor and (not who or who.user != requestor):
|
||||
logger.debug("The requester %s is different from who %s that means that the requester must \
|
||||
be authorized on the parameters of its request" % (requestor, who.user))
|
||||
administration = Action.objects.get(name='administration')
|
||||
p = isAuthorizedRBAC2(set_default_alias(requestor), what, administration)
|
||||
if not is_policy_object_creator(requestor, policy) and not p:
|
||||
logger.debug('is_authorized_by_names_with_abac: %s is not authorized on %s' \
|
||||
% (requestor, what))
|
||||
return (False, None, -9)
|
||||
p = isAuthorizedRBAC2(set_default_alias(requestor), how, administration)
|
||||
if not is_policy_action_creator(requestor, policy) and not p:
|
||||
logger.debug('is_authorized_by_names_with_abac: %s is not authorized on %s' \
|
||||
% (requestor, how))
|
||||
return (False, None, -10)
|
||||
if who:
|
||||
p = isAuthorizedRBAC2(set_default_alias(requestor), who, administration)
|
||||
if not is_policy_user_administrator(requestor, policy) and not p:
|
||||
logger.debug('is_authorized_by_names_with_abac: %s is not authorized on %s' \
|
||||
% (requestor, who))
|
||||
return (False, None, -11)
|
||||
|
||||
|
||||
'''
|
||||
Attribute loading in profile object
|
||||
'''
|
||||
|
||||
if not who.user:
|
||||
# We should remove the possibility to have a UserAlias not pointing to a
|
||||
# user
|
||||
logger.critical('is_authorized_by_names_with_abac: \
|
||||
No user associated with that alias %s' % who)
|
||||
return (False, None, -12)
|
||||
profile = UserAttributeProfile(user=who.user)
|
||||
profile.save()
|
||||
|
||||
from abac.core import load_profile_by_dic
|
||||
|
||||
if attributes:
|
||||
load_profile_by_dic(profile, attributes)
|
||||
|
||||
'''
|
||||
Requester is who, that means that the user is logged on
|
||||
the application.
|
||||
Requester is also who if both are None, the user is anonymous.
|
||||
We look for attributes in the session.
|
||||
'''
|
||||
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'])
|
||||
|
||||
if who and not no_attribute_signal:
|
||||
attributes_provided = attributes_call.send(sender=None,
|
||||
request=request, user=who)
|
||||
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])
|
||||
|
||||
logger.debug('is_authorized_by_names_with_abac: The profile contains')
|
||||
ads = AssertionData.objects.filter(profile=profile)
|
||||
for ad in ads:
|
||||
attribute_data = ad.attribute_data
|
||||
logger.debug("From %s, definition %s" % (ad.source, attribute_data.definition.id))
|
||||
if attribute_data.definition.attribute_type == ACS_XACML_DATATYPE_STRING:
|
||||
values = StringM.objects.filter(data=attribute_data)
|
||||
logger.debug("with values %s" % str([x.value for x in values]))
|
||||
elif attribute_data.definition.attribute_type == ACS_XACML_DATATYPE_INTEGER:
|
||||
values = IntegerM.objects.filter(data=attribute_data)
|
||||
logger.debug("with values %s" % str([x.value for x in values]))
|
||||
|
||||
'''
|
||||
All the permissions with and view or an activity containing the what
|
||||
and how
|
||||
'''
|
||||
what_list = []
|
||||
if isinstance(what, AcsObject):
|
||||
views = View.objects.filter(acs_objects__id=what.id)
|
||||
for view in views:
|
||||
if view.namespace == ns:
|
||||
what_list.append(view)
|
||||
elif isinstance(what, View):
|
||||
if what.namespace == ns:
|
||||
what_list.append(what)
|
||||
elif isinstance(what, UserAlias):
|
||||
views = View.objects.filter(users__id=what.id)
|
||||
for view in views:
|
||||
if view.namespace == ns:
|
||||
what_list.append(view)
|
||||
elif isinstance(what, Role):
|
||||
views = View.objects.filter(roles__id=what.id)
|
||||
for view in views:
|
||||
if view.namespace == ns:
|
||||
what_list.append(view)
|
||||
elif isinstance(what, Action):
|
||||
views = View.objects.filter(actions__id=what.id)
|
||||
for view in views:
|
||||
if view.namespace == ns:
|
||||
what_list.append(view)
|
||||
elif isinstance(what, Activity):
|
||||
views = View.objects.filter(activities__id=what.id)
|
||||
for view in views:
|
||||
if view.namespace == ns:
|
||||
what_list.append(view)
|
||||
|
||||
'''Limit the number of views to check'''
|
||||
limit = 0
|
||||
if not settings.VIEW_GRAPH_LIMIT:
|
||||
logger.warning('is_authorized_by_names_with_abac: Not Limit to research')
|
||||
else:
|
||||
limit = settings.VIEW_GRAPH_LIMIT
|
||||
#logger.info('is_authorized_by_names_with_abac: Limit is at %s' %limit)
|
||||
i = 0
|
||||
while i < len(what_list) and (limit == 0 or i < limit):
|
||||
for it in View.objects.filter(views__id=what_list[i].id):
|
||||
if it not in what_list and it.namespace == ns:
|
||||
what_list.append(it)
|
||||
i = i + 1
|
||||
what_list.append(what)
|
||||
|
||||
how_list = []
|
||||
if isinstance(how, Action):
|
||||
activities = Activity.objects.filter(actions__id=how.id)
|
||||
for activity in activities:
|
||||
if activity.namespace == ns:
|
||||
how_list.append(activity)
|
||||
elif isinstance(how, Activity):
|
||||
activities = Activity.objects.filter(activities__id=how.id)
|
||||
for activity in activities:
|
||||
if activity.namespace == ns:
|
||||
how_list.append(activity)
|
||||
|
||||
'''Limit the number of activities to check'''
|
||||
limit = 0
|
||||
if not settings.ACTIVITY_GRAPH_LIMIT:
|
||||
logger.warning('is_authorized_by_names_with_abac: Not Limit to research')
|
||||
else:
|
||||
limit = settings.ACTIVITY_GRAPH_LIMIT
|
||||
#logger.info('is_authorized_by_names_with_abac: Limit is at %s' %limit)
|
||||
i = 0
|
||||
while i < len(how_list) and (limit == 0 or i < limit):
|
||||
for it in Activity.objects.filter(activities__id=how_list[i].id):
|
||||
if it not in how_list:
|
||||
how_list.append(it)
|
||||
i = i + 1
|
||||
how_list.append(how)
|
||||
|
||||
permissions = []
|
||||
for what in what_list:
|
||||
for how in how_list:
|
||||
t_what = ContentType.objects.get_for_model(what)
|
||||
t_how = ContentType.objects.get_for_model(how)
|
||||
'''Permissions for anybody'''
|
||||
permissions = permissions + list(AcsAbacPermission.objects.filter(who=None,
|
||||
content_type_what__pk=t_what.id,
|
||||
object_id_what=what.id,
|
||||
content_type_how__pk=t_how.id,
|
||||
object_id_how=how.id))
|
||||
'''Permissions specific for a user'''
|
||||
if who:
|
||||
permissions = permissions + list(AcsAbacPermission.objects.filter(who=who,
|
||||
content_type_what__pk=t_what.id,
|
||||
object_id_what=what.id,
|
||||
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)
|
||||
|
||||
logger.debug('is_authorized_by_names_with_abac: permissions %s' % str([str(x) for x in permissions]))
|
||||
|
||||
from abac.core import check_predicates, \
|
||||
make_new_rule_from_missing_predicates
|
||||
from acs.abac.logic import evaluation, return_sorted_variables_to_truth
|
||||
|
||||
new_rule = ''
|
||||
dic_of_new_rules = []
|
||||
for permission in permissions:
|
||||
if not getattr(permission, 'rule', None) or permission.rule == '':
|
||||
logger.debug('is_authorized_by_names_with_abac: The permission %s has no rule - access granted!' % permission)
|
||||
return (True, permission, 0)
|
||||
logger.debug('is_authorized_by_names_with_abac: permission %s' % permission)
|
||||
l = check_predicates(permission.rule, profile)
|
||||
logger.debug('is_authorized_by_names_with_abac: result on %s is %s' % (permission.rule.expression, l))
|
||||
res = evaluation(permission.rule.expression, l)
|
||||
if res:
|
||||
return (True, permission, 0)
|
||||
elif not no_rule_returned:
|
||||
logger.debug('is_authorized_by_names_with_abac: permission not successful')
|
||||
missing_p = return_sorted_variables_to_truth(permission.rule.expression, l)
|
||||
logger.debug('is_authorized_by_names_with_abac: missing predicates %s' % missing_p)
|
||||
r = make_new_rule_from_missing_predicates(missing_p)
|
||||
if new_rule != '':
|
||||
if not r in dic_of_new_rules:
|
||||
new_rule += '|' + r
|
||||
else:
|
||||
new_rule = r
|
||||
dic_of_new_rules.append(r)
|
||||
logger.debug('is_authorized_by_names_with_abac: access denied')
|
||||
|
||||
profile.delete()
|
||||
|
||||
if new_rule != '':
|
||||
logger.debug('is_authorized_by_names_with_abac: new rule %s' % new_rule)
|
||||
return (False, new_rule, 0)
|
||||
else:
|
||||
return (False, None, 0)
|
||||
|
||||
|
||||
def is_authorized_by_names(requester, who, what, how, namespace,
|
||||
role=False, view=False, activity=False):
|
||||
'''
|
||||
|
@ -1933,9 +2537,14 @@ def mod_role(requester, target_role, policy,
|
|||
logger.error('mod_role: Missing argument')
|
||||
return -1
|
||||
if is_authorized_on_alias_or_role(requester, target_role, policy):
|
||||
logger.error('mod_role: requester not authorized')
|
||||
logger.error('mod_role: requester not authorized on role %s' \
|
||||
% target_role)
|
||||
return -2
|
||||
for user in users_removed:
|
||||
if is_authorized_on_alias_or_role(requester, user, policy):
|
||||
logger.error('mod_role: requester not authorized on user %s' \
|
||||
% user)
|
||||
return -2
|
||||
try:
|
||||
target_role.users.remove(user)
|
||||
except Exception, err:
|
||||
|
@ -1943,6 +2552,10 @@ def mod_role(requester, target_role, policy,
|
|||
% (user, target_role, err))
|
||||
return -3
|
||||
for user in users_added:
|
||||
if is_authorized_on_alias_or_role(requester, user, policy):
|
||||
logger.error('mod_role: requester not authorized on user %s' \
|
||||
% user)
|
||||
return -2
|
||||
try:
|
||||
target_role.users.add(user)
|
||||
except Exception, err:
|
||||
|
@ -1950,6 +2563,10 @@ def mod_role(requester, target_role, policy,
|
|||
% (user, target_role, err))
|
||||
return -4
|
||||
for role in roles_removed:
|
||||
if is_authorized_on_alias_or_role(requester, role, policy):
|
||||
logger.error('mod_role: requester not authorized on role %s' \
|
||||
% role)
|
||||
return -2
|
||||
try:
|
||||
target_role.roles.remove(role)
|
||||
except Exception, err:
|
||||
|
@ -1957,6 +2574,10 @@ def mod_role(requester, target_role, policy,
|
|||
% (role, target_role, err))
|
||||
return -5
|
||||
for role in roles_added:
|
||||
if is_authorized_on_alias_or_role(requester, role, policy):
|
||||
logger.error('mod_role: requester not authorized on role %s' \
|
||||
% role)
|
||||
return -2
|
||||
try:
|
||||
target_role.roles.add(role)
|
||||
except Exception, err:
|
||||
|
@ -2026,6 +2647,197 @@ def add_object(requester, name, policy, regex=None):
|
|||
return -4
|
||||
|
||||
|
||||
def add_view(requester, name, policy):
|
||||
if not requester or not name or not policy:
|
||||
logger.error('add_view: Missing argument')
|
||||
return -1
|
||||
if not is_policy_object_creator(requester, policy):
|
||||
logger.error('add_view: requester not authorized')
|
||||
return -2
|
||||
try:
|
||||
o = None
|
||||
created = None
|
||||
o, created = View.objects.get_or_create(name=name,
|
||||
namespace=policy.namespace)
|
||||
try:
|
||||
policy.admin_view.views.add(o)
|
||||
if not created:
|
||||
logger.error('add_view: existing view %s' % o)
|
||||
return o
|
||||
logger.debug('add_view: view %s created' % o)
|
||||
return o
|
||||
except Exception, err:
|
||||
logger.error('add_view: error adding view in policy admin \
|
||||
view due to %s' % err)
|
||||
return -3
|
||||
except Exception, err:
|
||||
logger.error('add_view: error getting or creating view \
|
||||
due to %s' % err)
|
||||
return -4
|
||||
|
||||
|
||||
def mod_view(requester, target_view, policy,
|
||||
users_added=[], users_removed=[],
|
||||
roles_added=[], roles_removed=[],
|
||||
objects_added=[], objects_removed=[],
|
||||
views_added=[], views_removed=[],
|
||||
actions_added=[], actions_removed=[],
|
||||
activities_added=[], activities_removed=[]):
|
||||
if not requester or not target_view:
|
||||
logger.error('mod_view: Missing argument')
|
||||
return -1
|
||||
if is_authorized_on_object_or_view(requester, target_view, policy):
|
||||
logger.error('mod_view: requester not authorized on view %s' \
|
||||
% target_view)
|
||||
return -2
|
||||
|
||||
'''
|
||||
If not admin view, only objects and views
|
||||
'''
|
||||
if target_view in policy.admin_views.all() \
|
||||
and (users_added or users_removed or roles_added \
|
||||
or roles_removed or actions_added or actions_removed \
|
||||
or activities_added or activities_removed):
|
||||
logger.error('mod_view: you cannot add users, roles, actions or \
|
||||
activities to normal views')
|
||||
return -15
|
||||
|
||||
for user in users_removed:
|
||||
if is_authorized_on_alias_or_role(requester, user, policy):
|
||||
logger.error('mod_role: requester not authorized on user %s' \
|
||||
% user)
|
||||
return -2
|
||||
try:
|
||||
target_view.users.remove(user)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to remove %s of %s due to %s' \
|
||||
% (user, target_view, err))
|
||||
return -3
|
||||
for user in users_added:
|
||||
if is_authorized_on_alias_or_role(requester, user, policy):
|
||||
logger.error('mod_role: requester not authorized on user %s' \
|
||||
% user)
|
||||
return -2
|
||||
try:
|
||||
target_view.users.add(user)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to add %s of %s due to %s' \
|
||||
% (user, target_view, err))
|
||||
return -4
|
||||
for role in roles_removed:
|
||||
if is_authorized_on_alias_or_role(requester, role, policy):
|
||||
logger.error('mod_role: requester not authorized on role %s' \
|
||||
% role)
|
||||
return -2
|
||||
try:
|
||||
target_view.roles.remove(role)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to remove %s of %s due to %s' \
|
||||
% (role, target_view, err))
|
||||
return -5
|
||||
for role in roles_added:
|
||||
if is_authorized_on_alias_or_role(requester, role, policy):
|
||||
logger.error('mod_role: requester not authorized on role %s' \
|
||||
% role)
|
||||
return -2
|
||||
try:
|
||||
target_view.roles.add(role)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to add %s of %s due to %s' \
|
||||
% (role, target_view, err))
|
||||
return -6
|
||||
for o in objects_removed:
|
||||
if is_authorized_on_object_or_view(requester, o, policy):
|
||||
logger.error('mod_role: requester not authorized on object %s' \
|
||||
% o)
|
||||
return -2
|
||||
try:
|
||||
target_view.acs_objects.remove(o)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to remove %s of %s due to %s' \
|
||||
% (o, target_view, err))
|
||||
return -7
|
||||
for o in objects_added:
|
||||
if is_authorized_on_object_or_view(requester, o, policy):
|
||||
logger.error('mod_role: requester not authorized on object %s' \
|
||||
% o)
|
||||
return -2
|
||||
try:
|
||||
target_view.acs_objects.add(o)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to add %s of %s due to %s' \
|
||||
% (o, target_view, err))
|
||||
return -8
|
||||
for view in views_removed:
|
||||
if is_authorized_on_object_or_view(requester, view, policy):
|
||||
logger.error('mod_view: requester not authorized on view %s' \
|
||||
% view)
|
||||
return -2
|
||||
try:
|
||||
target_view.views.remove(view)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to remove %s of %s due to %s' \
|
||||
% (view, target_view, err))
|
||||
return -9
|
||||
for view in views_added:
|
||||
if is_authorized_on_object_or_view(requester, view, policy):
|
||||
logger.error('mod_view: requester not authorized on view %s' \
|
||||
% view)
|
||||
return -2
|
||||
try:
|
||||
target_view.views.add(view)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to add %s of %s due to %s' \
|
||||
% (view, target_view, err))
|
||||
return -10
|
||||
for action in actions_removed:
|
||||
if is_authorized_on_action_or_activity(requester, action, policy):
|
||||
logger.error('mod_view: requester not authorized on action %s' \
|
||||
% action)
|
||||
return -2
|
||||
try:
|
||||
target_view.actions.remove(action)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to remove %s of %s due to %s' \
|
||||
% (action, target_view, err))
|
||||
return -11
|
||||
for action in actions_added:
|
||||
if is_authorized_on_action_or_activity(requester, action, policy):
|
||||
logger.error('mod_view: requester not authorized on action %s' \
|
||||
% action)
|
||||
return -2
|
||||
try:
|
||||
target_view.actions.add(action)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to add %s of %s due to %s' \
|
||||
% (action, target_view, err))
|
||||
return -12
|
||||
for activity in activities_removed:
|
||||
if is_authorized_on_action_or_activity(requester, activity, policy):
|
||||
logger.error('mod_view: requester not authorized on activity %s' \
|
||||
% activity)
|
||||
return -2
|
||||
try:
|
||||
target_view.activities.remove(activity)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to remove %s of %s due to %s' \
|
||||
% (activity, target_view, err))
|
||||
return -13
|
||||
for activity in activities_added:
|
||||
if is_authorized_on_action_or_activity(requester, activity, policy):
|
||||
logger.error('mod_view: requester not authorized on activity %s' \
|
||||
% activity)
|
||||
return -2
|
||||
try:
|
||||
target_view.activities.add(activity)
|
||||
except Exception, err:
|
||||
logger.critical('mod_view: unable to add %s of %s due to %s' \
|
||||
% (activity, target_view, err))
|
||||
return -14
|
||||
logger.debug('mod_view: view %s successfully modified' % target_view)
|
||||
return 0
|
||||
|
||||
|
||||
def is_authorized_on_object_or_view(requester, item, policy):
|
||||
if not requester or not item or not policy:
|
||||
logger.error('is_authorized_on_object_or_view: Missing argument')
|
||||
|
@ -2077,6 +2889,94 @@ def add_action(requester, name, policy):
|
|||
return -4
|
||||
|
||||
|
||||
def add_activity(requester, name, policy):
|
||||
if not requester or not name or not policy:
|
||||
logger.error('add_activity: Missing argument')
|
||||
return -1
|
||||
if not is_policy_action_creator(requester, policy):
|
||||
logger.error('add_activity: requester not authorized')
|
||||
return -2
|
||||
try:
|
||||
o = None
|
||||
created = None
|
||||
o, created = Activity.objects.get_or_create(name=name,
|
||||
namespace=policy.namespace)
|
||||
try:
|
||||
policy.admin_view.activities.add(o)
|
||||
if not created:
|
||||
logger.error('add_activity: existing activity %s' % o)
|
||||
return o
|
||||
logger.debug('add_activity: activity %s created' % o)
|
||||
return o
|
||||
except Exception, err:
|
||||
logger.error('add_activity: error adding activity in policy admin \
|
||||
view due to %s' % err)
|
||||
return -3
|
||||
except Exception, err:
|
||||
logger.error('add_activity: error getting or creating activity \
|
||||
due to %s' % err)
|
||||
return -4
|
||||
|
||||
|
||||
def mod_activity(requester, target_activity, policy,
|
||||
actions_added=[], actions_removed=[],
|
||||
activities_added=[], activities_removed=[]):
|
||||
if not requester or not target_activity:
|
||||
logger.error('mod_activity: Missing argument')
|
||||
return -1
|
||||
if is_authorized_on_action_or_activity(requester, target_activity, policy):
|
||||
logger.error('mod_activity: requester not authorized on activity %s' \
|
||||
% target_activity)
|
||||
return -2
|
||||
|
||||
for action in actions_removed:
|
||||
if is_authorized_on_action_or_activity(requester, action, policy):
|
||||
logger.error('mod_activity: requester not authorized on action %s' \
|
||||
% action)
|
||||
return -2
|
||||
try:
|
||||
target_activity.actions.remove(action)
|
||||
except Exception, err:
|
||||
logger.critical('mod_activity: unable to remove %s of %s due to %s' \
|
||||
% (action, target_activity, err))
|
||||
return -11
|
||||
for action in actions_added:
|
||||
if is_authorized_on_action_or_activity(requester, action, policy):
|
||||
logger.error('mod_activity: requester not authorized on action %s' \
|
||||
% action)
|
||||
return -2
|
||||
try:
|
||||
target_activity.actions.add(action)
|
||||
except Exception, err:
|
||||
logger.critical('mod_activity: unable to add %s of %s due to %s' \
|
||||
% (action, target_activity, err))
|
||||
return -12
|
||||
for activity in activities_removed:
|
||||
if is_authorized_on_action_or_activity(requester, activity, policy):
|
||||
logger.error('mod_activity: requester not authorized on activity %s' \
|
||||
% activity)
|
||||
return -2
|
||||
try:
|
||||
target_activity.activities.remove(activity)
|
||||
except Exception, err:
|
||||
logger.critical('mod_activity: unable to remove %s of %s due to %s' \
|
||||
% (activity, target_activity, err))
|
||||
return -13
|
||||
for activity in activities_added:
|
||||
if is_authorized_on_action_or_activity(requester, activity, policy):
|
||||
logger.error('mod_activity: requester not authorized on activity %s' \
|
||||
% activity)
|
||||
return -2
|
||||
try:
|
||||
target_activity.activities.add(activity)
|
||||
except Exception, err:
|
||||
logger.critical('mod_activity: unable to add %s of %s due to %s' \
|
||||
% (activity, target_activity, err))
|
||||
return -14
|
||||
logger.debug('mod_activity: activity %s successfully modified' % target_activity)
|
||||
return 0
|
||||
|
||||
|
||||
def is_authorized_on_action_or_activity(requester, item, policy):
|
||||
if not requester or not item or not policy:
|
||||
logger.error('is_authorized_on_action_or_activity: Missing argument')
|
||||
|
|
Reference in New Issue