[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:
Mikaël Ates 2011-09-02 18:40:06 +02:00
parent 62c722654b
commit bda42675e0
1 changed files with 904 additions and 4 deletions

View File

@ -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')