예제 #1
0
def start_tcp_proxy(src, dst, handler, **kwargs):
    """Run a simple TCP proxy (tunneling raw connections from src to dst), using a message handler
        that can be used to intercept messages and return predefined responses for certain requests.

    Arguments:
    src -- Source IP address and port string. I.e.: '127.0.0.1:8000'
    dst -- Destination IP address and port. I.e.: '127.0.0.1:8888'
    handler -- a handler function to intercept requests (returns tuple (forward_value, response_value))
    """

    src = "%s:%s" % (BIND_HOST, src) if is_number(src) else src
    dst = "%s:%s" % (LOCALHOST_IP, dst) if is_number(dst) else dst
    thread = kwargs.get("_thread")

    def ip_to_tuple(ip):
        ip, port = ip.split(":")
        return ip, int(port)

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(ip_to_tuple(src))
    s.listen(1)
    s.settimeout(10)

    def handle_request(s_src, thread):
        s_dst = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s_dst.connect(ip_to_tuple(dst))

        sockets = [s_src, s_dst]

        try:
            while thread.running:
                s_read, _, _ = select.select(sockets, [], [])

                for s in s_read:
                    data = s.recv(BUFFER_SIZE)
                    if data in [b"", "", None]:
                        return

                    if s == s_src:
                        forward, response = data, None
                        if handler:
                            forward, response = handler(data)
                        if forward is not None:
                            s_dst.sendall(forward)
                        elif response is not None:
                            s_src.sendall(response)
                            return
                    elif s == s_dst:
                        s_src.sendall(data)
        finally:
            run_safe(s_src.close)
            run_safe(s_dst.close)

    while thread.running:
        try:
            src_socket, _ = s.accept()
            start_worker_thread(
                lambda *args, _thread: handle_request(src_socket, _thread))
        except socket.timeout:
            pass
예제 #2
0
 def _create_response(result, status_code=200):
     """ Create the final response for the given invocation result """
     if isinstance(result, Response):
         return result
     details = {
         'StatusCode': status_code,
         'Payload': result,
         'Headers': {}
     }
     if isinstance(result, dict):
         for key in ('StatusCode', 'Payload', 'FunctionError'):
             if result.get(key):
                 details[key] = result[key]
     # Try to parse parse payload as JSON
     payload = details['Payload']
     if payload and isinstance(payload, (str, bytes)) and payload[0] in ('[', '{'):
         try:
             details['Payload'] = json.loads(details['Payload'])
         except Exception:
             pass
     # Set error headers
     if details.get('FunctionError'):
         details['Headers']['X-Amz-Function-Error'] = str(details['FunctionError'])
     # Construct response object
     response_obj = details['Payload']
     if isinstance(response_obj, (dict, list, bool)) or is_number(response_obj):
         # Assume this is a JSON response
         response_obj = jsonify(response_obj)
     else:
         response_obj = str(response_obj)
         details['Headers']['Content-Type'] = 'text/plain'
     return response_obj, details['StatusCode'], details['Headers']
예제 #3
0
def publish_log_metrics_for_events(data):
    """Filter and publish log metrics for matching events"""
    from moto.logs.models import (  # TODO: create separate RegionBackend class to store state
        logs_backends, )

    data = data if isinstance(data, dict) else json.loads(data)
    log_events = data.get("logEvents") or []
    logs_backend = logs_backends[aws_stack.get_region()]
    metric_filters = logs_backend.filters.metric_filters
    client = aws_stack.connect_to_service("cloudwatch")
    for metric_filter in metric_filters:
        pattern = metric_filter.get("filterPattern", "")
        if log_events_match_filter_pattern(pattern, log_events):
            for tf in metric_filter.get("metricTransformations", []):
                value = tf.get("metricValue") or "1"
                if "$size" in value:
                    LOG.info(
                        "Expression not yet supported for log filter metricValue: %s"
                        % value)
                value = float(value) if is_number(value) else 1
                data = [{"MetricName": tf["metricName"], "Value": value}]
                try:
                    client.put_metric_data(Namespace=tf["metricNamespace"],
                                           MetricData=data)
                except Exception as e:
                    LOG.info(
                        "Unable to put metric data for matching CloudWatch log events: %s"
                        % e)
예제 #4
0
def publish_log_metrics_for_events(data):
    """ Filter and publish log metrics for matching events """
    from moto.logs.models import logs_backends  # TODO: create separate RegionBackend class to store state
    data = data if isinstance(data, dict) else json.loads(data)
    log_events = data.get('logEvents') or []
    logs_backend = logs_backends[aws_stack.get_region()]
    metric_filters = logs_backend.metric_filters = getattr(
        logs_backend, 'metric_filters', [])
    client = aws_stack.connect_to_service('cloudwatch')
    for metric_filter in metric_filters:
        pattern = metric_filter.get('filterPattern', '')
        if log_events_match_filter_pattern(pattern, log_events):
            for tf in metric_filter.get('metricTransformations', []):
                value = tf.get('metricValue') or '1'
                if '$size' in value:
                    LOG.info(
                        'Expression not yet supported for log filter metricValue: %s'
                        % value)
                value = float(value) if is_number(value) else 1
                data = [{'MetricName': tf['metricName'], 'Value': value}]
                try:
                    client.put_metric_data(Namespace=tf['metricNamespace'],
                                           MetricData=data)
                except Exception as e:
                    LOG.info(
                        'Unable to put metric data for matching CloudWatch log events: %s'
                        % e)
예제 #5
0
 def put_log_events(
     self,
     context: RequestContext,
     log_group_name: LogGroupName,
     log_stream_name: LogStreamName,
     log_events: InputLogEvents,
     sequence_token: SequenceToken = None,
 ) -> PutLogEventsResponse:
     logs_backend = logs_backends[aws_stack.get_region()]
     metric_filters = logs_backend.filters.metric_filters
     for metric_filter in metric_filters:
         pattern = metric_filter.get("filterPattern", "")
         transformations = metric_filter.get("metricTransformations", [])
         matches = get_pattern_matcher(pattern)
         for log_event in log_events:
             if matches(pattern, log_event):
                 for tf in transformations:
                     value = tf.get("metricValue") or "1"
                     if "$size" in value:
                         LOG.info(
                             "Expression not yet supported for log filter metricValue", value
                         )
                     value = float(value) if is_number(value) else 1
                     data = [{"MetricName": tf["metricName"], "Value": value}]
                     try:
                         self.cw_client.put_metric_data(
                             Namespace=tf["metricNamespace"], MetricData=data
                         )
                     except Exception as e:
                         LOG.info(
                             "Unable to put metric data for matching CloudWatch log events", e
                         )
     return call_moto(context)
예제 #6
0
 def escapeJavaScript(self, s):
     try:
         return json.dumps(json.loads(s))
     except Exception:
         primitive_types = (str, int, bool, float, type(None))
         s = s if isinstance(s, primitive_types) else str(s)
     if str(s).strip() in ["true", "false"]:
         s = bool(s)
     elif s not in [True, False] and is_number(s):
         s = to_number(s)
     return json.dumps(s)
예제 #7
0
 def test_is_number(self):
     env = common.is_number(5)
     self.assertEqual(env, True)
예제 #8
0
 def test_is_number(self):
     assert common.is_number(5)
예제 #9
0
 def test_is_number(self):
     env = common.is_number(5)
     self.assertTrue(env)