Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8319332 Security properties files inclusion
  3. JDK-8336162

Write user guide documentation for security properties inclusion

XMLWordPrintable

    • Icon: Sub-task Sub-task
    • Resolution: Delivered
    • Icon: P4 P4
    • 24
    • None
    • docs

      ## Security properties files inclusion

      The _java.security_ file defines global security properties for the JDK. These properties can be extended or replaced on a per-execution basis by setting the _java.security.properties_ system property to an external file or URL stream. To provide a more flexible organization, all security properties files can include other files inline by means of `include` statements. When a file is included, all its properties are added to the security properties map as if defined starting at the inclusion point.

      ### Syntax and semantics

      While `include` statements and security properties share the syntax described for the [java.util.Properties::load](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Properties.html#load%28java.io.Reader%29) API and can be intermixed in the same file, they operate with different semantics. In order to stress this difference and gain clarity, the grammatical form having a white space separator between the key and the value is preferred for `include` statements over those having a double colon or an equals character:

      `include file-system-path`

      `include` is a reserved word that takes the position of a key in the syntax. This reserved word is not available to define a security property. Any call to `java.security.Security.getProperty("include")` or `java.security.Security.setProperty("include", ...)` throws an unchecked `IllegalArgumentException` exception.

      A file system path, in turn, takes the position of a value in the syntax. File system paths depend on the platform and can be either absolute or relative. When relative, the location of the file that contains the `include` statement is used as a base. If the `include` statement is not in a local file but in a URL stream, relative includes are not allowed. On Windows, double backward slashes, single forward slashes and UNC paths are supported. On Linux, standard forward slashes paths are supported. URL-file paths (i.e. `file://...`) are not supported.

      As is the case for some security properties values, file system paths may contain placeholders that are replaced at run time with the value of their respective system property. The construction `${system-property}` is available for this purpose. For more information visit the [Property Expansion in Policy Files](https://docs.oracle.com/en/java/javase/22/security/permissions-jdk1.html#GUID-B614FBFF-0C3C-42F3-B766-DE709CA4D73A) section of the Security Developer’s Guide. Contrary to placeholders in security properties values, an undefined system property causes a placeholder in a file system path to be ignored (i.e. replaced by an empty string) instead of a failure.

      Each `include` statement is processed immediately it is encountered, irrespective of preceding or subsequent occurrences. Its position in the file may affect security properties values as described in the section _Order_. However, `include` statements do not interfere with each other in the sense that their actions are always executed. By contrast, security properties defined later in the file or brought in by a following inclusion would override a previous definition if names are equal.

      An error is thrown if a file cannot be included. This may happen if the file cannot be resolved, does not exist, is a directory, there are insufficient permissions to read it, it is recursively included more than once, or for any other reason.

      ### Order

      When a file is included, properties defined in the included file may be either added to the security properties map or replace existing ones if names are equal. Thus, the effect of an `include` statement may depend on its position in the properties file. This behavior can be leveraged to define overridable security properties (placed _before_ an `include`) and non-overridable security properties (placed _after_ an `include`).

      ### Recursion and cycles

      Included files may include others recursively in a tree-like structure. To prevent infinite cycles, included paths are normalized and can only be used once per branch. If a cycle is detected, an error is thrown. It is a good practice to keep the number of included files and their depth level low in order to facilitate a clear reasoning about the security properties that will be effective on the JDK.

      The following structure contains a cycle because _A.security_ is included twice in a branch:

      ```
      ╭───────────────────────────────────────────────────────────────────╮
      │ │
      │ java.security ---> A.security ---> B.security ---> A.security │
      │ │
      ╰───────────────────────────────────────────────────────────────────╯
      ```

      The following structure does not contain a cycle because _A.security_ is included once per branch:

      ```
      ╭───────────────────────────────────────────────────────────────────╮
      │ │
      │ java.security ---> A.security │
      │ | │
      │ ---> B.security │
      │ | │
      │ ---> A.security │
      │ │
      ╰───────────────────────────────────────────────────────────────────╯
      ```

      Note: arrows represent `include` statements.

      ### Security Profiles

      System administrators frequently require the enforcement of security policies to Java applications for security hardening, regulatory compliance or preserving backward compatibility. These policies are typically transversal to multiple JDK deployments and would benefit from centralized management. The includes feature supports the establishment of global profiles organized through separate security properties files. A bridge file that includes the profile enforced by default is a practical mechanism to switch between them. Every JDK deployment that adheres to this architecture must include the bridge from its _java.security_ file.

      To illustrate this concept, let's assume the following layout of security properties files and include relationships:

      - /global/profiles
        - profile-.security (bridge)
          - include profile-fips.security (profile enforced by default)
        - profile-fips.security
        - profile-pci-dss.security
        - profile-legacy.security


      - $JAVA_24_HOME/conf/security/java.security
        - include /global/profiles/profile-${securityProfile}.security


      - $JAVA_25_HOME/conf/security/java.security
        - include /global/profiles/profile-${securityProfile}.security

      The _profile-.security_ file is a bridge to the global policy enforced by default. This policy is currently the one defined in _profile-fips.security_. A system administrator can change the default policy by modifying the `include` statement in the bridge and referring to any of the policies in _/global/profiles_. When the system property `securityProfile` is undefined, JDK 24 and 25 deployments end up including the bridge from their respective _java.security_ files.

      On some occasions, applications require a profile different from the one enforced by default. For this reason, `include` statements in each of the above _java.security_ examples employ a placeholder suffix. When the system property `securityProfile` is undefined, this placeholder is ignored and the included file is _profile-.security_ (bridge). A layout in which the file _profile-.security_ does not exist would prevent a default choice and force `securityProfile` to be defined. By setting `securityProfile` to one of the available values (`fips`, `pci-dss` or `legacy`), a profile can be selected on a per-application basis. For example, a Java application may be launched with the `-DsecurityProfile=legacy` JVM argument for the profile _legacy_ to be applied, irrespective of the profile enforced by default. Security properties are processed at `java.security.Security` class initialization time. If a placeholder's system property is programmatically set after this point, it will not be effective.

      The previous example can be further extended with the definition of security profiles that are specific to a JDK release, such as _profile-.24.security_ and _profile-fips.24.security_. In this case, the _java.security_ for JDK 24 must include both the global and the release-specific bridges to the current global policy. Having a release-specific policy may be useful when the list of security properties is not the same across all JDK releases.

      The JDK does not provide curated security profiles or favors any particular structure for their organization. It is important to maintain profiles updated and opt for secure defaults whenever possible. It is also recommended to analyze how profiles apply to each JDK release in terms of security properties availability.

      ### Security considerations

      Security properties have a direct implication in the security of the JDK. As stated in the _Recursion and cycles_ section, the files layout should be one that allows a clear understanding and reasoning about the security properties that are defined and their overrides. It is a good practice to check the final map of security properties in the JDK with the methods indicated in the _Troubleshooting_ section.

      When including a security properties file, it is strongly recommended to verify that it comes from a trusted source and to check write permissions not only for the included file but also for the entire chain of parent directories starting at the file system root. Any user who has capabilities to modify an included file may downgrade the security of the JDK by either replacing security properties or adding new ones that cause overrides. Any user that can rename a directory in the chain of parents may be able to impersonate the included file with a rogue version, leading to a downgrade in the JDK security as well. As a rule of thumb, an included file and its chain of parent directories should have equal or more restrictive permissions than the file containing its `include` statement.

      When placeholders are used in file system paths and system properties are passed, it is worth noting the impact of a typo: if the typo is in the property name, the placeholder will be ignored; if the typo is in the property value, an error will be thrown because included files must exist. Always check system properties in placeholders and arguments for typos.

      ### Troubleshooting

      Debugging information is available when enabling security properties logs. To enable these logs, the argument `-Djava.security.debug=properties` should be passed to `java`. Messages prefixed by _properties_ contain the final values for all security properties and information on how `include` statements are processed.

      In addition, the `java` argument `-XshowSettings:security` shows an overview of the security settings that are effective in the JDK.

      Finally, the [JFR event jdk.InitialSecurityProperty](https://www.oracle.com/java/technologies/javase/17-0-7-relnotes.html#JDK-8292177) can be used to obtain the initial values for security properties on a running JDK.

      ### Examples (valid)

      Relative path (multi-platform):

      `include extra.security`

      Absolute path using a placeholder with a system property pointing to the JDK directory (multi-platform):

      `include ${java.home}/conf/security/extra.security`

      Absolute path (Linux):

      `include /etc/crypto-policies/back-ends/java.config`

      Absolute path, backward slashes (Windows):

      `include C:\\Program Files\\Common Files\\OpenJDK\\java.config`

      Absolute path, forward slashes (Windows):

      `include C:/Program Files/Common Files/OpenJDK/java.config`

      UNC path (Windows):

      `include \\\\WindowsHost\\Share\\java.config`

      ### Examples (invalid)

      URLs are not allowed:

      `include file:///etc/crypto-policies/back-ends/java.config`

      Included files must exist:

      `include non-existent-file.security`

      Directories cannot be included:

      `include /etc/crypto-policies/back-ends/`

            rgallard Raymond Gallardo
            mbalao Martin Balao Alonso
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: