-
Notifications
You must be signed in to change notification settings - Fork 80
JEP 411
Changes in Java, over some number of releases starting with Java 17, will force important functional changes in PL/Java.
PL/Java supports at least two PostgreSQL CREATE LANGUAGE
declarations,
one with and one without the TRUSTED
property, and
enforces limits on what a function declared in the TRUSTED
language can do.
The PL/Java 1.6 series goes further and makes those restrictions configurable,
and more than two PL/Java "languages" can be declared, with different
configurable restrictions for each, as described
in the documentation.
To provide and support these controls, PL/Java relies on many features of the groundbreaking Java 2 security architecture as specified in 2002.
In April 2021, the Java developers announced a JDK Enhancement Proposal, JEP 411, that will remove this functionality from Java over a series of releases, with the first changes already shipped in Java 17.
As originally described, the "major components of the security model are security policy, access permissions, protection domain, access control checking, privileged operation, and class loading and resolution." JEP 411 will eventually eliminate the first, fourth and fifth, with the second and third remaining in vestigial form. PL/Java relies on those.
In Java 17, however, all of the functionality remains; only warnings and deprecation markings have been added. Java 17 is also positioned as a long-term support release, the successor in that role to Java 11. It will therefore be possible to run current PL/Java versions without difficulty for a number of years.
However, Java 17 will be designed to write an unconditional warning on its
standard error channel (which will go into PostgreSQL's log file, if
logging_collector
is enabled), every time any backend loads PL/Java.
The JEP 411 proponents rebuffed requests to allow a higher layer,
like PL/Java, to suppress the low-level JVM warning and issue one that is
layer-appropriate (such as an explanation about trusted functions or a link
to this wiki page).
The JVM's boilerplate warning will look like this:
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by org.postgresql.pljava.internal.Backend
WARNING: Please consider reporting this to the maintainers of org.postgresql.pljava.internal.Backend
WARNING: System::setSecurityManager will be removed in a future release
As much as the warnings will urge you, please do not consider reporting them to the maintainers of PL/Java.
The PL/Java 1.6 series, as described below, does attempt to suppress the boilerplate JVM warning, and issue a "migration advisory" ereport
of a more useful nature, only upon certain administrative actions like CREATE EXTENSION
or installing a jar, and no more than once in a session. That should cut down on the log spam.
Two things are expected in Java 18 or later:
- a special JVM option,
-Djava.security.manager=allow
, will be needed at launch time, to allow PL/Java to use the necessary components in the JVM - the components in the JVM, even if allowed, may have been "degraded" or changed into no-ops.
While the JEP does not read quite clearly on this point, it is possible both changes will ship in the same Java version, in which case there will be no point in using the special option.
If the changes arrive separately, so that there is a version where the special
option is needed but the components still work if allowed, then adding
-Djava.security.manager=allow
to pljava.vmoptions
will allow
PL/Java to use that Java version.
Update: as of Java 23, the functionality does not seem degraded yet, as long
as -Djava.security.manager=allow
is specified, as is needed for Java 18
and above.
For both current release series of PL/Java, 1.5 and 1.6, there will eventually be a Java version on which they will be unable to enforce the intended security policies. Where that enforcement is needed, they should be run on any earlier Java version, including 17 and 21, which are positioned for long-term support.
PL/Java 1.5 is the series minimally maintained for legacy support (PostgreSQL back to 8.2, Java back to 6). Its build process requires Java 14 or earlier, but it can be run on later Java versions. Minimal changes will be made in 1.5.
- Because it already does not support building on newer Java versions, it will not need any source code changes to suppress the new deprecation warnings.
- It will make no attempt to intercept the fixed warning message described above. When running on Java 17 or later, that warning will be written on the backend's standard error channel, every time a backend starts PL/Java.
- Code will not be added to automatically supply the
-Djava.security.manager=allow
option for any Java version. - Code will be added (in 1.5.8) to attempt to detect when the needed
components have become no-ops, and then throw an exception rather than
executing any function declared as
trusted
.
Options if that exception is seen can include:
- Continuing to use PL/Java 1.5, downgrading Java to the preceding version
- Changing all
trusted
function declarations to untrusted and accepting that they will run without security enforcement - Upgrading to a newer PL/Java version if available.
Note that even functions declared as untrusted have normally had a few limits enforced in PL/Java 1.5, and even those limits will be unenforced if running on a version of Java where the needed components are no-ops.
PL/Java 1.6 is the current recommended series covering PostgreSQL 9.5 and later, Java 9 and later.
- The source code will need warning-suppression annotations added (in 1.6.3)
for clean builds with Java 17 and later. In fact it does not, because
1.6 is built with
--release 9
, for which the deprecations are not effective. - Code will be added (1.6.3) to attempt to suppress the boilerplate, low-level warning from the JVM, so that more meaningful notice in relevant PL/Java terms can be given. Suppression of the boilerplate will be best-effort, relying on JDK internals, given the rebuffed request for an exposed control serving that purpose.
- Code will be added (1.6.3) to:
- Issue warnings of the upcoming JEP 411 impacts, including a link to this wiki page
- Issue the warning whenever the runtime Java major version is above 11, so as to warn not only sites that have moved from 11 LTS to 17 LTS, but also sites that update more frequently between LTS versions
- Issue the warning when PL/Java is installed or upgraded, or when
a cluster that has PL/Java installed undergoes a binary
pg_upgrade
(in thepg_upgrade
case, the warning will be unconditional, because no JVM is started at that time to query its version) - Issue warning, at most one per session, at commit of a transaction that has declared or redeclared at least one PL/Java function
- Refuse to execute, if the needed support is detectably stubbed out, unless a special configuration option is set
- Add a new configuration option that can be set, by a superuser, to try to allow all functions to execute with no security enforcement regardless of their declarations. Whether this is possible, or PL/Java will just break, depends on exactly how the Java developers choose to "degrade" the functionality.
- 1.6.3 will not be usable on whatever version of Java finally removes the deprecated APIs. It will fail with linkage errors.
- Code may be added (in a release after 1.6.3), to automatically supply a
-Djava.security.manager=allow
option if there would be any point (that is, if there is expected to be a Java release where the option is needed but the needed functionality is not yet stubbed out). - A release after 1.6.3 may also be adapted to run without linkage errors on a Java version where the APIs have been finally removed.
Note that even functions declared as untrusted run with significant limits by default in PL/Java 1.6, and the limits on both trusted and untrusted functions are configurable in policy, and all such limits will be unenforced if running on a version of Java where the needed components are no-ops.
PL/Java 1.6 will continue to see active development for the foreseeable future. The existing enforcement mechanisms will continue to be supported at least through Java 17 LTS, and for some applications, its fine-grained security policy may remain more attractive than what post-JEP-411 versions will support.
A new major version of PL/Java will need to be developed that can support some notion of trusted-function enforcement without relying on the rescinded Java mechanisms.
This will be a big undertaking, and will have to scale back expectations to a much more basic model of what can be enforced: chiefly filesystem access, process manipulations, and IPC. The result will probably land somewhere more fine-grained and configurable than PL/Java 1.5, but much less so than 1.6.
All usual disclaimers about forward-looking statements must be applied.
During that development, both existing PL/Java series, as described above, can continue to be used, and with all functionality unimpaired, on Java versions up to and including 17 LTS.