Skip to content

Commit

Permalink
Fix: 4xx and 5xx responses from API Gateway cause Invicti findings (#154
Browse files Browse the repository at this point in the history
)
  • Loading branch information
dsotirho-ucsc committed Sep 14, 2024
1 parent 416e7b4 commit 67ae8d0
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
28 changes: 27 additions & 1 deletion src/azul/terraform.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
config,
require,
)
from azul.chalice import (
AzulChaliceApp,
)
from azul.deployment import (
aws,
)
Expand Down Expand Up @@ -800,11 +803,34 @@ def tf_config(self, app_name):
# Setting this property using AWS API Gateway extensions to the OpenAPI
# specification works around this issue.
#
# We ran into similar difficulties when using Terraform to configure
# default responses for the API, so we use these extensions for that
# purpose, too.
#
openapi_spec = json.loads(locals[app_name])
rest_api = resources['aws_api_gateway_rest_api'][app_name]
assert 'minimum_compression_size' not in rest_api, rest_api
openapi_spec = json.loads(locals[app_name])
key = 'x-amazon-apigateway-minimum-compression-size'
openapi_spec[key] = config.minimum_compression_size
assert 'aws_api_gateway_gateway_response' not in resources, resources
openapi_spec['x-amazon-apigateway-gateway-responses'] = {
f'DEFAULT_{response_type}': {
'responseParameters': {
# Static value response header parameters must be enclosed
# within a pair of single quotes.
#
# https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html#mapping-response-parameters
# https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-gateway-responses.html
#
# Note that azul.strings.single_quote() is not used here
# since API Gateway allows internal single quotes in the
# value, which that function would prohibit.
#
f'gatewayresponse.header.{k}': f"'{v}'"
for k, v in AzulChaliceApp.default_response_headers.items()
}
} for response_type in ['4XX', '5XX']
}
locals[app_name] = json.dumps(openapi_spec)

return {
Expand Down
8 changes: 8 additions & 0 deletions test/integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2093,3 +2093,11 @@ def test_response_security_headers(self):
response.raise_for_status()
expected = AzulChaliceApp.security_headers | expected_headers
self.assertIsSubset(expected.items(), response.headers.items())

def test_default_4xx_response_headers(self):
for endpoint in (config.service_endpoint, config.indexer_endpoint):
with self.subTest(endpoint=endpoint):
response = requests.get(str(endpoint / 'does-not-exist'))
self.assertEqual(403, response.status_code)
self.assertIsSubset(AzulChaliceApp.default_response_headers.items(),
response.headers.items())

0 comments on commit 67ae8d0

Please sign in to comment.