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

Add SECURITY DEFINER to internal functions #191

Merged
merged 6 commits into from
Oct 25, 2023
Merged

Conversation

andrew-farries
Copy link
Collaborator

@andrew-farries andrew-farries commented Oct 18, 2023

We want to work on the security model for the pgroll schema, allowing admins to remove access while maintaining functionality intact. Because of this, some functions must still be marked as executable for any user doing migrations directly with postgres.

This PR adds SECURITY DEFINER to these functions

This function must be able to write to the `pgroll.migrations` table
regardless of the permissions of the user who causes it to be executed.
This function needs to be able to read the `pgroll.migrations`  table
regardless of the permissions of the invoking user.
@@ -51,6 +51,7 @@ CREATE OR REPLACE FUNCTION %[1]s.is_active_migration_period(schemaname NAME) RET

-- Get the latest version name (this is the one with child migrations)
CREATE OR REPLACE FUNCTION %[1]s.latest_version(schemaname NAME) RETURNS text
SECURITY DEFINER

Choose a reason for hiding this comment

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

This probably needs a search path and probably should also get some explicit schemas for all called functions, otherwise I can imagine that this can be used to gain the rights of the user used for migrations.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for raising this! I'm adding SET search_path and reviewing calls

@exekias
Copy link
Member

exekias commented Oct 24, 2023

I took over this PR and updated the description, let me know what you think!

@exekias exekias marked this pull request as ready for review October 24, 2023 09:42
@@ -192,7 +196,7 @@ BEGIN
VALUES (
schemaname,
format('sql_%%s', substr(md5(random()::text), 0, 15)),
Copy link

@jankatins jankatins Oct 24, 2023

Choose a reason for hiding this comment

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

While I currently think adding a search path is sufficient, I find it good practise to use schema qualified function calls all over, e.g. also pg_catalog.format and pg_catalog.count(DISTINCT schema_name).

LANGUAGE plpgsql AS $$
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = %[1]s, pg_catalog AS $$

Choose a reason for hiding this comment

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

This suggests that this should also include pg_temp as a last entry: https://github.com/timescale/pgspot/blob/main/src/pgspot/state.py#L123-L127

        # we require explicit pg_temp as last entry for a schema to
        # be safe because not having explicit pg_temp in search_path
        # will result in a search_path with pg_temp as first entry
        if schemas == ["pg_temp"]:
            return True

@exekias
Copy link
Member

exekias commented Oct 24, 2023

Thank you @jankatins for your input! I believe I've addressed all comments

@exekias exekias requested review from urso and kvch October 24, 2023 14:10
@jankatins
Copy link

jankatins commented Oct 24, 2023

There are probably a few more which could be schema qualified (e.g. stuff like > is also overwriteable by a user which can manipulate the search path, as well as md5() and random(). But yeah, search_path is set according to best practises...

If you want to have some fun with testing/linting: https://github.com/Aiven-Open/pghostile and https://github.com/timescale/pgspot

@exekias exekias merged commit 536295b into main Oct 25, 2023
22 checks passed
@exekias exekias deleted the security-definer-functions branch October 25, 2023 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants