mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Invent "trusted" extensions, and remove the pg_pltemplate catalog.
This patch creates a new extension property, "trusted". An extension that's marked that way in its control file can be installed by a non-superuser who has the CREATE privilege on the current database, even if the extension contains objects that normally would have to be created by a superuser. The objects within the extension will (by default) be owned by the bootstrap superuser, but the extension itself will be owned by the calling user. This allows replicating the old behavior around trusted procedural languages, without all the special-case logic in CREATE LANGUAGE. We have, however, chosen to loosen the rules slightly: formerly, only a database owner could take advantage of the special case that allowed installation of a trusted language, but now anyone who has CREATE privilege can do so. Having done that, we can delete the pg_pltemplate catalog, moving the knowledge it contained into the extension script files for the various PLs. This ends up being no change at all for the in-core PLs, but it is a large step forward for external PLs: they can now have the same ease of installation as core PLs do. The old "trusted PL" behavior was only available to PLs that had entries in pg_pltemplate, but now any extension can be marked trusted if appropriate. This also removes one of the stumbling blocks for our Python 2 -> 3 migration, since the association of "plpythonu" with Python 2 is no longer hard-wired into pg_pltemplate's initial contents. Exactly where we go from here on that front remains to be settled, but one problem is fixed. Patch by me, reviewed by Peter Eisentraut, Stephen Frost, and others. Discussion: https://postgr.es/m/5889.1566415762@sss.pgh.pa.us
This commit is contained in:
@ -225,11 +225,6 @@
|
||||
<entry>information about partition key of tables</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link></entry>
|
||||
<entry>template data for procedural languages</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><link linkend="catalog-pg-policy"><structname>pg_policy</structname></link></entry>
|
||||
<entry>row-security policies</entry>
|
||||
@ -4911,113 +4906,6 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="catalog-pg-pltemplate">
|
||||
<title><structname>pg_pltemplate</structname></title>
|
||||
|
||||
<indexterm zone="catalog-pg-pltemplate">
|
||||
<primary>pg_pltemplate</primary>
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
The catalog <structname>pg_pltemplate</structname> stores
|
||||
<quote>template</quote> information for procedural languages.
|
||||
A template for a language allows the language to be created in a
|
||||
particular database by a simple <command>CREATE LANGUAGE</command> command,
|
||||
with no need to specify implementation details.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Unlike most system catalogs, <structname>pg_pltemplate</structname>
|
||||
is shared across all databases of a cluster: there is only one
|
||||
copy of <structname>pg_pltemplate</structname> per cluster, not
|
||||
one per database. This allows the information to be accessible in
|
||||
each database as it is needed.
|
||||
</para>
|
||||
|
||||
<table>
|
||||
<title><structname>pg_pltemplate</structname> Columns</title>
|
||||
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Name</entry>
|
||||
<entry>Type</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><structfield>tmplname</structfield></entry>
|
||||
<entry><type>name</type></entry>
|
||||
<entry>Name of the language this template is for</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>tmpltrusted</structfield></entry>
|
||||
<entry><type>boolean</type></entry>
|
||||
<entry>True if language is considered trusted</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>tmpldbacreate</structfield></entry>
|
||||
<entry><type>boolean</type></entry>
|
||||
<entry>True if language may be created by a database owner</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>tmplhandler</structfield></entry>
|
||||
<entry><type>text</type></entry>
|
||||
<entry>Name of call handler function</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>tmplinline</structfield></entry>
|
||||
<entry><type>text</type></entry>
|
||||
<entry>Name of anonymous-block handler function, or null if none</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>tmplvalidator</structfield></entry>
|
||||
<entry><type>text</type></entry>
|
||||
<entry>Name of validator function, or null if none</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>tmpllibrary</structfield></entry>
|
||||
<entry><type>text</type></entry>
|
||||
<entry>Path of shared library that implements language</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>tmplacl</structfield></entry>
|
||||
<entry><type>aclitem[]</type></entry>
|
||||
<entry>Access privileges for template (not actually used)</entry>
|
||||
</row>
|
||||
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
There are not currently any commands that manipulate procedural language
|
||||
templates; to change the built-in information, a superuser must modify
|
||||
the table using ordinary <command>INSERT</command>, <command>DELETE</command>,
|
||||
or <command>UPDATE</command> commands.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
It is likely that <structname>pg_pltemplate</structname> will be removed in some
|
||||
future release of <productname>PostgreSQL</productname>, in favor of
|
||||
keeping this knowledge about procedural languages in their respective
|
||||
extension installation scripts.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="catalog-pg-policy">
|
||||
<title><structname>pg_policy</structname></title>
|
||||
|
||||
@ -8519,7 +8407,15 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l
|
||||
<row>
|
||||
<entry><structfield>superuser</structfield></entry>
|
||||
<entry><type>bool</type></entry>
|
||||
<entry>True if only superusers are allowed to install this extension</entry>
|
||||
<entry>True if only superusers are allowed to install this extension
|
||||
(but see <structfield>trusted</structfield>)</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><structfield>trusted</structfield></entry>
|
||||
<entry><type>bool</type></entry>
|
||||
<entry>True if the extension can be installed by non-superusers
|
||||
with appropriate privileges</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
|
@ -1742,6 +1742,7 @@ REVOKE ALL ON accounts FROM PUBLIC;
|
||||
<listitem>
|
||||
<para>
|
||||
For databases, allows new schemas and publications to be created within
|
||||
the database, and allows trusted extensions to be installed within
|
||||
the database.
|
||||
</para>
|
||||
<para>
|
||||
@ -1753,8 +1754,11 @@ REVOKE ALL ON accounts FROM PUBLIC;
|
||||
<para>
|
||||
For tablespaces, allows tables, indexes, and temporary files to be
|
||||
created within the tablespace, and allows databases to be created that
|
||||
have the tablespace as their default tablespace. (Note that revoking
|
||||
this privilege will not alter the placement of existing objects.)
|
||||
have the tablespace as their default tablespace.
|
||||
</para>
|
||||
<para>
|
||||
Note that revoking this privilege will not alter the existence or
|
||||
location of existing objects.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -576,6 +576,31 @@
|
||||
version. If it is set to <literal>false</literal>, just the privileges
|
||||
required to execute the commands in the installation or update script
|
||||
are required.
|
||||
This should normally be set to <literal>true</literal> if any of the
|
||||
script commands require superuser privileges. (Such commands would
|
||||
fail anyway, but it's more user-friendly to give the error up front.)
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>trusted</varname> (<type>boolean</type>)</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This parameter, if set to <literal>true</literal> (which is not the
|
||||
default), allows some non-superusers to install an extension that
|
||||
has <varname>superuser</varname> set to <literal>true</literal>.
|
||||
Specifically, installation will be permitted for anyone who has
|
||||
<literal>CREATE</literal> privilege on the current database.
|
||||
When the user executing <command>CREATE EXTENSION</command> is not
|
||||
a superuser but is allowed to install by virtue of this parameter,
|
||||
then the installation or update script is run as the bootstrap
|
||||
superuser, not as the calling user.
|
||||
This parameter is irrelevant if <varname>superuser</varname> is
|
||||
<literal>false</literal>.
|
||||
Generally, this should not be set true for extensions that could
|
||||
allow access to otherwise-superuser-only abilities, such as
|
||||
filesystem access.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -641,6 +666,18 @@
|
||||
extension, a state of affairs that's a bit tedious to recover from.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the extension script contains the
|
||||
string <literal>@extowner@</literal>, that string is replaced with the
|
||||
(suitably quoted) name of the user calling <command>CREATE
|
||||
EXTENSION</command> or <command>ALTER EXTENSION</command>. Typically
|
||||
this feature is used by extensions that are marked trusted to assign
|
||||
ownership of selected objects to the calling user rather than the
|
||||
bootstrap superuser. (One should be careful about doing so, however.
|
||||
For example, assigning ownership of a C-language function to a
|
||||
non-superuser would create a privilege escalation path for that user.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
While the script files can contain any characters allowed by the specified
|
||||
encoding, control files should contain only plain ASCII, because there
|
||||
|
@ -153,7 +153,7 @@
|
||||
<para>
|
||||
Daredevils, who want to build a Python-3-only operating system
|
||||
environment, can change the contents of
|
||||
<link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link>
|
||||
<literal>plpythonu</literal>'s extension control and script files
|
||||
to make <literal>plpythonu</literal> be equivalent
|
||||
to <literal>plpython3u</literal>, keeping in mind that this
|
||||
would make their installation incompatible with most of the rest
|
||||
|
@ -47,14 +47,25 @@ CREATE EXTENSION [ IF NOT EXISTS ] <replaceable class="parameter">extension_name
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Loading an extension requires the same privileges that would be
|
||||
required to create its component objects. For most extensions this
|
||||
means superuser or database owner privileges are needed.
|
||||
The user who runs <command>CREATE EXTENSION</command> becomes the
|
||||
owner of the extension for purposes of later privilege checks, as well
|
||||
as the owner of any objects created by the extension's script.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Loading an extension ordinarily requires the same privileges that would
|
||||
be required to create its component objects. For many extensions this
|
||||
means superuser privileges are needed.
|
||||
However, if the extension is marked <firstterm>trusted</firstterm> in
|
||||
its control file, then it can be installed by any user who has
|
||||
<literal>CREATE</literal> privilege on the current database.
|
||||
In this case the extension object itself will be owned by the calling
|
||||
user, but the contained objects will be owned by the bootstrap superuser
|
||||
(unless the extension's script explicitly assigns them to the calling
|
||||
user). This configuration gives the calling user the right to drop the
|
||||
extension, but not to modify individual objects within it.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -21,9 +21,9 @@ PostgreSQL documentation
|
||||
|
||||
<refsynopsisdiv>
|
||||
<synopsis>
|
||||
CREATE [ OR REPLACE ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
|
||||
CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
|
||||
HANDLER <replaceable class="parameter">call_handler</replaceable> [ INLINE <replaceable class="parameter">inline_handler</replaceable> ] [ VALIDATOR <replaceable>valfunction</replaceable> ]
|
||||
CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
|
||||
</synopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@ -37,21 +37,6 @@ CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="pa
|
||||
defined in this new language.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
As of <productname>PostgreSQL</productname> 9.1, most procedural
|
||||
languages have been made into <quote>extensions</quote>, and should
|
||||
therefore be installed with <xref linkend="sql-createextension"/>
|
||||
not <command>CREATE LANGUAGE</command>. Direct use of
|
||||
<command>CREATE LANGUAGE</command> should now be confined to
|
||||
extension installation scripts. If you have a <quote>bare</quote>
|
||||
language in your database, perhaps as a result of an upgrade,
|
||||
you can convert it to an extension using
|
||||
<literal>CREATE EXTENSION <replaceable>langname</replaceable> FROM
|
||||
unpackaged</literal>.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
<command>CREATE LANGUAGE</command> effectively associates the
|
||||
language name with handler function(s) that are responsible for executing
|
||||
@ -59,54 +44,33 @@ CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="pa
|
||||
for more information about language handlers.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
There are two forms of the <command>CREATE LANGUAGE</command> command.
|
||||
In the first form, the user supplies just the name of the desired
|
||||
language, and the <productname>PostgreSQL</productname> server consults
|
||||
the <link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link>
|
||||
system catalog to determine the correct parameters. In the second form,
|
||||
the user supplies the language parameters along with the language name.
|
||||
The second form can be used to create a language that is not defined in
|
||||
<structname>pg_pltemplate</structname>, but this approach is considered obsolescent.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When the server finds an entry in the <structname>pg_pltemplate</structname> catalog
|
||||
for the given language name, it will use the catalog data even if the
|
||||
command includes language parameters. This behavior simplifies loading of
|
||||
old dump files, which are likely to contain out-of-date information
|
||||
about language support functions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Ordinarily, the user must have the
|
||||
<productname>PostgreSQL</productname> superuser privilege to
|
||||
register a new language. However, the owner of a database can register
|
||||
a new language within that database if the language is listed in
|
||||
the <structname>pg_pltemplate</structname> catalog and is marked
|
||||
as allowed to be created by database owners (<structfield>tmpldbacreate</structfield>
|
||||
is true). The default is that trusted languages can be created
|
||||
by database owners, but this can be adjusted by superusers by modifying
|
||||
the contents of <structname>pg_pltemplate</structname>.
|
||||
The creator of a language becomes its owner and can later
|
||||
drop it, rename it, or assign it to a new owner.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<command>CREATE OR REPLACE LANGUAGE</command> will either create a
|
||||
new language, or replace an existing definition. If the language
|
||||
already exists, its parameters are updated according to the values
|
||||
specified or taken from <structname>pg_pltemplate</structname>,
|
||||
already exists, its parameters are updated according to the command,
|
||||
but the language's ownership and permissions settings do not change,
|
||||
and any existing functions written in the language are assumed to still
|
||||
be valid. In addition to the normal privilege requirements for creating
|
||||
a language, the user must be superuser or owner of the existing language.
|
||||
The <literal>REPLACE</literal> case is mainly meant to be used to
|
||||
ensure that the language exists. If the language has a
|
||||
<structname>pg_pltemplate</structname> entry then <literal>REPLACE</literal>
|
||||
will not actually change anything about an existing definition, except in
|
||||
the unusual case where the <structname>pg_pltemplate</structname> entry
|
||||
has been modified since the language was created.
|
||||
be valid.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
One must have the
|
||||
<productname>PostgreSQL</productname> superuser privilege to
|
||||
register a new language or change an existing language's parameters.
|
||||
However, once the language is created it is valid to assign ownership of
|
||||
it to a non-superuser, who may then drop it, change its permissions,
|
||||
rename it, or assign it to a new owner. (Do not, however, assign
|
||||
ownership of the underlying C functions to a non-superuser; that would
|
||||
create a privilege escalation path for that user.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The form of <command>CREATE LANGUAGE</command> that does not supply
|
||||
any handler function is obsolete. For backwards compatibility with
|
||||
old dump files, it is interpreted as <command>CREATE EXTENSION</command>.
|
||||
That will work if the language has been packaged into an extension of
|
||||
the same name, which is the conventional way to set up procedural
|
||||
languages.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
@ -218,12 +182,6 @@ CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="pa
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>
|
||||
The <literal>TRUSTED</literal> option and the support function name(s) are
|
||||
ignored if the server has an entry for the specified language
|
||||
name in <structname>pg_pltemplate</structname>.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="sql-createlanguage-notes">
|
||||
@ -254,18 +212,6 @@ CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="pa
|
||||
all subsequently-created databases.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The call handler function, the inline handler function (if any),
|
||||
and the validator function (if any)
|
||||
must already exist if the server does not have an entry for the language
|
||||
in <structname>pg_pltemplate</structname>. But when there is an entry,
|
||||
the functions need not already exist;
|
||||
they will be automatically defined if not present in the database.
|
||||
(This might result in <command>CREATE LANGUAGE</command> failing, if the
|
||||
shared library that implements the language is not available in
|
||||
the installation.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In <productname>PostgreSQL</productname> versions before 7.3, it was
|
||||
necessary to declare handler functions as returning the placeholder
|
||||
@ -281,23 +227,20 @@ CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="pa
|
||||
<title>Examples</title>
|
||||
|
||||
<para>
|
||||
The preferred way of creating any of the standard procedural languages
|
||||
is just:
|
||||
<programlisting>
|
||||
CREATE LANGUAGE plperl;
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For a language not known in the <structname>pg_pltemplate</structname> catalog, a
|
||||
sequence such as this is needed:
|
||||
A minimal sequence for creating a new procedural language is:
|
||||
<programlisting>
|
||||
CREATE FUNCTION plsample_call_handler() RETURNS language_handler
|
||||
AS '$libdir/plsample'
|
||||
LANGUAGE C;
|
||||
CREATE LANGUAGE plsample
|
||||
HANDLER plsample_call_handler;
|
||||
</programlisting></para>
|
||||
</programlisting>
|
||||
Typically that would be written in an extension's creation script,
|
||||
and users would do this to install the extension:
|
||||
<programlisting>
|
||||
CREATE EXTENSION plsample;
|
||||
</programlisting>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="sql-createlanguage-compat">
|
||||
|
@ -190,7 +190,7 @@ CREATE FUNCTION plperl_call_handler() RETURNS language_handler AS
|
||||
|
||||
<programlisting>
|
||||
CREATE FUNCTION plperl_inline_handler(internal) RETURNS void AS
|
||||
'$libdir/plperl' LANGUAGE C;
|
||||
'$libdir/plperl' LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION plperl_validator(oid) RETURNS void AS
|
||||
'$libdir/plperl' LANGUAGE C STRICT;
|
||||
|
Reference in New Issue
Block a user