##// END OF EJS Templates
black: reformat source
black: reformat source

File last commit:

r153:32f4b641
r153:32f4b641
Show More
security.py
352 lines | 13.1 KiB | text/x-python | PythonLexer
project: initial commit
r0 # -*- coding: utf-8 -*-
license: change the license to Apache 2.0
r112 # Copyright 2010 - 2017 RhodeCode GmbH and the AppEnlight project authors
project: initial commit
r0 #
license: change the license to Apache 2.0
r112 # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
project: initial commit
r0 #
license: change the license to Apache 2.0
r112 # http://www.apache.org/licenses/LICENSE-2.0
project: initial commit
r0 #
license: change the license to Apache 2.0
r112 # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
project: initial commit
r0
from pyramid.security import Allow, Everyone, Authenticated, ALL_PERMISSIONS
from pyramid.authentication import CallbackAuthenticationPolicy
import appenlight.models.resource
from appenlight.models.services.auth_token import AuthTokenService
from appenlight.models.services.application import ApplicationService
from appenlight.models.services.report_group import ReportGroupService
from appenlight.models.services.plugin_config import PluginConfigService
from appenlight.lib import to_integer_safe
from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest
from ziggurat_foundations.permissions import permission_to_04_acls
requirements: bump ziggurat_foundations to 0.8.3
r135 from ziggurat_foundations.models.services.user import UserService
from ziggurat_foundations.models.services.resource import ResourceService
project: initial commit
r0 import defusedxml.ElementTree as ElementTree
import urllib.request, urllib.error, urllib.parse
import logging
import re
from xml.sax.saxutils import quoteattr
log = logging.getLogger(__name__)
def groupfinder(userid, request):
black: reformat source
r153 if userid and hasattr(request, "user") and request.user:
groups = ["group:%s" % g.id for g in request.user.groups]
project: initial commit
r0 return groups
return []
class AuthTokenAuthenticationPolicy(CallbackAuthenticationPolicy):
def __init__(self, callback=None):
self.callback = callback
def remember(self, request, principal, **kw):
return []
def forget(self, request):
return []
def unauthenticated_userid(self, request):
black: reformat source
r153 token = request.headers.get("x-appenlight-auth-token")
project: initial commit
r0 if token:
auth_token = AuthTokenService.by_token(token)
if auth_token and not auth_token.is_expired:
black: reformat source
r153 log.info("%s is valid" % auth_token)
project: initial commit
r0 return auth_token.owner_id
elif auth_token:
black: reformat source
r153 log.warning("%s is expired" % auth_token)
project: initial commit
r0 else:
black: reformat source
r153 log.warning("token: %s is not found" % token)
project: initial commit
r0
def authenticated_userid(self, request):
return self.unauthenticated_userid(request)
def rewrite_root_perm(perm_user, perm_name):
"""
Translates root_administration into ALL_PERMISSIONS object
"""
black: reformat source
r153 if perm_name == "root_administration":
return (Allow, perm_user, ALL_PERMISSIONS)
project: initial commit
r0 else:
black: reformat source
r153 return (Allow, perm_user, perm_name)
project: initial commit
r0
def add_root_superperm(request, context):
"""
Adds ALL_PERMISSIONS to every resource if user somehow has 'root_permission'
non-resource permission
"""
black: reformat source
r153 if hasattr(request, "user") and request.user:
requirements: bump ziggurat_foundations to 0.8.3
r135 acls = permission_to_04_acls(UserService.permissions(request.user))
project: initial commit
r0 for perm_user, perm_name in acls:
black: reformat source
r153 if perm_name == "root_administration":
project: initial commit
r0 context.__acl__.append(rewrite_root_perm(perm_user, perm_name))
class RootFactory(object):
"""
General factory for non-resource/report specific pages
"""
def __init__(self, request):
black: reformat source
r153 self.__acl__ = [
(Allow, Authenticated, "authenticated"),
(Allow, Authenticated, "create_resources"),
]
project: initial commit
r0 # general page factory - append custom non resource permissions
black: reformat source
r153 if hasattr(request, "user") and request.user:
requirements: bump ziggurat_foundations to 0.8.3
r135 acls = permission_to_04_acls(UserService.permissions(request.user))
project: initial commit
r0 for perm_user, perm_name in acls:
self.__acl__.append(rewrite_root_perm(perm_user, perm_name))
black: reformat source
r153
project: initial commit
r0 class ResourceFactory(object):
"""
Checks permissions to specific resource based on user permissions or
API key headers
"""
def __init__(self, request):
Resource = appenlight.models.resource.Resource
self.__acl__ = []
black: reformat source
r153 resource_id = request.matchdict.get(
"resource_id", request.GET.get("resource_id")
)
project: initial commit
r0 resource_id = to_integer_safe(resource_id)
black: reformat source
r153 self.resource = (
ResourceService.by_resource_id(resource_id) if resource_id else None
)
project: initial commit
r0 if self.resource and request.user:
self.__acl__ = self.resource.__acl__
requirements: bump ziggurat_foundations to 0.8.3
r135 permissions = ResourceService.perms_for_user(self.resource, request.user)
project: initial commit
r0 for perm_user, perm_name in permission_to_04_acls(permissions):
self.__acl__.append(rewrite_root_perm(perm_user, perm_name))
add_root_superperm(request, self)
class ResourceReportFactory(object):
"""
Checks permissions to specific resource based on user permissions or
API key headers
Resource is fetched based on report group information
"""
def __init__(self, request):
Resource = appenlight.models.resource.Resource
self.__acl__ = []
black: reformat source
r153 group_id = request.matchdict.get("group_id", request.params.get("group_id"))
project: initial commit
r0 group_id = to_integer_safe(group_id)
black: reformat source
r153 self.report_group = ReportGroupService.by_id(group_id) if group_id else None
project: initial commit
r0 if not self.report_group:
raise HTTPNotFound()
self.public = self.report_group.public
black: reformat source
r153 self.resource = (
ResourceService.by_resource_id(self.report_group.resource_id)
if self.report_group
else None
)
project: initial commit
r0
if self.resource:
self.__acl__ = self.resource.__acl__
if request.user:
requirements: bump ziggurat_foundations to 0.8.3
r135 permissions = ResourceService.perms_for_user(self.resource, request.user)
project: initial commit
r0 for perm_user, perm_name in permission_to_04_acls(permissions):
self.__acl__.append(rewrite_root_perm(perm_user, perm_name))
if self.public:
black: reformat source
r153 self.__acl__.append((Allow, Everyone, "view"))
project: initial commit
r0 if not request.user:
# unauthed users need to visit using both group and report pair
black: reformat source
r153 report_id = request.params.get(
"reportId", request.params.get("report_id", -1)
)
project: initial commit
r0 report = self.report_group.get_report(report_id, public=True)
if not report:
raise HTTPNotFound()
add_root_superperm(request, self)
class APIFactory(object):
"""
Checks permissions to perform client API actions based on keys
"""
def __init__(self, request):
self.__acl__ = []
self.possibly_public = False
private_api_key = request.headers.get(
black: reformat source
r153 "x-appenlight-api-key", request.params.get("api_key")
project: initial commit
r0 )
log.debug("private key: %s" % private_api_key)
if private_api_key:
black: reformat source
r153 self.resource = ApplicationService.by_api_key_cached()(private_api_key)
project: initial commit
r0 # then try public key
else:
public_api_key = request.headers.get(
black: reformat source
r153 "x-appenlight-public-api-key", request.GET.get("public_api_key")
)
project: initial commit
r0 log.debug("public key: %s" % public_api_key)
self.resource = ApplicationService.by_public_api_key(
black: reformat source
r153 public_api_key, from_cache=True, request=request
)
project: initial commit
r0 self.possibly_public = True
if self.resource:
black: reformat source
r153 self.__acl__.append((Allow, Everyone, "create"))
project: initial commit
r0
class AirbrakeV2APIFactory(object):
"""
Check permission based on Airbrake XML report
"""
def __init__(self, request):
self.__acl__ = []
self.possibly_public = False
black: reformat source
r153 fixed_xml_data = ""
project: initial commit
r0 try:
black: reformat source
r153 data = request.GET.get("data")
project: initial commit
r0 if data:
self.possibly_public = True
except (UnicodeDecodeError, UnicodeEncodeError) as exc:
black: reformat source
r153 log.warning("Problem parsing Airbrake data: %s, failed decoding" % exc)
project: initial commit
r0 raise HTTPBadRequest()
try:
if not data:
data = request.body
# fix shitty airbrake js client not escaping line method attr
def repl(input):
black: reformat source
r153 return "line method=%s file" % quoteattr(input.group(1))
project: initial commit
r0
fixed_xml_data = re.sub('line method="(.*?)" file', repl, data)
root = ElementTree.fromstring(fixed_xml_data)
except Exception as exc:
black: reformat source
r153 log.info("Problem parsing Airbrake " "data: %s, trying unquoting" % exc)
project: initial commit
r0 self.possibly_public = True
try:
root = ElementTree.fromstring(urllib.parse.unquote(fixed_xml_data))
except Exception as exc:
black: reformat source
r153 log.warning(
"Problem parsing Airbrake " "data: %s, failed completly" % exc
)
project: initial commit
r0 raise HTTPBadRequest()
self.airbrake_xml_etree = root
black: reformat source
r153 api_key = root.findtext("api-key", "")
project: initial commit
r0
self.resource = ApplicationService.by_api_key_cached()(api_key)
if not self.resource:
black: reformat source
r153 self.resource = ApplicationService.by_public_api_key(
api_key, from_cache=True, request=request
)
project: initial commit
r0 if self.resource:
self.possibly_public = True
if self.resource:
black: reformat source
r153 self.__acl__.append((Allow, Everyone, "create"))
project: initial commit
r0
def parse_sentry_header(header):
black: reformat source
r153 parsed = header.split(" ", 1)[1].split(",") or []
return dict([x.strip().split("=") for x in parsed])
project: initial commit
r0
class SentryAPIFactory(object):
"""
Check permission based on Sentry payload
"""
def __init__(self, request):
self.__acl__ = []
self.possibly_public = False
black: reformat source
r153 if request.headers.get("X-Sentry-Auth", "").startswith("Sentry"):
header_string = request.headers["X-Sentry-Auth"]
project: initial commit
r0 result = parse_sentry_header(header_string)
black: reformat source
r153 elif request.headers.get("Authorization", "").startswith("Sentry"):
header_string = request.headers["Authorization"]
project: initial commit
r0 result = parse_sentry_header(header_string)
else:
black: reformat source
r153 result = dict(
(k, v) for k, v in list(request.GET.items()) if k.startswith("sentry_")
)
key = result.get("sentry_key")
log.info("sentry request {}".format(result))
project: initial commit
r0
self.resource = ApplicationService.by_api_key_cached()(key)
black: reformat source
r153 if not self.resource or result.get("sentry_client", "").startswith("raven-js"):
project: initial commit
r0 self.resource = ApplicationService.by_public_api_key(
black: reformat source
r153 key, from_cache=True, request=request
)
project: initial commit
r0 if self.resource:
black: reformat source
r153 self.__acl__.append((Allow, Everyone, "create"))
project: initial commit
r0
class ResourcePluginConfigFactory(object):
def __init__(self, request):
Resource = appenlight.models.resource.Resource
self.__acl__ = []
self.resource = None
black: reformat source
r153 plugin_id = to_integer_safe(request.matchdict.get("id"))
project: initial commit
r0 self.plugin = PluginConfigService.by_id(plugin_id)
if not self.plugin:
raise HTTPNotFound()
if self.plugin.resource_id:
requirements: bump ziggurat_foundations to 0.8.3
r135 self.resource = ResourceService.by_resource_id(self.plugin.resource_id)
project: initial commit
r0 if self.resource:
self.__acl__ = self.resource.__acl__
if request.user and self.resource:
requirements: bump ziggurat_foundations to 0.8.3
r135 permissions = ResourceService.perms_for_user(self.resource, request.user)
project: initial commit
r0 for perm_user, perm_name in permission_to_04_acls(permissions):
self.__acl__.append(rewrite_root_perm(perm_user, perm_name))
add_root_superperm(request, self)
class ResourceJSONBodyFactory(object):
"""
Checks permissions to specific resource based on user permissions or
API key headers from json body
"""
def __init__(self, request):
Resource = appenlight.models.resource.Resource
self.__acl__ = []
black: reformat source
r153 resource_id = request.unsafe_json_body().get("resource_id")
project: initial commit
r0 resource_id = to_integer_safe(resource_id)
requirements: bump ziggurat_foundations to 0.8.3
r135 self.resource = ResourceService.by_resource_id(resource_id)
project: initial commit
r0 if self.resource and request.user:
self.__acl__ = self.resource.__acl__
requirements: bump ziggurat_foundations to 0.8.3
r135 permissions = ResourceService.perms_for_user(self.resource, request.user)
project: initial commit
r0 for perm_user, perm_name in permission_to_04_acls(permissions):
self.__acl__.append(rewrite_root_perm(perm_user, perm_name))
add_root_superperm(request, self)
class ResourcePluginMixedFactory(object):
def __init__(self, request):
Resource = appenlight.models.resource.Resource
self.__acl__ = []
json_body = request.safe_json_body
self.resource = None
if json_body:
black: reformat source
r153 resource_id = json_body.get("resource_id")
project: initial commit
r0 else:
black: reformat source
r153 resource_id = request.GET.get("resource_id")
project: initial commit
r0 if resource_id:
resource_id = to_integer_safe(resource_id)
requirements: bump ziggurat_foundations to 0.8.3
r135 self.resource = ResourceService.by_resource_id(resource_id)
project: initial commit
r0 if self.resource and request.user:
self.__acl__ = self.resource.__acl__
requirements: bump ziggurat_foundations to 0.8.3
r135 permissions = ResourceService.perms_for_user(self.resource, request.user)
project: initial commit
r0 for perm_user, perm_name in permission_to_04_acls(permissions):
self.__acl__.append(rewrite_root_perm(perm_user, perm_name))
add_root_superperm(request, self)