def handler_wrapper(event, context, **kwargs): for param in required_querystring if required_querystring else {}: value = utils.deep_get(event, 'queryStringParameters', param) if not value: logger.error( f'queryStringParameter [{param}] missing from event [{event}].' ) return { 'statusCode': 400, 'body': error or f'Invalid {param}.' } kwargs[param] = value for param in optional_querystring if optional_querystring else {}: value = utils.deep_get(event, 'queryStringParameters', param) if value: kwargs[param] = value for param in path if path else {}: value = utils.deep_get(event, 'pathParameters', param) if not value: logger.error( f'pathParameter [{param}] missing from event [{event}].' ) return { 'statusCode': 400, 'body': error or f'Invalid {param}.' } kwargs[param] = value return handler(event, context, **kwargs)
def test_environ_aware_opts(context): event = {} handler = decs.environ_aware(required=[], optional=['NAMESPACE', 'FOO'])(identity_handler) response = handler(event, None) assert utils.deep_get(response, 'body', 'kwargs', 'NAMESPACE') == context.os['environ']['NAMESPACE'] assert not utils.deep_get(response, 'body', 'kwargs', 'FOO')
def test_sub_aware(): event = { 'requestContext': { 'authorizer': { 'sub': 'uuid', }, }, } handler = decs.sub_aware(identity_handler) response = handler(event, None) assert utils.deep_get(response, 'body', 'kwargs', 'sub') == utils.deep_get(event, 'requestContext', 'authorizer', 'sub')
def handler_wrapper(event, context, **kwargs): logger.debug(f'Checking origin for event: {event}') # Check Origin request_origin = utils.deep_get(event, 'headers', 'origin', ignore_case=True) if not any(re.match(o, str(request_origin)) for o in origins): logger.warning(f'Invalid request origin: {request_origin}') return {'statusCode': 403, 'body': 'Unknown origin.'} # call handler kwargs['request_origin'] = request_origin response = handler(event, context, **kwargs) if not isinstance(response, dict): raise Exception( f'Unsupported response type {type(response)}; response must be dict for *_response decorators.' ) # add origin to response headers current_headers = response.get('headers', {}) cors_headers = { 'Access-Control-Allow-Origin': request_origin, 'Access-Control-Allow-Credentials': 'true' } response['headers'] = {**current_headers, **cors_headers} return response
def test_namespace_aware(context): event = {} handler = decs.namespace_aware(identity_handler) response = handler(event, None) assert utils.deep_get(response, 'body', 'kwargs', 'NAMESPACE') == context.os['environ']['NAMESPACE']
def test_domain_aware(): domain = 'test.com' event = {'requestContext': {'authorizer': {'domain': domain}}} handler = decs.domain_aware(identity_handler) response = handler(event, None) assert utils.deep_get(response, 'body', 'kwargs', 'domain') == domain
def test_body(): body = {'a': 1, 'b': 2, 'c': 3} event = {'body': json.dumps(body)} handler = decs.body(required=body.keys())(identity_handler) response = handler(event, None) kwargs_body = utils.deep_get(response, 'body', 'kwargs', 'body') assert all([k in kwargs_body for k in body])
def test_body_missing_optional_key(): body = {'a': 1, 'b': 2, 'c': 3} event = {'body': json.dumps({k: body[k] for k in ['a', 'b']})} handler = decs.body(optional=body.keys())(identity_handler) response = handler(event, None) kwargs_body = utils.deep_get(response, 'body', 'kwargs', 'body') assert all([k in kwargs_body for k in body])
def handler_wrapper(event, context, **kwargs): sub = utils.deep_get(event, 'requestContext', 'authorizer', 'sub') if not sub: logger.error('Sub requestContext variable missing.') return {'statusCode': 500, 'body': 'Invalid sub.'} kwargs['sub'] = sub return handler(event, context, **kwargs)
def handler_wrapper(event, context, **kwargs): domain = utils.deep_get(event, 'requestContext', 'authorizer', 'domain') if not domain: logger.error('Domain requestContext variable missing.') raise HTTPResponseException('Invalid domain.') kwargs['domain'] = domain return handler(event, context, **kwargs)
def handler_wrapper(event, context, **kwargs): sub = utils.deep_get(event, 'requestContext', 'authorizer', 'sub') if not sub: logger.error('Sub requestContext variable missing.') raise HTTPResponseException('Invalid sub.') kwargs['sub'] = sub return handler(event, context, **kwargs)
def test_cors_origin_ok(context): origins = [ 'https://app.cloudzero.com', 'https://deeply.nested.subdomain.cloudzero.com' ] for origin in origins: event = {'headers': {'origin': origin}} handler = decs.allow_origin_response(r'.*\.cloudzero\.com')( identity_handler) response = handler(event, None) assert utils.deep_get(response, 'body', 'kwargs', 'request_origin') == origin assert utils.deep_get(response, 'headers', 'Access-Control-Allow-Origin') == origin assert utils.deep_get(response, 'headers', 'Access-Control-Allow-Credentials') == 'true'
def handler_wrapper(event, context, **kwargs): domain = utils.deep_get(event, 'requestContext', 'authorizer', 'domain') if not domain: logger.error('Domain requestContext variable missing.') return {'statusCode': 500, 'body': 'Invalid domain.'} kwargs['domain'] = domain return handler(event, context, **kwargs)
def handler_wrapper(event, context, **kwargs): token_scopes = utils.deep_get(event, 'requestContext', 'authorizer', 'scopes') if not token_scopes: raise HTTPResponseException('Invalid token scopes: missing!') if not all((s in token_scopes for s in string_scope_list)): logger.warning(f'There is a required scope [{scope_list}] missing from token scopes [{token_scopes}].') raise HTTPResponseException('access_token has insufficient access.', statusCode=403) return handler(event, context, **kwargs)
def test_deep_get_exact_match(): input_dict = { 'foo': { '123': 'abc', '456': 'def' }, 'bar': { '789': 'ghi', '012': 'jkl' }, 'baz': { '345': 'mno', '678': 'pqr' } } result = utils.deep_get(input_dict, 'baz', '345') assert 'mno' == result result = utils.deep_get(input_dict, 'foo') assert {'123': 'abc', '456': 'def'} == result result = utils.deep_get(input_dict, 'BaR', '012') assert result is None
def test_deep_get_no_match(): input_dict = { 'foo': { '123': 'abc', '456': 'def' }, 'bar': { '789': 'ghi', '012': 'jkl' }, 'baz': { '345': 'mno', '678': 'pqr' } } result = utils.deep_get(input_dict, 'bar', 'aaa') assert result is None result = utils.deep_get(input_dict, 'foobar') assert result is None result = utils.deep_get(input_dict, None) assert result is None
def test_deep_get_case_mixed_keys(): input_dict = { frozenset({1, 2, 3}): { 123: 'abc', 456.9: 'def' }, 123: { (3, 4): 'ghi', (5, 6): 'jkl' }, (1, 2): { '345': 'mno', '678': 'pqr' } } result = utils.deep_get(input_dict, 123, (5, 6), ignore_case=True) assert 'jkl' == result result = utils.deep_get(input_dict, (1, 2), '678', ignore_case=False) assert 'pqr' == result result = utils.deep_get(input_dict, frozenset({1, 2, 3}), 456.9) assert 'def' == result
def test_deep_get_case_insensitive_match(): input_dict = { 'foo': { '123': 'abc', '456': 'def', 'AAA': { 'BBB': '919' } }, 'bar': { '789': 'ghi', '012': 'jkl' }, 'bAz': { '345': 'mno', '678': 'pqr' } } result = utils.deep_get(input_dict, 'BaR', '012', ignore_case=True) assert 'jkl' == result result = utils.deep_get(input_dict, 'bar', '012', ignore_case=True) assert 'jkl' == result result = utils.deep_get(input_dict, 'baz', '345', ignore_case=True) assert 'mno' == result result = utils.deep_get(input_dict, 'FOO', 'aAa', 'BbB', ignore_case=True) assert '919' == result result = utils.deep_get(input_dict, 'BaR', '012', ignore_case=False) assert result is None result = utils.deep_get(input_dict, 'bar', '012', ignore_case=False) assert 'jkl' == result
def test_cors_origin_not_case_sensitive(context): origins = [ 'https://app.cloudzero.com', 'https://deeply.nested.subdomain.cloudzero.com' ] for origin in origins: event = { 'headers': { 'Origin': origin # CloudFront often rewrites headers and may assign different case like this } } handler = decs.allow_origin_response(r'.*\.cloudzero\.com')( identity_handler) response = handler(event, None) assert utils.deep_get(response, 'body', 'kwargs', 'request_origin') == origin assert utils.deep_get(response, 'headers', 'Access-Control-Allow-Origin') == origin assert utils.deep_get(response, 'headers', 'Access-Control-Allow-Credentials') == 'true'
def handler_wrapper(event, context, **kwargs): token_scopes = utils.deep_get(event, 'requestContext', 'authorizer', 'scopes') if not token_scopes: return { 'statusCode': 500, 'body': 'Invalid token scopes: missing!' } if not all((s in token_scopes for s in string_scope_list)): logger.warning( f'There is a required scope [{scope_list}] missing from token scopes [{token_scopes}].' ) return { 'statusCode': 403, 'body': 'access_token has insufficient access.' } return handler(event, context, **kwargs)
def test_parameters_missing_optional_querystring(): required_qs_params = {'a': 1, 'b': 2} optional_qs_params = {'c': 1, 'd': 2} path_params = {'e': 1, 'f': 2} event = { 'queryStringParameters': required_qs_params, 'pathParameters': path_params, } handler = decs.parameters(required_querystring=required_qs_params.keys(), optional_querystring=optional_qs_params.keys(), path=path_params.keys())(identity_handler) response = handler(event, None) response_kwargs = utils.deep_get(response, 'body', 'kwargs') expected_params = dict() expected_params.update(**required_qs_params, **path_params) assert all([ response_kwargs.get(ek) and response_kwargs[ek] == ev for ek, ev in (expected_params.items()) ])
def test_deep_get_identity_input(): result = utils.deep_get({'foo': 'bar'}) assert result == {'foo': 'bar'}
def test_deep_get_bad_input(): result = utils.deep_get(None, 'foo', '012') assert result is None result = utils.deep_get([], 'foo', '012') assert result is None