def authenticate(self, request, auth): """Try to authenticate using an already existing token. :param request: A request object. :param auth: Dictionary representing the authentication request. :returns: A tuple containing the user reference, project identifier, token expiration, bind information, and original audit information. """ if 'token' not in auth: raise exception.ValidationError(attribute='token', target='auth') if 'id' not in auth['token']: raise exception.ValidationError(attribute='id', target='token') old_token = auth['token']['id'] if len(old_token) > CONF.max_token_size: raise exception.ValidationSizeError(attribute='token', size=CONF.max_token_size) try: v3_token_data = self.token_provider_api.validate_token(old_token) # NOTE(lbragstad): Even though we are not using the v2.0 token # reference after we translate it in v3_to_v2_token(), we still # need to perform that check. We have to do this because # v3_to_v2_token will ensure we don't use specific tokens only # attainable via v3 to get new tokens on v2.0. For example, an # exception would be raised if we passed a federated token to # v3_to_v2_token, because federated tokens aren't supported by # v2.0 (the same applies to OAuth tokens, domain-scoped tokens, # etc..). v2_helper = V2TokenDataHelper() v2_helper.v3_to_v2_token(v3_token_data, old_token) token_model_ref = token_model.KeystoneToken( token_id=old_token, token_data=v3_token_data) except exception.NotFound as e: raise exception.Unauthorized(e) wsgi.validate_token_bind(request.context_dict, token_model_ref) self._restrict_scope(token_model_ref) user_id = token_model_ref.user_id project_id = self._get_project_id_from_auth(auth) if not CONF.trust.enabled and 'trust_id' in auth: raise exception.Forbidden('Trusts are disabled.') elif CONF.trust.enabled and 'trust_id' in auth: try: trust_ref = self.trust_api.get_trust(auth['trust_id']) except exception.TrustNotFound: raise exception.Forbidden() # If a trust is being used to obtain access to another project and # the other project doesn't match the project in the trust, we need # to bail because trusts are only good up to a single project. if (trust_ref['project_id'] and project_id != trust_ref['project_id']): raise exception.Forbidden() expiry = token_model_ref.expires user_ref = self.identity_api.get_user(user_id) bind = token_model_ref.bind original_audit_id = token_model_ref.audit_chain_id return (user_ref, project_id, expiry, bind, original_audit_id)
def _authenticate_token(self, context, auth): """Try to authenticate using an already existing token. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ if 'token' not in auth: raise exception.ValidationError(attribute='token', target='auth') if "id" not in auth['token']: raise exception.ValidationError(attribute="id", target="token") old_token = auth['token']['id'] if len(old_token) > CONF.max_token_size: raise exception.ValidationSizeError(attribute='token', size=CONF.max_token_size) try: token_model_ref = token_model.KeystoneToken( token_id=old_token, token_data=self.token_provider_api.validate_token(old_token)) except exception.NotFound as e: raise exception.Unauthorized(e) wsgi.validate_token_bind(context, token_model_ref) self._restrict_scope(token_model_ref) user_id = token_model_ref.user_id tenant_id = self._get_project_id_from_auth(auth) if not CONF.trust.enabled and 'trust_id' in auth: raise exception.Forbidden('Trusts are disabled.') elif CONF.trust.enabled and 'trust_id' in auth: try: trust_ref = self.trust_api.get_trust(auth['trust_id']) except exception.TrustNotFound: raise exception.Forbidden() if user_id != trust_ref['trustee_user_id']: raise exception.Forbidden() if (trust_ref['project_id'] and tenant_id != trust_ref['project_id']): raise exception.Forbidden() if ('expires' in trust_ref) and (trust_ref['expires']): expiry = trust_ref['expires'] if expiry < timeutils.parse_isotime(timeutils.isotime()): raise exception.Forbidden() user_id = trust_ref['trustor_user_id'] trustor_user_ref = self.identity_api.get_user( trust_ref['trustor_user_id']) if not trustor_user_ref['enabled']: raise exception.Forbidden() trustee_user_ref = self.identity_api.get_user( trust_ref['trustee_user_id']) if not trustee_user_ref['enabled']: raise exception.Forbidden() if trust_ref['impersonation'] is True: current_user_ref = trustor_user_ref else: current_user_ref = trustee_user_ref else: current_user_ref = self.identity_api.get_user(user_id) metadata_ref = {} tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref( user_id, tenant_id) expiry = token_model_ref.expires if CONF.trust.enabled and 'trust_id' in auth: trust_id = auth['trust_id'] trust_roles = [] for role in trust_ref['roles']: if 'roles' not in metadata_ref: raise exception.Forbidden() if role['id'] in metadata_ref['roles']: trust_roles.append(role['id']) else: raise exception.Forbidden() if 'expiry' in trust_ref and trust_ref['expiry']: trust_expiry = timeutils.parse_isotime(trust_ref['expiry']) if trust_expiry < expiry: expiry = trust_expiry metadata_ref['roles'] = trust_roles metadata_ref['trustee_user_id'] = trust_ref['trustee_user_id'] metadata_ref['trust_id'] = trust_id bind = token_model_ref.bind audit_id = token_model_ref.audit_chain_id return (current_user_ref, tenant_ref, metadata_ref, expiry, bind, audit_id)
def _populate_roles(self, token_data, user_id, system, domain_id, project_id, trust, access_token): if 'roles' in token_data: # no need to repopulate roles return if access_token: filtered_roles = [] access_token_ref = PROVIDERS.oauth_api.get_access_token( access_token['id'] ) authed_role_ids = jsonutils.loads(access_token_ref['role_ids']) all_roles = PROVIDERS.role_api.list_roles() for role in all_roles: for authed_role in authed_role_ids: if authed_role == role['id']: filtered_roles.append({'id': role['id'], 'name': role['name']}) token_data['roles'] = filtered_roles return if CONF.trust.enabled and trust: # If redelegated_trust_id is set, then we must traverse the # trust_chain in order to determine who the original trustor is. We # need to do this because the user ID of the original trustor helps # us determine scope in the redelegated context. if trust.get('redelegated_trust_id'): trust_chain = PROVIDERS.trust_api.get_trust_pedigree( trust['id'] ) token_user_id = trust_chain[-1]['trustor_user_id'] else: token_user_id = trust['trustor_user_id'] token_project_id = trust['project_id'] # trusts do not support domains yet token_domain_id = None else: token_user_id = user_id token_project_id = project_id token_domain_id = domain_id if system or token_domain_id or token_project_id: filtered_roles = [] if CONF.trust.enabled and trust: # First expand out any roles that were in the trust to include # any implied roles, whether global or domain specific refs = [{'role_id': role['id']} for role in trust['roles']] effective_trust_roles = ( PROVIDERS.assignment_api.add_implied_roles(refs)) # Now get the current role assignments for the trustor, # including any domain specific roles. assignments = PROVIDERS.assignment_api.list_role_assignments( user_id=token_user_id, system=system, project_id=token_project_id, effective=True, strip_domain_roles=False) current_effective_trustor_roles = ( list(set([x['role_id'] for x in assignments]))) # Go through each of the effective trust roles, making sure the # trustor still has them, if any have been removed, then we # will treat the trust as invalid for trust_role in effective_trust_roles: match_roles = [x for x in current_effective_trustor_roles if x == trust_role['role_id']] if match_roles: role = PROVIDERS.role_api.get_role(match_roles[0]) if role['domain_id'] is None: filtered_roles.append(role) else: raise exception.Forbidden( _('Trustee has no delegated roles.')) else: for role in self._get_roles_for_user(token_user_id, system, token_domain_id, token_project_id): filtered_roles.append({'id': role['id'], 'name': role['name']}) # user has no project or domain roles, therefore access denied if not filtered_roles: if token_project_id: msg = _('User %(user_id)s has no access ' 'to project %(project_id)s') % { 'user_id': user_id, 'project_id': token_project_id} elif token_domain_id: msg = _('User %(user_id)s has no access ' 'to domain %(domain_id)s') % { 'user_id': user_id, 'domain_id': token_domain_id} elif system: msg = _('User %(user_id)s has no access ' 'to the system') % {'user_id': user_id} LOG.debug(msg) raise exception.Unauthorized(msg) token_data['roles'] = filtered_roles
def _admin_trustor_trustee_only(context, trust, user_id): if (user_id != trust.get('trustor_user_id') and user_id != trust.get('trustor_user_id') and context['is_admin']): raise exception.Forbidden()
def assert_enabled_identity_provider(federation_api, idp_id): identity_provider = federation_api.get_idp(idp_id) if identity_provider.get('enabled') is not True: msg = _('Identity Provider %(idp)s is disabled') % {'idp': idp_id} LOG.debug(msg) raise exception.Forbidden(msg)
def delete_domain(self, domain_id): self._validate_default_domain_id(domain_id) raise exception.Forbidden(_('Domains are read-only against LDAP'))
def _authenticate_token(self, context, auth): """Try to authenticate using an already existing token. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ if 'token' not in auth: raise exception.ValidationError( attribute='token', target='auth') if "id" not in auth['token']: raise exception.ValidationError( attribute="id", target="token") old_token = auth['token']['id'] if len(old_token) > CONF.max_token_size: raise exception.ValidationSizeError(attribute='token', size=CONF.max_token_size) try: old_token_ref = self.token_api.get_token(old_token) except exception.NotFound as e: raise exception.Unauthorized(e) wsgi.validate_token_bind(context, old_token_ref) #A trust token cannot be used to get another token if 'trust' in old_token_ref: raise exception.Forbidden() if 'trust_id' in old_token_ref['metadata']: raise exception.Forbidden() user_ref = old_token_ref['user'] user_id = user_ref['id'] if not CONF.trust.enabled and 'trust_id' in auth: raise exception.Forbidden('Trusts are disabled.') elif CONF.trust.enabled and 'trust_id' in auth: trust_ref = self.trust_api.get_trust(auth['trust_id']) if trust_ref is None: raise exception.Forbidden() if user_id != trust_ref['trustee_user_id']: raise exception.Forbidden() if ('expires' in trust_ref) and (trust_ref['expires']): expiry = trust_ref['expires'] if expiry < timeutils.parse_isotime(timeutils.isotime()): raise exception.Forbidden()() user_id = trust_ref['trustor_user_id'] trustor_user_ref = self.identity_api.get_user( trust_ref['trustor_user_id']) if not trustor_user_ref['enabled']: raise exception.Forbidden()() trustee_user_ref = self.identity_api.get_user( trust_ref['trustee_user_id']) if not trustee_user_ref['enabled']: raise exception.Forbidden()() if trust_ref['impersonation'] == 'True': current_user_ref = trustor_user_ref else: current_user_ref = trustee_user_ref else: current_user_ref = self.identity_api.get_user(user_id) metadata_ref = {} tenant_id = self._get_project_id_from_auth(auth) tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref( user_id, tenant_id) expiry = old_token_ref['expires'] if CONF.trust.enabled and 'trust_id' in auth: trust_id = auth['trust_id'] trust_roles = [] for role in trust_ref['roles']: if 'roles' not in metadata_ref: raise exception.Forbidden()() if role['id'] in metadata_ref['roles']: trust_roles.append(role['id']) else: raise exception.Forbidden() if 'expiry' in trust_ref and trust_ref['expiry']: trust_expiry = timeutils.parse_isotime(trust_ref['expiry']) if trust_expiry < expiry: expiry = trust_expiry metadata_ref['roles'] = trust_roles metadata_ref['trustee_user_id'] = trust_ref['trustee_user_id'] metadata_ref['trust_id'] = trust_id bind = old_token_ref.get('bind', None) return (current_user_ref, tenant_ref, metadata_ref, expiry, bind)
def change_password(self, user_id, new_password): raise exception.Forbidden(READ_ONLY_LDAP_ERROR_MESSAGE)
def remove_user_from_group(self, user_id, group_id): raise exception.Forbidden(READ_ONLY_LDAP_ERROR_MESSAGE)
def _disallow_write(self): if not common_ldap.WRITABLE: raise exception.Forbidden(READ_ONLY_LDAP_ERROR_MESSAGE)
def delete_user(self, user_id): raise exception.Forbidden(READ_ONLY_LDAP_ERROR_MESSAGE)
def authorize_aura(credentials, target): print "***********************" print "POLICY ENFORCE" print "***** TARGET:" print target print "***** Credentials:" print credentials print "***********************" admin_unit = ['target.admin_unit'] admin_admin_unit = credentials.get('admin_unit') admin_location = credentials.get('location') print admin_location admin_admin_roles = credentials.get('admin_roles') user_admin_unit = target.get('target.admin_unit') user_location = target.get('target.location') print user_location user_user_clearance = target.get('target.user_clearance') target_role = target.get('target.role.name') with open( '/opt/stack/keystone/keystone/policy/backends/attribute_policy.json' ) as policy: policy = json.load(policy) for i in range(len(policy)): print "ADMIN ROLES" print policy[i]["role"] #for j in (policy[i]["role"]): if True == (target_role in policy[i]["role"]): print "target role is present!" print target_role #for j in (policy[i]["role"]): #if j == target_role: if (str(policy[i]["admin"]["admin_unit"]) ) == admin_admin_unit and (str( policy[i]["user"]["admin_unit"])) == user_admin_unit: print "ADMIN UNIT IS PRESENT!" print admin_admin_unit print user_admin_unit if (str(policy[i]["admin"]["location"]) ) == admin_location and (str( policy[i]["user"]["location"])) == user_location: print "LOCATION IS PRESENT" print admin_location print user_location print policy[i]["admin"]["admin_roles"] print admin_admin_roles for k in (policy[i]["admin"]["admin_roles"]): print "INSIDE ADMIN ROLES" if k == admin_admin_roles: print "ADMIN ROLES MATCH.." print policy[i]["admin"]["admin_roles"] print admin_admin_roles print "**********************************" print policy[i]["user"]["clearance"] print user_user_clearance if (str(policy[i]["user"]["clearance"]) ) == user_user_clearance: print "USER CLEARANCE MATCH" print(time.time()) print("**********") print("Authorized granted!") print("**********") return True raise exception.Forbidden("Unathorised user role assignment attempt!!")
def _assert_expired(self, ref): current_time = timeutils.normalize_time(timeutils.utcnow()) expires = ref['expires_at'] if current_time > timeutils.normalize_time(expires): raise exception.Forbidden() return ref
def set_user_password(self, context, user_id, user): token_id = context.get('token_id') original_password = user.get('original_password') token_data = self.token_provider_api.validate_token(token_id) token_ref = token_model.KeystoneToken(token_id=token_id, token_data=token_data) if token_ref.user_id != user_id: raise exception.Forbidden('Token belongs to another user') if original_password is None: raise exception.ValidationError(target='user', attribute='original password') try: user_ref = self.identity_api.authenticate( context, user_id=token_ref.user_id, password=original_password) if not user_ref.get('enabled', True): # NOTE(dolph): why can't you set a disabled user's password? raise exception.Unauthorized('User is disabled') except AssertionError: raise exception.Unauthorized() update_dict = {'password': user['password'], 'id': user_id} admin_context = copy.copy(context) admin_context['is_admin'] = True super(UserController, self).set_user_password(admin_context, user_id, update_dict) # Issue a new token based upon the original token data. This will # always be a V2.0 token. # TODO(morganfainberg): Add a mechanism to issue a new token directly # from a token model so that this code can go away. This is likely # not the norm as most cases do not need to yank apart a token to # issue a new one. new_token_ref = {} metadata_ref = {} roles_ref = None new_token_ref['user'] = user_ref if token_ref.bind: new_token_ref['bind'] = token_ref.bind if token_ref.project_id: new_token_ref['tenant'] = self.assignment_api.get_project( token_ref.project_id) if token_ref.role_names: roles_ref = [dict(name=value) for value in token_ref.role_names] if token_ref.role_ids: metadata_ref['roles'] = token_ref.role_ids if token_ref.trust_id: metadata_ref['trust'] = { 'id': token_ref.trust_id, 'trustee_user_id': token_ref.trustee_user_id} new_token_ref['metadata'] = metadata_ref new_token_ref['id'] = uuid.uuid4().hex catalog_ref = self.catalog_api.get_catalog(user_id, token_ref.project_id) new_token_id, new_token_data = self.token_provider_api.issue_v2_token( token_ref=new_token_ref, roles_ref=roles_ref, catalog_ref=catalog_ref) LOG.debug('TOKEN_REF %s', new_token_data) return new_token_data
def _trustor_trustee_only(trust, user_id): if (user_id != trust.get('trustee_user_id') and user_id != trust.get('trustor_user_id')): raise exception.Forbidden()
def delete_group(self, group_id): raise exception.Forbidden(READ_ONLY_LDAP_ERROR_MESSAGE)
def create_domain(self, domain_id, domain): if domain_id == CONF.identity.default_domain_id: msg = _('Duplicate ID, %s.') % domain_id raise exception.Conflict(type='domain', details=msg) raise exception.Forbidden(_('Domains are read-only against LDAP'))
def _authenticate_token(self, context, auth): """Try to authenticate using an already existing token. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ if 'token' not in auth: raise exception.ValidationError(attribute='token', target='auth') if "id" not in auth['token']: raise exception.ValidationError(attribute="id", target="token") old_token = auth['token']['id'] if len(old_token) > CONF.max_token_size: raise exception.ValidationSizeError(attribute='token', size=CONF.max_token_size) try: old_token_ref = self.token_api.get_token(context=context, token_id=old_token) except exception.NotFound as e: raise exception.Unauthorized(e) #A trust token cannot be used to get another token if 'trust' in old_token_ref: raise exception.Forbidden() if 'trust_id' in old_token_ref['metadata']: raise exception.Forbidden() user_ref = old_token_ref['user'] user_id = user_ref['id'] if not CONF.trust.enabled and 'trust_id' in auth: raise exception.Forbidden('Trusts are disabled.') elif CONF.trust.enabled and 'trust_id' in auth: trust_ref = self.trust_api.get_trust(context, auth['trust_id']) if trust_ref is None: raise exception.Forbidden() if user_id != trust_ref['trustee_user_id']: raise exception.Forbidden() if ('expires' in trust_ref) and (trust_ref['expires']): expiry = trust_ref['expires'] if expiry < timeutils.parse_isotime(timeutils.isotime()): raise exception.Forbidden()() user_id = trust_ref['trustor_user_id'] trustor_user_ref = (self.identity_api.get_user( context=context, user_id=trust_ref['trustor_user_id'])) if not trustor_user_ref['enabled']: raise exception.Forbidden()() trustee_user_ref = self.identity_api.get_user( context, trust_ref['trustee_user_id']) if not trustee_user_ref['enabled']: raise exception.Forbidden()() if trust_ref['impersonation'] == 'True': current_user_ref = trustor_user_ref else: current_user_ref = trustee_user_ref else: current_user_ref = self.identity_api.get_user(context=context, user_id=user_id) tenant_id = self._get_project_id_from_auth(context, auth) tenant_ref = self._get_project_ref(context, user_id, tenant_id) metadata_ref = self._get_metadata_ref(context, user_id, tenant_id) # TODO(henry-nash): If no tenant was specified, instead check for a # domain and find any related user/group roles self._append_roles( metadata_ref, self._get_group_metadata_ref(context, user_id, tenant_id)) expiry = old_token_ref['expires'] if CONF.trust.enabled and 'trust_id' in auth: trust_id = auth['trust_id'] trust_roles = [] for role in trust_ref['roles']: if not 'roles' in metadata_ref: raise exception.Forbidden()() if role['id'] in metadata_ref['roles']: trust_roles.append(role['id']) else: raise exception.Forbidden() if 'expiry' in trust_ref and trust_ref['expiry']: trust_expiry = timeutils.parse_isotime(trust_ref['expiry']) if trust_expiry < expiry: expiry = trust_expiry metadata_ref['roles'] = trust_roles metadata_ref['trustee_user_id'] = trust_ref['trustee_user_id'] metadata_ref['trust_id'] = trust_id return (current_user_ref, tenant_ref, metadata_ref, expiry)
def enforce_call(cls, enforcer=None, action=None, target_attr=None, member_target_type=None, member_target=None, filters=None): """Enforce RBAC on the current request. This will do some legwork and then instantiate the Enforcer if an enforcer is not passed in. :param enforcer: A pre-instantiated Enforcer object (optional) :type enforcer: :class:`RBACEnforcer` :param action: the name of the rule/policy enforcement to be checked against, e.g. `identity:get_user` (optional may be replaced by decorating the method/function with `policy_enforcer_action`. :type action: str :param target_attr: complete override of the target data. This will replace all other generated target data meaning `member_target_type` and `member_target` are ignored. This will also prevent extraction of data from the X-Subject-Token. The `target` dict should contain a series of key-value pairs such as `{'user': user_ref_dict}`. :type target_attr: dict :param member_target_type: the type of the target, e.g. 'user'. Both this and `member_target` must be passed if either is passed. :type member_target_type: str :param member_target: the (dict form) reference of the member object. Both this and `member_target_type` must be passed if either is passed. :type member_target: dict :param filters: A variable number of optional string filters, these are used to extract values from the query params. The filters are added to the reques data that is passed to the enforcer and may be used to determine policy action. In practice these are mainly supplied in the various "list" APIs and are un-used in the default supplied policies. :type filters: iterable """ # NOTE(morgan) everything in the policy_dict may be used by the policy # DSL to action on RBAC and request information/response data. policy_dict = {} # If "action" has not explicitly been overridden, see if it is set in # Flask.g app-context (per-request thread local) meaning the # @policy_enforcer_action decorator was used. action = action or getattr(flask.g, cls.ACTION_STORE_ATTR, None) if action not in _POSSIBLE_TARGET_ACTIONS: LOG.warning( 'RBAC: Unknown enforcement action name `%s`. ' 'Rejecting as Forbidden, this is a programming error ' 'and a bug should be filed with as much information ' 'about the request that caused this as possible.', action) # NOTE(morgan): While this is an internal error, a 500 is never # desirable, we have handled the case and the most appropriate # response here is to issue a 403 (FORBIDDEN) to any API calling # enforce_call with an inappropriate action/name to look up the # policy rule. This is simply a short-circuit as the enforcement # code raises a 403 on an unknown action (in keystone) by default. raise exception.Forbidden(message=_( 'Internal RBAC enforcement error, invalid rule (action) ' 'name.')) # Mark flask.g as "enforce_call" has been called. This should occur # before anything except the "is this a valid action" check, ensuring # all proper "after request" checks pass, showing that the API has # enforcement. setattr(flask.g, _ENFORCEMENT_CHECK_ATTR, True) # Assert we are actually authenticated cls._assert_is_authenticated() # Check if "is_admin", this is in support of the old "admin auth token" # middleware with a shared "admin" token for auth if cls._shared_admin_auth_token_set(): LOG.warning('RBAC: Bypassing authorization') return # NOTE(morgan): !!! ORDER OF THESE OPERATIONS IS IMPORTANT !!! # The lowest priority values are set first and the highest priority # values are set last. # Get the Target Data Set. if target_attr is None: policy_dict.update( cls._extract_member_target_data(member_target_type, member_target)) # Special Case, extract and add subject_token data. subj_token_target_data = cls._extract_subject_token_target_data() if subj_token_target_data: policy_dict.setdefault('target', {}).update(subj_token_target_data) else: policy_dict['target'] = target_attr # Pull the data from the submitted json body to generate # appropriate input/target attributes, we take an explicit copy here # to ensure we're not somehow corrupting json_input = flask.request.get_json(force=True, silent=True) or {} policy_dict.update(json_input.copy()) # Generate the filter_attr dataset. policy_dict.update(cls._extract_filter_values(filters)) # Extract the cred data creds = cls._extract_policy_check_credentials() flattened = utils.flatten_dict(policy_dict) if LOG.logger.getEffectiveLevel() <= log.DEBUG: # LOG the Args args_str = ', '.join([ '%s=%s' % (k, v) for k, v in (flask.request.view_args or {}).items() ]) args_str = strutils.mask_password(args_str) LOG.debug('RBAC: Authorizing `%(action)s(%(args)s)`', { 'action': action, 'args': args_str }) # LOG the Cred Data cred_str = ', '.join(['%s=%s' % (k, v) for k, v in creds.items()]) cred_str = strutils.mask_password(cred_str) LOG.debug( 'RBAC: Policy Enforcement Cred Data ' '`%(action)s creds(%(cred_str)s)`', { 'action': action, 'cred_str': cred_str }) # Log the Target Data target_str = ', '.join( ['%s=%s' % (k, v) for k, v in flattened.items()]) target_str = strutils.mask_password(target_str) LOG.debug( 'RBAC: Policy Enforcement Target Data ' '`%(action)s => target(%(target_str)s)`', { 'action': action, 'target_str': target_str }) # Instantiate the enforcer object if needed. enforcer_obj = enforcer or cls() enforcer_obj._enforce(credentials=creds, action=action, target=flattened) LOG.debug('RBAC: Authorization granted')
def authorize_aura(credentials, target): print "***********************" print "POLICY ENFORCE" print "***** TARGET:" print target print "***** Credentials:" print credentials print "***********************" admin_unit = ['target.admin_unit'] admin_admin_unit = credentials.get('admin_unit') admin_location = credentials.get('location') #print admin_location admin_admin_roles = credentials.get('admin_roles') user_admin_unit = target.get('target.admin_unit') user_location = target.get('target.location') #print user_location user_user_clearance = target.get('target.user_clearance') target_role = target.get('target.role.name') # for i in range(11): # try: # admin_attribute+str(i) = credentials.get('attribute'+str(i)) # user_attribute+str(i) = credentials.get('target.attribute'+str(i)) # except: # continue # with open('/opt/stack/keystone/keystone/policy/backends/policy_files/equal_attribute.json') as policy: # policy = json.load(policy) # for i in range(len(policy)): # if True == (target_role in policy[i]["role"]): # if True == (admin_admin_unit in policy[i]["admin"]["admin_unit"]) and True == (user_admin_unit in policy[i]["user"]["admin_unit"]): # print "ADMIN UNIT IS PRESENT!" # # else: # # print "admin_unit mismatch" # # else: # # print "target role not found" # raise exception.Forbidden("Unathorised user role assignment attempt!!") with open( '/opt/stack/keystone/keystone/policy/backends/attribute_policy.json' ) as policy: policy = json.load(policy) for i in range(len(policy)): print "ADMIN ROLES: " print policy[i]["role"] print "Target Role: " + target_role #for j in (policy[i]["role"]): if True == (target_role in policy[i]["role"]): print "target role is present: <<" + target_role + ">>" #for j in (policy[i]["role"]): #if j == target_role: #print "ADMIN_ADMIN_UNIT: <<" + admin_admin_unit + ">> in ROLES:" #print policy[i]["admin"]["admin_unit"] #print "USER_ADMIN_UNIT: <<" + user_admin_unit + ">> in ROLES:" #print policy[i]["user"]["admin_unit"] if (True == (admin_admin_unit in policy[i]["admin"]["admin_unit"]) and True == (user_admin_unit in policy[i]["user"]["admin_unit"])): print "ADMIN UNIT IS PRESENT: <<" + admin_admin_unit + ">>" #print "USER ADMIN UNIT IS PRESENT: <<"+ user_admin_unit + ">>" #print "ADMIN LOCATION: <<" + admin_location + ">>, User location: <<" + user_location + ">>" #print "Admin policy location:" #print policy[i]["admin"]["location"] #print "User location policy:" #print policy[i]["user"]["location"] if admin_location in policy[i]["admin"]["location"] and \ user_location in policy[i]["user"]["location"]: print "LOCATION IS PRESENT" if (True == (admin_admin_roles in policy[i]["admin"]["admin_roles"])): print "ADMIN ROLES MATCH.." print "**********************************" print "USER CLEARANCE :" + user_user_clearance print policy[i]["user"]["clearance"] print "**********************************" if (True == (user_user_clearance in policy[i]["user"]["clearance"])): print "USER CLEARANCE MATCH" print "getting there......." # print(time.time()) # print("**********") # print ("Authorized granted!") # print("**********") # return True for j in range(11): print "-------------------------------------" print "admin_attribute" + str(j) print 'user_attribute' + str(j) print policy[i]["admin"] print policy[i]["user"] if "attribute"+str(j) in policy[i]["admin"] and \ "attribute"+str(j) in policy[i]["user"]: admin_attribute_i = credentials.get( 'attribute' + str(j)) user_attribute_i = target.get( 'target.attribute' + str(j)) if admin_attribute_i in policy[i]["admin"]["attribute"+str(j)] and \ user_attribute_i in policy[i]["user"]["attribute"+str(j)]: print "USER + ADMIN ATTRIBUTE" + str( j) + " ARE VALID" else: print "USER + ADMIN ATTRIBUTE" + str( j) + " ARE **NOT** VALID" print admin_attribute_i print policy[i]["admin"]["attribute" + str(j)] print user_attribute_i print policy[i]["user"]["attribute" + str(j)] raise exception.Forbidden( "Unathorised user role assignment attempt!!" )
def _trustor_only(context, trust, user_id): if user_id != trust.get('trustor_user_id'): raise exception.Forbidden()
def authorize_request_token(self, context, request_token_id, roles): """An authenticated user is going to authorize a request token. As a security precaution, the requested roles must match those in the request token. Because this is in a CLI-only world at the moment, there is not another easy way to make sure the user knows which roles are being requested before authorizing. """ auth_context = context.get('environment', {}).get('KEYSTONE_AUTH_CONTEXT', {}) if auth_context.get('is_delegated_auth'): raise exception.Forbidden( _('Cannot authorize a request token' ' with a token issued via delegation.')) req_token = self.oauth_api.get_request_token(request_token_id) expires_at = req_token['expires_at'] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_('Request token is expired')) # put the roles in a set for easy comparison authed_roles = set() for role in roles: authed_roles.add(role['id']) # verify the authorizing user has the roles user_token = utils.get_token_ref(context) user_id = user_token.user_id project_id = req_token['requested_project_id'] user_roles = self.assignment_api.get_roles_for_user_and_project( user_id, project_id) cred_set = set(user_roles) if not cred_set.issuperset(authed_roles): msg = _('authorizing user does not have role required') raise exception.Unauthorized(message=msg) # create list of just the id's for the backend role_list = list(authed_roles) # verify the user has the project too req_project_id = req_token['requested_project_id'] user_projects = self.assignment_api.list_projects_for_user(user_id) for user_project in user_projects: if user_project['id'] == req_project_id: break else: msg = _("User is not a member of the requested project") raise exception.Unauthorized(message=msg) # finally authorize the token authed_token = self.oauth_api.authorize_request_token( request_token_id, user_id, role_list) to_return = {'token': {'oauth_verifier': authed_token['verifier']}} return to_return
def _admin_trustor_only(context, trust, user_id): if user_id != trust.get('trustor_user_id') and not context['is_admin']: raise exception.Forbidden()
def issue_v3_token(self, user_id, method_names, expires_at=None, project_id=None, domain_id=None, auth_context=None, trust=None, metadata_ref=None, include_catalog=True): # for V2, trust is stashed in metadata_ref if (CONF.trust.enabled and not trust and metadata_ref and 'trust_id' in metadata_ref): trust = self.trust_api.get_trust(metadata_ref['trust_id']) access_token = None if 'oauth1' in method_names: if self.oauth_api: access_token_id = auth_context['access_token_id'] access_token = self.oauth_api.get_access_token(access_token_id) else: raise exception.Forbidden(_('Oauth is disabled.')) token_data = self.v3_token_data_helper.get_token_data( user_id, method_names, auth_context.get('extras') if auth_context else None, domain_id=domain_id, project_id=project_id, expires=expires_at, trust=trust, bind=auth_context.get('bind') if auth_context else None, include_catalog=include_catalog, access_token=access_token) token_id = self._get_token_id(token_data) try: expiry = token_data['token']['expires_at'] if isinstance(expiry, basestring): expiry = timeutils.normalize_time( timeutils.parse_isotime(expiry)) # FIXME(gyee): is there really a need to store roles in metadata? role_ids = [] if metadata_ref is None: metadata_ref = {} if 'project' in token_data['token']: # project-scoped token, fill in the v2 token data # all we care are the role IDs role_ids = [r['id'] for r in token_data['token']['roles']] metadata_ref = {'roles': role_ids} if trust: metadata_ref.setdefault('trust_id', trust['id']) metadata_ref.setdefault('trustee_user_id', trust['trustee_user_id']) data = dict(key=token_id, id=token_id, expires=expiry, user=token_data['token']['user'], tenant=token_data['token'].get('project'), metadata=metadata_ref, token_data=token_data, trust_id=trust['id'] if trust else None, token_version=token.provider.V3) self.token_api.create_token(token_id, data) except Exception: exc_info = sys.exc_info() # an identical token may have been created already. # if so, return the token_data as it is also identical try: self.token_api.get_token(token_id) except exception.TokenNotFound: raise exc_info[0], exc_info[1], exc_info[2] return (token_id, token_data)
def assert_enabled_service_provider_object(service_provider): if service_provider.get('enabled') is not True: sp_id = service_provider['id'] msg = _('Service Provider %(sp)s is disabled') % {'sp': sp_id} LOG.debug(msg) raise exception.Forbidden(msg)
def _require_user_is_trustor(self, context, trust): user_id = self._get_user_id(context) if user_id != trust.get('trustor_user_id'): raise exception.Forbidden( _("The authenticated user should match the trustor."))
def test_403_title(self): e = exception.Forbidden() resp = wsgi.render_exception(e) j = jsonutils.loads(resp.body) self.assertEqual('Forbidden', e.title) self.assertEqual('Forbidden', j['error'].get('title'))
def _require_role(self, trust): if not trust.get('roles'): raise exception.Forbidden( _('At least one role should be specified.'))
def _populate_roles(self, token_data, user_id, domain_id, project_id, trust, access_token): if 'roles' in token_data: # no need to repopulate roles return if access_token: filtered_roles = [] authed_role_ids = json.loads(access_token['role_ids']) all_roles = self.assignment_api.list_roles() for role in all_roles: for authed_role in authed_role_ids: if authed_role == role['id']: filtered_roles.append({ 'id': role['id'], 'name': role['name'] }) token_data['roles'] = filtered_roles return if CONF.trust.enabled and trust: token_user_id = trust['trustor_user_id'] token_project_id = trust['project_id'] # trusts do not support domains yet token_domain_id = None else: token_user_id = user_id token_project_id = project_id token_domain_id = domain_id if token_domain_id or token_project_id: roles = self._get_roles_for_user(token_user_id, token_domain_id, token_project_id) filtered_roles = [] if CONF.trust.enabled and trust: for trust_role in trust['roles']: match_roles = [ x for x in roles if x['id'] == trust_role['id'] ] if match_roles: filtered_roles.append(match_roles[0]) else: raise exception.Forbidden( _('Trustee has no delegated roles.')) else: for role in roles: filtered_roles.append({ 'id': role['id'], 'name': role['name'] }) # user has no project or domain roles, therefore access denied if not filtered_roles: if token_project_id: msg = _('User %(user_id)s has no access ' 'to project %(project_id)s') % { 'user_id': user_id, 'project_id': token_project_id } else: msg = _('User %(user_id)s has no access ' 'to domain %(domain_id)s') % { 'user_id': user_id, 'domain_id': token_domain_id } LOG.debug(msg) raise exception.Unauthorized(msg) token_data['roles'] = filtered_roles
def _trustor_trustee_only(trust, user_id): if user_id not in [ trust.get('trustee_user_id'), trust.get('trustor_user_id') ]: raise exception.Forbidden()