Beispiel #1
0
async def proxy(request: web.Request, handler: web.RequestHandler):
    try:
        req_start_time = time()
        if pydash.starts_with(request.path_qs, '/raven'):
            return await handler(request)

        service = Regex.best_match(await Regex.get_matched_paths(request.path, DB.get(request, service_controller.table)))
        await handle_service(service, request.remote)

        rate_limiter_rules = await RateLimiter.get_rule_by_service_id(str(service['_id']), DB.get_redis(request))
        rate_limiter_rule = rate_limiter_rules[0] if rate_limiter_rules else None
        await handle_rate_limiter(request, str(service['_id']), rate_limiter_rule)

        breakers = await CircuitBreaker.get_by_service_id(str(service['_id']), DB.get(request, circuit_breaker_controller.table))
        breaker = breakers[0] if breakers else None

        request_validators = await RequestValidator.get_by_service_id(str(service['_id']), DB.get(request, request_validator_controller.table))
        request_validator = request_validators[0] if request_validators else None

        endpoint_cachers = not pydash.is_empty(service) and await EndpointCacher.get_by_service_id(str(service['_id']), DB.get_redis(request)) or None
        endpoint_cacher = endpoint_cachers[0] if endpoint_cachers else None

        await handle_request_validator(request_validator, json.loads(await request.text()), request.method)
        req, req_cache_hit = await handle_request(request, service, endpoint_cacher)

        checks = []

        if not pydash.is_empty(
                breaker) and breaker['status'] == CircuitBreakerStatus.ON.name:
            if req['status'] in breaker['status_codes']:
                checks.append(handle_circuit_breaker(
                    breaker, service, request, req))
            else:
                await CircuitBreaker.incr_count(str(breaker['_id']), DB.get_redis(request))

        queue_async_func.s({
            'func': 'Service.advance_target',
            'args': [str(service['_id']), f'mongo:{service_controller.table}'],
            'kwargs': {}
        }).apply_async()
        req_finish_time = time()
        req_elapsed_time = req_finish_time - req_start_time
        checks.append(handle_insights(request, req, str(
            service['_id']), req_elapsed_time, req_cache_hit))
        await Async.all(checks)

        return web.Response(
            body=Bytes.decode_bytes(
                req['body_bytes']),
            status=req['status'],
            content_type=req['content_type'],
            headers=CIMultiDict(
                pydash.omit(
                    req['headers'],
                    'Content-Type',
                    'Transfer-Encoding',
                    'Content-Encoding')))
    except Exception as err:
        return Error.handle(err)
Beispiel #2
0
 def _pad_data(data: str):
     """
     appends padding to the provided data
     """
     padder = padding.PKCS7(128).padder()
     padded_data = padder.update(Bytes.str_to_bytes(data))
     padded_data += padder.finalize()
     return padded_data
Beispiel #3
0
    def sign(message: object, private_key: str) -> str:
        """
        signs a message

        @param message: (object) message to sign
        @param private_key: (str) private key to sign with
        """
        private_key_bytes = serialization.load_pem_private_key(
            private_key.encode('utf-8'),
            password=None,
            backend=default_backend()
        )
        message_bytes = Bytes.object_to_bytes(message)
        signature_bytes = private_key_bytes.sign(
            message_bytes,
            ec.ECDSA(hashes.SHA256())
        )
        return Bytes.encode_bytes(signature_bytes).decode('utf-8')
Beispiel #4
0
    def verify(message: object, signature: str, public_key: str) -> bool:
        """
        verfies message with digital signature

        @param message: (object) message to verify
        @param signature: (str) signature to verify message with
        @param public_key: (str) public key to verify message with
        """
        try:
            public_key_bytes = serialization.load_pem_public_key(
                public_key.encode('utf-8'),
                backend=default_backend()
            )
            signature_bytes = Bytes.decode_bytes(signature.encode('utf-8'))
            message_bytes = Bytes.object_to_bytes(message)
            public_key_bytes.verify(
                signature_bytes,
                message_bytes,
                ec.ECDSA(hashes.SHA256())
            )
            return True
        except InvalidSignature:
            return False
Beispiel #5
0
    async def call(method=None,
                   url=None,
                   params=None,
                   data=None,
                   json=None,
                   cookies=None,
                   headers=None,
                   auth=None):
        """
        makes a request

        @returns: request response
        """
        async with aiohttp.request(method=method,
                                   url=url,
                                   params=params,
                                   data=data,
                                   json=json,
                                   cookies=cookies,
                                   headers=headers,
                                   auth=auth) as response:
            return {
                'headers':
                dict(response.headers),
                'body_bytes':
                Bytes.encode_bytes(await response.read()).decode('utf-8'),
                'body_text':
                await response.text(),
                'content_length':
                response.content_length,
                'content_type':
                response.content_type,
                'cookies':
                dict(response.cookies),
                'method':
                response.method,
                'reason':
                response.reason,
                'status':
                int(response.status),
                'url':
                str(response.url),
            }
Beispiel #6
0
    def encrypt(
            message: object,
            private_key: str,
            receiver_public_key: str) -> str:
        """
        encrypts message

        @param message: (object) message to encrypt
        @param private_key: (str) private key to encrypt message with
        @param receiver_public_key: (str) public key of person able to decrypt message
        """
        iv = '000000000000'.encode('utf-8')
        private_key_bytes = serialization.load_pem_private_key(
            private_key.encode('utf-8'),
            password=None,
            backend=default_backend()
        )
        receiver_public_key = serialization.load_pem_public_key(
            receiver_public_key.encode('utf-8'),
            backend=default_backend()
        )
        shared_key = private_key_bytes.exchange(ec.ECDH(), receiver_public_key)
        point = private_key_bytes.public_key().public_numbers().encode_point()
        xkdf = x963kdf.X963KDF(
            algorithm=hashes.SHA256(),
            length=32,
            sharedinfo=''.encode('utf-8'),
            backend=default_backend()
        )
        key = xkdf.derive(shared_key)
        encryptor = Cipher(
            algorithms.AES(key),
            modes.GCM(iv),
            backend=default_backend()
        ).encryptor()
        padded_message = Crypt._pad_data(json.dumps(message))
        ciphertext = encryptor.update(padded_message) + encryptor.finalize()
        complete_ciphertext = point + encryptor.tag + ciphertext
        return Bytes.encode_bytes(complete_ciphertext).decode('utf-8')
Beispiel #7
0
    def decrypt(message: str, receiver_private_key: str) -> str:
        """
        decrypts message

        @param message: (str) message to decrypt
        @param receiver_private_key: (str) private key to decrypt with
        """
        message = Bytes.decode_bytes(message.encode('utf-8'))
        point = message[0:65]
        tag = message[65:81]
        ciphertext = message[81:]
        receiver_private_key_bytes = serialization.load_pem_private_key(
            receiver_private_key.encode('utf-8'),
            password=None,
            backend=default_backend()
        )
        sender_public_numbers = ec.EllipticCurvePublicNumbers.from_encoded_point(
            ec.SECP256K1(), point)
        sender_public_key = sender_public_numbers.public_key(default_backend())
        shared_key = receiver_private_key_bytes.exchange(
            ec.ECDH(),
            sender_public_key
        )
        iv = '000000000000'.encode('utf-8')
        xkdf = x963kdf.X963KDF(
            algorithm=hashes.SHA256(),
            length=32,
            sharedinfo=''.encode('utf-8'),
            backend=default_backend()
        )
        key = xkdf.derive(shared_key)
        decryptor = Cipher(
            algorithms.AES(key),
            modes.GCM(iv, tag),
            backend=default_backend()
        ).decryptor()

        dt = decryptor.update(ciphertext) + decryptor.finalize()
        return Crypt._unpad_data(dt).decode('utf-8')