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 <
ch...@christopherschultz.net> 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: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
>
>

Reply via email to