OpenNTF / org.openntf.xsp.jakartaee

XPages Jakarta EE support libraries
Apache License 2.0
21 stars 7 forks source link

Investigate relieving the need to alter java.policy #47

Open jesse-gallagher opened 2 years ago

jesse-gallagher commented 2 years ago

Something in the stack requests reflective access, and it's not alleviated by wrapping the whole thing in an AccessController block.

jesse-gallagher commented 2 years ago

The stack trace in question is:

java.lang.ExceptionInInitializerError
     at java.lang.J9VMInternals.ensureError(J9VMInternals.java:145)
     at java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:134)
     at java.lang.J9VMInternals.newInstanceImpl(Native Method)
     at java.lang.Class.newInstance(Class.java:2062)
     at org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:158)
     at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:343)
     at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:417)
     at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:321)
     at org.openntf.xsp.jsp.nsf.NSFJspServlet.lambda$0(NSFJspServlet.java:88)
     at org.openntf.xsp.jsp.nsf.NSFJspServlet$$Lambda$9/0x0000000000000000.run(Unknown Source)
     at java.security.AccessController.doPrivileged(AccessController.java:738)
     at org.openntf.xsp.jsp.nsf.NSFJspServlet.doService(NSFJspServlet.java:78)
     at org.openntf.xsp.jakartaee.AbstractXspLifecycleServlet.service(AbstractXspLifecycleServlet.java:118)
     at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:587)
     at org.openntf.xsp.jakartaee.servlet.NewHttpServletWrapper.service(NewHttpServletWrapper.java:65)
     at com.ibm.designer.runtime.domino.adapter.ComponentModule.invokeServlet(ComponentModule.java:600)
     at com.ibm.domino.xsp.module.nsf.NSFComponentModule.invokeServlet(NSFComponentModule.java:1352)
     at com.ibm.designer.runtime.domino.adapter.ComponentModule$AdapterInvoker.invokeServlet(ComponentModule.java:877)
     at com.ibm.designer.runtime.domino.adapter.ComponentModule$ServletInvoker.doService(ComponentModule.java:820)
     at com.ibm.designer.runtime.domino.adapter.ComponentModule.doService(ComponentModule.java:589)
     at com.ibm.domino.xsp.module.nsf.NSFComponentModule.doService(NSFComponentModule.java:1336)
     at com.ibm.domino.xsp.module.nsf.NSFService.doServiceInternal(NSFService.java:725)
     at com.ibm.domino.xsp.module.nsf.NSFService.doService(NSFService.java:515)
     at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.doService(LCDEnvironment.java:363)
     at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.service(LCDEnvironment.java:319)
     at com.ibm.domino.xsp.bridge.http.engine.XspCmdManager.service(XspCmdManager.java:272)
Caused by:
java.security.AccessControlException: Access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
     at java.security.AccessController.throwACE(AccessController.java:176)
     at java.security.AccessController.checkPermissionHelper(AccessController.java:238)
     at java.security.AccessController.checkPermission(AccessController.java:385)
     at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
     at lotus.notes.AgentSecurityManager.checkPermission(Unknown Source)
     at java.lang.Class.checkMemberAccess(Class.java:254)
     at java.lang.Class.getDeclaredMethod(Class.java:962)
     at org.apache.jasper.runtime.ProtectedFunctionMapper.getMapForFunction(ProtectedFunctionMapper.java:160)
     at org.apache.jsp.hello_jsp.<clinit>(hello_jsp.java:13)
     ... 24 more

I'm not really sure why wrapping the whole call in a doPrivileged block isn't doing it already, really.

jesse-gallagher commented 2 years ago

This was alleviated in JSP by setting the package.definition Java system property to "org.apache.jsp". The presence of this property as non-empty at all signals to Jasper that it should use AccessController.doPrivileged blocks in general, while setting it to that package should avoid interfering with other normal cases.

jesse-gallagher commented 2 years ago

This now leaves trouble in JNoSQL:

java.security.AccessControlException: Access denied (\"java.lang.RuntimePermission\" \"getClassLoader\"),
  at java.security.AccessController.throwACE(AccessController.java:176),
  at java.security.AccessController.checkPermissionHelper(AccessController.java:238),
  at java.security.AccessController.checkPermission(AccessController.java:385),
  at java.lang.SecurityManager.checkPermission(SecurityManager.java:549),
  at lotus.notes.AgentSecurityManager.checkPermission(Unknown Source),
  at java.lang.Class.getClassLoader(Class.java:500),
  at org.eclipse.jnosql.mapping.document.query.RepositoryDocumentBean.create(RepositoryDocumentBean.java:85),
  at org.eclipse.jnosql.mapping.document.query.RepositoryDocumentBean.create(RepositoryDocumentBean.java:38),
  at org.jboss.weld.contexts.AbstractContext.get(AbstractContext.java:96),
  at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.get(ContextualInstanceStrategy.java:100),
  at org.jboss.weld.bean.ContextualInstance.get(ContextualInstance.java:50),
  at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:102),
  at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:105),
  at org.jboss.weld.generated.proxies.default.PersonRepository$2011351562$Proxy$_$$_WeldClientProxy.findByLastName(Unknown Source),
  at rest.NoSQLExample.get(NoSQLExample.java:62),

This may be tricky, as there's no direct path to get to this that would work in all scenarios. One possibility may be an upstream contribution, but ideally we would avoid that: it'd be unnecessary in almost all cases other than Domino. Unfortunately, this class is used explicitly with new RepositoryDocumentBean, so it couldn't be subclassed and provided separately. A last-ditch effort could be OSGi weaving: wrap the whole method contents in AccessController.doPrivileged, which should be at least reasonably resilient against upstream changes.

jesse-gallagher commented 2 years ago

The MicroProfile REST Client runs into similar trouble:

java.security.AccessControlException: Access denied (\"java.lang.RuntimePermission\" \"getClassLoader\"),
  at java.security.AccessController.throwACE(AccessController.java:176),
  at java.security.AccessController.checkPermissionHelper(AccessController.java:238),
  at java.security.AccessController.checkPermission(AccessController.java:385),
  at java.lang.SecurityManager.checkPermission(SecurityManager.java:549),
  at lotus.notes.AgentSecurityManager.checkPermission(Unknown Source),
  at java.lang.Thread.getContextClassLoader(Thread.java:538),
  at org.jboss.resteasy.microprofile.client.RestClientListeners.get(RestClientListeners.java:44),
  at org.jboss.resteasy.microprofile.client.RestClientBuilderImpl.build(RestClientBuilderImpl.java:239),
  at org.jboss.resteasy.microprofile.client.RestClientBuilderImpl.build(RestClientBuilderImpl.java:388),
  at rest.RestClientExample.get(RestClientExample.java:60)

The good news here is that it keeps a per-ClassLoader cache, so it may be possible to "prime" it by calling RestClientListeners.get() in an AccessController.doPrivileged block before the request starts. It could be annoying to cover each case (a ServiceParticipant for JAX-RS, a request customizer for XPages, a new entrypoint for JSP), but that could avoid further hacks.

jesse-gallagher commented 2 years ago

The current stack trace for NoSQL is:

java.security.AccessControlException: Access denied ("java.lang.RuntimePermission" "getClassLoader")
    java.security.AccessController.throwACE(AccessController.java:176)
    java.security.AccessController.checkPermissionHelper(AccessController.java:238)
    java.security.AccessController.checkPermission(AccessController.java:385)
    java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    lotus.notes.AgentSecurityManager.checkPermission(Unknown Source)
    java.lang.Class.getClassLoader(Class.java:500)
    org.eclipse.jnosql.mapping.document.query.DefaultDocumentRepositoryProducer.get(DefaultDocumentRepositoryProducer.java:57)
    org.eclipse.jnosql.mapping.document.query.DefaultDocumentRepositoryProducer$Proxy$_$$_WeldClientProxy.get(Unknown Source)
    org.openntf.xsp.nosql.mapping.extension.impl.DominoRepositoryBean.create(DominoRepositoryBean.java:82)