Пример #1
0
def get_port_from_custom_rules(method, path, data, headers):
    """ Determine backend port based on custom rules. """

    # detect S3 presigned URLs
    if 'AWSAccessKeyId=' in path or 'Signature=' in path:
        return config.PORT_S3

    # heuristic for SQS queue URLs
    if is_sqs_queue_url(path):
        return config.PORT_SQS

    # DynamoDB shell URLs
    if path.startswith('/shell') or path.startswith('/dynamodb/shell'):
        return config.PORT_DYNAMODB

    data_bytes = to_bytes(data or '')

    if path == '/' and to_bytes('QueueName=') in data_bytes:
        return config.PORT_SQS

    # TODO: move S3 public URLs to a separate port/endpoint, OR check ACLs here first
    stripped = path.strip('/')
    if method in ['GET', 'HEAD'] and '/' in stripped:
        # assume that this is an S3 GET request with URL path `/<bucket>/<key ...>`
        return config.PORT_S3

    if stripped and '/' not in stripped:
        if method == 'PUT':
            # assume that this is an S3 PUT bucket request with URL path `/<bucket>`
            return config.PORT_S3
        if method == 'POST' and is_s3_form_data(data_bytes):
            # assume that this is an S3 POST request with form parameters or multipart form in the body
            return config.PORT_S3
Пример #2
0
def get_api_from_custom_rules(method, path, data, headers):
    """ Determine backend port based on custom rules. """

    # detect S3 presigned URLs
    if 'AWSAccessKeyId=' in path or 'Signature=' in path:
        return 's3', config.PORT_S3

    # heuristic for SQS queue URLs
    if is_sqs_queue_url(path):
        return 'sqs', config.PORT_SQS

    # DynamoDB shell URLs
    if path.startswith('/shell') or path.startswith('/dynamodb/shell'):
        return 'dynamodb', config.PORT_DYNAMODB

    # API Gateway invocation URLs
    if ('/%s/' % PATH_USER_REQUEST) in path:
        return 'apigateway', config.PORT_APIGATEWAY

    data_bytes = to_bytes(data or '')

    if path == '/' and b'QueueName=' in data_bytes:
        return 'sqs', config.PORT_SQS

    if path.startswith('/2015-03-31/functions/'):
        return 'lambda', config.PORT_LAMBDA

    # TODO: move S3 public URLs to a separate port/endpoint, OR check ACLs here first
    stripped = path.strip('/')
    if method in ['GET', 'HEAD'] and '/' in stripped:
        # assume that this is an S3 GET request with URL path `/<bucket>/<key ...>`
        return 's3', config.PORT_S3

    # detect S3 URLs
    if stripped and '/' not in stripped:
        if method == 'HEAD':
            # assume that this is an S3 HEAD bucket request with URL path `/<bucket>`
            return config.PORT_S3
        if method == 'PUT':
            # assume that this is an S3 PUT bucket request with URL path `/<bucket>`
            return 's3', config.PORT_S3
        if method == 'POST' and is_s3_form_data(data_bytes):
            # assume that this is an S3 POST request with form parameters or multipart form in the body
            return 's3', config.PORT_S3

    if stripped.count('/') == 1 and method == 'PUT':
        # assume that this is an S3 PUT bucket object request with URL path `/<bucket>/object`
        return 's3', config.PORT_S3

    # detect S3 requests sent from aws-cli using --no-sign-request option
    if 'aws-cli/' in headers.get('User-Agent', ''):
        return 's3', config.PORT_S3

    # S3 delete object requests
    if method == 'POST' and 'delete=' in path and b'<Delete' in data_bytes and b'<Key>' in data_bytes:
        return 's3', config.PORT_S3

    # SQS queue requests
    if ('QueueUrl=' in path and 'Action=' in path) or (b'QueueUrl=' in data_bytes and b'Action=' in data_bytes):
        return 'sqs', config.PORT_SQS
Пример #3
0
def get_api_from_custom_rules(method, path, data, headers):
    """ Determine backend port based on custom rules. """

    # detect S3 presigned URLs
    if 'AWSAccessKeyId=' in path or 'Signature=' in path:
        return 's3', config.PORT_S3

    # heuristic for SQS queue URLs
    if is_sqs_queue_url(path):
        return 'sqs', config.PORT_SQS

    # DynamoDB shell URLs
    if path.startswith('/shell') or path.startswith('/dynamodb/shell'):
        return 'dynamodb', config.PORT_DYNAMODB

    # API Gateway invocation URLs
    if ('/%s/' % PATH_USER_REQUEST) in path:
        return 'apigateway', config.PORT_APIGATEWAY

    data_bytes = to_bytes(data or '')

    if path == '/' and b'QueueName=' in data_bytes:
        return 'sqs', config.PORT_SQS

    if 'Action=ConfirmSubscription' in path:
        return 'sns', config.PORT_SNS

    if path.startswith('/2015-03-31/functions/'):
        return 'lambda', config.PORT_LAMBDA

    if b'Action=AssumeRoleWithWebIdentity' in data_bytes or 'Action=AssumeRoleWithWebIdentity' in path:
        return 'sts', config.PORT_STS

    if b'Action=AssumeRoleWithSAML' in data_bytes or 'Action=AssumeRoleWithSAML' in path:
        return 'sts', config.PORT_STS

    # CloudWatch backdoor API to retrieve raw metrics
    if path.startswith(PATH_GET_RAW_METRICS):
        return 'cloudwatch', config.PORT_CLOUDWATCH

    # SQS queue requests
    if ('QueueUrl=' in path
            and 'Action=' in path) or (b'QueueUrl=' in data_bytes
                                       and b'Action=' in data_bytes):
        return 'sqs', config.PORT_SQS

    # TODO: move S3 public URLs to a separate port/endpoint, OR check ACLs here first
    stripped = path.strip('/')
    if method in ['GET', 'HEAD'] and '/' in stripped:
        # assume that this is an S3 GET request with URL path `/<bucket>/<key ...>`
        return 's3', config.PORT_S3

    # detect S3 URLs
    if stripped and '/' not in stripped:
        if method == 'HEAD':
            # assume that this is an S3 HEAD bucket request with URL path `/<bucket>`
            return 's3', config.PORT_S3
        if method == 'PUT':
            # assume that this is an S3 PUT bucket request with URL path `/<bucket>`
            return 's3', config.PORT_S3
        if method == 'POST' and is_s3_form_data(data_bytes):
            # assume that this is an S3 POST request with form parameters or multipart form in the body
            return 's3', config.PORT_S3

    # detect S3 requests sent from aws-cli using --no-sign-request option
    if 'aws-cli/' in headers.get('User-Agent', ''):
        return 's3', config.PORT_S3

    # S3 delete object requests
    if method == 'POST' and 'delete=' in path and b'<Delete' in data_bytes and b'<Key>' in data_bytes:
        return 's3', config.PORT_S3

    # Put Object API can have multiple keys
    if stripped.count('/') >= 1 and method == 'PUT':
        # assume that this is an S3 PUT bucket object request with URL path `/<bucket>/object`
        # or `/<bucket>/object/object1/+`
        return 's3', config.PORT_S3

    auth_header = headers.get('Authorization') or ''

    # detect S3 requests with "AWS id:key" Auth headers
    if auth_header.startswith('AWS '):
        return 's3', config.PORT_S3
Пример #4
0
def get_api_from_custom_rules(method, path, data, headers):
    """Determine backend port based on custom rules."""

    # API Gateway invocation URLs
    if ("/%s/" % PATH_USER_REQUEST) in path:
        return "apigateway", config.service_port("apigateway")

    # detect S3 presigned URLs
    if "AWSAccessKeyId=" in path or "Signature=" in path:
        return "s3", config.service_port("s3")

    # heuristic for SQS queue URLs
    if is_sqs_queue_url(path):
        return "sqs", config.service_port("sqs")

    # DynamoDB shell URLs
    if path.startswith("/shell") or path.startswith("/dynamodb/shell"):
        return "dynamodb", config.service_port("dynamodb")

    data_bytes = to_bytes(data or "")
    version, action = extract_version_and_action(path, data_bytes)

    def _in_path_or_payload(search_str):
        return to_str(search_str) in path or to_bytes(search_str) in data_bytes

    if path == "/" and b"QueueName=" in data_bytes:
        return "sqs", config.service_port("sqs")

    if "Action=ConfirmSubscription" in path:
        return "sns", config.service_port("sns")

    if path.startswith("/2015-03-31/functions/"):
        return "lambda", config.service_port("lambda")

    if _in_path_or_payload("Action=AssumeRoleWithWebIdentity"):
        return "sts", config.service_port("sts")

    if _in_path_or_payload("Action=AssumeRoleWithSAML"):
        return "sts", config.service_port("sts")

    if _in_path_or_payload("Action=AssumeRole"):
        return "sts", config.service_port("sts")

    # CloudWatch backdoor API to retrieve raw metrics
    if path.startswith(PATH_GET_RAW_METRICS):
        return "cloudwatch", config.service_port("cloudwatch")

    # SQS queue requests
    if _in_path_or_payload("QueueUrl=") and _in_path_or_payload("Action="):
        return "sqs", config.service_port("sqs")
    if matches_service_action("sqs", action, version=version):
        return "sqs", config.service_port("sqs")

    # SNS topic requests
    if matches_service_action("sns", action, version=version):
        return "sns", config.service_port("sns")

    # TODO: move S3 public URLs to a separate port/endpoint, OR check ACLs here first
    stripped = path.strip("/")
    if method in ["GET", "HEAD"] and stripped:
        # assume that this is an S3 GET request with URL path `/<bucket>/<key ...>`
        return "s3", config.service_port("s3")

    # detect S3 URLs
    if stripped and "/" not in stripped:
        if method == "PUT":
            # assume that this is an S3 PUT bucket request with URL path `/<bucket>`
            return "s3", config.service_port("s3")
        if method == "POST" and is_s3_form_data(data_bytes):
            # assume that this is an S3 POST request with form parameters or multipart form in the body
            return "s3", config.service_port("s3")

    # detect S3 requests sent from aws-cli using --no-sign-request option
    if "aws-cli/" in headers.get("User-Agent", ""):
        return "s3", config.service_port("s3")

    # S3 delete object requests
    if (method == "POST" and "delete=" in path and b"<Delete" in data_bytes
            and b"<Key>" in data_bytes):
        return "s3", config.service_port("s3")

    # Put Object API can have multiple keys
    if stripped.count("/") >= 1 and method == "PUT":
        # assume that this is an S3 PUT bucket object request with URL path `/<bucket>/object`
        # or `/<bucket>/object/object1/+`
        return "s3", config.service_port("s3")

    auth_header = headers.get("Authorization") or ""

    # detect S3 requests with "AWS id:key" Auth headers
    if auth_header.startswith("AWS "):
        return "s3", config.service_port("s3")

    # certain EC2 requests from Java SDK contain no Auth headers (issue #3805)
    if b"Version=2016-11-15" in data_bytes:
        return "ec2", config.service_port("ec2")