Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1t6d0q-00ELfV-EL for pgsql-hackers@arkaria.postgresql.org; Thu, 31 Oct 2024 21:47:28 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1t6d0o-006Jnq-4H for pgsql-hackers@arkaria.postgresql.org; Thu, 31 Oct 2024 21:47:26 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1t6d0n-006Jm2-OU for pgsql-hackers@lists.postgresql.org; Thu, 31 Oct 2024 21:47:26 +0000 Received: from mail-wr1-x432.google.com ([2a00:1450:4864:20::432]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1t6d0h-0044LJ-P7 for pgsql-hackers@lists.postgresql.org; Thu, 31 Oct 2024 21:47:25 +0000 Received: by mail-wr1-x432.google.com with SMTP id ffacd0b85a97d-37d4ac91d97so1087983f8f.2 for ; Thu, 31 Oct 2024 14:47:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1730411238; x=1731016038; darn=lists.postgresql.org; h=user-agent:in-reply-to:content-disposition:mime-version:references :subject:cc:to:from:date:sender:message-id:from:to:cc:subject:date :message-id:reply-to; bh=SPoypsfLov7zf5277S4uFM6tYwc5S4pO5iteY0T6uIU=; b=eI+nFNkwlgc8k4LpcQDQlZD9vC3UDi8tUp4n9/3DMUaVQ2HOufAlZkrxAfVeUGxzL1 rewTeQ1jF/8YOr/YJuv8MPvGNWaTxGCK4B18A/LyLR24y7JpwQaJpaPhOz7aCR+ZhhMV z7/wt18dVxIF/HHpadjl9M4ypx3paJSit2LSTe+RowaMzpTM1WmamnQ14BWaU2OxHyHl 7ivi0CCJcO3sPJIwm+IKKOdjrnXpcp9Lu0J1g1KZOUG1cjS/0OvFoNWaWldArtdwYNfH 5M6G1Fqt1NYEq23h47FNN8NMdRFM7fiV3leJfGi7LlqVpS4NDhPe1ZUf/ljADewrqYLh mRWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730411238; x=1731016038; h=user-agent:in-reply-to:content-disposition:mime-version:references :subject:cc:to:from:date:sender:message-id:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=SPoypsfLov7zf5277S4uFM6tYwc5S4pO5iteY0T6uIU=; b=kRgFxIjaWiq2+c6/VfY8O+wspK6l7q1T8S+gYK+wLSR56caLQJdeZdXVE1CJ4ATP5y YTf7jzjzutgtM8eqUcL1uefaMc4+S3qGdMwJjOrmy2R7ZYTwvLEKgO6jCUOYRIQQoJDX O7k8hKg6FDo0FYMiO8t4Ve2ryfwpfuISdCroT1UTkUWt1ebRBLDXtLY72hbiI8AUipwY 92xRtEu1OISaczXMjz9XXHlvpD6tdO66vKw8q/7iM9sHxxUWmaPERM/KisGxEFWRLe9O H0NyB0nDiieeolkeulUA85GLhjIiNHPxj7uVhvxEAdkx7fmq+xWKamwT1/6UqBvQvFbP 7ntg== X-Gm-Message-State: AOJu0Yw2KE6HC7qGNpsFZAZZoU+iUFmKdsWkZWfA9COMtGUcJJ59mOXT QO92qhp1va3IpbEQg5oZU5Na+jkVTXOAhUY7d9uLVpNOplsxMAEM X-Google-Smtp-Source: AGHT+IE+pwLJP8+82fe5VOeCFhTXx9oSsi7UV/Xs5dXAevSK0w1iSOZ/2g/XX2LKQLk34MQAV/Lkig== X-Received: by 2002:a5d:6dab:0:b0:37e:d2b8:883a with SMTP id ffacd0b85a97d-381c7a464c6mr1329837f8f.12.1730411237597; Thu, 31 Oct 2024 14:47:17 -0700 (PDT) Received: from lightning.caipicrew.dd-dns.de ([2001:a61:a49:e301:666c:78e:5e29:e70c]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5ceb0241bcasm755693a12.8.2024.10.31.14.47.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 31 Oct 2024 14:47:16 -0700 (PDT) Message-ID: <6723fae4.a70a0220.28a8f2.27e4@mx.google.com> X-Google-Original-Message-ID: <20241031214716.GA18591@caipicrew.dd-dns.de;lightning.caipicrew.dd-dns.de> Sender: Michael Banck Received: from mbanck by lightning.caipicrew.dd-dns.de with local (Exim 4.92) (envelope-from ) id 1t6d0e-0006GE-9r; Thu, 31 Oct 2024 22:47:16 +0100 Date: Thu, 31 Oct 2024 22:47:16 +0100 From: Michael Banck To: Jelte Fennema-Nio Cc: PostgreSQL Hackers Subject: Re: [PATCH] New predefined role pg_manage_extensions References: <65a1524e.050a0220.49266.7670@mx.google.com> <65a247d9.050a0220.ecb2e.1177@mx.google.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="tKW2IUtsqtDRztdT" Content-Disposition: inline In-Reply-To: <65a247d9.050a0220.ecb2e.1177@mx.google.com> User-Agent: Mutt/1.10.1 (2018-07-13) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --tKW2IUtsqtDRztdT Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 --tKW2IUtsqtDRztdT Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v2-0001-Add-new-pg_manage_extensions-predefined-role.patch" From bda5db90d6d56a025f275c85f775f48c8083b7f0 Mon Sep 17 00:00:00 2001 From: Michael Banck 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; + + pg_manage_extensions + + + pg_manage_extensions allows creating, removing or + updating extensions, even if the extensions are untrusted or the user is + not the database owner. + + + + pg_monitor pg_read_all_settings 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 --tKW2IUtsqtDRztdT--