Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WFCORE-4296][WFCORE-5406] Add required --add-opens for java.base/com.sun.net.ssl.internal.ssl when HTTPS is configured #4966

Merged
merged 4 commits into from
Sep 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions core-feature-pack/common/src/main/resources/content/bin/common.bat
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ if exist "%COMMON_CONF%" (
endlocal
goto :eof

:setPackageAvailable
"%JAVA%" --add-opens=%~1=ALL-UNNAMED -version >nul 2>&1 && (set PACKAGE_AVAILABLE=true) || (set PACKAGE_AVAILABLE=false)
goto :eof

:setEnhancedSecurityManager
"%JAVA%" -Djava.security.manager=allow -version >nul 2>&1 && (set ENHANCED_SM=true) || (set ENHANCED_SM=false)
goto :eof
Expand Down Expand Up @@ -48,6 +52,12 @@ goto :eof
set "DEFAULT_MODULAR_JVM_OPTIONS=!DEFAULT_MODULAR_JVM_OPTIONS! --add-exports=java.naming/com.sun.jndi.url.ldaps=ALL-UNNAMED"
rem Needed by Netty
set "DEFAULT_MODULAR_JVM_OPTIONS=!DEFAULT_MODULAR_JVM_OPTIONS! --add-exports=jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED"
rem Needed by WildFly Elytron Extension
set PACKAGE_NAME="java.base/com.sun.net.ssl.internal.ssl"
call :setPackageAvailable !PACKAGE_NAME!
if "!PACKAGE_AVAILABLE!" == "true" (
set "DEFAULT_MODULAR_JVM_OPTIONS=!DEFAULT_MODULAR_JVM_OPTIONS! --add-opens=!PACKAGE_NAME!=ALL-UNNAMED"
)
rem Needed if Hibernate applications use Javassist
set "DEFAULT_MODULAR_JVM_OPTIONS=!DEFAULT_MODULAR_JVM_OPTIONS! --add-opens=java.base/java.lang=ALL-UNNAMED"
rem Needed by the MicroProfile REST Client subsystem
Expand Down
15 changes: 15 additions & 0 deletions core-feature-pack/common/src/main/resources/content/bin/common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ Function Get-Java-Opts {
return $JAVA_OPTS
}

Function SetPackageAvailable($packageName) {
$PACKAGE_AVAILABLE = $false
& $JAVA "--add-opens=$packageName=ALL-UNNAMED" -version >$null 2>&1
if ($LastExitCode -eq 0){
$PACKAGE_AVAILABLE = $true
}
return $PACKAGE_AVAILABLE
}

Function SetEnhancedSecurityManager {
$ENHANCED_SM = $false
& $JAVA "-Djava.security.manager=allow" -version >$null 2>&1
Expand Down Expand Up @@ -174,6 +183,12 @@ Param(
$DEFAULT_MODULAR_JVM_OPTIONS += "--add-exports=java.naming/com.sun.jndi.url.ldaps=ALL-UNNAMED"
# Needed by Netty
$DEFAULT_MODULAR_JVM_OPTIONS += "--add-exports=jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED"
# Needed by WildFly Elytron Extension
$packageName = "java.base/com.sun.net.ssl.internal.ssl"
$PACKAGE_AVAILABLE = setPackageAvailable($packageName)
if($PACKAGE_AVAILABLE) {
$DEFAULT_MODULAR_JVM_OPTIONS += "--add-opens=$packageName=ALL-UNNAMED"
}
# Needed if Hibernate applications use Javassist
$DEFAULT_MODULAR_JVM_OPTIONS += "--add-opens=java.base/java.lang=ALL-UNNAMED"
# Needed by the MicroProfile REST Client subsystem
Expand Down
15 changes: 15 additions & 0 deletions core-feature-pack/common/src/main/resources/content/bin/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ if [ -r "$COMMON_CONF" ]; then
. "$COMMON_CONF"
fi

setPackageAvailable() {
PACKAGE_STRING=`"$JAVA" --add-opens=$1=ALL-UNNAMED -version 2>&1 | $GREP "WARNING"`
if [ "x$PACKAGE_STRING" = "x" ]; then
PACKAGE_AVAILABLE=true
else
PACKAGE_AVAILABLE=false
fi
}

setEnhancedSecurityManager() {
"$JAVA" -Djava.security.manager=allow -version > /dev/null 2>&1 && ENHANCED_SM=true || ENHANCED_SM=false
}
Expand Down Expand Up @@ -44,6 +53,12 @@ setDefaultModularJvmOptions() {
DEFAULT_MODULAR_JVM_OPTIONS="$DEFAULT_MODULAR_JVM_OPTIONS --add-exports=java.naming/com.sun.jndi.url.ldaps=ALL-UNNAMED"
# Needed by Netty
DEFAULT_MODULAR_JVM_OPTIONS="$DEFAULT_MODULAR_JVM_OPTIONS --add-exports=jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED"
# Needed by WildFly Elytron Extension
PACKAGE_NAME="java.base/com.sun.net.ssl.internal.ssl"
setPackageAvailable $PACKAGE_NAME
if [ "$PACKAGE_AVAILABLE" = "true" ]; then
DEFAULT_MODULAR_JVM_OPTIONS="$DEFAULT_MODULAR_JVM_OPTIONS --add-opens=$PACKAGE_NAME=ALL-UNNAMED"
fi
# Needed if Hibernate applications use Javassist
DEFAULT_MODULAR_JVM_OPTIONS="$DEFAULT_MODULAR_JVM_OPTIONS --add-opens=java.base/java.lang=ALL-UNNAMED"
# Needed by the MicroProfile REST Client subsystem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ private List<String> getServerLaunchCommand(boolean includeProcessId, boolean fo
}

command.addAll(localJvmType.getDefaultArguments());
command.addAll(localJvmType.getOptionalDefaultArguments());

command.add(String.format("-D%s=%s", ServerEnvironment.SERVER_LOG_DIR, this.logDir));
command.add(String.format("-D%s=%s", ServerEnvironment.SERVER_TEMP_DIR, this.tmpDir));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,18 @@

package org.jboss.as.host.controller.jvm;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import org.jboss.as.host.controller.logging.HostControllerLogger;
import org.wildfly.security.manager.WildFlySecurityManager;
Expand All @@ -42,7 +49,10 @@ public final class JvmType {
private static final String JAVA_HOME_SYS_PROP = "java.home";
private static final String JAVA_HOME_ENV_VAR = "JAVA_HOME";
private static final String OS_NAME_SYS_PROP = "os.name";
/** Packages being exported or opened are available on all JVMs */
private static final Collection<String> DEFAULT_MODULAR_JVM_ARGUMENTS;
/** Packages being exported or opened may not be available on all JVMs */
private static final Collection<String> DEFAULT_OPTIONAL_MODULAR_JVM_ARGUMENTS;
private static final String JAVA_EXECUTABLE;
private static final String JAVA_UNIX_EXECUTABLE = "java";
private static final String JAVA_WIN_EXECUTABLE = "java.exe";
Expand Down Expand Up @@ -74,6 +84,9 @@ public final class JvmType {
modularJavaOpts.add("--add-opens=java.management/javax.management=ALL-UNNAMED");
modularJavaOpts.add("--add-opens=java.naming/javax.naming=ALL-UNNAMED");
DEFAULT_MODULAR_JVM_ARGUMENTS = Collections.unmodifiableList(modularJavaOpts);
final ArrayList<String> modularOptionalJavaOpts = new ArrayList<>();
modularOptionalJavaOpts.add("--add-opens=java.base/com.sun.net.ssl.internal.ssl=ALL-UNNAMED");
DEFAULT_OPTIONAL_MODULAR_JVM_ARGUMENTS = Collections.unmodifiableList(modularOptionalJavaOpts);
}

private JvmType(final boolean forLaunch, final boolean isModularJvm, final String javaExecutable) {
Expand Down Expand Up @@ -107,6 +120,27 @@ public Collection<String> getDefaultArguments() {
return isModularJvm ? DEFAULT_MODULAR_JVM_ARGUMENTS : Collections.EMPTY_LIST;
}

/**
* The expectation is this method is called once per JvmType instance.
* In theory we could cache the result for reuse, but if we change how
* we use these instances it may not be the case that a cached value
* would be correct over multiple invocations.
* @return collection of optional (may not be available on all JDK versions) modular JVM arguments
*/
public Collection<String> getOptionalDefaultArguments() {
if (isModularJvm) {
Collection<String> retVal = null;
ropalka marked this conversation as resolved.
Show resolved Hide resolved
for (final String optionalModularArgument : DEFAULT_OPTIONAL_MODULAR_JVM_ARGUMENTS) {
if (packageAvailableOnJvm(javaExecutable, true, optionalModularArgument)) {
if (retVal == null) retVal = new ArrayList<>();
retVal.add(optionalModularArgument);
}
}
if (retVal != null) return retVal;
}
return Collections.EMPTY_LIST;
}

/**
* Create a {@code JvmType} based on the location of the root dir of the JRE/JDK installation.
* @param javaHome the root dir of the JRE/JDK installation. Cannot be {@code null} or empty
Expand Down Expand Up @@ -147,6 +181,54 @@ private static boolean isModularJvm(final String javaExecutable, final boolean f
return false;
}

private static boolean packageAvailableOnJvm(final String javaExecutable, final boolean forLaunch, final String optionalModularArgument) {
if (!forLaunch) return false;
boolean result;
final ProcessBuilder builder = new ProcessBuilder(javaExecutable, optionalModularArgument, "-version");
Process process = null;
Path stdout = null;
try {
// Create a temporary file for stdout
stdout = Files.createTempFile("stdout", ".txt");
process = builder.redirectErrorStream(true)
.redirectOutput(stdout.toFile()).start();

if (process.waitFor(30, TimeUnit.SECONDS)) {
result = process.exitValue() == 0;
} else {
result = false;
}
} catch (IOException | InterruptedException e) {
result = false;
} finally {
if (process != null && process.isAlive()) {
process.destroyForcibly();
}
if (stdout != null) {
try {
if (containsWarning(stdout)) {
result = false;
}
Files.deleteIfExists(stdout);
} catch (IOException ignore) {
}
}
}
return result;
}

private static boolean containsWarning(final Path logFile) throws IOException {
String line;
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(logFile.toFile())))) {
while ((line = br.readLine()) != null) {
if (line.startsWith("WARNING:")) {
return true;
}
}
}
return false;
}

/**
* Create a {@code JvmType} based on the location of the java executable.
* @param javaExecutable the location of the java executable. Cannot be {@code null} or empty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ public void testCreateConfiguration() throws UnknownHostException {
Assert.assertNotNull(result);
}

private static int getJavaVersion() throws NumberFormatException {
final String versionString = System.getProperty("java.version");
int indexOfDot = versionString.indexOf('.');
return Integer.valueOf(versionString.substring(0, indexOfDot)).intValue();
}

/**
* Test of getServerLaunchCommand method, of class
* ManagedServerBootCmdFactory.
Expand All @@ -129,7 +135,7 @@ public void testGetServerLaunchCommand() throws UnknownHostException {
List<String> result = instance.getServerLaunchCommand();
MatcherAssert.assertThat(result.size(), is(notNullValue()));
if (result.size() > 18) {
MatcherAssert.assertThat(result.size(), is(33));
MatcherAssert.assertThat(result.size(), is(getJavaVersion() <= 12 ? 34 : 33)); // for condition see WFCORE-4296 - java.base/com.sun.net.ssl.internal.ssl isn't available since JDK13
} else {
MatcherAssert.assertThat(result.size(), is(18));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ abstract class AbstractCommandBuilder<T extends AbstractCommandBuilder<T>> imple
static final String SECURITY_MANAGER_PROP = "java.security.manager";
static final String SECURITY_MANAGER_PROP_WITH_ALLOW_VALUE = "-D" + SECURITY_MANAGER_PROP + "=" + ALLOW_VALUE;
static final String[] DEFAULT_VM_ARGUMENTS;
/** Packages being exported or opened are available on all JVMs */
static final Collection<String> DEFAULT_MODULAR_VM_ARGUMENTS;
/** Packages being exported or opened may not be available on all JVMs */
static final Collection<String> OPTIONAL_DEFAULT_MODULAR_VM_ARGUMENTS;

static {
// Default JVM parameters for all versions
Expand All @@ -62,7 +65,8 @@ abstract class AbstractCommandBuilder<T extends AbstractCommandBuilder<T>> imple
// Additions to these should include good explanations why in the relevant JIRA
// Keep them alphabetical to avoid the code history getting confused by reordering commits
final ArrayList<String> modularJavaOpts = new ArrayList<>();
if (!Boolean.parseBoolean(System.getProperty("launcher.skip.jpms.properties", "false"))) {
final boolean skipJPMSOptions = Boolean.getBoolean("launcher.skip.jpms.properties");
if (!skipJPMSOptions) {
modularJavaOpts.add("--add-exports=java.desktop/sun.awt=ALL-UNNAMED");
modularJavaOpts.add("--add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED");
modularJavaOpts.add("--add-exports=java.naming/com.sun.jndi.url.ldap=ALL-UNNAMED");
Expand All @@ -83,6 +87,12 @@ abstract class AbstractCommandBuilder<T extends AbstractCommandBuilder<T>> imple
modularJavaOpts.add("--add-modules=java.se");
}
DEFAULT_MODULAR_VM_ARGUMENTS = Collections.unmodifiableList(modularJavaOpts);

final ArrayList<String> optionalModularJavaOpts = new ArrayList<>();
if (!skipJPMSOptions) {
optionalModularJavaOpts.add("--add-opens=java.base/com.sun.net.ssl.internal.ssl=ALL-UNNAMED");
}
OPTIONAL_DEFAULT_MODULAR_VM_ARGUMENTS = Collections.unmodifiableList(optionalModularJavaOpts);
}

protected final Environment environment;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,11 @@ public List<String> buildArguments() {
if (modularLauncher) {
if (environment.getJvm().isModular()) {
cmd.addAll(AbstractCommandBuilder.DEFAULT_MODULAR_VM_ARGUMENTS);
for (final String optionalModularArgument : AbstractCommandBuilder.OPTIONAL_DEFAULT_MODULAR_VM_ARGUMENTS) {
if (environment.getJvm().isPackageAvailable(environment.getJvm().getPath(), optionalModularArgument)) {
cmd.add(optionalModularArgument);
}
}
}
}
if (environment.getJvm().enhancedSecurityManagerAvailable()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,11 @@ public List<String> buildArguments() {
cmd.addAll(processControllerJavaOpts.asList());
if (environment.getJvm().isModular()) {
cmd.addAll(DEFAULT_MODULAR_VM_ARGUMENTS);
for (final String optionalModularArgument : OPTIONAL_DEFAULT_MODULAR_VM_ARGUMENTS) {
if (environment.getJvm().isPackageAvailable(environment.getJvm().getPath(), optionalModularArgument)) {
cmd.add(optionalModularArgument);
}
}
}
if (environment.getJvm().enhancedSecurityManagerAvailable()) {
cmd.add(SECURITY_MANAGER_PROP_WITH_ALLOW_VALUE);
Expand Down Expand Up @@ -746,6 +751,11 @@ public List<String> buildArguments() {
cmd.addAll(hostControllerJavaOpts.asList());
if (hostControllerJvm.isModular()) {
cmd.addAll(DEFAULT_MODULAR_VM_ARGUMENTS);
for (final String optionalModularArgument : OPTIONAL_DEFAULT_MODULAR_VM_ARGUMENTS) {
if (environment.getJvm().isPackageAvailable(environment.getJvm().getPath(), optionalModularArgument)) {
cmd.add(optionalModularArgument);
}
}
}
if (hostControllerJvm.enhancedSecurityManagerAvailable()) {
cmd.add(SECURITY_MANAGER_PROP_WITH_ALLOW_VALUE);
Expand Down
32 changes: 29 additions & 3 deletions launcher/src/main/java/org/wildfly/core/launcher/Jvm.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
package org.wildfly.core.launcher;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -57,11 +59,13 @@ class Jvm {
final String javaSpecVersion = System.getProperty("java.specification.version");
boolean modularJvm = true;
boolean enhancedSecurityManager = false;
int jvmVersion = 8;
if (javaSpecVersion != null) {
final Matcher matcher = Pattern.compile("^(?:1\\.)?(\\d+)$").matcher(javaSpecVersion);
if (matcher.find()) {
modularJvm = Integer.parseInt(matcher.group(1)) >= 9;
enhancedSecurityManager = Integer.parseInt(matcher.group(1)) >= 12;
jvmVersion = Integer.parseInt(matcher.group(1));
modularJvm = jvmVersion >= 9;
enhancedSecurityManager = jvmVersion >= 12;
}
}
MODULAR_JVM = modularJvm;
Expand Down Expand Up @@ -215,6 +219,14 @@ private static boolean hasEnhancedSecurityManager(final Path javaHome) {
return checkProcessStatus(cmd);
}

static boolean isPackageAvailable(final Path javaHome, final String optionalModularArgument) {
final List<String> cmd = new ArrayList<>();
cmd.add(resolveJavaCommand(javaHome));
cmd.add(optionalModularArgument);
cmd.add("-version");
return checkProcessStatus(cmd);
}

/**
* Checks to see if the {@code javaHome} is a modular JVM.
*
Expand Down Expand Up @@ -247,7 +259,7 @@ private static boolean checkProcessStatus(final List<String> cmd) {
process = builder.redirectErrorStream(true)
.redirectOutput(stdout.toFile()).start();

if (process.waitFor(1, TimeUnit.SECONDS)) {
if (process.waitFor(30, TimeUnit.SECONDS)) {
result = process.exitValue() == 0;
} else {
result = false;
Expand All @@ -260,6 +272,9 @@ private static boolean checkProcessStatus(final List<String> cmd) {
}
if (stdout != null) {
try {
if (containsWarning(stdout)) {
result = false;
}
Files.deleteIfExists(stdout);
} catch (IOException ignore) {
}
Expand All @@ -268,6 +283,17 @@ private static boolean checkProcessStatus(final List<String> cmd) {
return result;
}

private static boolean containsWarning(final Path logFile) throws IOException {
String line;
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(logFile.toFile())))) {
while ((line = br.readLine()) != null) {
if (line.startsWith("WARNING:")) {
return true;
}
}
}
return false;
}

/**
* Returns the Java executable command.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,11 @@ public List<String> buildArguments() {
cmd.addAll(getJavaOptions());
if (environment.getJvm().isModular()) {
cmd.addAll(DEFAULT_MODULAR_VM_ARGUMENTS);
for (final String optionalModularArgument : OPTIONAL_DEFAULT_MODULAR_VM_ARGUMENTS) {
if (environment.getJvm().isPackageAvailable(environment.getJvm().getPath(), optionalModularArgument)) {
cmd.add(optionalModularArgument);
}
}
}
if (environment.getJvm().enhancedSecurityManagerAvailable()) {
cmd.add(SECURITY_MANAGER_PROP_WITH_ALLOW_VALUE);
Expand Down
Loading