public inbox for [email protected]help / color / mirror / Atom feed
[PATCH] New predefined role pg_manage_extensions 27+ messages / 10 participants [nested] [flat]
* [PATCH] New predefined role pg_manage_extensions @ 2024-01-12 14:53 Michael Banck <[email protected]> 0 siblings, 1 reply; 27+ messages in thread From: Michael Banck @ 2024-01-12 14:53 UTC (permalink / raw) To: PostgreSQL Hackers <[email protected]> Hi, I propose to add a new predefined role to Postgres, pg_manage_extensions. The idea is that it allows Superusers to delegate the rights to create, update or delete extensions to other roles, even if those extensions are not trusted or those users are not the database owner. I have attached a WIP patch for this. Thoughts? Michael Attachments: [text/x-diff] 0001-Add-new-pg_manage_extensions-predefined-role.patch (3.9K, ../../[email protected]/2-0001-Add-new-pg_manage_extensions-predefined-role.patch) download | inline diff: From 59497e825184f0de30a18573ffd7d331be3b233d Mon Sep 17 00:00:00 2001 From: Michael Banck <[email protected]> Date: Fri, 12 Jan 2024 13:56:59 +0100 Subject: [PATCH] Add new pg_manage_extensions predefined role. This allows any role that is granted this new predefined role to CREATE, UPDATE or DROP extensions, no matter whether they are trusted or not. --- doc/src/sgml/user-manag.sgml | 5 +++++ src/backend/commands/extension.c | 11 ++++++----- src/include/catalog/pg_authid.dat | 5 +++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml index 92a299d2d3..ebb82801ec 100644 --- a/doc/src/sgml/user-manag.sgml +++ b/doc/src/sgml/user-manag.sgml @@ -693,6 +693,11 @@ DROP ROLE doomed_role; database to issue <link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link>.</entry> </row> + <row> + <entry>pg_manage_extensions</entry> + <entry>Allow creating, removing or updating extensions, even if the + extensions are untrusted or the user is not the database owner.</entry> + </row> </tbody> </tgroup> </table> diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 226f85d0e3..71481d9a73 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -882,13 +882,14 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, ListCell *lc2; /* - * Enforce superuser-ness if appropriate. We postpone these checks until - * here so that the control flags are correctly associated with the right + * Enforce superuser-ness/membership of the pg_manage_extensions + * predefined role if appropriate. We postpone these checks until here + * so that the control flags are correctly associated with the right * script(s) if they happen to be set in secondary control files. */ if (control->superuser && !superuser()) { - if (extension_is_trusted(control)) + if (extension_is_trusted(control) || has_privs_of_role(GetUserId(), ROLE_PG_MANAGE_EXTENSIONS)) switch_to_superuser = true; else if (from_version == NULL) ereport(ERROR, @@ -897,7 +898,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, control->name), control->trusted ? errhint("Must have CREATE privilege on current database to create this extension.") - : errhint("Must be superuser to create this extension."))); + : errhint("Only roles with privileges of the \"%s\" role are allowed to create this extension.", "pg_manage_extensions"))); else ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), @@ -905,7 +906,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, control->name), control->trusted ? errhint("Must have CREATE privilege on current database to update this extension.") - : errhint("Must be superuser to update this extension."))); + : errhint("Only roles with privileges of the \"%s\" role are allowed to update this extension.", "pg_manage_extensions"))); } filename = get_extension_script_filename(control, from_version, version); diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat index 82a2ec2862..ac70603d26 100644 --- a/src/include/catalog/pg_authid.dat +++ b/src/include/catalog/pg_authid.dat @@ -94,5 +94,10 @@ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f', rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1', rolpassword => '_null_', rolvaliduntil => '_null_' }, +{ oid => '8801', oid_symbol => 'ROLE_PG_MANAGE_EXTENSIONS', + rolname => 'pg_manage_extensions', rolsuper => 'f', rolinherit => 't', + rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f', + rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1', + rolpassword => '_null_', rolvaliduntil => '_null_' }, ] -- 2.39.2 ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2024-01-12 15:13 Jelte Fennema-Nio <[email protected]> parent: Michael Banck <[email protected]> 0 siblings, 2 replies; 27+ messages in thread From: Jelte Fennema-Nio @ 2024-01-12 15:13 UTC (permalink / raw) To: Michael Banck <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> On Fri, 12 Jan 2024 at 15:53, Michael Banck <[email protected]> wrote: > I propose to add a new predefined role to Postgres, > pg_manage_extensions. The idea is that it allows Superusers to delegate > the rights to create, update or delete extensions to other roles, even > if those extensions are not trusted or those users are not the database > owner. I agree that extension creation is one of the main reasons people require superuser access, and I think it would be beneficial to try to reduce that. But I'm not sure that such a pg_manage_extensions role would have any fewer permissions than superuser in practice. Afaik many extensions that are not marked as trusted, are not trusted because they would allow fairly trivial privilege escalation to superuser if they were. ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2024-01-13 08:20 Michael Banck <[email protected]> parent: Jelte Fennema-Nio <[email protected]> 1 sibling, 1 reply; 27+ messages in thread From: Michael Banck @ 2024-01-13 08:20 UTC (permalink / raw) To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> Hi, On Fri, Jan 12, 2024 at 04:13:27PM +0100, Jelte Fennema-Nio wrote: > But I'm not sure that such a pg_manage_extensions role would have any > fewer permissions than superuser in practice. Note that just being able to create an extension does not give blanket permission to use it. I did a few checks with things I thought might be problematic like adminpack or plpython3u, and a pg_manage_extensions user is not allowed to call those functions or use the untrusted language. > Afaik many extensions that are not marked as trusted, are not trusted > because they would allow fairly trivial privilege escalation to > superuser if they were. While that might be true (or we err on the side of caution), I thought the rationale was more that they either disclose more information about the database server than we want to disclose to ordinary users, or that they allow access to the file system etc. I think if we have extensions in contrib that trivially allow non-superusers to become superusers just by being installed, that should be a bug and be fixed by making it impossible for ordinary users to use those extensions without being granted some access to them in addition. After all, socially engineering a DBA into installing an extension due to user demand would be a thing anyway (even if most DBAs might reject it) and at least DBAs should be aware of the specific risks of a particular extension probably? Michael ^ permalink raw reply [nested|flat] 27+ messages in thread
* [PATCH v20 2/8] Row pattern recognition patch (parse/analysis). @ 2024-05-24 02:26 Tatsuo Ishii <[email protected]> 0 siblings, 0 replies; 27+ messages in thread From: Tatsuo Ishii @ 2024-05-24 02:26 UTC (permalink / raw) --- src/backend/parser/parse_agg.c | 7 + src/backend/parser/parse_clause.c | 296 +++++++++++++++++++++++++++++- src/backend/parser/parse_expr.c | 6 + src/backend/parser/parse_func.c | 3 + 4 files changed, 311 insertions(+), 1 deletion(-) diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index bee7d8346a..9bc22a836a 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -577,6 +577,10 @@ check_agglevels_and_constraints(ParseState *pstate, Node *expr) errkind = true; break; + case EXPR_KIND_RPR_DEFINE: + errkind = true; + break; + /* * There is intentionally no default: case here, so that the * compiler will warn if we add a new ParseExprKind without @@ -967,6 +971,9 @@ transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc, case EXPR_KIND_CYCLE_MARK: errkind = true; break; + case EXPR_KIND_RPR_DEFINE: + errkind = true; + break; /* * There is intentionally no default: case here, so that the diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 8118036495..9762dce81f 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -98,7 +98,14 @@ static WindowClause *findWindowClause(List *wclist, const char *name); static Node *transformFrameOffset(ParseState *pstate, int frameOptions, Oid rangeopfamily, Oid rangeopcintype, Oid *inRangeFunc, Node *clause); - +static void transformRPR(ParseState *pstate, WindowClause *wc, WindowDef *windef, + List **targetlist); +static List *transformDefineClause(ParseState *pstate, WindowClause *wc, WindowDef *windef, + List **targetlist); +static void transformPatternClause(ParseState *pstate, WindowClause *wc, + WindowDef *windef); +static List *transformMeasureClause(ParseState *pstate, WindowClause *wc, + WindowDef *windef); /* * transformFromClause - @@ -2956,6 +2963,10 @@ transformWindowDefinitions(ParseState *pstate, rangeopfamily, rangeopcintype, &wc->endInRangeFunc, windef->endOffset); + + /* Process Row Pattern Recognition related clauses */ + transformRPR(pstate, wc, windef, targetlist); + wc->winref = winref; result = lappend(result, wc); @@ -3820,3 +3831,286 @@ transformFrameOffset(ParseState *pstate, int frameOptions, return node; } + +/* + * transformRPR + * Process Row Pattern Recognition related clauses + */ +static void +transformRPR(ParseState *pstate, WindowClause *wc, WindowDef *windef, + List **targetlist) +{ + /* + * Window definition exists? + */ + if (windef == NULL) + return; + + /* + * Row Pattern Common Syntax clause exists? + */ + if (windef->rpCommonSyntax == NULL) + return; + + /* Check Frame option. Frame must start at current row */ + if ((wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW) == 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("FRAME must start at current row when row patttern recognition is used"))); + + /* Transform AFTER MACH SKIP TO clause */ + wc->rpSkipTo = windef->rpCommonSyntax->rpSkipTo; + + /* Transform AFTER MACH SKIP TO variable */ + wc->rpSkipVariable = windef->rpCommonSyntax->rpSkipVariable; + + /* Transform SEEK or INITIAL clause */ + wc->initial = windef->rpCommonSyntax->initial; + + /* Transform DEFINE clause into list of TargetEntry's */ + wc->defineClause = transformDefineClause(pstate, wc, windef, targetlist); + + /* Check PATTERN clause and copy to patternClause */ + transformPatternClause(pstate, wc, windef); + + /* Transform MEASURE clause */ + transformMeasureClause(pstate, wc, windef); +} + +/* + * transformDefineClause Process DEFINE clause and transform ResTarget into + * list of TargetEntry. + * + * XXX we only support column reference in row pattern definition search + * condition, e.g. "price". <row pattern definition variable name>.<column + * reference> is not supported, e.g. "A.price". + */ +static List * +transformDefineClause(ParseState *pstate, WindowClause *wc, WindowDef *windef, + List **targetlist) +{ + /* DEFINE variable name initials */ + static char *defineVariableInitials = "abcdefghijklmnopqrstuvwxyz"; + + ListCell *lc, + *l; + ResTarget *restarget, + *r; + List *restargets; + List *defineClause; + char *name; + int initialLen; + int i; + + /* + * If Row Definition Common Syntax exists, DEFINE clause must exist. (the + * raw parser should have already checked it.) + */ + Assert(windef->rpCommonSyntax->rpDefs != NULL); + + /* + * Check and add "A AS A IS TRUE" if pattern variable is missing in DEFINE + * per the SQL standard. + */ + restargets = NIL; + foreach(lc, windef->rpCommonSyntax->rpPatterns) + { + A_Expr *a; + bool found = false; + + if (!IsA(lfirst(lc), A_Expr)) + ereport(ERROR, + errmsg("node type is not A_Expr")); + + a = (A_Expr *) lfirst(lc); + name = strVal(a->lexpr); + + foreach(l, windef->rpCommonSyntax->rpDefs) + { + restarget = (ResTarget *) lfirst(l); + + if (!strcmp(restarget->name, name)) + { + found = true; + break; + } + } + + if (!found) + { + /* + * "name" is missing. So create "name AS name IS TRUE" ResTarget + * node and add it to the temporary list. + */ + A_Const *n; + + restarget = makeNode(ResTarget); + n = makeNode(A_Const); + n->val.boolval.type = T_Boolean; + n->val.boolval.boolval = true; + n->location = -1; + restarget->name = pstrdup(name); + restarget->indirection = NIL; + restarget->val = (Node *) n; + restarget->location = -1; + restargets = lappend((List *) restargets, restarget); + } + } + + if (list_length(restargets) >= 1) + { + /* add missing DEFINEs */ + windef->rpCommonSyntax->rpDefs = + list_concat(windef->rpCommonSyntax->rpDefs, restargets); + list_free(restargets); + } + + /* + * Check for duplicate row pattern definition variables. The standard + * requires that no two row pattern definition variable names shall be + * equivalent. + */ + restargets = NIL; + foreach(lc, windef->rpCommonSyntax->rpDefs) + { + restarget = (ResTarget *) lfirst(lc); + name = restarget->name; + + /* + * Add DEFINE expression (Restarget->val) to the targetlist as a + * TargetEntry if it does not exist yet. Planner will add the column + * ref var node to the outer plan's target list later on. This makes + * DEFINE expression could access the outer tuple while evaluating + * PATTERN. + * + * XXX: adding whole expressions of DEFINE to the plan.targetlist is + * not so good, because it's not necessary to evalute the expression + * in the target list while running the plan. We should extract the + * var nodes only then add them to the plan.targetlist. + */ + findTargetlistEntrySQL99(pstate, (Node *) restarget->val, + targetlist, EXPR_KIND_RPR_DEFINE); + + /* + * Make sure that the row pattern definition search condition is a + * boolean expression. + */ + transformWhereClause(pstate, restarget->val, + EXPR_KIND_RPR_DEFINE, "DEFINE"); + + foreach(l, restargets) + { + char *n; + + r = (ResTarget *) lfirst(l); + n = r->name; + + if (!strcmp(n, name)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("row pattern definition variable name \"%s\" appears more than once in DEFINE clause", + name), + parser_errposition(pstate, exprLocation((Node *) r)))); + } + restargets = lappend(restargets, restarget); + } + list_free(restargets); + + /* + * Create list of row pattern DEFINE variable name's initial. We assign + * [a-z] to them (up to 26 variable names are allowed). + */ + restargets = NIL; + i = 0; + initialLen = strlen(defineVariableInitials); + + foreach(lc, windef->rpCommonSyntax->rpDefs) + { + char initial[2]; + + restarget = (ResTarget *) lfirst(lc); + name = restarget->name; + + if (i >= initialLen) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("number of row pattern definition variable names exceeds %d", + initialLen), + parser_errposition(pstate, + exprLocation((Node *) restarget)))); + } + initial[0] = defineVariableInitials[i++]; + initial[1] = '\0'; + wc->defineInitial = lappend(wc->defineInitial, + makeString(pstrdup(initial))); + } + + defineClause = transformTargetList(pstate, windef->rpCommonSyntax->rpDefs, + EXPR_KIND_RPR_DEFINE); + + /* mark column origins */ + markTargetListOrigins(pstate, defineClause); + + /* mark all nodes in the DEFINE clause tree with collation information */ + assign_expr_collations(pstate, (Node *) defineClause); + + return defineClause; +} + +/* + * transformPatternClause + * Process PATTERN clause and return PATTERN clause in the raw parse tree + */ +static void +transformPatternClause(ParseState *pstate, WindowClause *wc, + WindowDef *windef) +{ + ListCell *lc; + + /* + * Row Pattern Common Syntax clause exists? + */ + if (windef->rpCommonSyntax == NULL) + return; + + wc->patternVariable = NIL; + wc->patternRegexp = NIL; + foreach(lc, windef->rpCommonSyntax->rpPatterns) + { + A_Expr *a; + char *name; + char *regexp; + + if (!IsA(lfirst(lc), A_Expr)) + ereport(ERROR, + errmsg("node type is not A_Expr")); + + a = (A_Expr *) lfirst(lc); + name = strVal(a->lexpr); + + wc->patternVariable = lappend(wc->patternVariable, makeString(pstrdup(name))); + regexp = strVal(lfirst(list_head(a->name))); + + wc->patternRegexp = lappend(wc->patternRegexp, makeString(pstrdup(regexp))); + } +} + +/* + * transformMeasureClause + * Process MEASURE clause + * XXX MEASURE clause is not supported yet + */ +static List * +transformMeasureClause(ParseState *pstate, WindowClause *wc, + WindowDef *windef) +{ + if (windef->rowPatternMeasures == NIL) + return NIL; + + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("%s", "MEASURE clause is not supported yet"), + parser_errposition(pstate, exprLocation((Node *) windef->rowPatternMeasures)))); + return NIL; +} diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index aba3546ed1..e98b45e06e 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -578,6 +578,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) case EXPR_KIND_COPY_WHERE: case EXPR_KIND_GENERATED_COLUMN: case EXPR_KIND_CYCLE_MARK: + case EXPR_KIND_RPR_DEFINE: /* okay */ break; @@ -1860,6 +1861,9 @@ transformSubLink(ParseState *pstate, SubLink *sublink) case EXPR_KIND_GENERATED_COLUMN: err = _("cannot use subquery in column generation expression"); break; + case EXPR_KIND_RPR_DEFINE: + err = _("cannot use subquery in DEFINE expression"); + break; /* * There is intentionally no default: case here, so that the @@ -3197,6 +3201,8 @@ ParseExprKindName(ParseExprKind exprKind) return "GENERATED AS"; case EXPR_KIND_CYCLE_MARK: return "CYCLE"; + case EXPR_KIND_RPR_DEFINE: + return "DEFINE"; /* * There is intentionally no default: case here, so that the diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 9b23344a3b..4c482abb30 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -2658,6 +2658,9 @@ check_srf_call_placement(ParseState *pstate, Node *last_srf, int location) case EXPR_KIND_CYCLE_MARK: errkind = true; break; + case EXPR_KIND_RPR_DEFINE: + errkind = true; + break; /* * There is intentionally no default: case here, so that the -- 2.25.1 ----Next_Part(Fri_May_24_11_39_19_2024_763)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="v20-0003-Row-pattern-recognition-patch-rewriter.patch" ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2024-10-31 21:47 Michael Banck <[email protected]> parent: Michael Banck <[email protected]> 0 siblings, 3 replies; 27+ messages in thread From: Michael Banck @ 2024-10-31 21:47 UTC (permalink / raw) To: Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> Hi, Even though there has not been a lot of discussion on this, here is a rebased patch. I have also added it to the upcoming commitfest. On Sat, Jan 13, 2024 at 09:20:40AM +0100, Michael Banck wrote: > On Fri, Jan 12, 2024 at 04:13:27PM +0100, Jelte Fennema-Nio wrote: > > But I'm not sure that such a pg_manage_extensions role would have any > > fewer permissions than superuser in practice. > > Note that just being able to create an extension does not give blanket > permission to use it. I did a few checks with things I thought might be > problematic like adminpack or plpython3u, and a pg_manage_extensions > user is not allowed to call those functions or use the untrusted > language. > > > Afaik many extensions that are not marked as trusted, are not trusted > > because they would allow fairly trivial privilege escalation to > > superuser if they were. > > While that might be true (or we err on the side of caution), I thought > the rationale was more that they either disclose more information about > the database server than we want to disclose to ordinary users, or that > they allow access to the file system etc. > > I think if we have extensions in contrib that trivially allow > non-superusers to become superusers just by being installed, that should > be a bug and be fixed by making it impossible for ordinary users to > use those extensions without being granted some access to them in > addition. > > After all, socially engineering a DBA into installing an extension due > to user demand would be a thing anyway (even if most DBAs might reject > it) and at least DBAs should be aware of the specific risks of a > particular extension probably? Michael Attachments: [text/x-diff] v2-0001-Add-new-pg_manage_extensions-predefined-role.patch (4.2K, ../../[email protected]/2-v2-0001-Add-new-pg_manage_extensions-predefined-role.patch) download | inline diff: From bda5db90d6d56a025f275c85f775f48c8083b7f0 Mon Sep 17 00:00:00 2001 From: Michael Banck <[email protected]> Date: Thu, 31 Oct 2024 22:36:12 +0100 Subject: [PATCH v2] Add new pg_manage_extensions predefined role. This allows any role that is granted this new predefined role to CREATE, UPDATE or DROP extensions, no matter whether they are trusted or not. --- doc/src/sgml/user-manag.sgml | 11 +++++++++++ src/backend/commands/extension.c | 11 ++++++----- src/include/catalog/pg_authid.dat | 5 +++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml index ed18704a9c..b25f985697 100644 --- a/doc/src/sgml/user-manag.sgml +++ b/doc/src/sgml/user-manag.sgml @@ -669,6 +669,17 @@ GRANT pg_signal_backend TO admin_user; </listitem> </varlistentry> + <varlistentry id="predefined-role-pg-manage-extensions" xreflabel="pg_manage_extensions"> + <term><varname>pg_manage_extensions</varname></term> + <listitem> + <para> + <literal>pg_manage_extensions</literal> allows creating, removing or + updating extensions, even if the extensions are untrusted or the user is + not the database owner. + </para> + </listitem> + </varlistentry> + <varlistentry id="predefined-role-pg-monitor" xreflabel="pg_monitor"> <term><varname>pg_monitor</varname></term> <term><varname>pg_read_all_settings</varname></term> diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index af6bd8ff42..3974da0ef9 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -994,13 +994,14 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, ListCell *lc2; /* - * Enforce superuser-ness if appropriate. We postpone these checks until - * here so that the control flags are correctly associated with the right + * Enforce superuser-ness/membership of the pg_manage_extensions + * predefined role if appropriate. We postpone these checks until here + * so that the control flags are correctly associated with the right * script(s) if they happen to be set in secondary control files. */ if (control->superuser && !superuser()) { - if (extension_is_trusted(control)) + if (extension_is_trusted(control) || has_privs_of_role(GetUserId(), ROLE_PG_MANAGE_EXTENSIONS)) switch_to_superuser = true; else if (from_version == NULL) ereport(ERROR, @@ -1009,7 +1010,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, control->name), control->trusted ? errhint("Must have CREATE privilege on current database to create this extension.") - : errhint("Must be superuser to create this extension."))); + : errhint("Only roles with privileges of the \"%s\" role are allowed to create this extension.", "pg_manage_extensions"))); else ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), @@ -1017,7 +1018,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, control->name), control->trusted ? errhint("Must have CREATE privilege on current database to update this extension.") - : errhint("Must be superuser to update this extension."))); + : errhint("Only roles with privileges of the \"%s\" role are allowed to update this extension.", "pg_manage_extensions"))); } filename = get_extension_script_filename(control, from_version, version); diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat index 0129f67eaa..c6781b0acf 100644 --- a/src/include/catalog/pg_authid.dat +++ b/src/include/catalog/pg_authid.dat @@ -104,5 +104,10 @@ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f', rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1', rolpassword => '_null_', rolvaliduntil => '_null_' }, +{ oid => '8801', oid_symbol => 'ROLE_PG_MANAGE_EXTENSIONS', + rolname => 'pg_manage_extensions', rolsuper => 'f', rolinherit => 't', + rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f', + rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1', + rolpassword => '_null_', rolvaliduntil => '_null_' }, ] -- 2.39.5 ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2024-11-14 12:30 Jelte Fennema-Nio <[email protected]> parent: Michael Banck <[email protected]> 2 siblings, 0 replies; 27+ messages in thread From: Jelte Fennema-Nio @ 2024-11-14 12:30 UTC (permalink / raw) To: Michael Banck <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> On Thu, 31 Oct 2024 at 22:47, Michael Banck <[email protected]> wrote: > Even though there has not been a lot of discussion on this, here is a > rebased patch. I have also added it to the upcoming commitfest. After considering this again, I actually think this is a good change. Basically all cloud providers already provide something similar. It would be great if we could have a standardized way of doing this. Regarding the actual patch: I think it looks good, but it needs some tests. ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2024-11-18 06:26 Kirill Reshke <[email protected]> parent: Michael Banck <[email protected]> 2 siblings, 1 reply; 27+ messages in thread From: Kirill Reshke @ 2024-11-18 06:26 UTC (permalink / raw) To: Michael Banck <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> On Fri, 1 Nov 2024 at 02:47, Michael Banck <[email protected]> wrote: > > Hi, > > Even though there has not been a lot of discussion on this, here is a > rebased patch. I have also added it to the upcoming commitfest. Hi! > + <literal>pg_manage_extensions</literal> allows creating, removing or > + updating extensions, even if the extensions are untrusted or the user is > + not the database owner. Users are not required to be a database owner to create extensions. They are required to have CREATE priv on database. > On Sat, Jan 13, 2024 at 09:20:40AM +0100, Michael Banck wrote: > > On Fri, Jan 12, 2024 at 04:13:27PM +0100, Jelte Fennema-Nio wrote: > > > But I'm not sure that such a pg_manage_extensions role would have any > > > fewer permissions than superuser in practice. > > > > Note that just being able to create an extension does not give blanket > > permission to use it. I did a few checks with things I thought might be > > problematic like adminpack or plpython3u, and a pg_manage_extensions > > user is not allowed to call those functions or use the untrusted > > language. > > > > > Afaik many extensions that are not marked as trusted, are not trusted > > > because they would allow fairly trivial privilege escalation to > > > superuser if they were. > > > > While that might be true (or we err on the side of caution), I thought > > the rationale was more that they either disclose more information about > > the database server than we want to disclose to ordinary users, or that > > they allow access to the file system etc. Extension installation script can execute arbitrary code with superuser privilege if markled trusted. Take this example ``` reshke@yezzey-cbdb:~/postgres/contrib/fooe$ cat fooe.control # fooe extnesion comment = 'foo bar baz' default_version = '1.0' module_pathname = '$libdir/fooe' relocatable = true trusted = true reshke@yezzey-cbdb:~/postgres/contrib/fooe$ cat fooe--1.0.sql /* contrib/fooe/fooe--1.0.sql */ -- complain if script is sourced in psql, rather than via CREATE EXTENSION \echo Use "CREATE EXTENSION fooe" to load this file. \quit CREATE ROLE pwned WITH LOGIN SUPERUSER; reshke@yezzey-cbdb:~/postgres/contrib/fooe$ ../../pgbin/bin/psql -d db2 db2=# create role user_no_sup with login; CREATE ROLE db2=# ^C \q reshke@yezzey-cbdb:~/postgres/contrib/fooe$ ../../pgbin/bin/psql -U user_no_sup -d db2 psql (18devel) Type "help" for help. db2=> create extension fooe ; CREATE EXTENSION db2=> \du+ List of roles Role name | Attributes | Description -------------+------------------------------------------------------------+------------- pwned | Superuser | reshke | Superuser, Create role, Create DB, Replication, Bypass RLS | user1 | | user2 | | user_no_sup | | db2=> ^C ``` > > I think if we have extensions in contrib that trivially allow > > non-superusers to become superusers just by being installed, that should > > be a bug and be fixed by making it impossible for ordinary users to > > use those extensions without being granted some access to them in > > addition. > > > > After all, socially engineering a DBA into installing an extension due > > to user demand would be a thing anyway (even if most DBAs might reject > > it) and at least DBAs should be aware of the specific risks of a > > particular extension probably? > > > Michael In general, this concept is rather dubious. Why should we have such a dangerous pre-defined role? I would prefer to have complete control over what gets installed in the database if I were a superuser. Additionally, if a dangerous extension is inadvertently or otherwise loaded on the host, I never want a normal user to run code with superuser privileges. For a thorough understanding of the current situation and the rationale behind the design, you can read this[1] discussion. [1] https://www.postgresql.org/message-id/5889.1566415762%40sss.pgh.pa.us -- Best regards, Kirill Reshke ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2024-12-31 11:15 Michael Banck <[email protected]> parent: Kirill Reshke <[email protected]> 0 siblings, 1 reply; 27+ messages in thread From: Michael Banck @ 2024-12-31 11:15 UTC (permalink / raw) To: Kirill Reshke <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> Hi, first, sorry for the late reply :-/ On Mon, Nov 18, 2024 at 11:26:40AM +0500, Kirill Reshke wrote: > On Fri, 1 Nov 2024 at 02:47, Michael Banck <[email protected]> wrote: > > Even though there has not been a lot of discussion on this, here is a > > rebased patch. I have also added it to the upcoming commitfest. > > > > + <literal>pg_manage_extensions</literal> allows creating, removing or > > + updating extensions, even if the extensions are untrusted or the user is > > + not the database owner. > > Users are not required to be a database owner to create extensions. > They are required to have CREATE priv on database. Ah right, thanks, I have changed that. > > On Sat, Jan 13, 2024 at 09:20:40AM +0100, Michael Banck wrote: > > > On Fri, Jan 12, 2024 at 04:13:27PM +0100, Jelte Fennema-Nio wrote: > > > > But I'm not sure that such a pg_manage_extensions role would have any > > > > fewer permissions than superuser in practice. > > > > > > Note that just being able to create an extension does not give blanket > > > permission to use it. I did a few checks with things I thought might be > > > problematic like adminpack or plpython3u, and a pg_manage_extensions > > > user is not allowed to call those functions or use the untrusted > > > language. > > > > > > > Afaik many extensions that are not marked as trusted, are not trusted > > > > because they would allow fairly trivial privilege escalation to > > > > superuser if they were. > > > > > > While that might be true (or we err on the side of caution), I thought > > > the rationale was more that they either disclose more information about > > > the database server than we want to disclose to ordinary users, or that > > > they allow access to the file system etc. > > Extension installation script can execute arbitrary code with > superuser privilege if markled trusted. > > Take this example [...] Right, but this implies that a superuser installed that rogue/sketchy/unsafe-but-declared-safe extension in the first place. I would assume that the person having pg_manage_extensions privs not have the ability to install extensions at the system level. Maybe this should be cautioned some more in the documentation part of this patch, though. Unless one of the current untrusted contrib extensions allows to attain superuser rights by being created? My opinion was that superusers (or system administrators) would need to explicitly install this (presumably external) extension somehow, either via package management or by compile-installing it. So, what is the threat vector here? I think the system administrator has (in most/all(?) cases) superuser access to Postgres in practise anyway, via sudo/root access to the postgres user. Maybe this should be revisited in light of the extension_destdir GUC patch, but I think in that case the system admins/postgres superuser should make sure that this auxiliary directory is not writable to others. > In general, this concept is rather dubious. Why should we have such a > dangerous pre-defined role? Well, I would say pg_execute_server_program could be regarded as a precedent. > I would prefer to have complete control over what gets installed in > the database if I were a superuser. A superuser will have to grant this attribute to somebody, so there is certainly some gate-keeping here. As a side note, maybe what we are missing is a way for site admins to disable some of the predefined roles (i.e. something better than just DELETE FROM pg_authid). > Additionally, if a dangerous extension is inadvertently or otherwise > loaded on the host, I never want a normal user to run code with > superuser privileges. Well again, normal users with pg_execute_server_program rights can basically already do this. I would consider a user with a pg_manage_extensions right not a normal user, but an application DBA or a pseudo-superuser in the managed Postgres cloud parlance. > For a thorough understanding of the current situation and the > rationale behind the design, you can read this[1] discussion. I have re-read this since, thanks. I do think having a whitelist of allowed-to-be-installed extensions (similar/like https://github.com/dimitri/pgextwlist) makes sense additionally in today's container/cloud word where the local Postgres admin might not have control over which packages get installed but wants to have control over which extension the application admins (or whoever) may create, but that is another topic I think. Michael ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-01-16 07:09 Shinya Kato <[email protected]> parent: Michael Banck <[email protected]> 0 siblings, 1 reply; 27+ messages in thread From: Shinya Kato @ 2025-01-16 07:09 UTC (permalink / raw) To: Michael Banck <[email protected]>; +Cc: Kirill Reshke <[email protected]>; Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> On Thu, Jan 16, 2025 at 3:31 PM Michael Banck <[email protected]> wrote: I agree with this idea. I think it is natural to delegate a part of superuser privileges to another role because superuser privilege is too strong. > > In general, this concept is rather dubious. Why should we have such a > > dangerous pre-defined role? > > Well, I would say pg_execute_server_program could be regarded as a > precedent. Exactly. pg_execute_server_program can escalate to superuser privileges, so pg_manage_extensions is not the only dangerous pre-defined role. > I do think having a whitelist of allowed-to-be-installed extensions > (similar/like https://github.com/dimitri/pgextwlist) makes sense > additionally in today's container/cloud word where the local Postgres > admin might not have control over which packages get installed but wants > to have control over which extension the application admins (or whoever) > may create, but that is another topic I think. To use a certain extension, you may need to install the postgresql-contrib package. In that case, is there a way to restrict extensions other than the required one? Or is it unnecessary to impose such restrictions? Regards, Shinya Kato ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-01-16 07:35 Michael Banck <[email protected]> parent: Shinya Kato <[email protected]> 0 siblings, 0 replies; 27+ messages in thread From: Michael Banck @ 2025-01-16 07:35 UTC (permalink / raw) To: Shinya Kato <[email protected]>; +Cc: Kirill Reshke <[email protected]>; Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> Hi, On Thu, Jan 16, 2025 at 04:09:44PM +0900, Shinya Kato wrote: > On Thu, Jan 16, 2025 at 3:31 PM Michael Banck <[email protected]> wrote: > > I do think having a whitelist of allowed-to-be-installed extensions > > (similar/like https://github.com/dimitri/pgextwlist) makes sense > > additionally in today's container/cloud word where the local Postgres > > admin might not have control over which packages get installed but wants > > to have control over which extension the application admins (or whoever) > > may create, but that is another topic I think. > > To use a certain extension, you may need to install the > postgresql-contrib package. In that case, is there a way to restrict > extensions other than the required one? Or is it unnecessary to impose > such restrictions? I was thinking about the following (increasinly common, I think) use-case: we have a largish organisation where the platform/whatever team wants to deploy Postgres in a uniform way and install the common set of all contrib and external extensions that might be needed for each instance. But then you have instance-specific admins that might want to restrict the set of extensions their instance (or their developers/app admins/whatever) is allowed to use. However, this is not the purpose of the patch in discussion, just a side-remark that this functionality would be good to have in addition. Michael ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-01-17 09:03 Laurenz Albe <[email protected]> parent: Michael Banck <[email protected]> 2 siblings, 1 reply; 27+ messages in thread From: Laurenz Albe @ 2025-01-17 09:03 UTC (permalink / raw) To: Michael Banck <[email protected]>; Jelte Fennema-Nio <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> On Thu, 2024-10-31 at 22:47 +0100, Michael Banck wrote: > Even though there has not been a lot of discussion on this, here is a > rebased patch. I have also added it to the upcoming commitfest. I had a look at the patch. > --- a/doc/src/sgml/user-manag.sgml > +++ b/doc/src/sgml/user-manag.sgml > @@ -669,6 +669,17 @@ GRANT pg_signal_backend TO admin_user; > </listitem> > </varlistentry> > > + <varlistentry id="predefined-role-pg-manage-extensions" xreflabel="pg_manage_extensions"> > + <term><varname>pg_manage_extensions</varname></term> > + <listitem> > + <para> > + <literal>pg_manage_extensions</literal> allows creating, removing or > + updating extensions, even if the extensions are untrusted or the user is > + not the database owner. > + </para> > + </listitem> > + </varlistentry> > + The inaccuracy of the database owner has already been mentioned. Should we say "creating, altering or dropping extensions" to make the connection to the respective commands obvious? > --- a/src/backend/commands/extension.c > +++ b/src/backend/commands/extension.c > @@ -994,13 +994,14 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, > ListCell *lc2; > > /* > - * Enforce superuser-ness if appropriate. We postpone these checks until > - * here so that the control flags are correctly associated with the right > + * Enforce superuser-ness/membership of the pg_manage_extensions > + * predefined role if appropriate. We postpone these checks until here > + * so that the control flags are correctly associated with the right > * script(s) if they happen to be set in secondary control files. > */ This is just an attempt to improve the English: If appropriate, enforce superuser-ness or membership of the predefined role pg_manage_extensions. > - : errhint("Must be superuser to create this extension."))); > + : errhint("Only roles with privileges of the \"%s\" role are allowed to create this extension.", "pg_manage_extensions"))); I don't see the point of breaking out the role name from the message. We don't do that in other places. Besides, I think that the mention of the superuser should be retained. Moreover, I think that commit 8d9978a717 pretty much established that we should not quote names if they contain underscores. Perhaps: errhint("Must be superuser or member of pg_manage_extensions to create this extension."))); Yours, Laurenz Albe ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-02-28 18:16 Michael Banck <[email protected]> parent: Laurenz Albe <[email protected]> 0 siblings, 1 reply; 27+ messages in thread From: Michael Banck @ 2025-02-28 18:16 UTC (permalink / raw) To: Laurenz Albe <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> Hi, On Fri, Jan 17, 2025 at 10:03:17AM +0100, Laurenz Albe wrote: > On Thu, 2024-10-31 at 22:47 +0100, Michael Banck wrote: > > Even though there has not been a lot of discussion on this, here is a > > rebased patch. I have also added it to the upcoming commitfest. > > I had a look at the patch. Thanks! And sorry for the long delay... > > --- a/doc/src/sgml/user-manag.sgml > > +++ b/doc/src/sgml/user-manag.sgml > > @@ -669,6 +669,17 @@ GRANT pg_signal_backend TO admin_user; > > </listitem> > > </varlistentry> > > > > + <varlistentry id="predefined-role-pg-manage-extensions" xreflabel="pg_manage_extensions"> > > + <term><varname>pg_manage_extensions</varname></term> > > + <listitem> > > + <para> > > + <literal>pg_manage_extensions</literal> allows creating, removing or > > + updating extensions, even if the extensions are untrusted or the user is > > + not the database owner. > > + </para> > > + </listitem> > > + </varlistentry> > > + > > The inaccuracy of the database owner has already been mentioned. Right, I had already changed that in my tree but never sent out an updated version with this. > Should we say "creating, altering or dropping extensions" to make the connection to > the respective commands obvious? Alright, did so. > > --- a/src/backend/commands/extension.c > > +++ b/src/backend/commands/extension.c > > @@ -994,13 +994,14 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, > > ListCell *lc2; > > > > /* > > - * Enforce superuser-ness if appropriate. We postpone these checks until > > - * here so that the control flags are correctly associated with the right > > + * Enforce superuser-ness/membership of the pg_manage_extensions > > + * predefined role if appropriate. We postpone these checks until here > > + * so that the control flags are correctly associated with the right > > * script(s) if they happen to be set in secondary control files. > > */ > > This is just an attempt to improve the English: > > If appropriate, enforce superuser-ness or membership of the predefined role > pg_manage_extensions. Done. > > - : errhint("Must be superuser to create this extension."))); > > + : errhint("Only roles with privileges of the \"%s\" role are allowed to create this extension.", "pg_manage_extensions"))); > > I don't see the point of breaking out the role name from the message. > We don't do that in other places. We actually do, I think I modelled it after other predefined roles, e.g.: |src/backend/commands/subscriptioncmds.c: errdetail("Only roles with privileges of the \"%s\" role may create subscriptions.", |src/backend/commands/subscriptioncmds.c- "pg_create_subscription"))); |-- |src/backend/commands/copy.c: errdetail("Only roles with privileges of the \"%s\" role may COPY to or from an external program.", |src/backend/commands/copy.c- "pg_execute_server_program"), |-- |src/backend/commands/copy.c: errdetail("Only roles with privileges of the \"%s\" role may COPY from a file.", |src/backend/commands/copy.c- "pg_read_server_files"), |-- |src/backend/commands/copy.c: errdetail("Only roles with privileges of the \"%s\" role may COPY to a file.", |src/backend/commands/copy.c- "pg_write_server_files"), However, those are all errdetail, while the previous "Must be superuser to [...]" is errhint, and that error message has different hints based on whether the extension is trusted or not... > Besides, I think that the mention of the superuser should be retained. > Moreover, I think that commit 8d9978a717 pretty much established that we > should not quote names if they contain underscores. > Perhaps: > > errhint("Must be superuser or member of pg_manage_extensions to create this extension."))); Alright, I think it makes more sense to have it like that than the above, so changed it to that. New version 3 attached. Michael Attachments: [text/x-diff] v3-0001-Add-new-pg_manage_extensions-predefined-role.patch (4.2K, ../../[email protected]/2-v3-0001-Add-new-pg_manage_extensions-predefined-role.patch) download | inline diff: From 57e02d95ace2a390ea1e40266735529f313b31ec Mon Sep 17 00:00:00 2001 From: Michael Banck <[email protected]> Date: Thu, 31 Oct 2024 22:36:12 +0100 Subject: [PATCH v3] Add new pg_manage_extensions predefined role. This allows any role that is granted this new predefined role to CREATE, UPDATE or DROP extensions, no matter whether they are trusted or not. --- doc/src/sgml/user-manag.sgml | 11 +++++++++++ src/backend/commands/extension.c | 11 ++++++----- src/include/catalog/pg_authid.dat | 5 +++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml index ed18704a9c2..2a44f41da4f 100644 --- a/doc/src/sgml/user-manag.sgml +++ b/doc/src/sgml/user-manag.sgml @@ -669,6 +669,17 @@ GRANT pg_signal_backend TO admin_user; </listitem> </varlistentry> + <varlistentry id="predefined-role-pg-manage-extensions" xreflabel="pg_manage_extensions"> + <term><varname>pg_manage_extensions</varname></term> + <listitem> + <para> + <literal>pg_manage_extensions</literal> allows creating, altering or + dropping extensions, even if the extensions are untrusted or the user + does not have <literal>CREATE</literal> rights on the database. + </para> + </listitem> + </varlistentry> + <varlistentry id="predefined-role-pg-monitor" xreflabel="pg_monitor"> <term><varname>pg_monitor</varname></term> <term><varname>pg_read_all_settings</varname></term> diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index d9bb4ce5f1e..2426c3e0eda 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -996,13 +996,14 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, ListCell *lc2; /* - * Enforce superuser-ness if appropriate. We postpone these checks until - * here so that the control flags are correctly associated with the right + * Enforce superuser-ness/membership of the pg_manage_extensions + * predefined role if appropriate. We postpone these checks until here + * so that the control flags are correctly associated with the right * script(s) if they happen to be set in secondary control files. */ if (control->superuser && !superuser()) { - if (extension_is_trusted(control)) + if (extension_is_trusted(control) || has_privs_of_role(GetUserId(), ROLE_PG_MANAGE_EXTENSIONS)) switch_to_superuser = true; else if (from_version == NULL) ereport(ERROR, @@ -1011,7 +1012,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, control->name), control->trusted ? errhint("Must have CREATE privilege on current database to create this extension.") - : errhint("Must be superuser to create this extension."))); + : errhint("Must be superuser or member of pg_manage_extensions to create this extension."))); else ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), @@ -1019,7 +1020,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, control->name), control->trusted ? errhint("Must have CREATE privilege on current database to update this extension.") - : errhint("Must be superuser to update this extension."))); + : errhint("Must be superuser or member of pg_manage_extensions to update this extension."))); } filename = get_extension_script_filename(control, from_version, version); diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat index eb4dab5c6aa..0e3eb20e2b9 100644 --- a/src/include/catalog/pg_authid.dat +++ b/src/include/catalog/pg_authid.dat @@ -104,5 +104,10 @@ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f', rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1', rolpassword => '_null_', rolvaliduntil => '_null_' }, +{ oid => '8801', oid_symbol => 'ROLE_PG_MANAGE_EXTENSIONS', + rolname => 'pg_manage_extensions', rolsuper => 'f', rolinherit => 't', + rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f', + rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1', + rolpassword => '_null_', rolvaliduntil => '_null_' }, ] -- 2.39.5 ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 13:14 Laurenz Albe <[email protected]> parent: Michael Banck <[email protected]> 0 siblings, 1 reply; 27+ messages in thread From: Laurenz Albe @ 2025-03-07 13:14 UTC (permalink / raw) To: Michael Banck <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> On Fri, 2025-02-28 at 19:16 +0100, Michael Banck wrote: > New version 3 attached. I am fine with v3, and I'll mark it "ready for committer". I have been wondering about regression tests. We cannot have them in the core tests, because we cannot rely on any extension being available. We could shove a test into a regression test for an existing contrib, but that would be somewhat off-topic there. Not sure what would be best. Yours, Laurenz Albe ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 13:40 Dagfinn Ilmari Mannsåker <[email protected]> parent: Laurenz Albe <[email protected]> 0 siblings, 0 replies; 27+ messages in thread From: Dagfinn Ilmari Mannsåker @ 2025-03-07 13:40 UTC (permalink / raw) To: Laurenz Albe <[email protected]>; +Cc: Michael Banck <[email protected]>; Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> Laurenz Albe <[email protected]> writes: > On Fri, 2025-02-28 at 19:16 +0100, Michael Banck wrote: >> New version 3 attached. > > I am fine with v3, and I'll mark it "ready for committer". > > I have been wondering about regression tests. > We cannot have them in the core tests, because we cannot rely on any > extension being available. That's what the extensions in src/test/modules/ are for. The test_extensions subdirectory seems suitable, it has tests for all sorts of behaviour around extensions. - ilmari ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 13:57 Robert Haas <[email protected]> parent: Jelte Fennema-Nio <[email protected]> 1 sibling, 1 reply; 27+ messages in thread From: Robert Haas @ 2025-03-07 13:57 UTC (permalink / raw) To: Jelte Fennema-Nio <[email protected]>; +Cc: Michael Banck <[email protected]>; PostgreSQL Hackers <[email protected]> On Fri, Jan 12, 2024 at 10:13 AM Jelte Fennema-Nio <[email protected]> wrote: > On Fri, 12 Jan 2024 at 15:53, Michael Banck <[email protected]> wrote: > > I propose to add a new predefined role to Postgres, > > pg_manage_extensions. The idea is that it allows Superusers to delegate > > the rights to create, update or delete extensions to other roles, even > > if those extensions are not trusted or those users are not the database > > owner. > > I agree that extension creation is one of the main reasons people > require superuser access, and I think it would be beneficial to try to > reduce that. But I'm not sure that such a pg_manage_extensions role > would have any fewer permissions than superuser in practice. Afaik > many extensions that are not marked as trusted, are not trusted > because they would allow fairly trivial privilege escalation to > superuser if they were. I see that Jelte walked this comment back, but I think this issue needs more discussion. I'm not intrinsically against having a role like pg_execute_server_programs that allows escalation to superuser, but I don't see how it would help a cloud provider whose goal is to NOT allow administrators to escalate to superuser. What am I missing? -- Robert Haas EDB: http://www.enterprisedb.com ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 14:02 Jelte Fennema-Nio <[email protected]> parent: Robert Haas <[email protected]> 0 siblings, 2 replies; 27+ messages in thread From: Jelte Fennema-Nio @ 2025-03-07 14:02 UTC (permalink / raw) To: Robert Haas <[email protected]>; +Cc: Michael Banck <[email protected]>; PostgreSQL Hackers <[email protected]> On Fri, 7 Mar 2025 at 14:58, Robert Haas <[email protected]> wrote: > I see that Jelte walked this comment back, but I think this issue > needs more discussion. I'm not intrinsically against having a role > like pg_execute_server_programs that allows escalation to superuser, > but I don't see how it would help a cloud provider whose goal is to > NOT allow administrators to escalate to superuser. > > What am I missing? The reason why I walked back my comment was that cloud providers can simply choose which extensions they actually add to the image. If an extension is marked as not trusted by the author, then with this role they can still choose to add it without having to make changes to the control file if they think it's "secure enough". ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 14:17 Robert Haas <[email protected]> parent: Jelte Fennema-Nio <[email protected]> 1 sibling, 2 replies; 27+ messages in thread From: Robert Haas @ 2025-03-07 14:17 UTC (permalink / raw) To: Jelte Fennema-Nio <[email protected]>; +Cc: Michael Banck <[email protected]>; PostgreSQL Hackers <[email protected]> On Fri, Mar 7, 2025 at 9:02 AM Jelte Fennema-Nio <[email protected]> wrote: > The reason why I walked back my comment was that cloud providers can > simply choose which extensions they actually add to the image. If an > extension is marked as not trusted by the author, then with this role > they can still choose to add it without having to make changes to the > control file if they think it's "secure enough". Hmm. It would be easy to do dumb things here, but I agree there are probably a bunch of debatable cases. Maybe it would be smart if we labelled our untrusted extensions somehow with why they're untrusted, or documented that. Why wouldn't the cloud provider just change add 'trusted = true' to the relevant control files instead of doing this? -- Robert Haas EDB: http://www.enterprisedb.com ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 14:33 Laurenz Albe <[email protected]> parent: Robert Haas <[email protected]> 1 sibling, 0 replies; 27+ messages in thread From: Laurenz Albe @ 2025-03-07 14:33 UTC (permalink / raw) To: Robert Haas <[email protected]>; Jelte Fennema-Nio <[email protected]>; +Cc: Michael Banck <[email protected]>; PostgreSQL Hackers <[email protected]> On Fri, 2025-03-07 at 09:17 -0500, Robert Haas wrote: > On Fri, Mar 7, 2025 at 9:02 AM Jelte Fennema-Nio <[email protected]> wrote: > > The reason why I walked back my comment was that cloud providers can > > simply choose which extensions they actually add to the image. If an > > extension is marked as not trusted by the author, then with this role > > they can still choose to add it without having to make changes to the > > control file if they think it's "secure enough". > > Hmm. It would be easy to do dumb things here, but I agree there are > probably a bunch of debatable cases. Maybe it would be smart if we > labelled our untrusted extensions somehow with why they're untrusted, > or documented that. > > Why wouldn't the cloud provider just change add 'trusted = true' to > the relevant control files instead of doing this? That's quite true. Perhaps the patch should be rejected after all. Yours, Laurenz Albe ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 14:37 Michael Banck <[email protected]> parent: Robert Haas <[email protected]> 1 sibling, 2 replies; 27+ messages in thread From: Michael Banck @ 2025-03-07 14:37 UTC (permalink / raw) To: Robert Haas <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> Hi, On Fri, Mar 07, 2025 at 09:17:46AM -0500, Robert Haas wrote: > Why wouldn't the cloud provider just change add 'trusted = true' to > the relevant control files instead of doing this? That would be possible, but maybe the cloud provider is using distribution packages and does not want to muck around in the file system (as is usually frowned upon), or, maybe more likely, is using container images based on (what I've seen most of them are) the Debian packages and cannot (or does not want to anyway) muck around in the file system easily. Also, I think there is case to be made that a cloud provider (or site admin) would like to delegate the decision whether users with CREATE rights on a particular database are allowed to install some extensions or not. Or rather, assign somebody they believe would make the right call to do that, by granting pg_manage_extensions. On the other hand, maybe trusted should be part of the catalog and not (just) the extension control file, so that somebody with appropriate permissions (like the cloud provider during instance bootstrap) could do "ALTER EXTENSION foo (SET trusted|TRUSTED);" or whatever. ISTR that I reviewed the discussion around trusted back then and did not see that possiblity discussed at all, but I might be misremembering, it's been a while. Michael ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 14:54 Jelte Fennema-Nio <[email protected]> parent: Michael Banck <[email protected]> 1 sibling, 0 replies; 27+ messages in thread From: Jelte Fennema-Nio @ 2025-03-07 14:54 UTC (permalink / raw) To: Michael Banck <[email protected]>; +Cc: Robert Haas <[email protected]>; PostgreSQL Hackers <[email protected]> On Fri, 7 Mar 2025 at 15:37, Michael Banck <[email protected]> wrote: > On Fri, Mar 07, 2025 at 09:17:46AM -0500, Robert Haas wrote: > > Why wouldn't the cloud provider just change add 'trusted = true' to > > the relevant control files instead of doing this? > > That would be possible, but maybe the cloud provider is using > distribution packages and does not want to muck around in the file > system (as is usually frowned upon), or, maybe more likely, is using > container images based on (what I've seen most of them are) the Debian > packages and cannot (or does not want to anyway) muck around in the file > system easily. Yeah exactly, having to do this for every extension that you onboard is quite a hassle to maintain. It seems much nicer to allow people to assign a single role and be done with it. Also many cloud providers have some slightly forked/extended postgres to allow this already. > Also, I think there is case to be made that a cloud provider (or site > admin) would like to delegate the decision whether users with CREATE > rights on a particular database are allowed to install some extensions > or not. Or rather, assign somebody they believe would make the right > call to do that, by granting pg_manage_extensions. I think this is a really good point. Adding trusted=true gives any database owner the ability to install these more dangerous extensions. While by using pg_manage_extensions you can limit this ability to the cluster administrator. > On the other hand, maybe trusted should be part of the catalog and not > (just) the extension control file, so that somebody with appropriate > permissions (like the cloud provider during instance bootstrap) could do > "ALTER EXTENSION foo (SET trusted|TRUSTED);" or whatever. ISTR that I > reviewed the discussion around trusted back then and did not see that > possiblity discussed at all, but I might be misremembering, it's been a > while. I think that would be hard because there's no record in the pg_extension for extensions that are not installed. So there's also no way to mark such an extension as trusted. To be able to do this we'd probably need a system-wide catalog. If we'd go this route then I think what we'd really want is a way to do: GRANT INSTALL ON EXTENSION TO user; And that seems orthogonal to having this pg_manage_extensions role, because then pg_manage_extensions could grant that permission to people. ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 15:56 Robert Haas <[email protected]> parent: Michael Banck <[email protected]> 1 sibling, 1 reply; 27+ messages in thread From: Robert Haas @ 2025-03-07 15:56 UTC (permalink / raw) To: Michael Banck <[email protected]>; +Cc: Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> On Fri, Mar 7, 2025 at 9:37 AM Michael Banck <[email protected]> wrote: > Also, I think there is case to be made that a cloud provider (or site > admin) would like to delegate the decision whether users with CREATE > rights on a particular database are allowed to install some extensions > or not. Or rather, assign somebody they believe would make the right > call to do that, by granting pg_manage_extensions. Hypothetically, somebody could want a feature at various levels of granularity. The most fine-grained would be something like: [1] allow user X to install extension Y. Then, more broadly, you could have: [2] allow any user who can install extensions to install extension Y. Or conversely: [3] allow user X to install any extension. This patch implements [3], but you could make an argument for any of the others. My previous proposal amounted to allowing [2] via filesystem hacks, but you could also have a GUC to allow [2], approximately: artifically_trusted_extensions = foo, bar. That would actually allow for [1] as well, because you could apply that GUC via ALTER ROLE .. SET. I'm not saying that's necessarily better than what you're proposing, but I think it's worth taking the time to think through the options carefully. -- Robert Haas EDB: http://www.enterprisedb.com ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 16:21 Tom Lane <[email protected]> parent: Robert Haas <[email protected]> 0 siblings, 1 reply; 27+ messages in thread From: Tom Lane @ 2025-03-07 16:21 UTC (permalink / raw) To: Robert Haas <[email protected]>; +Cc: Michael Banck <[email protected]>; Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> Robert Haas <[email protected]> writes: > On Fri, Mar 7, 2025 at 9:37 AM Michael Banck <[email protected]> wrote: >> Also, I think there is case to be made that a cloud provider (or site >> admin) would like to delegate the decision whether users with CREATE >> rights on a particular database are allowed to install some extensions >> or not. Or rather, assign somebody they believe would make the right >> call to do that, by granting pg_manage_extensions. > Hypothetically, somebody could want a feature at various levels of > granularity. The most fine-grained would be something like: [1] allow > user X to install extension Y. Then, more broadly, you could have: [2] > allow any user who can install extensions to install extension Y. Or > conversely: [3] allow user X to install any extension. This patch > implements [3], but you could make an argument for any of the others. It's not apparent to me how [3] is meaningfully different from giving user X superuser. If you have the ability to install and use, say, file_fdw, then nothing except honesty stands between you and a superuser bit. Is the argument for this feature that cloud providers won't realize that? Or perhaps the argument is that the provider will only provide pre-vetted extensions to install --- but then the existing "trusted extension" feature does everything they need. While I'm all for chipping away at what superuser privilege is needed for, we have to tread VERY carefully about chipping away at things that allow any outside-the-database access. regards, tom lane ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 16:23 Tom Lane <[email protected]> parent: Jelte Fennema-Nio <[email protected]> 1 sibling, 0 replies; 27+ messages in thread From: Tom Lane @ 2025-03-07 16:23 UTC (permalink / raw) To: Jelte Fennema-Nio <[email protected]>; +Cc: Robert Haas <[email protected]>; Michael Banck <[email protected]>; PostgreSQL Hackers <[email protected]> Jelte Fennema-Nio <[email protected]> writes: > The reason why I walked back my comment was that cloud providers can > simply choose which extensions they actually add to the image. If an > extension is marked as not trusted by the author, then with this role > they can still choose to add it without having to make changes to the > control file if they think it's "secure enough". If they think it's "secure enough", they can mark it trusted in their images. Why do we need anything beyond that? regards, tom lane ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-03-07 16:46 Robert Haas <[email protected]> parent: Tom Lane <[email protected]> 0 siblings, 1 reply; 27+ messages in thread From: Robert Haas @ 2025-03-07 16:46 UTC (permalink / raw) To: Tom Lane <[email protected]>; +Cc: Michael Banck <[email protected]>; Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> On Fri, Mar 7, 2025 at 11:21 AM Tom Lane <[email protected]> wrote: > While I'm all for chipping away at what superuser privilege is > needed for, we have to tread VERY carefully about chipping away > at things that allow any outside-the-database access. I agree, but I also don't want the security decisions that the core project takes to become irrelevant in practice. It seems like what's starting to happen is that all of the cloud providers end up finding the same issues and working around them in very similar ways and they don't do anything in PostgreSQL itself, I guess because that would require winning an argument on the mailing list. I think that dynamic is bad for us as an open-source project, so I'm trying to be particularly careful about evaluating proposals that smell like "all the cloud providers are already doing this, why don't we maybe just agree that it's needed". I'm not certain that this is such a case, and I'd like to have more information about what the cloud providers are actually doing in this area, but I'm alert to the possibility that it might be the case. -- Robert Haas EDB: http://www.enterprisedb.com ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-04-05 23:07 Tom Lane <[email protected]> parent: Robert Haas <[email protected]> 0 siblings, 1 reply; 27+ messages in thread From: Tom Lane @ 2025-04-05 23:07 UTC (permalink / raw) To: Robert Haas <[email protected]>; +Cc: Michael Banck <[email protected]>; Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> I took another look at this patch, and I still can't persuade myself that a good case has been made for it. There are too many scenarios where pg_manage_extensions would be a security problem and too few where it seems to really improve manageability. As an example, it was asserted upthread that it's not a security problem to let someone install plpython3u, because they still couldn't create any plpython3u functions unless they were superuser. Well, fine, but then what's the point of installing it? If there is someone around with enough privilege to use plpython3u, that person can install it first. I also don't buy the argument that service providers would be unwilling to set the "trusted" flag on extensions that for whatever reason they are willing to let be installed by non-superusers. This thread is full of (unsupported) assertions that those same providers are making far more invasive changes to the PG code base to achieve their desired results. Robert Haas <[email protected]> writes: > I agree, but I also don't want the security decisions that the core > project takes to become irrelevant in practice. It seems like what's > starting to happen is that all of the cloud providers end up finding > the same issues and working around them in very similar ways and they > don't do anything in PostgreSQL itself, I guess because that would > require winning an argument on the mailing list. It would at least require showing up on the mailing list. None of the assertions made in this thread about what cloud providers are doing have been supported by a whit of evidence about that. What I'm wishing for is that some of the providers would show up here and provide specific details (preferably patches) about what they are changing and why. Then we could have an informed discussion about how to make their lives less painful in the future. Right now I think we're guessing --- I certainly am. Maybe some of the people on this thread have access to such details, but they aren't sharing. regards, tom lane ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-04-09 08:42 Laurenz Albe <[email protected]> parent: Tom Lane <[email protected]> 0 siblings, 1 reply; 27+ messages in thread From: Laurenz Albe @ 2025-04-09 08:42 UTC (permalink / raw) To: Tom Lane <[email protected]>; Robert Haas <[email protected]>; +Cc: Michael Banck <[email protected]>; Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> On Sat, 2025-04-05 at 19:07 -0400, Tom Lane wrote: > I took another look at this patch, and I still can't persuade > myself that a good case has been made for it. There are too > many scenarios where pg_manage_extensions would be a security > problem and too few where it seems to really improve manageability. > > As an example, it was asserted upthread that it's not a security > problem to let someone install plpython3u, because they still > couldn't create any plpython3u functions unless they were > superuser. Well, fine, but then what's the point of installing > it? If there is someone around with enough privilege to use > plpython3u, that person can install it first. > > I also don't buy the argument that service providers would be > unwilling to set the "trusted" flag on extensions that for whatever > reason they are willing to let be installed by non-superusers. > This thread is full of (unsupported) assertions that those same > providers are making far more invasive changes to the PG code base > to achieve their desired results. > > Robert Haas <[email protected]> writes: > > I agree, but I also don't want the security decisions that the core > > project takes to become irrelevant in practice. It seems like what's > > starting to happen is that all of the cloud providers end up finding > > the same issues and working around them in very similar ways and they > > don't do anything in PostgreSQL itself, I guess because that would > > require winning an argument on the mailing list. > > It would at least require showing up on the mailing list. > None of the assertions made in this thread about what cloud > providers are doing have been supported by a whit of evidence > about that. > > What I'm wishing for is that some of the providers would show up here > and provide specific details (preferably patches) about what they are > changing and why. Then we could have an informed discussion about > how to make their lives less painful in the future. Right now > I think we're guessing --- I certainly am. Maybe some of the people > on this thread have access to such details, but they aren't sharing. So - should this patch be rejected or moved to the next CF in the hope to attract some review from said hosting providers? Michael, do you know any hosting providers you can prompt to comment? Yours, Laurenz Albe ^ permalink raw reply [nested|flat] 27+ messages in thread
* Re: [PATCH] New predefined role pg_manage_extensions @ 2025-05-09 22:45 John H <[email protected]> parent: Laurenz Albe <[email protected]> 0 siblings, 0 replies; 27+ messages in thread From: John H @ 2025-05-09 22:45 UTC (permalink / raw) To: Laurenz Albe <[email protected]>; +Cc: Tom Lane <[email protected]>; Robert Haas <[email protected]>; Michael Banck <[email protected]>; Jelte Fennema-Nio <[email protected]>; PostgreSQL Hackers <[email protected]> Hi, Chiming in as one of said providers... > On Sat, 2025-04-05 at 19:07 -0400, Tom Lane wrote: > > I took another look at this patch, and I still can't persuade > > myself that a good case has been made for it. There are too > > many scenarios where pg_manage_extensions would be a security > > problem and too few where it seems to really improve manageability. I agree extensions expose a large surface area making it possible for privilege escalation. However, I think a new role that allows CREATE EXTENSION is fairly similar to Trusted Extensions and the scrutiny that requires. Providers that care about superuser distinction should already be vetting extensions marked as trusted don't allow elevation today. If they want to allow end-users to leverage the pg_manage_extensions role, they would need to extend that review to all extensions that they are offering. There isn't anything preventing a community extension from incorrectly marking a dangerous (however that is viewed) extension as trusted. > > What I'm wishing for is that some of the providers would show up here > > and provide specific details (preferably patches) about what they are > > changing and why. Then we could have an informed discussion about > > how to make their lives less painful in the future. superusers can always provide a SECURITY DEFINER function that wraps around CREATE EXTENSION with some input, but end-users expect to call "CREATE EXTENSION" instead of some random function. I view these new roles as a quality of life change for users. One reason we introduced our own extension role, 'rds_extensions', was we had users wanting to provide 'CREATE EXTENSION' functionality to their own end-users. They were also not necessarily comfortable with allowing their users to install *all* extensions like Robert suggested so we provided a way for them to specify a subset of them through a parameter. Going back to the patch, I think it depends on what we're trying to solve. Given that we've been trying to split out superuser powers out, do we want to make it easier to create "all extensions" like superuser, or delegate a subset of extensions out without having to edit all the control files as trusted. -- John Hsu - Amazon Web Services ^ permalink raw reply [nested|flat] 27+ messages in thread
end of thread, other threads:[~2025-05-09 22:45 UTC | newest] Thread overview: 27+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2024-01-12 14:53 [PATCH] New predefined role pg_manage_extensions Michael Banck <[email protected]> 2024-01-12 15:13 ` Jelte Fennema-Nio <[email protected]> 2024-01-13 08:20 ` Michael Banck <[email protected]> 2024-10-31 21:47 ` Michael Banck <[email protected]> 2024-11-14 12:30 ` Jelte Fennema-Nio <[email protected]> 2024-11-18 06:26 ` Kirill Reshke <[email protected]> 2024-12-31 11:15 ` Michael Banck <[email protected]> 2025-01-16 07:09 ` Shinya Kato <[email protected]> 2025-01-16 07:35 ` Michael Banck <[email protected]> 2025-01-17 09:03 ` Laurenz Albe <[email protected]> 2025-02-28 18:16 ` Michael Banck <[email protected]> 2025-03-07 13:14 ` Laurenz Albe <[email protected]> 2025-03-07 13:40 ` Dagfinn Ilmari Mannsåker <[email protected]> 2025-03-07 13:57 ` Robert Haas <[email protected]> 2025-03-07 14:02 ` Jelte Fennema-Nio <[email protected]> 2025-03-07 14:17 ` Robert Haas <[email protected]> 2025-03-07 14:33 ` Laurenz Albe <[email protected]> 2025-03-07 14:37 ` Michael Banck <[email protected]> 2025-03-07 14:54 ` Jelte Fennema-Nio <[email protected]> 2025-03-07 15:56 ` Robert Haas <[email protected]> 2025-03-07 16:21 ` Tom Lane <[email protected]> 2025-03-07 16:46 ` Robert Haas <[email protected]> 2025-04-05 23:07 ` Tom Lane <[email protected]> 2025-04-09 08:42 ` Laurenz Albe <[email protected]> 2025-05-09 22:45 ` John H <[email protected]> 2025-03-07 16:23 ` Tom Lane <[email protected]> 2024-05-24 02:26 [PATCH v20 2/8] Row pattern recognition patch (parse/analysis). Tatsuo Ishii <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox