RFR: 8319332: Security properties files inclusion
Francisco Ferrari Bihurriet
fferrari at openjdk.org
Thu Nov 2 19:56:20 UTC 2023
The implementation of this proposal is based on the requirements, specification and design choices described in the [JDK-8319332] ticket and its respective CSR [JDK-8319333]. What follows are implementation notes organized per functional component, with the purpose of assisting to navigate the code changes in this pull-request.
## Security properties loading (overview)
A new static class named `SecPropLoader` (nested within `java.security.Security`) is introduced to handle the loading of all security properties. Its method `loadAll` is the first one to be called, at `java.security.Security` static class initialization. The master security properties file is then loaded by `loadMaster`. When additional security properties files are allowed (the security property `security.overridePropertiesFile` is set to `true`) and the `java.security.properties` system property is passed, the method `loadExtra` handles the extra load.
The master properties file is loaded in `OVERRIDE` mode, meaning that the map of properties is originally empty. Any failure occurred while loading these properties is considered fatal. The extra properties file (`java.security.properties`) may be loaded in `OVERRIDE` or `APPEND` mode. Any failure in this case is ignored. This behavior maintains compatibility with the previous implementation.
While the `java.security.properties` system property is documented to accept an URL type of value, filesystem path values are supported in the same way that they were prior to this enhancement. Values are then interpreted as paths and, only if that fails, are considered URLs. In the latter case, there is one more attempt after opening the stream to check if there is a local file path underneath (e.g. the URL has the form of `file:///path/to/a/local/file`). The reason for preferring paths over URLs is to support relative path file inclusion in properties files.
## Loading security properties from paths (`loadFromPath` method)
When loading a properties file from a path, the normalized file location is stored in the static field `currentPath`. This value is the current base to resolve any relative path encountered while handling an _include_ definition. Normalized paths are also saved in the `activePaths` set to detect recursive cycles. As we move down or up in the _includes_ stack, `currentPath` and `activePaths` values are updated.
## Loading security properties from URLs (`loadFromUrl` method)
The extra properties file can be loaded from a URL. If the URL has a local path underneath, `loadFromPath` is preferred to do the job. Otherwise, the load starts without a base assigned to `currentPath`. The absence of a base implies that any relative path _include_ definition will fail. For example, the extra properties file loaded when passing `-Djava.security.properties=https://example.com/some/path/java.config` to the JVM cannot contain a relative _include_. However, this same file can contain an absolute _include_ which, in turn, can contain a relative one.
## Loading included files (`loadInclude` method)
In order to handle the new _include_ property according to the defined semantics, the `java.util.Properties` class was extended and the method `put` overwritten. When the property key is _include_, the method `loadInclude` is called and the entry is not added to the map.
The method `loadInclude` expands system properties in the _include_ property value and tries to interpret it as a path. If successful and the property value is a relative path, the current base (`currentPath`) is used for resolution to an absolute path. Once an absolute path is obtained, the aforementioned `loadFromPath` method is called to do the rest of the work. An error while handling an included file is considered fatal.
## System properties expansion
System properties between `${` and `}` characters in _include_ property values are expanded. If a property is not defined (e.g. its value is `null`), expansion is to an empty string. This expansion mode is called non-strict, and implemented in the method `expandNonStrict` of the `sun.security.util.PropertyExpander` class.
## Testing
* An existing test (`ConfigFileTest.java`) was refactored and extended to cover file inclusion scenarios.
* This test has been run on _Windows_ and _Linux_ platforms.
* No regressions have been observed in the following test categories:
* JDK tier-1
* `test/jdk/java/security/Security`
* `test/jdk/javax/net/ssl/compatibility`
* Other tests using `java.security.properties`
* `test/jdk/java/security/Provider/SecurityProviderModularTest.java`
* `test/jdk/javax/crypto/CryptoPermissions/CryptoPolicyFallback.java`
This contribution is co-authored by Francisco Ferrari and Martin Balao.
---
[JDK-8319332]: https://bugs.openjdk.org/browse/JDK-8319332
[JDK-8319333]: https://bugs.openjdk.org/browse/JDK-8319333
-------------
Commit messages:
- 8319332: Implement security properties 'include'
- 8319332: Refactor security properties file test
- 8319332: Refactor properties file loading code
Changes: https://git.openjdk.org/jdk/pull/16483/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=16483&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8319332
Stats: 1126 lines in 7 files changed: 901 ins; 161 del; 64 mod
Patch: https://git.openjdk.org/jdk/pull/16483.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/16483/head:pull/16483
PR: https://git.openjdk.org/jdk/pull/16483
More information about the security-dev
mailing list