def assert_user_has_rule_trigger_and_action_permission(user_db, rule_api): """ Check that the currently logged-in has necessary permissions on trhe trigger and action used / referenced inside the rule. """ if not cfg.CONF.rbac.enable: return True trigger = rule_api.trigger action = rule_api.action trigger_type = trigger['type'] action_ref = action['ref'] # Check that user has access to the specified trigger - right now we only check for # webhook permissions has_trigger_permission = RBACUtils.user_has_rule_trigger_permission( user_db=user_db, trigger=trigger) if not has_trigger_permission: msg = ( 'User "%s" doesn\'t have required permission (%s) to use trigger %s' % (user_db.name, PermissionType.WEBHOOK_CREATE, trigger_type)) raise AccessDeniedError(message=msg, user_db=user_db) # Check that user has access to the specified action has_action_permission = RBACUtils.user_has_rule_action_permission( user_db=user_db, action_ref=action_ref) if not has_action_permission: msg = ( 'User "%s" doesn\'t have required (%s) permission to use action %s' % (user_db.name, PermissionType.ACTION_EXECUTE, action_ref)) raise AccessDeniedError(message=msg, user_db=user_db) return True
def _validate_encrypted_query_parameter(self, encrypted, scope, requester_user): rbac_utils = get_rbac_backend().get_utils_class() is_admin = rbac_utils.user_is_admin(user_db=requester_user) if encrypted and not is_admin: msg = 'Pre-encrypted option requires administrator access' raise AccessDeniedError(message=msg, user_db=requester_user)
def get_all(self, prefix=None, scope=FULL_SYSTEM_SCOPE, user=None, decrypt=False, **kwargs): """ List all keys. Handles requests: GET /keys/ """ if not scope: scope = FULL_SYSTEM_SCOPE if user: # Providing a user implies a user scope scope = FULL_USER_SCOPE scope = get_datastore_full_scope(scope) requester_user = get_requester() user = user or requester_user is_all_scope = (scope == ALL_SCOPE) is_admin = request_user_is_admin(request=pecan.request) if is_all_scope and not is_admin: msg = '"all" scope requires administrator access' raise AccessDeniedError(message=msg, user_db=requester_user) # User needs to be either admin or requesting items for themselves self._validate_decrypt_query_parameter(decrypt=decrypt, scope=scope, is_admin=is_admin) # Validate that the authenticated user is admin if user query param is provided assert_request_user_is_admin_if_user_query_param_is_provided( request=pecan.request, user=user) from_model_kwargs = {'mask_secrets': not decrypt} kwargs['prefix'] = prefix if scope and scope not in ALL_SCOPE: self._validate_scope(scope=scope) kwargs['scope'] = scope if scope == USER_SCOPE or scope == FULL_USER_SCOPE: # Make sure we only returned values scoped to current user if kwargs['prefix']: kwargs['prefix'] = get_key_reference(name=kwargs['prefix'], scope=scope, user=requester_user) else: kwargs['prefix'] = get_key_reference(name='', scope=scope, user=user) kvp_apis = super(KeyValuePairController, self)._get_all(from_model_kwargs=from_model_kwargs, **kwargs) return kvp_apis
def assert_user_is_admin_if_user_query_param_is_provided(user_db, user, require_rbac=False): """ Function which asserts that the request user is administator if "user" query parameter is provided and doesn't match the current user. """ is_admin = user_is_admin(user_db=user_db) is_rbac_enabled = bool(cfg.CONF.rbac.enable) if user != user_db.name: if require_rbac and not is_rbac_enabled: msg = '"user" attribute can only be provided by admins when RBAC is enabled' raise AccessDeniedError(message=msg, user_db=user_db) if not is_admin: msg = '"user" attribute can only be provided by admins' raise AccessDeniedError(message=msg, user_db=user_db)
def _validate_decrypt_query_parameter(decrypt, scope, is_admin, user_db): """ Validate that the provider user is either admin or requesting to decrypt value for themselves. """ is_user_scope = scope == USER_SCOPE or scope == FULL_USER_SCOPE if decrypt and (not is_user_scope and not is_admin): msg = "Decrypt option requires administrator access" raise AccessDeniedError(message=msg, user_db=user_db)
def get_all(self, requester_user, prefix=None, scope=FULL_SYSTEM_SCOPE, user=None, decrypt=False, sort=None, offset=0, limit=None, **raw_filters): """ List all keys. Handles requests: GET /keys/ """ if not scope: scope = FULL_SYSTEM_SCOPE if user: # Providing a user implies a user scope scope = FULL_USER_SCOPE if not requester_user: requester_user = UserDB(cfg.CONF.system_user.user) scope = get_datastore_full_scope(scope) is_all_scope = (scope == ALL_SCOPE) is_admin = rbac_utils.user_is_admin(user_db=requester_user) if is_all_scope and not is_admin: msg = '"all" scope requires administrator access' raise AccessDeniedError(message=msg, user_db=requester_user) # User needs to be either admin or requesting items for themselves self._validate_decrypt_query_parameter(decrypt=decrypt, scope=scope, is_admin=is_admin, requester_user=requester_user) user = user or requester_user.name # Validate that the authenticated user is admin if user query param is provided assert_user_is_admin_if_user_query_param_is_provided(user_db=requester_user, user=user) from_model_kwargs = {'mask_secrets': not decrypt} if scope and scope not in ALL_SCOPE: self._validate_scope(scope=scope) raw_filters['scope'] = scope if scope == USER_SCOPE or scope == FULL_USER_SCOPE: # Make sure we only returned values scoped to current user if prefix: prefix = get_key_reference(name=prefix, scope=scope, user=user) else: prefix = get_key_reference(name='', scope=scope, user=user) raw_filters['prefix'] = prefix kvp_apis = super(KeyValuePairController, self)._get_all(from_model_kwargs=from_model_kwargs, sort=sort, offset=offset, limit=limit, raw_filters=raw_filters) return kvp_apis
def assert_user_is_admin_if_user_query_param_is_provided(user_db, user): """ Function which asserts that the request user is administator if "user" query parameter is provided and doesn't match the current user. """ is_admin = user_is_admin(user_db=user_db) if user != user_db.name and not is_admin: msg = '"user" attribute can only be provided by admins' raise AccessDeniedError(message=msg, user_db=user_db)
def _validate_decrypt_query_parameter(self, decrypt, scope, is_admin): """ Validate that the provider user is either admin or requesting to decrypt value for themselves. """ requester_user = get_requester() if decrypt and (scope != USER_SCOPE and not is_admin): msg = 'Decrypt option requires administrator access' raise AccessDeniedError(message=msg, user_db=requester_user)
def assert_user_is_admin(cls, user_db): """ Assert that the currently logged in user is an administrator. If the user is not an administrator, an exception is thrown. """ is_admin = cls.user_is_admin(user_db=user_db) if not is_admin: raise AccessDeniedError(message='Administrator access required', user_db=user_db)
def _validate_decrypt_query_parameter(self, decrypt, scope, requester_user): """ Validate that the provider user is either admin or requesting to decrypt value for themselves. """ is_admin = rbac_utils.user_is_admin(user_db=requester_user) is_user_scope = (scope == USER_SCOPE or scope == FULL_USER_SCOPE) if decrypt and (not is_user_scope and not is_admin): msg = 'Decrypt option requires administrator access' raise AccessDeniedError(message=msg, user_db=requester_user)
def _validate_all_scope(self, scope, requester_user): """ Validate that "all" scope can only be provided by admins on RBAC installations. """ scope = get_datastore_full_scope(scope) is_all_scope = (scope == ALL_SCOPE) is_admin = rbac_utils.user_is_admin(user_db=requester_user) if is_all_scope and not is_admin: msg = '"all" scope requires administrator access' raise AccessDeniedError(message=msg, user_db=requester_user)
def validate_limit_query_param(limit, requester_user=None): """ Validate that the provided value for "limit" query parameter is valid. Note: We only perform max_page_size check for non-admin users. Admin users can provide arbitrary limit value. """ rbac_utils = get_rbac_backend().get_utils_class() user_is_admin = rbac_utils.user_is_admin(user_db=requester_user) if limit: # Display all the results if int(limit) == -1: if not user_is_admin: # Only admins can specify limit -1 message = ( "Administrator access required to be able to specify limit=-1 and " "retrieve all the records" ) raise AccessDeniedError(message=message, user_db=requester_user) return 0 elif int(limit) <= -2: msg = 'Limit, "%s" specified, must be a positive number.' % (limit) raise ValueError(msg) elif int(limit) > cfg.CONF.api.max_page_size and not user_is_admin: msg = 'Limit "%s" specified, maximum value is "%s"' % ( limit, cfg.CONF.api.max_page_size, ) raise AccessDeniedError(message=msg, user_db=requester_user) # Disable n = 0 elif limit == 0: msg = ( 'Limit, "%s" specified, must be a positive number or -1 for full result set.' % (limit) ) raise ValueError(msg) return limit
def assert_user_is_admin_if_user_query_param_is_provided(user_db, user, require_rbac=False): """ Function which asserts that the request user is administator if "user" query parameter is provided and doesn't match the current user. """ # To avoid potential security issues when RBAC is disabled, we don't support ?user=foo # query param when RBAC is disabled is_rbac_enabled = bool(cfg.CONF.rbac.enable) if user != user_db.name and require_rbac and not is_rbac_enabled: msg = '"user" attribute can only be provided by admins when RBAC is enabled' raise AccessDeniedError(message=msg, user_db=user_db)
def assert_request_user_is_system_admin(request): """ Assert that the currently logged in user is a system administrator. If the user is not a system administrator, an exception is thrown. """ is_system_admin = request_user_is_system_admin(request=request) if not is_system_admin: user_db = get_user_db_from_request(request=request) raise AccessDeniedError(message='System Administrator access required', user_db=user_db)
def assert_user_is_system_admin(user_db): """ Assert that the currently logged in user is a system administrator. If the user is not a system administrator, an exception is thrown. """ is_system_admin = RBACUtils.user_is_system_admin(user_db=user_db) if not is_system_admin: raise AccessDeniedError( message='System Administrator access required', user_db=user_db)
def assert_user_is_admin_or_operating_on_own_resource(user_db, user=None): """ Assert that the currently logged in user is an administrator or operating on a resource which belongs to that user. """ if not cfg.CONF.rbac.enable: return True is_admin = user_is_admin(user_db=user_db) is_self = user is not None and (user_db.name == user) if not is_admin and not is_self: raise AccessDeniedError(message='Administrator or self access required', user_db=user_db)