Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix wrong 503 Service Unavailable on pg error 53400 #3383

Merged
merged 1 commit into from May 6, 2024

Conversation

taimoorzaeem
Copy link
Collaborator

Fixes #3257.

Comment on lines 3763 to 3767
create or replace function temp_file_limit()
returns bigint as $$
set temp_file_limit to '1MB';
select COUNT(*) FROM generate_series('-infinity'::TIMESTAMP, 'epoch'::TIMESTAMP, INTERVAL '1 DAY');
$$ language sql security definer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a good way to do the set temp_file_limit. Since it's part of the function body, the value is not reset when the function is done. Since it's not using local it possibly leaks outside this transaction / request.

It's better to do this:

Suggested change
create or replace function temp_file_limit()
returns bigint as $$
set temp_file_limit to '1MB';
select COUNT(*) FROM generate_series('-infinity'::TIMESTAMP, 'epoch'::TIMESTAMP, INTERVAL '1 DAY');
$$ language sql security definer;
create or replace function temp_file_limit()
returns bigint as $$
select COUNT(*) FROM generate_series('-infinity'::TIMESTAMP, 'epoch'::TIMESTAMP, INTERVAL '1 DAY');
$$ language sql security definer set temp_file_limit to '1MB';

Can you go lower than 1 MB, too? 1KB, maybe?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wolfgangwalther

grant set on parameter temp_file_limit to postgrest_test_anonymous;

create or replace function temp_file_limit()
returns bigint as $$
  select COUNT(*) FROM generate_series('-infinity'::TIMESTAMP, 'epoch'::TIMESTAMP, INTERVAL '1 DAY');
$$ language sql security definer set temp_file_limit to '1kB';

With the above, I am getting the following error on running this test:

but got:  {"code":"22023","details":null,"hint":"Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", 
and \"TB\".","message":"invalid value for parameter \"temp_file_limit\": \"1kb\""}

The test magically lowercases all parameter values. Same goes for 1MB to 1mb and then declaring it invalid.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works fine for me on PG15. Which version are you getting the error for?

postgres=# create or replace function temp_file_limit()
postgres-# returns bigint as $$
postgres$#   select COUNT(*) FROM generate_series('-infinity'::TIMESTAMP, 'epoch'::TIMESTAMP, INTERVAL '1 DAY');
postgres$# $$ language sql security definer set temp_file_limit to '1kB';
CREATE FUNCTION
postgres=# SELECT temp_file_limit();
ERROR:  temporary file size exceeds temp_file_limit (1kB)
CONTEXT:  SQL function "temp_file_limit" statement 1
postgres=#

Are you sure, you are not hitting #3358 (which is not merged, yet!), i.e. you are getting this because temp_file_limit is now suddenly hoisted? This would indicate another bug in the hoisting code, because apparently it doesn't keep the casing when doing so?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I am sure. I am working on a different branch. Let me share the PR with you.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am working on a different branch.

This is exactly what I mean. Because you have not included the changes in #3358 here, yet, the setting will still be hoisted in this case - there is no config option to prevent it, yet.

This means that temp_file_limit will actually be set via PostgREST. And this seems to turn 1kB to 1kb. This indicates a bug in the basic hoisting feature, that #3358 changes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this test run with a different role, which you then make SUPERUSER for this purpose?

How do I run just a single test with a different role? Changing the role would by itself might require superuser privileges.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@steve-chavez @laurenceisla Any idea on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could create another superuser role like:

CREATE ROLE postgrest_test_superuser WITH SUPERUSER;

Then grant usage on the schema, and do the request impersonating that user:

    context "test function temp_file_limit" $
      let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3Rfc3VwZXJ1c2VyIiwiaWQiOiJqZG9lIn0.LQ-qx0ArBnfkwQQhIHKF5cS-lzl0gnTPI8NLoPbL5Fg" in
      it "should return http status 500" $
        request methodGet "/rpc/temp_file_limit" [auth] "" `shouldRespondWith`
          [json|{"code":"53400","message":"temporary file size exceeds temp_file_limit (1kB)","details":null,"hint":null}|]
          { matchStatus = 500 }

You can copy paste to your test, it should work as-is. Additionally, you can do a if pgVersion>=15000 for the tests (without impersonation) and the SQL you already have. Something similar to what is done in IO tests:

DO $do$BEGIN
IF (SELECT current_setting('server_version_num')::INT >= 150000) THEN
ALTER ROLE postgrest_test_w_superuser_settings SET log_min_duration_sample = 12345;
GRANT SET ON PARAMETER log_min_duration_sample to postgrest_test_authenticator;
END IF;
END$do$;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@laurenceisla I tried this and it didn't work. I am still getting this error on all versions:

status mismatch:
         expected: 500
         but got:  403
       body mismatch:
         expected: {"code":"53400","details":null,"hint":null,"message":"temporary file size exceeds temp_file_limit (1kB)"}
         but got:  {"code":"42501","details":null,"hint":null,"message":"permission denied to set role \"postgrest_test_superuser\""}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a different error, though. You need to grant that role to the authenticator here:

GRANT postgrest_test_anonymous, postgrest_test_default_role, postgrest_test_author TO :PGUSER;

@taimoorzaeem taimoorzaeem force-pushed the fix/wrong-httpStatus branch 2 times, most recently from 92a48d9 to 7c4e294 Compare April 10, 2024 10:14
@steve-chavez
Copy link
Member

@steve-chavez steve-chavez merged commit 21bc48a into PostgREST:main May 6, 2024
24 checks passed
@taimoorzaeem taimoorzaeem deleted the fix/wrong-httpStatus branch May 11, 2024 07:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Wrong 503 Service Unavailable on pg 53400
4 participants