diff --git a/ansible/files/envoy_config/cds.yaml b/ansible/files/envoy_config/cds.yaml index 8f921396a..48fd1b9a5 100644 --- a/ansible/files/envoy_config/cds.yaml +++ b/ansible/files/envoy_config/cds.yaml @@ -10,6 +10,16 @@ resources: socket_address: address: 127.0.0.1 port_value: 8085 + circuit_breakers: + thresholds: + - priority: DEFAULT + max_connections: 10000 + max_pending_requests: 10000 + max_requests: 10000 + retry_budget: + budget_percent: + value: 100 + min_retry_concurrency: 100 - '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster name: gotrue load_assignment: @@ -21,6 +31,16 @@ resources: socket_address: address: 127.0.0.1 port_value: 9999 + circuit_breakers: + thresholds: + - priority: DEFAULT + max_connections: 10000 + max_pending_requests: 10000 + max_requests: 10000 + retry_budget: + budget_percent: + value: 100 + min_retry_concurrency: 100 - '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster name: postgrest load_assignment: @@ -32,6 +52,16 @@ resources: socket_address: address: 127.0.0.1 port_value: 3000 + circuit_breakers: + thresholds: + - priority: DEFAULT + max_connections: 10000 + max_pending_requests: 10000 + max_requests: 10000 + retry_budget: + budget_percent: + value: 100 + min_retry_concurrency: 100 - '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster name: postgrest_admin load_assignment: @@ -43,4 +73,14 @@ resources: socket_address: address: 127.0.0.1 port_value: 3001 + circuit_breakers: + thresholds: + - priority: DEFAULT + max_connections: 10000 + max_pending_requests: 10000 + max_requests: 10000 + retry_budget: + budget_percent: + value: 100 + min_retry_concurrency: 100 diff --git a/ansible/files/envoy_config/lds.yaml b/ansible/files/envoy_config/lds.yaml index dba85e9de..b74957780 100644 --- a/ansible/files/envoy_config/lds.yaml +++ b/ansible/files/envoy_config/lds.yaml @@ -87,8 +87,23 @@ resources: '@type': >- type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua source_codes: - remove_apikey_query_parameter: - filename: /etc/envoy/remove_apikey_query_parameter.lua + remove_apikey_and_empty_key_query_parameters: + inline_string: |- + function envoy_on_request(request_handle) + local path = request_handle:headers():get(":path") + request_handle + :headers() + :replace(":path", path:gsub("&=[^&]*", ""):gsub("?=[^&]*$", ""):gsub("?=[^&]*&", "?")) + :replace(":path", path:gsub("&apikey=[^&]*", ""):gsub("?apikey=[^&]*$", ""):gsub("?apikey=[^&]*&", "?")) + end + remove_empty_key_query_parameters: + inline_string: |- + function envoy_on_request(request_handle) + local path = request_handle:headers():get(":path") + request_handle + :headers() + :replace(":path", path:gsub("&=[^&]*", ""):gsub("?=[^&]*$", ""):gsub("?=[^&]*&", "?")) + end - name: envoy.filters.http.router typed_config: '@type': >- @@ -181,12 +196,14 @@ resources: retry_policy: num_retries: 3 retry_on: 5xx + timeout: 35s typed_per_filter_config: *ref_0 - match: prefix: /auth/v1/ route: cluster: gotrue prefix_rewrite: / + timeout: 35s - match: prefix: /rest/v1/ query_parameters: @@ -197,12 +214,12 @@ resources: route: cluster: postgrest prefix_rewrite: / - timeout: 120s + timeout: 125s typed_per_filter_config: envoy.filters.http.lua: '@type': >- type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute - name: remove_apikey_query_parameter + name: remove_apikey_and_empty_key_query_parameter - match: prefix: /rest/v1/ request_headers_to_remove: @@ -210,7 +227,12 @@ resources: route: cluster: postgrest prefix_rewrite: / - timeout: 120s + timeout: 125s + typed_per_filter_config: + envoy.filters.http.lua: + '@type': >- + type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute + name: remove_empty_key_query_parameter - match: prefix: /rest-admin/v1/ query_parameters: @@ -225,7 +247,7 @@ resources: envoy.filters.http.lua: '@type': >- type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute - name: remove_apikey_query_parameter + name: remove_apikey_and_empty_key_query_parameters - match: prefix: /rest-admin/v1/ request_headers_to_remove: @@ -242,7 +264,7 @@ resources: route: cluster: postgrest prefix_rewrite: /rpc/graphql - timeout: 120s + timeout: 125s - match: prefix: /admin/v1/ route: @@ -293,6 +315,13 @@ resources: direct_remote_ip: address_prefix: 10.0.0.0 prefix_len: 8 + include_attempt_count_in_response: true + retry_policy: + num_retries: 5 + retry_back_off: + base_interval: 0.1s + max_interval: 1s + retry_on: gateway-error stat_prefix: ingress_http - '@type': type.googleapis.com/envoy.config.listener.v3.Listener name: https_listener diff --git a/ansible/files/envoy_config/remove_apikey_query_parameter.lua b/ansible/files/envoy_config/remove_apikey_query_parameter.lua deleted file mode 100644 index 0aeabaeb1..000000000 --- a/ansible/files/envoy_config/remove_apikey_query_parameter.lua +++ /dev/null @@ -1,8 +0,0 @@ -function envoy_on_request(request_handle) - local path = request_handle:headers():get(":path") - - -- Remove `apikey` query parameter since PostgREST treats query parameters as conditions. - request_handle - :headers() - :replace(":path", path:gsub("([&?])apikey=[^&]+&?", "%1"):gsub("&$", "")) -end diff --git a/common-nix.vars.pkr.hcl b/common-nix.vars.pkr.hcl index c4473a683..2e75b5ed9 100644 --- a/common-nix.vars.pkr.hcl +++ b/common-nix.vars.pkr.hcl @@ -1 +1 @@ -postgres-version = "15.6.1.116" +postgres-version = "15.6.1.117" diff --git a/testinfra/test_ami.py b/testinfra/test_ami.py index 715da96f3..05ec773b8 100644 --- a/testinfra/test_ami.py +++ b/testinfra/test_ami.py @@ -343,7 +343,7 @@ def test_postgrest_can_connect_to_db(host): # There would be an error if the `apikey` query parameter isn't removed, # since PostgREST treats query parameters as conditions. # -# Worth testing since remove_apikey_query_parameter.lua uses regexp instead +# Worth testing since remove_apikey_query_parameters uses regexp instead # of parsed query parameters. def test_postgrest_starting_apikey_query_parameter_is_removed(host): res = requests.get( @@ -388,3 +388,52 @@ def test_postgrest_ending_apikey_query_parameter_is_removed(host): }, ) assert res.ok + +# There would be an error if the empty key query parameter isn't removed, +# since PostgREST treats empty key query parameters as malformed input. +# +# Worth testing since remove_apikey_and_empty_key_query_parameters uses regexp instead +# of parsed query parameters. +def test_postgrest_starting_empty_key_query_parameter_is_removed(host): + res = requests.get( + f"http://{host.backend.get_hostname()}/rest/v1/buckets", + headers={ + "accept-profile": "storage", + }, + params={ + "": "empty_key", + "id": "eq.absent", + "apikey": service_role_key, + }, + ) + assert res.ok + + +def test_postgrest_middle_empty_key_query_parameter_is_removed(host): + res = requests.get( + f"http://{host.backend.get_hostname()}/rest/v1/buckets", + headers={ + "accept-profile": "storage", + }, + params={ + "apikey": service_role_key, + "": "empty_key", + "id": "eq.absent", + }, + ) + assert res.ok + + +def test_postgrest_ending_empty_key_query_parameter_is_removed(host): + res = requests.get( + f"http://{host.backend.get_hostname()}/rest/v1/buckets", + headers={ + "accept-profile": "storage", + }, + params={ + "id": "eq.absent", + "apikey": service_role_key, + "": "empty_key", + }, + ) + assert res.ok diff --git a/testinfra/test_ami_nix.py b/testinfra/test_ami_nix.py index b89183ea4..18a366b34 100644 --- a/testinfra/test_ami_nix.py +++ b/testinfra/test_ami_nix.py @@ -343,7 +343,7 @@ def test_postgrest_can_connect_to_db(host): # There would be an error if the `apikey` query parameter isn't removed, # since PostgREST treats query parameters as conditions. # -# Worth testing since remove_apikey_query_parameter.lua uses regexp instead +# Worth testing since remove_apikey_query_parameters uses regexp instead # of parsed query parameters. def test_postgrest_starting_apikey_query_parameter_is_removed(host): res = requests.get( @@ -387,4 +387,53 @@ def test_postgrest_ending_apikey_query_parameter_is_removed(host): "apikey": service_role_key, }, ) - assert res.ok \ No newline at end of file + assert res.ok + +# There would be an error if the empty key query parameter isn't removed, +# since PostgREST treats empty key query parameters as malformed input. +# +# Worth testing since remove_apikey_and_empty_key_query_parameters uses regexp instead +# of parsed query parameters. +def test_postgrest_starting_empty_key_query_parameter_is_removed(host): + res = requests.get( + f"http://{host.backend.get_hostname()}/rest/v1/buckets", + headers={ + "accept-profile": "storage", + }, + params={ + "": "empty_key", + "id": "eq.absent", + "apikey": service_role_key, + }, + ) + assert res.ok + + +def test_postgrest_middle_empty_key_query_parameter_is_removed(host): + res = requests.get( + f"http://{host.backend.get_hostname()}/rest/v1/buckets", + headers={ + "accept-profile": "storage", + }, + params={ + "apikey": service_role_key, + "": "empty_key", + "id": "eq.absent", + }, + ) + assert res.ok + + +def test_postgrest_ending_empty_key_query_parameter_is_removed(host): + res = requests.get( + f"http://{host.backend.get_hostname()}/rest/v1/buckets", + headers={ + "accept-profile": "storage", + }, + params={ + "id": "eq.absent", + "apikey": service_role_key, + "": "empty_key", + }, + ) + assert res.ok