Example #1
0
    def test_get_binary_support_binary_custom_text_with_gzip_content_encoding(
            self, simple_app, text_content_type):
        simple_app.handler = make_lambda_handler(
            simple_app,
            binary_support=True,
            non_binary_content_type_prefixes=
            CUSTOM_NON_BINARY_CONTENT_TYPE_PREFIXES,
        )
        simple_app.headers = [
            ("Content-Type", text_content_type),
            ("Content-Encoding", "gzip"),
        ]
        simple_app.response = b"\x13\x37"

        response = simple_app.handler(make_v2_event(), None)

        assert response == {
            "statusCode": 200,
            "cookies": [],
            "headers": {
                "content-type": text_content_type,
                "content-encoding": "gzip",
            },
            "isBase64Encoded": True,
            "body": b64encode(b"\x13\x37").decode("utf-8"),
        }
Example #2
0
 def __init__(
     self,
     headers: list[tuple[str, str]],
     response: bytes,
     exc_info: _ExcInfoType,
 ) -> None:
     self.headers = headers
     self.response = response
     self.exc_info = exc_info
     self.handler = make_lambda_handler(self)
Example #3
0
def test_get_binary_support_default_text_content_types(simple_app, text_content_type):
    simple_app.handler = make_lambda_handler(simple_app, binary_support=True)
    simple_app.headers = [("Content-Type", text_content_type)]

    response = simple_app.handler(make_event(), None)
    assert response == {
        "statusCode": 200,
        "headers": {"Content-Type": text_content_type},
        "body": "Hello World\n",
    }
Example #4
0
    def test_empty_and_uncloseable_content(self):
        def app(environ, start_response):
            start_response("200 OK", [], None)
            return [b"Hi", b"", b" there!", b""]

        handler = make_lambda_handler(app)
        event = make_v2_event()

        response = handler(event, None)

        assert response["body"] == b64encode(b"Hi there!").decode("utf-8")
def simple_app():
    def app(environ, start_response):
        app.environ = environ
        start_response('200 OK', app.headers, app.exc_info)
        return BytesIO(app.response)

    app.headers = [('Content-Type', 'text/plain')]
    app.response = b'Hello World\n'
    app.handler = make_lambda_handler(app)
    app.exc_info = None
    yield app
Example #6
0
def simple_app():
    def app(environ, start_response):
        app.environ = environ
        start_response("200 OK", app.headers, app.exc_info)
        return BytesIO(app.response)

    app.headers = [("Content-Type", "text/plain")]
    app.response = b"Hello World\n"
    app.handler = make_lambda_handler(app)
    app.exc_info = None
    yield app
def test_get_binary_support_text(simple_app):
    simple_app.handler = make_lambda_handler(simple_app, binary_support=True)

    response = simple_app.handler(make_event(), None)

    assert response == {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'text/plain'
        },
        'body': 'Hello World\n',
    }
Example #8
0
def test_get_binary_support_text(simple_app):
    simple_app.handler = make_lambda_handler(simple_app, binary_support=True)

    response = simple_app.handler(make_event(), None)

    assert response == {
        "statusCode": 200,
        "headers": {
            "Content-Type": "text/plain"
        },
        "body": "Hello World\n",
    }
Example #9
0
def test_post_binary_support(simple_app):
    simple_app.handler = make_lambda_handler(simple_app)
    event = make_event(method="POST", body="dogfood", binary=True)

    response = simple_app.handler(event, None)

    assert simple_app.environ["wsgi.input"].read() == b"dogfood"
    assert simple_app.environ["CONTENT_LENGTH"] == str(len(b"dogfood"))
    assert response == {
        "statusCode": 200,
        "headers": {"Content-Type": "text/plain"},
        "body": "Hello World\n",
    }
Example #10
0
def test_override_wsgi_errors(simple_app):
    class customLogger:
        def write(self, data):
            pass

        def flush(self):
            pass

    errorsTo = customLogger()
    simple_app.handler = make_lambda_handler(simple_app, wsgi_errors=errorsTo)
    simple_app.handler(make_event(), None)

    assert simple_app.environ["wsgi.errors"] == errorsTo
def lambda_handler(event, context):
    """Entry point for web requests"""
    global _real_handler

    if _real_handler is None:
        install_secrets()

        from apig_wsgi import make_lambda_handler
        from django.core.wsgi import get_wsgi_application
        application = get_wsgi_application()
        _real_handler = make_lambda_handler(application)

    return _real_handler(event, context)
Example #12
0
def test_get_binary_support_binary(simple_app):
    simple_app.handler = make_lambda_handler(simple_app, binary_support=True)
    simple_app.headers = [("Content-Type", "application/octet-stream")]
    simple_app.response = b"\x13\x37"

    response = simple_app.handler(make_event(), None)

    assert response == {
        "statusCode": 200,
        "headers": {"Content-Type": "application/octet-stream"},
        "body": b64encode(b"\x13\x37").decode("utf-8"),
        "isBase64Encoded": True,
    }
def test_get_binary_support_no_content_type(simple_app):
    simple_app.handler = make_lambda_handler(simple_app, binary_support=True)
    simple_app.headers = []
    simple_app.response = b'\x13\x37'

    response = simple_app.handler(make_event(), None)

    assert response == {
        'statusCode': 200,
        'headers': {},
        'body': b64encode(b'\x13\x37').decode('utf-8'),
        'isBase64Encoded': True,
    }
Example #14
0
def test_get_binary_support_no_content_type(simple_app):
    simple_app.handler = make_lambda_handler(simple_app, binary_support=True)
    simple_app.headers = []
    simple_app.response = b"\x13\x37"

    response = simple_app.handler(make_event(), None)

    assert response == {
        "statusCode": 200,
        "multiValueHeaders": {},
        "body": b64encode(b"\x13\x37").decode("utf-8"),
        "isBase64Encoded": True,
    }
Example #15
0
def test_get_binary_support_custom_text_content_types(simple_app, text_content_type):
    simple_app.handler = make_lambda_handler(
        simple_app,
        binary_support=True,
        non_binary_content_type_prefixes=CUSTOM_NON_BINARY_CONTENT_TYPE_PREFIXES,
    )
    simple_app.headers = [("Content-Type", text_content_type)]

    response = simple_app.handler(make_event(), None)
    assert response == {
        "statusCode": 200,
        "headers": {"Content-Type": text_content_type},
        "body": "Hello World\n",
    }
Example #16
0
    def test_get_binary_support_default_text_content_types(
            self, simple_app, text_content_type):
        simple_app.handler = make_lambda_handler(simple_app,
                                                 binary_support=True)
        simple_app.headers = [("Content-Type", text_content_type)]

        response = simple_app.handler(make_v1_event(), None)
        assert response == {
            "statusCode": 200,
            "multiValueHeaders": {
                "Content-Type": [text_content_type]
            },
            "isBase64Encoded": False,
            "body": "Hello World\n",
        }
def test_get_binary_support_binary(simple_app):
    simple_app.handler = make_lambda_handler(simple_app, binary_support=True)
    simple_app.headers = [('Content-Type', 'application/octet-stream')]
    simple_app.response = b'\x13\x37'

    response = simple_app.handler(make_event(), None)

    assert response == {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'application/octet-stream'
        },
        'body': b64encode(b'\x13\x37').decode('utf-8'),
        'isBase64Encoded': True,
    }
def test_post_binary_support(simple_app):
    simple_app.handler = make_lambda_handler(simple_app)
    event = make_event(method='POST', body='dogfood', binary=True)

    response = simple_app.handler(event, None)

    assert simple_app.environ['wsgi.input'].read() == b'dogfood'
    assert simple_app.environ['CONTENT_LENGTH'] == str(len(b'dogfood'))
    assert response == {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'text/plain'
        },
        'body': 'Hello World\n',
    }
Example #19
0
    def test_get_binary_support_default_text_content_types(
            self, simple_app: App, text_content_type: str) -> None:
        simple_app.handler = make_lambda_handler(simple_app,
                                                 binary_support=True)
        simple_app.headers = [("Content-Type", text_content_type)]

        response = simple_app.handler(make_v2_event(), None)
        assert response == {
            "statusCode": 200,
            "cookies": [],
            "headers": {
                "content-type": text_content_type
            },
            "isBase64Encoded": False,
            "body": "Hello World\n",
        }
Example #20
0
def test_get_binary_support_binary_default_text_with_gzip_content_encoding(
    simple_app, text_content_type
):
    simple_app.handler = make_lambda_handler(simple_app, binary_support=True)
    simple_app.headers = [
        ("Content-Type", text_content_type),
        ("Content-Encoding", "gzip"),
    ]
    simple_app.response = b"\x13\x37"

    response = simple_app.handler(make_event(), None)

    assert response == {
        "statusCode": 200,
        "headers": {"Content-Type": text_content_type, "Content-Encoding": "gzip"},
        "body": b64encode(b"\x13\x37").decode("utf-8"),
        "isBase64Encoded": True,
    }
Example #21
0
    def test_get_binary_support_custom_text_content_types(
            self, simple_app: App, text_content_type: str) -> None:
        simple_app.handler = make_lambda_handler(
            simple_app,
            binary_support=True,
            non_binary_content_type_prefixes=
            CUSTOM_NON_BINARY_CONTENT_TYPE_PREFIXES,
        )
        simple_app.headers = [("Content-Type", text_content_type)]

        response = simple_app.handler(make_v1_event(), None)
        assert response == {
            "statusCode": 200,
            "multiValueHeaders": {
                "Content-Type": [text_content_type]
            },
            "isBase64Encoded": False,
            "body": "Hello World\n",
        }
import os
from apig_wsgi import make_lambda_handler
from application import create_app

app = create_app()


def proxied_app(environ, start_response):
    environ["SCRIPT_NAME"] = os.environ["stage_mount_point"]
    return app(environ, start_response)


lambda_handler = make_lambda_handler(proxied_app)
Example #23
0
from hmalib.common.logging import get_logger

from .action_rules_api import get_action_rules_api
from .actions_api import get_actions_api
from .content import get_content_api
from .datasets_api import get_datasets_api
from .matches import get_matches_api
from .stats import get_stats_api
from .submit import get_submit_api

# Set to 10MB for images
bottle.BaseRequest.MEMFILE_MAX = 10 * 1024 * 1024

app = bottle.default_app()
apig_wsgi_handler = make_lambda_handler(app)

logger = get_logger(__name__)

s3_client = boto3.client("s3")
dynamodb = boto3.resource("dynamodb")

THREAT_EXCHANGE_DATA_BUCKET_NAME = os.environ["THREAT_EXCHANGE_DATA_BUCKET_NAME"]
THREAT_EXCHANGE_DATA_FOLDER = os.environ["THREAT_EXCHANGE_DATA_FOLDER"]
THREAT_EXCHANGE_PDQ_FILE_EXTENSION = os.environ["THREAT_EXCHANGE_PDQ_FILE_EXTENSION"]
HMA_CONFIG_TABLE = os.environ["HMA_CONFIG_TABLE"]
DYNAMODB_TABLE = os.environ["DYNAMODB_TABLE"]
IMAGE_BUCKET_NAME = os.environ["IMAGE_BUCKET_NAME"]
IMAGE_FOLDER_KEY = os.environ[
    "IMAGE_FOLDER_KEY"
]  # Misnamed, this is a prefix, not a key, if renaming, use IMAGE_PREFIX
Example #24
0
    "tuckboxes": "Card Tuckboxes",
}

flask_app = Flask(__name__)
bootstrap = Bootstrap(flask_app)

secret_key = os.environ["FLASK_SECRET_KEY"]
assert secret_key, "Need secret key specified in env"
flask_app.config["SECRET_KEY"] = secret_key
flask_app.config["UPLOADS_DEFAULT_DEST"] = "/tmp"
flask_app.config["UPLOADED_FILES_ALLOW"] = IMAGES

logger = logging.getLogger("bgtools_logger")
logger.setLevel(int(os.environ.get("LOG_LEVEL", logging.INFO)))

apig_wsgi_handler = apig_wsgi.make_lambda_handler(flask_app,
                                                  binary_support=True)

if os.environ.get("DEBUG"):
    apig_wsgi_handler_helper = apig_wsgi_handler

    def apig_wsgi_handler(event, context):
        logger.info("in apig handler")
        print(json.dumps(event, indent=2, sort_keys=True))
        response = apig_wsgi_handler_helper(event, context)
        print(json.dumps(response, indent=2, sort_keys=True))
        return response


def get_pages():
    return {url_for(p): n for p, n in PAGES.items()}
Example #25
0
def bottle_init_once() -> t.Tuple[bottle.AppStack, t.Callable[
    [t.Dict[str, t.Any], t.Any], t.Dict[str, t.Any]]]:
    """
    Meant to be called once per lambda instance. Returns a bottle app and an
    api_wsgi_handler that can be plugged into a lambda handler.

    The method also serves as a closure for all dependencies that need to be
    resolved at startup.
    """
    app = bottle.default_app()

    # Initialize hmaconfig at module level. Mounted SubApps need not initialize
    # their own HMAConfigs.
    HMAConfig.initialize(HMA_CONFIG_TABLE)

    functionality_mapping = get_pytx_functionality_mapping()

    @app.get("/root/")
    def root():
        """
        root endpoint to make sure the API is live and check when it was last updated
        """
        context = bottle.request.environ.get("apig_wsgi.context")
        invoked_function_arn = context.invoked_function_arn
        client = boto3.client("lambda")
        last_modified = client.get_function_configuration(
            FunctionName=invoked_function_arn)["LastModified"]

        return {
            "message": "Welcome to the HMA API!",
            "last_modified": last_modified,
        }

    app.mount(
        "/action-rules/",
        get_action_rules_api(hma_config_table=HMA_CONFIG_TABLE),
    )

    app.mount(
        "/matches/",
        get_matches_api(
            datastore_table=dynamodb.Table(DYNAMODB_TABLE),
            hma_config_table=HMA_CONFIG_TABLE,
            indexes_bucket_name=INDEXES_BUCKET_NAME,
            writeback_queue_url=WRITEBACK_QUEUE_URL,
            bank_table=dynamodb.Table(BANKS_TABLE),
            signal_type_mapping=functionality_mapping.signal_and_content,
        ),
    )

    app.mount(
        "/content/",
        get_content_api(
            dynamodb_table=dynamodb.Table(DYNAMODB_TABLE),
            image_bucket=IMAGE_BUCKET_NAME,
            image_prefix=IMAGE_PREFIX,
            signal_type_mapping=functionality_mapping.signal_and_content,
        ),
    )

    app.mount(
        "/submit/",
        get_submit_api(
            dynamodb_table=dynamodb.Table(DYNAMODB_TABLE),
            image_bucket=IMAGE_BUCKET_NAME,
            image_prefix=IMAGE_PREFIX,
            submissions_queue_url=SUBMISSIONS_QUEUE_URL,
            hash_queue_url=HASHES_QUEUE_URL,
            signal_type_mapping=functionality_mapping.signal_and_content,
        ),
    )

    app.mount(
        "/datasets/",
        get_datasets_api(
            hma_config_table=HMA_CONFIG_TABLE,
            datastore_table=dynamodb.Table(DYNAMODB_TABLE),
            threat_exchange_data_bucket_name=THREAT_EXCHANGE_DATA_BUCKET_NAME,
            threat_exchange_data_folder=THREAT_EXCHANGE_DATA_FOLDER,
        ),
    )

    app.mount("/stats/",
              get_stats_api(counts_table=dynamodb.Table(COUNTS_TABLE_NAME)))

    app.mount(
        "/actions/",
        get_actions_api(hma_config_table=HMA_CONFIG_TABLE),
    )

    app.mount(
        "/banks/",
        get_bank_api(
            bank_table=dynamodb.Table(BANKS_TABLE),
            bank_user_media_bucket=BANKS_MEDIA_BUCKET_NAME,
            submissions_queue_url=SUBMISSIONS_QUEUE_URL,
            signal_type_mapping=functionality_mapping.signal_and_content,
        ),
    )

    app.mount(
        "/indexes/",
        get_indexes_api(
            indexes_bucket_name=INDEXES_BUCKET_NAME,
            indexer_function_name=INDEXER_FUNCTION_NAME,
        ),
    )

    app.mount(
        "/lcc/",
        get_lcc_api(
            storage_path=LCC_DURABLE_FS_PATH,
            signal_type_mapping=functionality_mapping.signal_and_content,
        ),
    )

    apig_wsgi_handler = make_lambda_handler(app)
    return (app, apig_wsgi_handler)
Example #26
0
import json
import os

from django.core.wsgi import get_wsgi_application

from apig_wsgi import make_lambda_handler

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testapp.settings")

application = get_wsgi_application()

apig_wsgi_handler = make_lambda_handler(application, binary_support=True)


def lambda_handler(event, context):
    print(json.dumps(event, indent=2, sort_keys=True))
    response = apig_wsgi_handler(event, context)
    print(json.dumps(response, indent=2, sort_keys=True))
    return response
Example #27
0
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
app.url_map.redirect_defaults = False
preview_app = Flask("Preview")

if GITHUB_APP_ID and GITHUB_APP_KEY and GITHUB_APP_SECRET:
    preview_app.config['GITHUBAPP_ID'] = int(GITHUB_APP_ID)
    preview_app.config['GITHUBAPP_KEY'] = reformat_ssh_key_to_pem_bytes(GITHUB_APP_KEY)
    preview_app.config['GITHUBAPP_SECRET'] = GITHUB_APP_SECRET
    app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {'/preview': preview_app})
else:
    preview_app.config['GITHUBAPP_ID'] = 0
    preview_app.config['GITHUBAPP_KEY'] = None
    preview_app.config['GITHUBAPP_SECRET'] = False

github_app = GitHubApp(preview_app)
handler = make_lambda_handler(app.wsgi_app)


@app.route('/')
def index():
    return render_template('index.html', stack="/" + os.getenv('BUCKET_PATH') if os.getenv('BUCKET_PATH') else '')


@app.route('/swagger.yml')
def swagger():
    return render_template('swagger.yml', local_url=f"- url: {os.getenv('API_URL')}" if os.getenv('API_URL') else '')


@app.route('/plugins/index')
def plugin_index() -> Response:
    return jsonify(get_index())
Example #28
0
def assign_lambda_handler(module_name: str,
                          wsgi_app,
                          wrap_handler: WrapAwsHandlerFunc = None):
    """Defines the global `handler` function in the loaded module
    named `module_name`.

    If the module is not loaded, does nothing.
    If the module already has `handler`, does nothing.

    Otherwise the `handler` is initialized with a function ready to process
    AWS Lambda requests. The requests will be processed with `app`.
    """

    #
    # When we programmatically call `ric_main` with `basename.handler`
    # argument, it will try to import file `basename.py` as module
    # `basename`, and then use the `handler` defined there.
    #
    # The easiest way is just declare the `handler` function inside the
    # `basename.py`.
    #
    # ```
    # def handler(event, context):
    #   pass
    # ```
    #
    #
    # PROBLEM 1
    # ---------
    #
    # We want to keep `basename.py` as simple as possible. We
    # assume, it contains only
    #
    # ```
    #   start(app) # app is Flask
    # ```
    #
    # It means, we have to detect the module, from which the `start`
    # is called (it's `basename`) and dynamically assign the handler
    # to it.
    #
    #
    # PROBLEM 2
    # ---------
    #
    # We also assume, that the `basename.py` is the entrypoint:
    # the Dockerfile runs it as ENTRYPOINT ["python", "basename.py"].
    #
    # So when it executed for the first time (as entrypoint), the
    # `basename.py` has name "__main__". Then ric_main will re-import
    # the same file under name "basename".
    #
    # We have to assign the `handler` to the `basename` module only
    # when it is re-imported by the `ric_main`. Defining `handler` on
    # `__main__` will have to effect.

    if module_name not in sys.modules:
        return
    module = sys.modules.get(module_name)
    if not module:
        return
    if 'handler' in module.__dict__:
        print(f'{module} already has the `handler` defined')
        return

    # noinspection PyTypeChecker
    aws_handler: AwsHandlerFunc = make_lambda_handler(wsgi_app,
                                                      binary_support=True)

    # todo unit test
    if wrap_handler is not None:
        aws_handler = wrap_handler(aws_handler)

    module.__dict__['handler'] = aws_handler
import logging

from apig_wsgi import make_lambda_handler
from aws_xray_sdk.ext.flask.middleware import XRayMiddleware
from aws_xray_sdk.core import xray_recorder
from bc_lambda import bc_lambda

import project

_app = project.create_app()

xray_recorder.configure(service='ProjectName')
XRayMiddleware(_app, xray_recorder)

_decorator = bc_lambda(level=logging.INFO, service='ProjectName')
handler = _decorator(make_lambda_handler(_app))
Example #30
0
import os

from apig_wsgi import make_lambda_handler
from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testapp.settings')

application = get_wsgi_application()

lambda_handler = make_lambda_handler(application)