I apologize for it being a bit rough - it's what I was using to
troubleshoot locally.
import static java.util.Objects.nonNull;
import java.lang.management.ManagementFactory;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type;
@javax.annotation.ManagedBean
public class MbeanFailure {
private static final Logger LOGGER = LogManager.getLogger();
private static final String LOCALHOST = "127.0.0.1";
private static final String SUBTYPE = "subType";
private static final String ADD_SSL_HOST_CONFIG_OP = "addSslHostConfig";
private static final Predicate<ObjectName> NOT_LOCALHOST = Predicate.not(on
->
Optional.ofNullable(on).map(ObjectName::getCanonicalName).orElse("").contains(LOCALHOST));
private static final Predicate<ObjectName> NOT_SUBTYPE = Predicate.not(on
->
Optional.ofNullable(on).map(ObjectName::getCanonicalName).orElse("").contains(SUBTYPE));
@javax.annotation.PostConstruct
public void run() throws Exception {
final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
final SSLHostConfig config = new SSLHostConfig();
config.setProtocols("TLSv1.2");
config.setHostName("test.test.com");
config.setCiphers("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
final SSLHostConfigCertificate cert = new SSLHostConfigCertificate(config,
Type.UNDEFINED);
config.addCertificate(cert);
final Map<MBeanServer, ObjectName> references = getObjectReferences(server,
"ProtocolHandler");
references.forEach((s, op) -> invoke(s, op, ADD_SSL_HOST_CONFIG_OP, new
Object[] {config}, new String[] {SSLHostConfig.class.getCanonicalName()}));
}
public Map<MBeanServer, ObjectName> getObjectReferences(final MBeanServer
server, final String discriminator) {
final Map<MBeanServer, ObjectName> results = new HashMap<>();
final Predicate<ObjectName> extendedFilters =
NOT_LOCALHOST.and(NOT_SUBTYPE);
final Optional<ObjectName> candidate = server.queryNames(null,
null).stream()
.filter(on -> nonNull(on.getCanonicalName()))
.filter(on -> on.getCanonicalName().contains(discriminator))
.filter(extendedFilters)
.findAny();
candidate.ifPresent(on -> results.put(server, on));
return Map.copyOf(results);
}
public Object invoke(final MBeanServer server, final ObjectName objectName,
final String method, final Object[] params, final String[] signature) {
try {
//This should return addSslHostConfig(SSLHostConfig, boolean)
final MBeanInfo info = server.getMBeanInfo(objectName);
final MBeanOperationInfo methodInfo = Arrays.stream(info.getOperations())
.filter(i -> i.getName().equals(method))
.findAny()
.orElseThrow(() -> new RuntimeException("Could not find method named" +
method));
LOGGER.error("Found available operation {}", methodInfo);
final Object result = server.invoke(objectName, method, params, signature);
return result;
} catch (final Exception e) {
throw new RuntimeException("Error invoking " + method + " with params " +
Arrays.toString(params) + " and signature " + Arrays.toString(signature),
e);
}
}
}
On Fri, Dec 8, 2023 at 4:55 PM Christopher Schultz <
[email protected]> wrote:
> Daniel,
>
> On 12/7/23 13:25, Daniel Skiles wrote:
> > All,
> > I've been doing some testing, and I'm pretty sure the addSslHostConfig
> > operation on ProtocolHandler is busted in 9.0.83.
> >
> > In versions prior to 9.0.82, you can call the operation with a single
> > argument of type SSLHostConfig.
> >
> > In 9.0.82, that contract seems to have been broken, and you had to call
> > it with two arguments: an SSLHostConfig and a boolean.
> >
> > In 9.0.83, it seems as though both operations are present, but which one
> > is actually accessible at runtime is non-deterministic.
> >
> > This behavior presents through a direct invoke(...) call and via a JMX
> > Proxy object instantiated through JMX.newMBeanProxy.
> >
> > I have attached a sample file that reproduces the behavior (sometimes,
> > as it is nondeterministic).
> >
> > Is this a bug, or am I simply using the available feature incorrectly?
> >
> > If it is the former, how do I formally report this? If it is the
> > latter, what is the "correct" way to call this operation from JMX?
>
> I think your attachment was stripped. Can it be posted in-line?
>
> -chris
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>