Пример #1
0
class ImageSimpleCache(ImageCache):
    """Simple image cache."""
    def __init__(self, app=None):
        """Initialize the cache."""
        super(ImageSimpleCache, self).__init__(app=app)
        self.cache = SimpleCache()

    def get(self, key):
        """Return the key value.

        :param key: the object's key
        :return: the stored object
        :rtype: `BytesIO` object
        """
        return self.cache.get(key)

    def set(self, key, value, timeout=None):
        """Cache the object.

        :param key: the object's key
        :param value: the stored object
        :type value: `BytesIO` object
        :param timeout: the cache timeout in seconds
        """
        timeout = timeout or self.timeout
        self.cache.set(key, value, timeout)
        self.set_last_modification(key, timeout=timeout)

    def get_last_modification(self, key):
        """Get last modification of cached file.

        :param key: the file object's key
        """
        return self.get(self._last_modification_key_name(key))

    def set_last_modification(self, key, last_modification=None, timeout=None):
        """Set last modification of cached file.

        :param key: the file object's key
        :param last_modification: Last modification date of
            file represented by the key
        :type last_modification: datetime.datetime
        :param timeout: the cache timeout in seconds
        """
        if not last_modification:
            last_modification = datetime.utcnow().replace(microsecond=0)
        timeout = timeout or self.timeout
        self.cache.set(self._last_modification_key_name(key),
                       last_modification, timeout)

    def delete(self, key):
        """Delete the specific key."""
        self.cache.delete(key)
        self.cache.delete(self._last_modification_key_name(key))

    def flush(self):
        """Flush the cache."""
        self.cache.clear()
Пример #2
0
class OpaqueValidator:
    def __init__(self,
                 introspection_url,
                 client_id,
                 client_secret,
                 verify_ssl_server=True):
        self.ctx = ssl.create_default_context()

        if not verify_ssl_server:
            self.ctx.check_hostname = False
            self.ctx.verify_mode = ssl.CERT_NONE

        self._introspection_url = introspection_url
        self._client_id = client_id
        self._client_secret = client_secret

        self._token_cache = SimpleCache()
        self.logger = logging.getLogger(__name__)

    def introspect_token(self, token):

        params = {'token': token}

        headers = {
            'content-type':
            'application/x-www-form-urlencoded',
            'accept':
            'application/jwt, application/json;q=0.9, text/plain;q=0.8, text/html;q=0.7'
        }

        req = request("POST",
                      self._introspection_url,
                      allow_redirects=False,
                      auth=(self._client_id, self._client_secret),
                      verify=self.ctx.check_hostname,
                      data=params,
                      headers=headers)

        response_content_type = req.headers.get("Content-Type",
                                                "text/plain").split(";")[0]
        result = {}
        cache_duration_header_value = req.headers.get("Cache-Duration", None)

        if cache_duration_header_value:
            # Turn 'public, max-age=31536000' into {'public': None, 'max-age': '31536000'}
            cache_duration_parts = dict(
                (part_values[0],
                 None if len(part_values) == 1 else part_values[1])
                for part_values in [
                    part.strip().split("=")
                    for part in cache_duration_header_value.split(",")
                ])

            if "public" in cache_duration_parts:
                result["cache_timeout"] = int(cache_duration_parts["max-age"])

        if req.status_code == 200:
            if response_content_type == "application/json":
                result.update(json.loads(req.text))
            elif response_content_type == "application/jwt":
                jws = jwkest.jws.factory(req.text)

                if jws is not None and len(jws.jwt.part) >= 2:
                    result["active"] = True
                    result.update(json.loads(jws.jwt.part[1]))
            else:
                self.logger.warning(
                    "Response type from introspection endpoint was unsupported, response_type = "
                    + response_content_type)

                raise Exception(
                    "Response type is from introspect endpoint is " +
                    response_content_type, req.text)
        elif req.status_code == 204:
            result.update(dict(active=False))
        else:
            raise Exception("HTTP POST error from introspection: %s" %
                            req.status_code)

        return result

    def validate(self, token):

        now = calendar.timegm(datetime.utcnow().utctimetuple())

        # Lookup in cache:
        cached_response = self._token_cache.get(token)
        if cached_response is not None:
            if cached_response['active']:
                if cached_response['exp'] >= now:
                    return cached_response
            else:
                return dict(active=False)

        introspect_response = self.introspect_token(token)
        cache_timeout = 0

        if "cache_timeout" in introspect_response:
            cache_timeout = introspect_response["cache_timeout"]
        elif "exp" in introspect_response:
            cache_timeout = introspect_response["exp"] - now

        if "active" not in introspect_response:
            # The token isn't know to be active, so we'll never introspect it again
            introspect_response["active"] = False

            self._token_cache.set(token,
                                  introspect_response,
                                  timeout=cache_timeout)

            raise OpaqueValidatorException(
                "No active field in introspection response")

        self._token_cache.set(token,
                              introspect_response,
                              timeout=cache_timeout)

        if not introspect_response['active']:
            return {"active": False}

        if 'sub' not in introspect_response:
            raise OpaqueValidatorException(
                "Missing sub field in introspection response")

        if 'exp' not in introspect_response:
            raise OpaqueValidatorException(
                "Missing exp field in introspection response")

        if 'scope' not in introspect_response:
            raise OpaqueValidatorException(
                "Missing scope field in introspection response")

        return introspect_response